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     // CONFIG4
102     .we_on = 20,        /* WE assertion time */
103     .we_off  = 20,      /* WE deassertion time */
104     // CONFIG4
105     .oe_on = 20,        /* OE assertion time */
106     .oe_off = 20,       /* OE deassertion time */
107     // CONFIG5
108     .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     // CONFIG6
113     .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 pinmux
146     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 pinmux
154     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 direction
164     WR_MEM_32(conf_gpio18, 1);           // MUXMODE=001
165     gpio_request(18, "gpio18_en");       // request gpio46
166     gpio_direction_output(18, 1);
167
168     WR_MEM_32(conf_gpio19, 1);           // MUXMODE=001
169     gpio_request(19, "gpio19_en");       // request gpio47
170     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 configed
178     // ti8168evm board_nand_init -> gpmc_nand_init
179     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 memory
187     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 irq
192     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 config1
196     gpmc_cs_write_reg(GPMC_FPGA_CS, GPMC_CS_CONFIG1, GPMC_CONFIG1_READTYPE_ASYNC|  // set read type async
197         GPMC_CONFIG1_WRITETYPE_ASYNC| // set write type async
198         GPMC_CONFIG1_DEVICESIZE_16|   // set device size 16bit
199         GPMC_CONFIG1_DEVICETYPE_NOR   // set device type nor
200     );
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 timings
206     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 memory
212     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/16bit
228     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 memory
243     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 channel
261     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 zero
272     edma_set_dest_index (dma_ch, desbidx, descidx);  // A mode
273
274     // A Sync Transfer Mode
275     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);   // 1us
308     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 ISR
319     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 CS3
356     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");

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芯片,本人刚接手开发也就两个月,文中若有不对之处欢迎指出。

时间: 2024-08-08 19:25:39

DSP与FPGA通信调试笔记——通过GPMC接口用EDMA传送的相关文章

Lattice FPGA 板子 调试笔记

最近在调试LATTICE  FPGA 做的视频板子,颇不顺利,所以记录下来作为以后的参考: 1.FPGA的IO口不是所有的都是双向的,有些有特殊作用的是单向的. 在查阅 LatticeECP3-17EAPinout.CSV 之后, 发现在LEF3-17EA-FN484C中,有以下几个管脚是单向的: C4  G7  G6     : jtag 管脚 C14  C15  B15   B16  :编程管脚 K1   L5   L1   K6   N17  M18   :PLL的反馈(fb)管脚 AB2

【RapidIO相关】DSP与FPGA通信

TI参考链接: http://www.ti.com.cn/general/cn/docs/gencontent.tsp?contentId=50741 ---------------------------------------------------------------------------- note: SWRITE:流写(Stream Write),数据长度必须是8字节的整数倍,不要求接收端响应.SWRITE是最高效的传输格式:带响应的写操作或读操作效率则较低,一般只能达到不带响应

创龙基于C66x平台DSP与FPGA通信测试

本文为基于创龙TL665xF-EasyEVM开发板的DSP与FPGA通信测试.TL665xF-EasyEV开发板的简介绍如下:由核心板+底板构成.核心板DSP端采用单核TMS320C6655或双核TMS320C6657处理器,FPGA端采用Xilinx Artix-7处理器,实现异构多核处理器架构,DSP与FPGA内部通过uPP.EMIF16.SRIO连接:底板接口资源丰富,支持uPP.EMIF16.SRIO.千兆以太网口等多种高速接口,引出PCIe接口,单端口双通道,每通道最高通信速率5GBa

CY68013 FPGA通信联调总结

1. 简介 CY68013是一款USB 2.0芯片,常用作fpga与pc的接口芯片,其硬件可以自动处理USB协议,也可以在里面下载对应的固件程序,由固件程序来完成USB协议的通信.我们只关心USB数据的传输,协议的不作深究,能用就行. 2. 开发 2.1 CY68013 2.1.1 CY68013资料摘抄 主要参考文档: 参考文档 描述 EZ-USB_TRM_001-13670_0E.pdf fx2的参考手册,相当于UserGuide CY7C68013A.pdf fx2的电气特性,相当于Dat

ARM、8051、AVR、MSP430、Coldfire、DSP、FPGA七种体系比较区别

概述 我以为这样比没有意义,做嵌入式系统最大特征是“嵌入”二字,也就是说你的控制系统是嵌入于你的控制对象之中,所以首先是服从于对象的需求和特征,脱离对象空论谁好谁坏有何依据? 每个MCU都有其存在的价值,每个使用者的选择都有其道理,AVR开始时是以单时钟周期指令为卖点,相对于当时 12个时钟的经典51确实有优势,而且基于CMOS的特征,时钟越高功耗越大,所以它在能耗上似乎明显占优. 可随着技术的改进,51现在已经早就有了4时钟周期,`2时钟周期乃至单时钟周期的芯片了,此时AVR的速度优势已不存在

DSP+ARM+FPGA核心板

  版权声明 阅前须知 本手册版权归属广州创龙电子科技有限公司所有,非经书面同意,任何单位及个人不得擅自摘录本手册部分或全部,违者我们将追究其法律责任.本文档一切解释权归广州创龙电子科技有限公司所有. 2014-2018 GuangzhouTronlong Electronic Technology Co.,Ltd. All rights reserved. 公司简介 广州创龙电子科技有限公司(简称"广州创龙",英文简称"Tronlong"),是杰出的嵌入式方案商,

USB wifi调试笔记

本文以realtek 8192CU WiFi模块为例,介绍USB wifi在Jelly Bean 4.1的调试笔记. 1.WIFI打不开现象概述 WiFi打不开是指您在UI的settings下选中WiFi选项,将其置为on(打开),但最终结果是自动变成off(关闭).正在打开Wi-Fi.正在扫描等一系列不能正常打开WiFi的提示. 2.问题分析流程 WiFi打不开从硬件和软件两方面进行定位,一般是先硬件,然后软件.总体分析流程如图: 3.确认硬件可以识别 8192CU WiFi模块是基于usb接

数字电路设计中DSP和FPGA的比较与选择

博主研究生所在的实验室是搞雷达的,项目所涉及的板卡都是DSP+FPGA架构的,至于原因,只知道FPGA是并行的,用来处理速度要求高,运算结构简单的大数据量过程或算法,比如接收处理天线各阵元采样的初始数据等:DSP是顺序的,用来处理数据量较低但运算量较大的算法,比如DBF算法.矩阵求逆算法等.看了下面的文章,有了更全面的理解. 原文地址:http://www.chinaaet.com/article/index.aspx?id=13921 摘  要: DSP和FPGA是目前数字电路设计采用的两种主

164-基于TI DSP TMS320C6455和Altera FPGA EP2S130的Full CameraLink PDS150接口板卡

一.板卡概述 本板卡由我公司自主研发,板卡采用DSP+FPGA的结构,DSP使用TMS320C6455芯片,FPGA采用ALTERA的高端FPGA芯片Stratix II EP2S系列EP2S130,板卡使用FPGA用于获取双通道数据采集,实现1路的FULL Camera Link输入,一路DVI输出,2路Rs232,一路千兆以太网,2路Can总线.FPGA控制高速SDRAM数据存取,并与DSP之间构建64-bit高速同步数据总线接口:一片TI 1GHz C6455 DSP除了内核处理性能之外,