美文网首页
实践1 . 使用树莓派A20启动FPGA

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

作者: wit_yuan | 来源:发表于2017-08-03 10:42 被阅读0次

    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;
    }
    

    基本上,就这些内容了。

    相关文章

      网友评论

          本文标题:实践1 . 使用树莓派A20启动FPGA

          本文链接:https://www.haomeiwen.com/subject/ztovkxtx.html