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

http://www.cnblogs.com/imapla/p/4122609.html

【DM8168】DSP与FPGA通信调试笔记之一——通过GPMC接口用EDMA传送

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

软件:linux-2.6.37

转载请注明出处~

http://www.cnblogs.com/imapla/p/4122609.html 

     近期项目需要实现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读指针复位

 DSP与FPGA通信调试笔记之一——通过GPMC接口用EDMA传送_第1张图片

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

 DSP与FPGA通信调试笔记之一——通过GPMC接口用EDMA传送_第2张图片

    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端口,并自加一次。

GPMC配置代码如下

 

复制代码
static struct gpmc_timings fpga_timings = {
    /*- GPMC timing configurations -*/
    .sync_clk = 0,
    // CONFIG2 chip-select time
    .cs_on = 0,         /* Assertion time */
    .cs_rd_off = 50,    /* Read deassertion time */
    .cs_wr_off = 50,    /* Write deassertion time */
    // CONFIG3
    .adv_on = 0,
    .adv_rd_off = 0,
    .adv_wr_off = 0,
    // CONFIG4
    .we_on = 20,        /* WE assertion time */
    .we_off  = 20,      /* WE deassertion time */
    // CONFIG4
    .oe_on = 20,        /* OE assertion time */
    .oe_off = 20,       /* OE deassertion time */
    // CONFIG5
    .page_burst_access = 0,
    .access = 30,       /* Start-cycle to first data valid delay */
    .rd_cycle = 50,     /* Total read cycle time */
    .wr_cycle = 50,     /* Total write cycle time */
    // CONFIG6
    .wr_access = 0,
    .wr_data_mux_bus = 0,
};
static int gpmc_config(void)
{
    // first reg gpmc_init() already called; io pinmux already configed
    // ti8168evm board_nand_init -> gpmc_nand_init
    u32 val = 0;
    int err = 0;
/*-
EXPORT_SYMBOL(gpmc_cs_write_reg);
EXPORT_SYMBOL(gpmc_cs_read_reg);
EXPORT_SYMBOL(gpmc_cs_set_timings);
-*/
    // gpmc cs disable memory
    val = gpmc_cs_read_reg(GPMC_FPGA_CS, GPMC_CS_CONFIG7);
    val &= ~GPMC_CONFIG7_CSVALID;
    gpmc_cs_write_reg(GPMC_FPGA_CS, GPMC_CS_CONFIG7, val);

    // disable cs3 irq
    gpmc_cs_configure(GPMC_FPGA_CS, GPMC_SET_IRQ_STATUS, 0);
    gpmc_cs_configure(GPMC_FPGA_CS, GPMC_ENABLE_IRQ, 0);

    // set config1
    gpmc_cs_write_reg(GPMC_FPGA_CS, GPMC_CS_CONFIG1, GPMC_CONFIG1_READTYPE_ASYNC|  // set read type async
        GPMC_CONFIG1_WRITETYPE_ASYNC| // set write type async
        GPMC_CONFIG1_DEVICESIZE_16|   // set device size 16bit
        GPMC_CONFIG1_DEVICETYPE_NOR   // set device type nor
    );
    val = gpmc_cs_read_reg(GPMC_FPGA_CS, GPMC_CS_CONFIG1);
    val &= ~GPMC_CONFIG1_MUXADDDATA;
    gpmc_cs_write_reg(GPMC_FPGA_CS, GPMC_CS_CONFIG1, val);
 
    // set gpmc timings
    err = gpmc_cs_set_timings(GPMC_FPGA_CS, &fpga_timings);
    if(err < 0){
        printk(KERN_ERR "Unable to set gpmc timings\n");
    }

    // apply gpmc select memory
    err = gpmc_cs_request(GPMC_FPGA_CS, GPMC_FIFO_SIZE, &gpmc_membase);
    if(err < 0){
        printk(KERN_ERR "Cannot request GPMC CS\n");
        return err;
    }

 //   request_mem_region(gpmc_membase, GPMC_FIFO_SIZE, DRIVERNAME);

 //   fpga_membase = ioremap(gpmc_membase, GPMC_FIFO_SIZE);

    return err;
}
复制代码

 

下面是总的代码,折叠了。

 

  View Code

    4、实验结果

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

DSP与FPGA通信调试笔记之一——通过GPMC接口用EDMA传送_第3张图片

 

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

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

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

DSP与FPGA通信调试笔记之一——通过GPMC接口用EDMA传送_第4张图片

 

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

DSP与FPGA通信调试笔记之一——通过GPMC接口用EDMA传送_第5张图片

 

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

DSP与FPGA通信调试笔记之一——通过GPMC接口用EDMA传送_第6张图片

 

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

DSP与FPGA通信调试笔记之一——通过GPMC接口用EDMA传送_第7张图片  

    总结,FPGA端代码比较简单就不上传了,如有需要欢迎私下交流。

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

    FPGA工程

 参考资料:

http://blog.csdn.net/hailin0716/article/details/26553389

http://blog.chinaunix.net/uid-28818752-id-3655729.html

http://blog.chinaunix.net/uid-28818752-id-3749701.html

http://blog.chinaunix.net/uid-28818752-id-3750016.html

 

联系本人:

QQ:5254961零7 

hihuanglong艾特foxmail.com

分类:  DSP学习笔记
标签:  达芬奇DSP,  DM8168,  Linux,  GPMC,  EDMA

你可能感兴趣的:(嵌入式)