实践1 . 使用树莓派A20启动FPGA


1 硬件接线

A20硬件原理图

可以使用PH1,PH3,PH7,PH17,PH19,PH23。

在sys_config.fex中配置如下:

A20基本引脚配置
[FPGA_set_para]
fpga_set_enable           = 1
fpga_set_nums             = 6
fpga_nCONFIG              = port:PH1<1><1><default><default>
fpga_DCLK                 = port:PH3<1><1><default><default>
fpga_DATA                 = port:PH7<1><1><default><default>
fpga_STATUS               = port:PH17<1><1><default><default>
fpga_CONFIG_DONE          = port:PH19<1><1><default><default>
fpga_INIT_DONE            = port:PH23<1><1><default><default>

2 驱动代码

将驱动代码命名为:fpga_driver.c,内容如下所示:

/**
*           copyright wit_yuan 2017-07-24 北京全景声信息科技有限公司
*
*           A20驱动fpga,升级fpga的程序
*
*/
#include "linux/init.h"
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/leds.h>
#include <plat/sys_config.h>
#include <linux/major.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/delay.h>


#define FPGA_DRIVER_DEBUG 0

#if FPGA_DRIVER_DEBUG
    #define fpga_loader_debug(fmt,...) printk("%s,%d"fmt,__FILE__,__LINE__,##__VA_ARGS__)
#else
    #define fpga_loader_debug(fmt,...)  
#endif

struct fpga_io_name{
    unsigned char *main_key;
    unsigned char *sub_key;  
    unsigned char status;/*input=0,output=1*/
    unsigned int    handler;    /* gpio handler*/
};

enum {
    TYPE_FPGA_START=1,
    TYPE_FPGA_BUFFER,
    TYPE_FPGA_CONFIG_END,
    TYPE_FPGA_INIT_END,
}ID_TYPE;

struct fpga_buffer{
    int id;/* 1.start 2.data 3.end*/
    unsigned char data;
};

static struct fpga_buffer fpga_buffer_t;

static struct fpga_io_name fpga_io_name_t[6]={
    {"FPGA_set_para","fpga_nCONFIG",1,0},
    {"FPGA_set_para","fpga_DCLK",1,0},
    {"FPGA_set_para","fpga_DATA",1,0},
    {"FPGA_set_para","fpga_STATUS",0,0},
    {"FPGA_set_para","fpga_CONFIG_DONE",0,0},
    {"FPGA_set_para","fpga_INIT_DONE",0,0},
};

static script_gpio_set_t info;
static struct class *fpga_loader_class;
static struct device *fpga_loader_device;
static unsigned int fpga_loader_major;

static  ssize_t fpga_loader_read (struct file *, char __user *, size_t, loff_t *);
static int fpga_loader_open(struct inode *inode, struct file *filp);
static ssize_t fpga_loader_write (struct file *filp, const char __user *buf, size_t len, loff_t *off);
static int fpga_loader_close(struct inode *inode, struct file *filp);


struct file_operations fpga_loader_operations = {
    .owner   = THIS_MODULE,
    .open    = fpga_loader_open,
    .read    = fpga_loader_read,
    .write   = fpga_loader_write,
    .release = fpga_loader_close,
};

static int fpga_loader_open(struct inode *inode, struct file *filp)
{
    int i = 0;
    int err = 0;
    int fpga_loader_test_enabled = 0;
    int ret = 0;

   fpga_loader_debug("-----open---\r\n");

#if 1
    err = script_parser_fetch("FPGA_set_para", "fpga_set_enable", &fpga_loader_test_enabled,
                    sizeof(fpga_loader_test_enabled)/sizeof(int));

    if(!err){
        fpga_loader_debug("---script.bin led get ok,value:%d----\n",fpga_loader_test_enabled);
    }
    else
    {
        fpga_loader_debug("---script.bin led get false----\n");    
        return -1;
    }

    for(i = 0 ; i < 6 ; i ++){
        
        err = script_parser_fetch(fpga_io_name_t[i].main_key, fpga_io_name_t[i].sub_key,
                    (int *)&info,
                    sizeof(script_gpio_set_t));
        if (err) {
            fpga_loader_debug("----script.bin get io error----\r\n");
            return -1;
        }
        /* reserve gpio for led */
        fpga_io_name_t[i].handler = gpio_request_ex(fpga_io_name_t[i].main_key, fpga_io_name_t[i].sub_key);
        if (!fpga_io_name_t[i].handler) {
            fpga_loader_debug("----script.bin can't requst nCONFIG handler----\r\n");
            return -1;
        }

        gpio_set_one_pin_io_status(fpga_io_name_t[i].handler, fpga_io_name_t[i].status,
                            fpga_io_name_t[i].sub_key);
        
        gpio_set_one_pin_pull(fpga_io_name_t[i].handler,1/*pull up*/,
                 fpga_io_name_t[i].sub_key);
                        
    }
#endif 


    return 0;
}


