美文网首页
实践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