TI中文支持网
TI专业的中文技术问题搜集分享网站

DM368与FPGA采用AEMIF接口进行通信,传输自增数没问题,传输视频等数据有问题!!

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_SHIFT3
#define TCINTEN_SHIFT20
#define ITCINTEN_SHIFT21
#define TCCHEN_SHIFT22
#define ITCCHEN_SHIFT23


//#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

chargDrvrName[]= "emif_cpu";// Name of driver in proc.
intgDrvrMajor = 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_h1

/* handy sizes */
#define SZ_1K0x00000400
#define SZ_4K0x00001000
#define SZ_8K0x00002000
#define SZ_16K0x00004000
#define SZ_32K0x00008000
#define SZ_64K0x00010000
#define SZ_128K0x00020000
#define SZ_256K0x00040000
#define SZ_512K0x00080000

#define SZ_1M0x00100000
#define SZ_2M0x00200000
#define SZ_4M0x00400000
#define SZ_8M0x00800000
#define SZ_16M0x01000000
#define SZ_31M0x01F00000
#define SZ_32M0x02000000
#define SZ_64M0x04000000
#define SZ_128M0x08000000
#define SZ_256M0x10000000
#define SZ_512M0x20000000

#define SZ_1G0x40000000
#define SZ_2G0x80000000

#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;
}

 

KK Z:

请各路大神多多指教哇

Da Li3:

回复 KK Z:

好巧啊,我也在研究DM368的EMIF接口呢,也遇到了些问题,你有没有试过mmap 映射/dev/mem在用户空间直接读写EMIF接口呀?我用这种方式写的时候出现提示segmentation fault,

操作emif口必须要写驱动吗?

HG:

你好! EMIF 接口其实是一种转接控制器挂在系统总线上。所以大数据量交互时,请严格参照示例代码。

 关于DM368的视频支持,TI提供相关支持见网址:http://www.ti.com.cn/tool/cn/linuxdvsdk-dm36x?keyMatch=DM368&tisearch=Search-CN-Everything。

用于 DM365、DM368 数字媒体处理器的 Linux 数字视频软件开发套件 (DVSDK)

赞(0)
未经允许不得转载:TI中文支持网 » DM368与FPGA采用AEMIF接口进行通信,传输自增数没问题,传输视频等数据有问题!!
分享到: 更多 (0)