首页 > 代码库 > DSP与FPGA通信调试笔记——通过GPMC接口用EDMA传送

DSP与FPGA通信调试笔记——通过GPMC接口用EDMA传送

硬件:TI达芬奇TMS320DM8168(以下简称DSP)、EP4CE6E22C8N(以下简称FPGA)

软件:linux-2.6.37

作者:Aadtech 杭州超距科技

     近期项目需要实现DSP与FPGA之间的高速数据交换,用到了DM8168的GPMC接口。这部分的中文资料网上还是比较少的,于是苦苦研究芯片的数据手册和参考指南,最近终于有所成果,在Linux下调用GPMC驱动函数调通了GPMC接口,因此发出调试过程与大家分享。目前以DSP端可以通过GPMC用EDMA的方式读取FPGA端的数据,读取8KB字节大概用了235us,即34MB/s的速度,实际上通过配置GPMC接口的时间参数,速度还可以更快。

     GPMC的全称是 General-Purpose Memory Controller,即通用存储控制器,是TI的DSP芯片DM8168用来与外部存储设备例如NOR FLASH、NAND FLASH、SRAM等等通信的一个接口。这个接口并不是DM8168特有的,在BeagleBone Black、AM35XX芯片上也有类似接口。

     1、硬件连接方式:在DM8168中GPMC接口时钟在异步模式下为125MHz,这里就把GPMC接口配置为异步模式并设置NOR FLASH、非地址数据线复用的模式与FPGA通信,但只用16位数据线,不用地址线,即采用类似于FIFO的方式与FPGA通信。目前实际只使用到了如下I/O口:

     GPMC_CS3:用CS3做片选信号

     GPMC_OEN:输出使能时钟 

     D[15:0]:16位数据总线

     FIFO_RRST:用于通知FPGA读指针复位

 

    2、接口协议:采用异步方式读取,即不使用GPMC_CLK,FPGA端在GPMC_OEN的下降沿把数据送出去。

 

    3、Linux下DSP端代码分析

    linux中gpmc驱动源代码在 /arch/arm/mach-omap2/gpmc.c

    配置方面主要包括与GPMC相关的7个特殊寄存器,其实linux函数中已经把相关配置封装成了函数,我们只需要调用相关函数就可以。

    EDMA的配置也是如此,需要注意的是,EDMA中配置的地址都为物理地址,即DMA传送到源端为外设的地址即GPMC的物理地址,目的地端为你申请的内存空间物理地址。由于DSP是使用FIFO模式读取FPGA端数据的,所以EDMA还需配置源地址为不自增模式。代码如下,内容不多,所以不做详细注释。

    FPGA端的代码只要是实现在每个OEN信号下降沿来的时候,把16bit的数据送到GPMC_DATA端口,并自加一次。

  1 /*  2 * fileName: fpga_perh.c  3 * for gpmc fpga communication  4 */  5 #include <linux/device.h>  6 #include <linux/fs.h>  7 #include <linux/module.h>  8 #include <linux/kernel.h>  9 #include <linux/init.h> 10 #include <linux/moduleparam.h> 11 #include <linux/list.h> 12 #include <linux/cdev.h> 13 #include <linux/proc_fs.h> 14 #include <linux/mm.h> 15 #include <linux/seq_file.h> 16 #include <linux/ioport.h> 17 #include <linux/delay.h> 18 #include <asm/io.h> 19 #include <linux/io.h> 20 #include <mach/gpio.h> 21 #include <linux/device.h> 22 #include <linux/platform_device.h> 23 // gpmc spec 24 #include <plat/gpmc.h> 25 // edma spec 26 #include <linux/interrupt.h> 27 #include <linux/dma-mapping.h> 28 #include <mach/memory.h> 29 #include <mach/hardware.h> 30 #include <mach/irqs.h> 31 #include <asm/hardware/edma.h> 32  33 #define DRIVERNAME  "fpga" 34  35 // once_dma = 8KByte = 4*1024*16bit  36 #define FPGA_FIFO_SIZE SZ_4K 37  38 /*------------------------------------------------------------------------------------------------------------------*/ 39 // GPMC Config 40 #define GPMC_FIFO_SIZE SZ_16K 41  42 #define GPMC_FPGA_CS   3           // gpmc use CS 3 43 #define GPMC_CONFIG1_3 0x00001010  // 16bit size NOR FLASH like 44 #define GPMC_CONFIG2_3 0x00101080  // CSWROFFTIME=16cy   CSRDOFFTIME=16cy     CSEXTRADELAY=1 45 #define GPMC_CONFIG3_3 0x00000000  // ADV TIME used 46 #define GPMC_CONFIG4_3 0x0F031003  // WEOFFTIME=15cy     WEONTIME=3cy         OEOFFTIME=16cy       OEONTIME=3cy 47 #define GPMC_CONFIG5_3 0x000F1111  // RDACCESSTIME=15cy  WRCYCLETIME=1cy      RDCYCLETIME=1cy 48 #define GPMC_CONFIG6_3 0x0F030000  // WRACCESSTIME=15cy  WRDATAONADMUXBUS=3cy Add CYCLE2CYCLEDELAY 49 #define GPMC_CONFIG7_3 0x00000F42  // set up CONFIG7 and enable cs3 50 // chip-select mask address = MASKADDRESS = 16MB 51 // CS enabled 52 // Chip-select base address = BASEADDRESS = 0x02000000 53 // Access address 0x02000000-0x02FFFFFF 54 #define GPMC_MASKADDRESS 0x00FFFFFF  // fifo_size 55 #define GPMC_BASEADDRESS 0x02000000  // gpmc address 56 /*------------------------------------------------------------------------------------------------------------------*/ 57 // FPGA GPIOs 58 #define CTRL_MODULE_BASE_ADDR    0x48140000 59 #define conf_gpio18              (CTRL_MODULE_BASE_ADDR + 0x0B98) 60 #define conf_gpio19              (CTRL_MODULE_BASE_ADDR + 0x0B9C) 61  62 #define WR_MEM_32(addr, data)    *(unsigned int*)OMAP2_L4_IO_ADDRESS(addr) = (unsigned int)(data) 63 #define RD_MEM_32(addr)          *(unsigned int*)OMAP2_L4_IO_ADDRESS(addr) 64  65 // delay for reset 66 #define _delay_ms(n)   mdelay(n)  67 #define _delay_ns(n)   ndelay(n)  68  69 // Read Point Low is Reset 70 #define FPGA_RRST_H gpio_set_value(18, 1); 71 #define FPGA_RRST_L gpio_set_value(18, 0); 72 /*------------------------------------------------------------------------------------------------------------------*/ 73 // EDMA Config 74 #define MAX_DMA_TRANSFER_IN_BYTES  (4096*2) 75 #define STATIC_SHIFT               3 76 #define TCINTEN_SHIFT              20   77 #define ITCINTEN_SHIFT             21 78 #define TCCHEN_SHIFT               22 79 #define ITCCHEN_SHIFT              23 80 /*------------------------------------------------------------------------------------------------------------------*/ 81 //unsigned int fpga_buf[FPGA_FIFO_SIZE] = {0}; 82 static unsigned long gpmc_membase = 0; 83 static void __iomem *fpga_membase = 0; 84 static int gpio[2]; 85 dma_addr_t dmaphysdest = 0; 86 unsigned short *fpga_buf = NULL; 87 unsigned int dma_ch = 0; 88 static volatile int irqraised1 = 0; 89  90 static struct gpmc_timings fpga_timings = { 91     /*- GPMC timing configurations -*/ 92     .sync_clk = 0, 93     // CONFIG2 chip-select time 94     .cs_on = 0,         /* Assertion time */ 95     .cs_rd_off = 50,    /* Read deassertion time */ 96     .cs_wr_off = 50,    /* Write deassertion time */ 97     // CONFIG3 98     .adv_on = 0, 99     .adv_rd_off = 0,100     .adv_wr_off = 0,101     // CONFIG4102     .we_on = 20,        /* WE assertion time */103     .we_off  = 20,      /* WE deassertion time */104     // CONFIG4105     .oe_on = 20,        /* OE assertion time */106     .oe_off = 20,       /* OE deassertion time */107     // CONFIG5108     .page_burst_access = 0,109     .access = 30,       /* Start-cycle to first data valid delay */110     .rd_cycle = 50,     /* Total read cycle time */111     .wr_cycle = 50,     /* Total write cycle time */112     // CONFIG6113     .wr_access = 0,114     .wr_data_mux_bus = 0,115 };116 117 // static         dev_t  dev;118 // static struct  cdev   cdev;119 // static struct  class  *gpmc_edma_class = NULL;120 121 static void callback1(unsigned lch, u16 ch_status, void *data)122 {123     switch(ch_status) {124     case DMA_COMPLETE:125         irqraised1 = 1;126         /*DMA_PRINTK ("\n From Callback 1: Channel %d status is: %u\n", lch, ch_status);*/127         break;128     case DMA_CC_ERROR:129         irqraised1 = -1;130         printk ("\nFrom Callback 1: DMA_CC_ERROR occured on Channel %d\n", lch);131         break;132     default:133         break;134     }135 }136 137 static int gpio_store(void);138 static int gpio_recover(void);139 static int gpio_config(void);140 static int gpmc_config(void);141 static int edma_config(void);142 143 static int gpio_store(void)144 {145     // store gpio pinmux146     gpio[0] = RD_MEM_32(conf_gpio18);147     gpio[1] = RD_MEM_32(conf_gpio19);148     return 0;149 }150 151 static int gpio_recover(void)152 {153     // recover gpio pinmux154     WR_MEM_32(conf_gpio18, gpio[0]);155     WR_MEM_32(conf_gpio19, gpio[1]);156     gpio_free(gpio[0]);157     gpio_free(gpio[1]);158     return 0;159 }160 161 static int gpio_config(void)162 {163     // config gpio direction164     WR_MEM_32(conf_gpio18, 1);           // MUXMODE=001165     gpio_request(18, "gpio18_en");       // request gpio46166     gpio_direction_output(18, 1);167 168     WR_MEM_32(conf_gpio19, 1);           // MUXMODE=001169     gpio_request(19, "gpio19_en");       // request gpio47170     gpio_direction_output(19, 1);171 172     return 0;173 }174 175 static int gpmc_config(void)176 {177     // first reg gpmc_init() already called; io pinmux already configed178     // ti8168evm board_nand_init -> gpmc_nand_init179     u32 val = 0;180     int err = 0;181 /*-182 EXPORT_SYMBOL(gpmc_cs_write_reg);183 EXPORT_SYMBOL(gpmc_cs_read_reg);184 EXPORT_SYMBOL(gpmc_cs_set_timings);185 -*/186     // gpmc cs disable memory187     val = gpmc_cs_read_reg(GPMC_FPGA_CS, GPMC_CS_CONFIG7);188     val &= ~GPMC_CONFIG7_CSVALID;189     gpmc_cs_write_reg(GPMC_FPGA_CS, GPMC_CS_CONFIG7, val);190 191     // disable cs3 irq192     gpmc_cs_configure(GPMC_FPGA_CS, GPMC_SET_IRQ_STATUS, 0);193     gpmc_cs_configure(GPMC_FPGA_CS, GPMC_ENABLE_IRQ, 0);194 195     // set config1196     gpmc_cs_write_reg(GPMC_FPGA_CS, GPMC_CS_CONFIG1, GPMC_CONFIG1_READTYPE_ASYNC|  // set read type async197         GPMC_CONFIG1_WRITETYPE_ASYNC| // set write type async198         GPMC_CONFIG1_DEVICESIZE_16|   // set device size 16bit199         GPMC_CONFIG1_DEVICETYPE_NOR   // set device type nor200     );201     val = gpmc_cs_read_reg(GPMC_FPGA_CS, GPMC_CS_CONFIG1);202     val &= ~GPMC_CONFIG1_MUXADDDATA;203     gpmc_cs_write_reg(GPMC_FPGA_CS, GPMC_CS_CONFIG1, val);204  205     // set gpmc timings206     err = gpmc_cs_set_timings(GPMC_FPGA_CS, &fpga_timings);207     if(err < 0){208         printk(KERN_ERR "Unable to set gpmc timings\n");209     }210 211     // apply gpmc select memory212     err = gpmc_cs_request(GPMC_FPGA_CS, GPMC_FIFO_SIZE, &gpmc_membase);213     if(err < 0){214         printk(KERN_ERR "Cannot request GPMC CS\n");215         return err;216     }217 218  //   request_mem_region(gpmc_membase, GPMC_FIFO_SIZE, DRIVERNAME);219 220  //   fpga_membase = ioremap(gpmc_membase, GPMC_FIFO_SIZE);221 222     return err;223 }224 225 static int edma_config(void)226 {227     // use AB mode, one_dma = 8KB/16bit228     static int acnt = 4096*2;229     static int bcnt = 1;230     static int ccnt = 1;231 232     int result = 0;233     unsigned int BRCnt = 0;234     int srcbidx = 0;235     int desbidx = 0;236     int srccidx = 0;237     int descidx = 0;238     struct edmacc_param param_set;239 240     printk("Initializing dma transfer...\n");241 242     // set dest memory243     fpga_buf  = dma_alloc_coherent (NULL, MAX_DMA_TRANSFER_IN_BYTES, &dmaphysdest, 0);244     if (!fpga_buf) {245         printk ("dma_alloc_coherent failed for physdest\n");246         return -ENOMEM;247     }248 249     /* Set B count reload as B count. */250     BRCnt = bcnt;251 252     /* Setting up the SRC/DES Index */253     srcbidx = 0;254     desbidx = acnt;255 256     /* A Sync Transfer Mode */257     srccidx = 0;258     descidx = acnt;259  260     // gpmc channel261     result = edma_alloc_channel (52, callback1, NULL, 0);262     263     if (result < 0) {264         printk ("edma_alloc_channel failed, error:%d", result);265         return result;266     }267      268     dma_ch = result;269     edma_set_src (dma_ch, (unsigned long)(gpmc_membase), INCR, W16BIT);270     edma_set_dest (dma_ch, (unsigned long)(dmaphysdest), INCR, W16BIT);271     edma_set_src_index (dma_ch, srcbidx, srccidx);   // use fifo, set zero272     edma_set_dest_index (dma_ch, desbidx, descidx);  // A mode273 274     // A Sync Transfer Mode275     edma_set_transfer_params (dma_ch, acnt, bcnt, ccnt, BRCnt, ASYNC);276 277     /* Enable the Interrupts on Channel 1 */278     edma_read_slot (dma_ch, &param_set);279     param_set.opt |= (1 << ITCINTEN_SHIFT);280     param_set.opt |= (1 << TCINTEN_SHIFT);281     param_set.opt |= EDMA_TCC(EDMA_CHAN_SLOT(dma_ch));282     edma_write_slot (dma_ch, &param_set);283 284     return 0;285 }286 287 static int __init fpga_perh_init(void)288 {289     unsigned int cnt;290     u32 val = 0;291     int ret = 0;292     int chk = 0;293 294     gpio_store();     // GPIO初始化295     gpio_config();296     gpmc_config();    // GPMC配置297     edma_config();    // EDMA配置298 299     for(cnt=0; cnt<7; cnt++){300         val = gpmc_cs_read_reg(GPMC_FPGA_CS, GPMC_CS_CONFIG1 + cnt*0x04);301         printk("GPMC_CS3_CONFIG_%d : [%08X]\n", cnt+1, val);302     }303 304     printk("Gpmc now start reading...\n");305 306     FPGA_RRST_L;307     _delay_ns(1);   // 1us308     FPGA_RRST_H;309 310 311     ret = edma_start(dma_ch);312     313     if (ret != 0) {314         printk ("dm8168_start_dma failed, error:%d", ret);315         return ret;316     }317 318     // wait for completion ISR319     while(irqraised1 == 0u){320         _delay_ms(10);321  //       break;322     }323 324 325     if (ret == 0) {326         for (cnt=0; cnt<FPGA_FIFO_SIZE; cnt++) {327 //            fpga_buf[cnt] = readw(fpga_membase);328             if (fpga_buf[cnt] != cnt+1) {            // 进行数据校验329                 chk = cnt+1;330                 break;331             }332         }333         edma_stop(dma_ch);334         edma_free_channel(dma_ch);335     }336 337     if (chk == 0){338         printk ("Gpmc&edma reading sequence data check successful!\n");339     }else{340         printk ("Gpmc&edma reading data check error at: %d\n", chk);341     }342 343     for(cnt=0; cnt<8; cnt++){344         printk("[%04X] [%04X] [%04X] [%04X]\n", fpga_buf[cnt*4], fpga_buf[cnt*4+1], fpga_buf[cnt*4+2], fpga_buf[cnt*4+3]);345     }346 347 //    gpmc_cs_free(GPMC_FPGA_CS);  348     return 0;349 }350 module_init(fpga_perh_init);351 352 static void __exit fpga_perh_exit(void)353 {354     gpio_recover();355     // free CS3356     gpmc_cs_free(GPMC_FPGA_CS); 357     dma_free_coherent (NULL, MAX_DMA_TRANSFER_IN_BYTES, fpga_buf, dmaphysdest);358     printk("fpga_perh exit!\n");359 }360 module_exit(fpga_perh_exit);361 362 MODULE_LICENSE("GPL");