/*
*               copyright wit_yuan 2017-07-24 北京全景声信息科技有限公司
*
*               读取数据状态
*
*               STATUS
*               CONFIG_DONE
*               INIT_DONE
*
*/
static  ssize_t fpga_loader_read(struct file *filp, char __user *buf, size_t len, loff_t *off)
{
    int ret_val = 0;
    switch(fpga_buffer_t.id){
        case TYPE_FPGA_START:
            /*status*/
            ret_val = -1;
            
            ret_val = gpio_read_one_pin_value(fpga_io_name_t[3].handler,fpga_io_name_t[3].sub_key);
            if(ret_val < 0){
                fpga_loader_debug("---read status value failed---\r\n");
            }
            //printk("---len:%d---\r\n",len);
            copy_to_user(buf,&ret_val,len);
        break;
        case TYPE_FPGA_BUFFER:
            /*status*/
            ret_val = -1;
            
            ret_val = gpio_read_one_pin_value(fpga_io_name_t[3].handler,fpga_io_name_t[3].sub_key);
            if(ret_val < 0){
                fpga_loader_debug("---read status value failed---\r\n");
            }
            copy_to_user(buf,&ret_val,len);
        break;
        case TYPE_FPGA_CONFIG_END:
            /*CONFIG_DONE*/
            ret_val = gpio_read_one_pin_value(fpga_io_name_t[4].handler,fpga_io_name_t[4].sub_key);
            if(ret_val < 0){
                fpga_loader_debug("---read CONFIG_DONE value failed---\r\n");
            }
            copy_to_user(buf,&ret_val,len);
        break;
        case TYPE_FPGA_INIT_END:
            /*INIT_DONE*/
            ret_val = gpio_read_one_pin_value(fpga_io_name_t[5].handler,fpga_io_name_t[5].sub_key);
            if(ret_val < 0){
                fpga_loader_debug("---read INIT_DONE value failed---\r\n");
            }
            copy_to_user(buf,&ret_val,len);
        break;

    }

    return ret_val;
}

static ssize_t fpga_loader_write (struct file *filp, const char __user *buf, size_t len, loff_t *off)
{
    int val;
    int i = 0;
    int i_ret = 1;
    unsigned char data;
    //struct fpga_buffer fpga_buffer_t ;
    copy_from_user(&fpga_buffer_t,buf,len); 

    switch(fpga_buffer_t.id){
        case TYPE_FPGA_START:
        fpga_loader_debug("----start message----\r\n");
        udelay(10);

        /*nconfig=1,dclk=0,data=0*/
        /*config*/
        gpio_write_one_pin_value(fpga_io_name_t[0].handler,
                   1, fpga_io_name_t[0].sub_key); 
        /*dclk*/
        gpio_write_one_pin_value(fpga_io_name_t[1].handler,
                   0, fpga_io_name_t[1].sub_key);       
        /*data*/
        gpio_write_one_pin_value(fpga_io_name_t[2].handler,
                  0, fpga_io_name_t[2].sub_key); 
        
        udelay(10);
        /*nCONFIG=0,DCLK=0*/
        gpio_write_one_pin_value(fpga_io_name_t[0].handler,
                   0, fpga_io_name_t[0].sub_key);       
        gpio_write_one_pin_value(fpga_io_name_t[1].handler,
                  0, fpga_io_name_t[1].sub_key); 
        
        udelay(2);

        /*nCONFIG=1*/
        gpio_write_one_pin_value(fpga_io_name_t[0].handler,
                   1, fpga_io_name_t[0].sub_key);       

        udelay(2);

        break;
        case TYPE_FPGA_BUFFER:
        //printk("----buffer message----\r\n");
        data = fpga_buffer_t.data;
        for(i = 0 ; i < 8 ; i ++){
            if(data & (1<<i)){
                /*data*/
                gpio_write_one_pin_value(fpga_io_name_t[2].handler,
                  1, fpga_io_name_t[2].sub_key); 
            }
            else
            {
                /*data*/
                gpio_write_one_pin_value(fpga_io_name_t[2].handler,
                  0, fpga_io_name_t[2].sub_key); 
            }

            udelay(1);

            /*dclk=1*/
            gpio_write_one_pin_value(fpga_io_name_t[1].handler,
                  1, fpga_io_name_t[1].sub_key);

            udelay(1);
            
            /*dclk=0*/
            gpio_write_one_pin_value(fpga_io_name_t[1].handler,
                  0, fpga_io_name_t[1].sub_key);

            udelay(1);
        }
        break;
        case TYPE_FPGA_CONFIG_END:
            /*CONFIG_DONE*/
        break;
        case TYPE_FPGA_INIT_END:
            /*INIT_DONE*/
        break;
        default:
        fpga_loader_debug("----default message----\r\n");
        break;
    }
    return 0;
}

