DM368通过EMIF将数据发送至FPGA,然后FPGA将数据再通过AEMIF接口发送回DM368,自增数没有问题,但是发送视频等实际的数据有问题!
求大神指教!!
代码如下:
驱动代码:emif_cpu.c emif_cpu.h 测试代码:emif_main_cpu.c
测试代码功能:从src.txt文件中读1k的数据,发送至FPGA,然后FPGA再将数据发回至DM368,程序将接收到的数据存在dst.txt文件中。
执行完成后比较src.txt 和dst.txt的数据,看是否有误。
症状:如果src.txt文件里面存的是自增数,收到的数据没有问题;
但是如果src.txt是实际中应用的数据,比如视频数据,则接收到的数据就会有部分出错!!!
!
求大神指教!!
代码如下:
驱动代码:emif_cpu.c emif_cpu.h 测试代码:emif_main_cpu.c
测试代码功能:从src.txt文件中读1k的数据,发送至FPGA,然后FPGA再将数据发回至DM368,程序将接收到的数据存在dst.txt文件中。
执行完成后比较src.txt 和dst.txt的数据,看是否有误。
症状:如果src.txt文件里面存的是自增数,收到的数据没有问题;
但是如果src.txt是实际中应用的数据,比如视频数据,则接收到的数据就会有部分出错!!!
--------------------------------------------------------------------------------------------------------------------------------
驱动代码:emif_cpu.c
/* * edma-test kernel module * * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /******************************************************************************* * HEADER FILES */ #include <linux/module.h> #include <linux/init.h> #include <linux/mm.h> #include <linux/dma-mapping.h> #include <linux/io.h> #include <linux/types.h> #include <mach/io.h> #include <mach/irqs.h> #include <mach/hardware.h> #include <mach/memory.h> #include <mach/edma.h> #include <mach/aemif.h> #include <linux/fs.h> #include "emif_cpu.h" #include <linux/uaccess.h> MODULE_LICENSE("Dual BSD/GPL"); /******************************************************************************* * LOCAL DEFINES */ /* #undef EDMA3_DEBUG */ #define EDMA3_DEBUG #ifdef EDMA3_DEBUG #define DMA_PRINTK(ARGS...) printk(KERN_INFO "<%s>: ",__FUNCTION__);printk(ARGS) #define DMA_FN_IN printk(KERN_INFO "[%s]: start\n", __FUNCTION__) #define DMA_FN_OUT printk(KERN_INFO "[%s]: end\n",__FUNCTION__) #else #define DMA_PRINTK( x... ) #define DMA_FN_IN #define DMA_FN_OUT #endif //#define MAX_DMA_TRANSFER_IN_BYTES (32768) #define MAX_DMA_TRANSFER_IN_BYTES (128*1024) #define STATIC_SHIFT 3 #define TCINTEN_SHIFT 20 #define ITCINTEN_SHIFT 21 #define TCCHEN_SHIFT 22 #define ITCCHEN_SHIFT 23 //#define USE_FIFO #define TSET_B //#define PRINT #define SAVE_TIME #define BIT_16 /******************************************************************************* * FILE GLOBALS */ static volatile int irqraised1 = 0; static volatile int irqraised2 = 0; int edma3_memtomemcpytest_dma_write(const char *buf, int acnt, int bcnt, int ccnt, int sync_mode, int event_queue); int edma3_memtomemcpytest_dma_read(char *buf, int acnt, int bcnt, int ccnt, int sync_mode, int event_queue); dma_addr_t dmaphyssrc1 = 0; dma_addr_t dmaphyssrc2 = 0; dma_addr_t dmaphysdest1 = 0; dma_addr_t dmaphysdest2 = 0; char *dmabufsrc1 = NULL; char *dmabufsrc2 = NULL; char *dmabufdest1 = NULL; char *dmabufdest2 = NULL; unsigned long ce1_start = DM365_ASYNC_EMIF_DATA_CE1_BASE; unsigned long ce1_end = DM365_ASYNC_EMIF_DATA_CE1_BASE + SZ_32M - 1; unsigned long ctrl_start = DM365_ASYNC_EMIF_CONTROL_BASE; unsigned long ctrl_end = DM365_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1; volatile unsigned short *pstr_emif; void __iomem *vaddr; //ce1 void __iomem *base; //ctrl char gDrvrName[]= "emif_cpu"; // Name of driver in proc. int gDrvrMajor = 242; // Major number not dynamic. /* module_param(acnt, int, S_IRUGO); module_param(bcnt, int, S_IRUGO); module_param(ccnt, int, S_IRUGO); */ int Emif_edma_Open(struct inode *inode, struct file *filp) { printk(KERN_INFO"%s: Open: module opened\n",gDrvrName); return 0; } int Emif_edma_Release(struct inode *inode, struct file *filp) { printk(KERN_INFO"%s: Release: module released\n",gDrvrName); return 0; } #if 1 static struct aemif_para my_aemif_para = { .wsetup = 15, .wstrobe = 63, .whold = 7, .rsetup = 15, .rstrobe = 63, .rhold = 7, .ta =3, }; #endif #if 0 static struct aemif_para my_aemif_para = { .wsetup = 1, .wstrobe = 2, .whold = 1, .rsetup = 0, .rstrobe = 7, .rhold = 1, .ta = 3, }; #endif #if 0 static struct aemif_para my_aemif_para = { .wsetup = 1, .wstrobe = 2, .whold = 1, .rsetup = 0, .rstrobe = 3, .rhold = 0, .ta = 3, }; #endif #if 0 static struct aemif_para my_aemif_para = { .wsetup = 0, .wstrobe = 0, .whold = 0, .rsetup = 0, .rstrobe = 3, .rhold = 0, .ta = 3, }; #endif #if 0 static struct aemif_para my_aemif_para = { .wsetup = 5, .wstrobe = 21, .whold = 2, .rsetup = 0, .rstrobe = 0, .rhold = 0, .ta =0, }; #endif //set the clock para of aemif static inline void emif_clkpara_set(void __iomem *base, unsigned cs) { unsigned set, val; unsigned offset = A1CR_OFFSET + cs * 4; set = TA(my_aemif_para.ta) | RHOLD(my_aemif_para.rhold) | RSTROBE(my_aemif_para.rstrobe) | RSETUP(my_aemif_para.rsetup) | WHOLD(my_aemif_para.whold) | WSTROBE(my_aemif_para.wstrobe) | WSETUP(my_aemif_para.wsetup); val = __raw_readl(base + offset); val &= ~TIMING_MASK; val |= set; __raw_writel(val, base + offset); return 0; } ssize_t Emif_edma_Write(struct file *filp, const char *buf, size_t count, loff_t *f_pos) { #if 0 int i = 0; for(i = 0; i < count/2; i++) { *(pstr_emif+i) = *(((unsigned short *)buf) + i); } #endif memcpy((char *)pstr_emif, buf, count); // printk(KERN_INFO"%s: Emif_cpu_Write: %d bytes have been written...\n", gDrvrName, count); return (0); } ssize_t Emif_edma_Read(struct file *filp, char *buf, size_t count, loff_t *f_pos) { #if 0 int i = 0; for(i = 0; i < count/2; i++) { *(((unsigned short *)buf) + i) = *(pstr_emif+i); } #endif memcpy(buf, (char *)pstr_emif, count); // printk(KERN_INFO"%s: Emif_cpu_Read: %d bytes have been read...\n", gDrvrName, count); return count; } static inline unsigned int emif_readl(void __iomem *base, int offset) { return __raw_readl(base + offset); } static inline void emif_writel(void __iomem *base, int offset, unsigned long value) { __raw_writel(value, base + offset); } /* All timings in nanoseconds */ static struct davinci_aemif_timing fpga_emif_timing = { .wsetup = 29, .wstrobe = 24, .whold = 14, .rsetup = 19, .rstrobe = 33, .rhold = 0, .ta = 29, }; void edma_test_exit(void) { printk("\nExiting edma3_sample_app module\n"); } /* DMA Channel, Mem-2-Mem Copy, ASYNC Mode, INCR Mode */ /* DMA Channel, Mem-2-Mem Copy, ASYNC Mode, INCR Mode */ // Aliasing write, read, ioctl, etc... struct file_operations Emif_edma_Intf = { owner: THIS_MODULE, read: Emif_edma_Read, write: Emif_edma_Write, open: Emif_edma_Open, release: Emif_edma_Release, }; static int __init emif_edma_init(void) { unsigned int ret; unsigned int chipsel = 1; unsigned int val; // unsigned short data_send[DATA_LENGTH]; // unsigned int i = 0; // unsigned int n = 0; vaddr = ioremap(ce1_start, ce1_end - ce1_start); base = ioremap(ctrl_start, ctrl_end - ctrl_start); if (!vaddr || !base) { printk("emif_mod: ioremap failed\n"); return -1; } val = emif_readl(base, A1CR_OFFSET + chipsel * 4); /* Extended Wait is not valid and Select Strobe mode is not used */ val &= ~(ACR_ASIZE_MASK | ACR_EW_MASK | ACR_SS_MASK); #ifdef BIT_16 val |= 0x1; //kang:16 bit data bus #else val |= 0x0; #endif emif_writel(base, A1CR_OFFSET + chipsel * 4, val); emif_clkpara_set(base, chipsel); //set time para #if 0 ret = davinci_aemif_setup_timing(&fpga_emif_timing, base, 1 ); //0:cs0, 1:cs1 if (ret < 0) { printk("emif_mod: emif timing values setup fail\n"); return -1; } #endif pstr_emif = (unsigned short *)vaddr; //--- START: Register Driver // Register with the kernel as a character device. if (0 > register_chrdev(gDrvrMajor, gDrvrName, &Emif_edma_Intf)) { printk(KERN_WARNING"%s: Init: will not register\n", gDrvrName); return -1; } printk(KERN_INFO"%s: Init: module registered\n", gDrvrName); printk(KERN_ALERT "Hello, world\n"); return 0; } static void emif_edma_exit(void) { iounmap(vaddr); iounmap(base); unregister_chrdev(gDrvrMajor, gDrvrName); } module_init(emif_edma_init); module_exit(emif_edma_exit); MODULE_AUTHOR("Texas Instruments"); MODULE_LICENSE("GPL");
:
驱动代码头文件:emif_cpu.h
struct aemif_para {
u8 wsetup;
u8 wstrobe;
u8 whold;
u8 rsetup;
u8 rstrobe;
u8 rhold;
u8 ta;
};
#define DM365_ASYNC_EMIF_CONTROL_BASE 0x01d10000
#define DM365_ASYNC_EMIF_DATA_CE0_BASE 0x02000000
#define DM365_ASYNC_EMIF_DATA_CE1_BASE 0x04000000
#define ACR_ASIZE_MASK 0x3
#define ACR_EW_MASK BIT(30)
#define ACR_SS_MASK BIT(31)
#define NRCSR_OFFSET 0x00
#define AWCCR_OFFSET 0x04
#define A1CR_OFFSET 0x10
#ifndef __sizes_h
#define __sizes_h 1
/* handy sizes */
#define SZ_1K 0x00000400
#define SZ_4K 0x00001000
#define SZ_8K 0x00002000
#define SZ_16K 0x00004000
#define SZ_32K 0x00008000
#define SZ_64K 0x00010000
#define SZ_128K 0x00020000
#define SZ_256K 0x00040000
#define SZ_512K 0x00080000
#define SZ_1M 0x00100000
#define SZ_2M 0x00200000
#define SZ_4M 0x00400000
#define SZ_8M 0x00800000
#define SZ_16M 0x01000000
#define SZ_31M 0x01F00000
#define SZ_32M 0x02000000
#define SZ_64M 0x04000000
#define SZ_128M 0x08000000
#define SZ_256M 0x10000000
#define SZ_512M 0x20000000
#define SZ_1G 0x40000000
#define SZ_2G 0x80000000
#endif
测试程序:emif_main_cpu.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/time.h>
#define DATA_LENGTH (1*1024)
//#define DATA_LENGTH (32*1024)
//#define DATA_LENGTH (256)
struct timeval emif_time_start;
struct timeval emif_time_end;
int main(void)
{
FILE* fp;
FILE* fp_1;
FILE* fp_2;
int g_devFile;
unsigned short data_send[DATA_LENGTH/2];
unsigned short data_recv[DATA_LENGTH/2];
int i = 0, ret = 0;
for(i = 0; i < DATA_LENGTH/2; i++){
data_send[i] = i;
}
for(i = 0; i < DATA_LENGTH/2; i++){
data_recv[i] = 0 ;
}
//open the device
g_devFile = open("/dev/emif_edma", O_RDWR);
if ( g_devFile < 0 ){
printf("emif_main: Error opening device file.\n");
return -1;
}
fp_1 = fopen("src.dat","ab+");
fp_2 = fopen("dst.dat","ab+");
while(1)
{
gettimeofday(&emif_time_start, NULL);
ret = fread((char *)data_send,1,DATA_LENGTH,fp_1);
if(ret < DATA_LENGTH){
return -1;
}
write(g_devFile,(char *)data_send, DATA_LENGTH);
usleep(1000);
#if 1
memset(data_recv, 0, DATA_LENGTH);
ret = read(g_devFile, (char *)data_recv, DATA_LENGTH);
if(ret < DATA_LENGTH){
return -1;
}
fwrite((char *)data_recv,1,DATA_LENGTH,fp_2);
for(i = 0; i < DATA_LENGTH/2;i++){
if(data_recv[i] != data_send[i]){
printf("error occur!!!");
// return -1;
}
}
#endif
gettimeofday(&emif_time_end, NULL);
printf("write time:%dus\n",(emif_time_end.tv_sec*1000000+emif_time_end.tv_usec)-(emif_time_start.tv_sec*1000000+emif_time_start.tv_usec));
}
return 0;
}