View Code

    4、实验结果

    (1)代码编译后通过insmod加载驱动,抓取CS3和OEN的波形如下,刚开始设计时没有用到EDMA传送,只是在linux循环读取,可以看见每个周期里片选信号CS3都会维持很长一段高电平的时间,GPMC一次的读取周期大概为250ns。

 

通道1为片选信号CS3,通道2为输出使能信号OEN

这样的速率大概只有 16bit / 250ns = 8MBytes/s

    (2)使用EDMA传送,这下读周期就小了很多了,只有57.6ns,和GPMC参数里设置的几乎一致。

 

    (3)传送8KBytes即4096次,大概用了235us,速率为 8KBytes / 235us = 34MB/s

 

    (4)fpga端使用signaltap抓取波形如下,可以看见GPMC_DATA为从1开始的自加顺序序列

 

    (5)linux端读取数据并做校验,还打印出了GPMC的7个寄存器的内容。校验通过,说明数据一致性正确!至此DSP与FPGA通过GPMC接口用EDMA实现数据高速传输,验证可行!

  

    总结,FPGA端代码比较简单就不上传了,如有需要可向本人获取,QQ:五二五四九六一0七

    DM8168这款DSP芯片,本人刚接手开发也就两个月,文中若有不对之处欢迎指出。

 

DSP与FPGA通信调试笔记——通过GPMC接口用EDMA传送