static int fpga_loader_close(struct inode *inode, struct file *filp)
{
    fpga_loader_debug("----fpga_loader close----\r\n");

#if 0
    int i = 0;
    //if (gpio_handler)
     //   gpio_release(gpio_handler, 1);
    for(i = 0 ; i < 6 ; i ++){
        if(fpga_io_name_t[i].handler){
            gpio_release(fpga_io_name_t[i].handler, 1);
        }
    }
#endif
    return 0;
}

static int __init fpga_loader_init(void)
{
   fpga_loader_major = register_chrdev(0, "fpga_loader_chrdev", &fpga_loader_operations);

    fpga_loader_class = class_create(THIS_MODULE, "fpga_loader_class");

    if(!fpga_loader_class){
        unregister_chrdev(fpga_loader_major, "fpga_loader_chrdev");
        fpga_loader_debug("----leds_chrdev error----\r\n");
        return -1;
    }
   fpga_loader_device = device_create(fpga_loader_class, NULL, MKDEV(fpga_loader_major,0),
                          NULL, "fpga_loader_device");
    if(!fpga_loader_device){
        class_destroy(fpga_loader_class);
        unregister_chrdev(fpga_loader_major, "fpga_loader_chrdev");
        fpga_loader_debug("----fpga_loader_device error----\r\n");
        return -1;
    }

    fpga_loader_debug("----fpga_loader init ok----\r\n");
    return 0;
}


static void __exit  fpga_loader_exit(void)
{
    device_destroy(fpga_loader_class, MKDEV(fpga_loader_major, 0));
    class_destroy(fpga_loader_class);
    unregister_chrdev(fpga_loader_major, "fpga_loader_chrdev");

    fpga_loader_debug("---driver exit---\r\n");
}

module_init(fpga_loader_init);
module_exit(fpga_loader_exit);

MODULE_DESCRIPTION("Driver for fpga loader 2017-07-24");
MODULE_AUTHOR("wit_yuan");
MODULE_LICENSE("GPL");

最终,将代码放到内核目录linux-sunxi/drivers/char下。并且修改Kconfig和Makefile内容:
Kconfig内容如下所示:

config FPGA_LOADR
    tristate "(wit_yuan add) loader for fpga slave boot"
    depends on ARCH_SUN7I
    default y
    help
      it is a driver for loading code for fpga.it is authorized by wit_yuan 2017-09-25 at QJ

Makefile内容如下:

obj-$(CONFIG_FPGA_LOADR)      += fpga_driver.o

最终可以看到设备:

$ ls /dev/fpga_loader_device

3 驱动测试

针对模块驱动程序,相应的Makefile如下所示:

ifeq ($(KERNELRELEASE),)
    KERNEL_DIR=/home/wityuan/Downloads/MarsBoard-A20-Linux-SDK-V1.1/linux-sunxi
    PWD=$(shell pwd)

modules:
    $(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
    arm-linux-gnueabihf-gcc -o fpga_driver fpga_driver.c

modules_install:
    $(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules_install
clean:
    rm -rf *.ko *.o .tmp_versions *.mod.c modules.order Module.symvers .*.cmd
else
    obj-m:=fpga_driver.o
endif

由于我已经将驱动程序放到内核中,所以上面的Makefile实际上用不着。
测试程序,命名为fpga_test.c,内容如下所示:

#include "stdio.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/time.h>

#define FPGA_DRIVER_DEBUG  0

#if FPGA_DRIVER_DEBUG
    #define fpga_loader_debug(fmt,...) printf("%s,%d"fmt,__FILE__,__LINE__,##__VA_ARGS__)
#else
    #define fpga_loader_debug(fmt,...)  
#endif

#define LOADER_FILE "output_file.rbf"

#define BUFFER_LOADER 1

enum {
    TYPE_FPGA_START=1,
    TYPE_FPGA_BUFFER,
    TYPE_FPGA_CONFIG_END,
    TYPE_FPGA_INIT_END,
}ID_TYPE;


struct fpga_buffer{
    int id;/* 1.start 2.data 3.end*/
    unsigned char data;
};
static struct fpga_buffer fpga_buffer_t;



int main(int argc,char *argv[])
{
    int fd;
    int val;
    int file_fd;
    int init_done_times = 0;
    int error_times = 0;
    int wait_status_error_times = 0;
    unsigned char *fileMapP;
    struct stat file_stat = {0};
    int init_done_flag = 0;
    int i = 0;

    struct timeval tv1;
    struct timeval tv2;

    gettimeofday(&tv1, NULL);
    

    file_fd = open(LOADER_FILE,O_RDONLY);
    if(file_fd < 0){
        printf("fpga loader file error,please make sure it exists\r\n");
        return -1;
    }
    memset(&file_stat, 0, sizeof(struct stat));
    if (fstat(file_fd, &file_stat) < 0) {
        printf("--file stat Error----\r\n");
        close(file_fd);
        return -1;
    }
    fpga_loader_debug("--file len:%d bytes----\r\n",(int)file_stat.st_size);

    if(file_stat.st_size == 0){
        printf("---file size error,please check it---\r\n");
        close(file_fd);
        return -1;
    }
    
    //Memory Map
    if ((fileMapP=mmap(NULL, file_stat.st_size, PROT_READ, MAP_PRIVATE, file_fd, 0)) == MAP_FAILED) {
        fpga_loader_debug("Mmap Error\r\n");

        close(file_fd);
        return -1;
    }
        
    fd = open("/dev/fpga_loader_device",O_RDWR);
    if(fd < 0){
        fpga_loader_debug("---open file error----\r\n");
        close(file_fd);
        return -1;
    }
        
label1:
    /*we only try 3 times to bootloade the fpga or will warn an error.  2017-07-25 wit_yuan*/
    while(error_times < 3){
        /*1.send start message*/

        fpga_buffer_t.id = TYPE_FPGA_START;
        write(fd,&fpga_buffer_t,sizeof(fpga_buffer_t)); 
            
        read(fd,&val,sizeof(val));
        if(val == 0){
            fpga_loader_debug("---start data ok---\r\n");
            usleep(1000);
        }
        else
        {
            fpga_loader_debug("---start data error:%d---\r\n",val);
            /*need a delay ,and then start another start signal*/
            usleep(1000);  // 1ms
            error_times ++;//error times count 
            continue;
        }

        /*1.1 wait the status to be high*/
        do{
            read(fd,&val,sizeof(val));
            if(val == 1){
                //printf("--now status be high--\r\n");
                break;
            }
            else
            {
                //printf("-- wait status --\r\n");
                wait_status_error_times ++;
                usleep(1000);  // 1ms
                if(wait_status_error_times == 3)
                {
                    wait_status_error_times  = 0;
                    error_times ++;//error times count      
                    goto label1;
                }
            }
        }
        while(val==0);
        
        /*2.send data*/
        for(i = 0 ;i < file_stat.st_size ;i ++){
            fpga_buffer_t.id = TYPE_FPGA_BUFFER;
            fpga_buffer_t.data =  *(fileMapP+i);    /*the data need to be send*/
            write(fd,&fpga_buffer_t,sizeof(fpga_buffer_t)); 
            /*read status*/
            fpga_buffer_t.id = TYPE_FPGA_BUFFER;
            read(fd,&val,sizeof(val));
            if(val == 0){
                fpga_loader_debug("---sending data error---\r\n");
                usleep(1000);  // 1ms
                error_times ++;//error times count      
                goto label1;                
            }
        }
        /*3.wait config_done status*/
        fpga_buffer_t.id = TYPE_FPGA_CONFIG_END;
        write(fd,&fpga_buffer_t,sizeof(fpga_buffer_t)); 
        read(fd,&val,sizeof(val));
        if(val == 0){
            fpga_loader_debug("---config_done data error---\r\n");
            usleep(1000);  // 1ms
            error_times ++;//error times count      
            goto label1;    
        }   
        
        /*4.wait init_done status*/
        while(init_done_times<3)
        {
            fpga_buffer_t.id = TYPE_FPGA_INIT_END;
            
            write(fd,&fpga_buffer_t,sizeof(fpga_buffer_t));     
            read(fd,&val,sizeof(val));
            if(val == 0){
                fpga_loader_debug("---init_done data error---\r\n");
                init_done_times++;
                usleep(1000);  // 1ms
                error_times ++;//error times count      
                goto label1;    
            }   
            else
            {
                fpga_loader_debug("----init done ok----\r\n");

                init_done_flag = 1;
                break;
            }
            usleep(100);
        }

        if(init_done_flag == 1)
        {
            break;
        }
        
    }

    if(error_times == 3){
        fpga_loader_debug("---we bootload the fpga error---\r\n");
    }

    gettimeofday(&tv2, NULL);
    
    /*we finish bootload the fpga,whenever goes right or wrong. 2017-07-25 wit_yuan*/
    munmap(fileMapP, file_stat.st_size);
    close(fd);
    close(file_fd);

    

    printf("time:%ld ms\r\n",(tv2.tv_sec-tv1.tv_sec)*1000+(tv2.tv_usec-tv1.tv_usec)/1000);

    if(init_done_flag == 1)
        printf("---sending fpga loader file done----\r\n ");

    else
        printf("---sending fpga loader file err----\r\n "); 
    
    return 0;
}

基本上,就这些内容了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容