MPC8377_dma的驱动程序

本文介绍了一个针对 MPC8377 核心 CPU 板的 DMA (直接内存访问) 驱动程序实现细节。该驱动程序支持 VxWorks 6.6 操作系统,并通过 FPGA 进行数据传输。文中详细描述了 DMA 控制器的初始化过程、DMA 读写操作、中断处理以及 FPGA 的配置方法。
下面是MPC8377_dma的驱动程序
/*
 * FPGA driver for MPC8377core CPUBoard vxworks6.6
 * author:tzx
 * date:2011.4.13
*/
#include <vxworks.h>
#include <iv.h>
#include <ioLib.h>
#include <iosLib.h>
#include <errnoLib.h>
#include <intLib.h>
#include <semLib.h>
#include <cacheLib.h>
#include <logLib.h>
#include <stdio.h>
#include <string.h>
#include <taskLib.h>

volatile unsigned char *fpga_virt_base;
#include "DMA.h"
#define FPGA_BASE_ADDR	(0xd5000000)	/*CS5 base addr=0xd5000000*/
#define FPGA_PHY_SIZE	(0x100000)	/*4Mbytes*/

//debug
#define DMA_DEBUG
#undef DMA_DEBUG
#define FPGA_DEBUG
#undef FPGA_DEBUG
#ifdef FPGA_DEBUG
#define DEBUG_INFO(fmt...) printf(fmt)
#else
#define DEBUG_INFO(fmt...) do{}while(0)
#endif

//pin
#define SIUMCR_OFFSET_ADDR (0x10000)

//bus
#define BR5_OFFSET_ADDR 	(0x5028)
#define OR5_OFFSET_ADDR 	(0x502C)
#define MAR_OFFSET_ADDR 	(0x5068)
#define MAMR_OFFSET_ADDR 	(0x5070)
#define MBMR_OFFSET_ADDR 	(0x5074)
#define MCMR_OFFSET_ADDR 	(0x5078)
#define MRTPR_OFFSET_ADDR 	(0x5084)
#define MDR_OFFSET_ADDR 	(0x5088)
#define LURT_OFFSET_ADDR	(0x50a0)
#define LBCR_OFFSET_ADDR	(0x50d0)
#define LCRR_OFFSET_ADDR	(0x50d4)

//#define BR_BA FPGA_BASE_ADDR
#define BR_PS		(3<<11)		/* PS = 0b11 */
#define BR_MSEL		(4<<5)		/* MSEL = 0b100 UPMA mode*/
#define BR_V		(1)		/* V =1 */

#define OR_AM		(0xff800<<15)	/*memory block size 1MBytes*/
#define OR_BCTLD	(1<<12)		/*change from (1<<11)*/
#define OR_TRLX_ETHR	(2<<1)		/*4 idle clock cycles are inserted*/

//irq
#define SIPRR_OFFSET_ADDR	(0x710)
#define SIPNR_L_OFFSET_ADDR	(0x70C)
#define SIMSR_L_OFFSET_ADDR	(0x724)
#define SICNR_OFFSET_ADDR	(0x728)

#define IRQ_NUM5		21
#define IRQ_NUM6		22
#define IRQ_NUM7		23

#define CFG_SEPNR  0xe000072C   /*System External Interrupt Pending Register*/
#define CFG_SEMSR  0xe0000738   /*System External Interrupt Mask Register */
#define CFG_SECNR  0xe000073C   /*System External Interrupt Control Register */

volatile unsigned int *SECNR=((unsigned int *)CFG_SECNR);
volatile unsigned int *SEMSR=((unsigned int *)CFG_SEMSR);
volatile unsigned int *SEPNR=((unsigned int *)CFG_SEPNR);

#define CFG_BASE		(0xe0000000)

#define CFG_SICRH_OFF  	(0x118)
#define CFG_SICRH		(CFG_BASE+CFG_SICRH_OFF)

#define CFG_IPIC_OFF	(0x0700)
#define CFG_SEFCR_OFF	(0x58)
#define CFG_SEFCR		(CFG_BASE+CFG_IPIC_OFF+CFG_SEFCR_OFF)	/*force external interrupt*/

#define IRQ5_MASK		(0x04000000)
#define IRQ6_MASK		(0x02000000)
#define IRQ7_MASK		(0x01000000)

#define CFG_IRQ5_MASK	(0x300)
#define CFG_IRQ6_MASK	(0xc0)
#define CFG_IRQ7_MASK	(0x30)

#define IRQ_MASK		(IRQ5_MASK|IRQ6_MASK|IRQ7_MASK)
#define CFG_FPGA_MASK	(CFG_IRQ5_MASK|CFG_IRQ6_MASK|CFG_IRQ7_MASK)

#define CFG_DMA_MASK		(0x01000000)

/* external  */
extern void sysUsDelay(unsigned long delay);
/* NOTE : implementation is platform specific */
#define US_DELAY(x) sysUsDelay(x*300)

#define CFG_LBLAWBAR1_PRELIM    FPGA_BASE_ADDR /* Window base at flash base */
#define CFG_LBLAWAR1_PRELIM     0x8000001b		/*Window size is 256M Bytes*/ 
#define LAWAR1_SIZE		(0x1b)		/*Window size is 256M Bytes*/
#define LBLAWBAR1    0x0028
#define LBLAWAR1     0x002c 

#define BUF_SIZE	1024*4

#define FPGA_IOCTL_CMD_SET_ROFFSET	1
#define FPGA_IOCTL_CMD_SET_WOFFSET	2
#define FPGA_IOCTL_CMD_INT_ENABLE 	3
#define FPGA_IOCTL_CMD_INT_DISABLE 	4

#define FPGA_REG_OFFSET	0x200000

struct fpga_controller{
		DEV_HDR devHdr;
		char * port_name;
		volatile unsigned char * io_data;
		volatile unsigned char * io_addr;
		int irq_nr;
		int write_status;//write status flag
		int read_wanted;//read status flag
		void *pInBuf;
		void *pOutBuf;
		int read_offset;
		int write_offset;
};
static struct fpga_controller fpga_var;
unsigned int immr_base_addr = 0xe0000000;
static int FPGA_Installed = 0;
static int FPGAInt_Connected = 0;

unsigned int swap32(unsigned int data32)
{
	return (((data32&0xff)<<24)|((data32&0xff00)<<8)|((data32&0xff0000)>>8)|((data32&0xff000000)>>24));
}

static void start_dma(int dma_no)
{
	dma_ctrl[dma_no]->mode |= swap32(DMA_MODE_START);
}

static void stop_dma(int dma_no)
{
	dma_ctrl[dma_no]->mode &= swap32(~DMA_MODE_START);
}

/* read data from fpga */
int dma_read(void *buf, unsigned int offset, unsigned int length)
{
	/* initialize DMA source address to FPGA physical address */
	dma_ctrl[DMA_READ]->src_addr = swap32(FPGA_BASE_ADDR + offset);
	/* initialize DMA destination address to buffer physical address */
	dma_ctrl[DMA_READ]->dest_addr = swap32((unsigned int)(buf));
	/* initialize DMA byte count to buffer physical address */
	dma_ctrl[DMA_READ]->cnt = swap32(length);
	cacheInvalidate(DATA_CACHE, buf, length);
	//CACHE_DMA_INVALIDATE(buf,length);	
	/* flush the cache for cache coherence */
#ifdef DMA_DEBUG
	printf("dma read dest_addr is 0x%08x \n",swap32(dma_ctrl[DMA_READ]->dest_addr));
	printf("dma read src_addr is  0x%08x \n",swap32(dma_ctrl[DMA_READ]->src_addr));
	printf("dma read count is     0x%08x \n",swap32(dma_ctrl[DMA_READ]->cnt));
#endif
	start_dma(DMA_READ);
	/* wait DMA transfer complete */
	semTake(dma_sync[DMA_READ],WAIT_FOREVER);

	return length;
}

/* write data to fpga */
int dma_write(void *buf, unsigned int offset, unsigned int length)
{
	/* intialize the destination address of DMA transfer */
	dma_ctrl[DMA_WRITE]->dest_addr = swap32(FPGA_BASE_ADDR + offset);
	/* intialize the source address of DMA transfer */
	dma_ctrl[DMA_WRITE]->src_addr = swap32((unsigned int)(buf));
	/* initialize DMA byte count to buffer physical address */
	dma_ctrl[DMA_WRITE]->cnt = swap32(length);
	//cacheInvalidate(DATA_CACHE, buf, length)
	cacheFlush(DATA_CACHE, buf, length);
#ifdef DMA_DEBUG
	printf("dma write dest_addr is 0x%08x \n",swap32(dma_ctrl[DMA_WRITE]->dest_addr));
	printf("dma write src_addr is  0x%08x \n",swap32(dma_ctrl[DMA_WRITE]->src_addr));
	printf("dma write count is     0x%08x \n",swap32(dma_ctrl[DMA_WRITE]->cnt));
#endif	
	//flush_dcache_range((unsigned int)buf, ((unsigned int)buf)+length);
	start_dma(DMA_WRITE);
	/* wait DMA transfer complete */
	semTake(dma_sync[DMA_WRITE],WAIT_FOREVER);
	return length;
}

/* dma interrupt handler */
static int dma_irq_handler(void)
{
	int i;
	unsigned int status;
	for(i=0; i<DMA_NUM; i++){
		status = swap32(dma_ctrl[i]->status);
		//logMsg("DMA status is 0x%08x\n",status,2,3,4,5,6);
		if(status & DMA_STATUS_MASK){
			/* now there is an interrupt in this DMA contollor */
			//logMsg("DMA Interrupt\n",1,2,3,4,5,6);
			if(status & DMA_STATUS_TE ){
				/* this error is transfer error. */
				stop_dma(i);
#ifdef DMA_DEBUG
				logMsg("dma %d transfer error,give the semaphore for debug.\n",i,2,3,4,5,6);
#endif
				semGive(dma_sync[i]);
			}else{
				/* up the semaphore, this transfer job has completed. */
				semGive(dma_sync[i]);
#ifdef DMA_DEBUG
				logMsg("dma %d transfer completed,give the semaphore.\n",i,2,3,4,5,6);
#endif			
			}
			dma_ctrl[i]->status = swap32(status);
		}else{
			continue;
		}
	}
	return 0;
}

/* initialize dma controller which is used by fpga to transfer data */
static int dma_init(void)
{
	int dma_no;
	for(dma_no = 0;dma_no < DMA_NUM;dma_no++){
		/* initialize the dma controller address */
		dma_ctrl[dma_no] = (struct dma_controller *)(immr_base_addr + dma_off[dma_no]);

		while(swap32(dma_ctrl[dma_no]->status) & DMA_STATUS_CB){
			printf("channel %d busy.\n",dma_no);
		}
		dma_ctrl[dma_no]->mode |= swap32(DMA_MODE_VALUE);
		US_DELAY(10);
		
		/* initialize the dma semaphore */
		dma_sync[dma_no] = semBCreate(SEM_Q_FIFO,SEM_EMPTY);
	}
	/* request interrupt for DMA */
	if(ERROR == intConnect(INUM_TO_IVEC(DMA_IRQ_VECTOR),(VOIDFUNCPTR)dma_irq_handler,(int)NULL))
	{
		printf("intConnect for DMA error.\n");
		return ERROR;
	}
	intEnable(DMA_IRQ_VECTOR);
	return 0;
}

void dma_reg_show(int dma_no)
{
	int reg;
	unsigned int dma_base_addr; 
			printf("dma %d mode is           0x%08x \n",dma_no,dma_ctrl[dma_no]->mode);
			printf("dma %d status is         0x%08x \n",dma_no,dma_ctrl[dma_no]->status);
			printf("dma %d cur desc addr is  0x%08x \n",dma_no,dma_ctrl[dma_no]->cur_des);
			printf("dma %d src addr is       0x%08x \n",dma_no,dma_ctrl[dma_no]->src_addr);
			printf("dma %d dest addr is      0x%08x \n",dma_no,dma_ctrl[dma_no]->dest_addr);
			printf("dma %d count is          0x%08x \n",dma_no,dma_ctrl[dma_no]->cnt);
			printf("dma %d next desc addr is 0x%08x \n",dma_no,dma_ctrl[dma_no]->next_des);
	dma_base_addr = immr_base_addr + dma_off[dma_no];
	printf("dma_base_addr is 0x%08x\n",dma_base_addr);
	for(reg=0; reg<10; reg++)
	{
		printf("dma reg %d addr 0x%08x,value is 0x%08x \n",reg,dma_base_addr + reg*4,*(volatile unsigned *)(dma_base_addr + reg*4));
	}
}

void dma_test(void)
{
	unsigned int buf[16];
	int i;
	dma_read(buf, 0x00, 64);
	for(i=0; i<16; i++){
		printf("0x%08x ", buf[i]);
		if(i!=0 && i%4==0)
			printf("\n");
	}
	printf("\n");
	dma_write(buf, 0x00, 64);
	memset(buf, 0, sizeof(buf));
	dma_read(buf, 0x00, 64);
	for(i=0; i<16; i++){
		printf("0x%08x ", buf[i]);
		if(i!=0 && i%4==0)
			printf("\n");
	}
	printf("\n");
}

static unsigned long fpga_upma_table[] =
{
    /*read single*/
#if 1    
    0x0ffffc00,  0x0ffffc00, 0x0ffffc00,  0x0ffffc00, //Words 0 to 3
    0x0ffffc00,  0x0ffffc00, 0x0ffffc04,  0xfffffc01, //Words 4 to 7
#else
    0x0ffffc00,  0x0fffff00,  0x0fffff00,  0x0ffffc00, //
    0xffffff00,  0xfffffc05,  0xfffffc01,  0xfffffc01, //
#endif
    /*read burst*/
    0xfffffc00,  0xfffffc00,  0xfffffc00,  0xfffffc00, //Words 8 to 11
    0xfffffc00,  0xfffffc00,  0xfffffc00,  0xfffffc00, //Words 12 to 15
    0xfffffc00,  0xfffffc00,  0xfffffc00,  0xfffffc00, //Words 16 to 19
    0xfffffc00,  0xfffffc00,  0xfffffc00,  0xfffffc01, //Words 20 to 23
    /*write single*/

#if 1 
    0x0ffffc00,  0x0ffffc00, 0x0ffffc00,  0x0ffffc00, //Words 0 to 3
    0x0ffffc00,  0x0ffffc00, 0x0ffffc04,  0xfffffc01, //Words 4 to 7

#else
    0x0ffffc00,  0x0fffff00,  0x0fffff00,  0x0ffffc00, //Words 24 to 27
    0xffffff00,  0xfffffc05,  0xfffffc01,  0xfffffc01, //Words 28 to 31
#endif
    /*write burst*/
    0xfffffc00,  0xfffffc00,  0xfffffc00,  0xfffffc00, //Words 32 to 35
    0xfffffc00,  0xfffffc00,  0xfffffc00,  0xfffffc00, //Words 36 to 39
    0xfffffc00,  0xfffffc00,  0xfffffc00,  0xfffffc00, //Words 40 to 43
    0xfffffc00,  0xfffffc00,  0xfffffc00,  0xfffffc01, //Words 44 to 47
    /*refresh timer*/
    0xfffffc00,  0xfffffc00,  0xfffffc00,  0xfffffc00, //Words 48 to 51
    0xfffffc00,  0xfffffc00,  0xfffffc00,  0xfffffc00, //Words 52 to 55
    0xfffffc00,  0xfffffc00,  0xfffffc00,  0xfffffc01, //Words 56 to 59
    /*exception*/
    0xfffffc00,  0xfffffc00,  0xfffffc00,  0xfffffc01  //Words 60 to 63
};

static void fpga_upma_prog(void)
{
	int i=0;

	volatile unsigned int * mamr=(volatile unsigned int *)(immr_base_addr+MAMR_OFFSET_ADDR);
	volatile unsigned int * mdr=(volatile unsigned int *)(immr_base_addr+MDR_OFFSET_ADDR);
#if 1
	for (i=0;i<64;i++){		
		*mdr = fpga_upma_table[i];
		while(*mdr!=fpga_upma_table[i]){
			;
		}
		
		*mamr = 0x10000000 | i;
		while(*mamr!=(0x10000000|i)){
			;
		}
		fpga_write_reg(0,0);
		while((*mamr&0x3f)!=((i+1)%64)){
			;
		}//wait until the write RAM completed.
	}
#endif	
	/*change MAMR back to normal mode*/
	*mamr = 0x00000000;
	/*wait until the write of MAMR finished*/
	while (*mamr!= 0x00000000);
	
	printf("UPM Prog OK.");
}

#define SUBBOARD_RESET_PIN  0x40000000
/* Set GPIO1 low and then high */
void subboard_reset(void)
{
		
	volatile unsigned int *pReg32;	
	
	pReg32 = (volatile unsigned int*)(immr_base_addr+0x114);//SICRL BIT7 to 0 to  GPIO 
	pReg32[0] &= ~0x01000000;
	printf("SICRL is set to 0x%08x\n",pReg32[0]);
	
	
	pReg32 = (volatile unsigned int*)(immr_base_addr+0xc00);//DIR
	pReg32[0] |= SUBBOARD_RESET_PIN;
	printf("GPIO Dir is set to 0x%08x\n",pReg32[0]);
	
	pReg32 = (volatile unsigned int*)(immr_base_addr+0xc04);//ODR
	pReg32[0] &= ~SUBBOARD_RESET_PIN;
	printf("GPIO ODR is set to 0x%08x\n",pReg32[0]);
	
	pReg32 = (volatile unsigned int*)(immr_base_addr+0xc08);//DAT
	pReg32[0] &= ~SUBBOARD_RESET_PIN;
	printf("GPIO DAT is set to 0x%08x\n",pReg32[0]);
	
	taskDelay(10);
	
	pReg32 = (volatile unsigned int*)(immr_base_addr+0xc08);//DAT
	pReg32[0] |= SUBBOARD_RESET_PIN;
	printf("GPIO DAT is set to 0x%08x\n",pReg32[0]);
	taskDelay(10);
	
	printf("SubBoard Reset OK\n");
	return ;		
	}
	
	
void subboard_SetRstPin(int High)
{
	volatile unsigned int *pReg32,Data32;	
	
	pReg32 = (volatile unsigned int*)(immr_base_addr+0xc08);//DAT
	
	if(High)
			pReg32[0] |= SUBBOARD_RESET_PIN;
	else
			pReg32[0] &= ~SUBBOARD_RESET_PIN;
	
	printf("GPIO DAT is set to 0x%08x\n",pReg32[0]);
	taskDelay(10);
}

static void board_bus_init(void)
{
	/********  FPGA , CAN and Serial ************/
	//volatile unsigned int *pReg32;	

	*(volatile unsigned *)(immr_base_addr+OR5_OFFSET_ADDR) = OR_AM| 0x0100;// UPMA
	//*(volatile unsigned *)(immr_base_addr+OR5_OFFSET_ADDR) = OR_AM| 0x0193;// GPCM
	US_DELAY(10);
#ifdef FPGA_DEBUG
	printf("set OR5 regist addr 0x%08x ,value is 0x%08x\n ",
			immr_base_addr + OR5_OFFSET_ADDR, *(volatile unsigned *)(immr_base_addr + OR5_OFFSET_ADDR));	
#endif

	*(volatile unsigned *)(immr_base_addr+BR5_OFFSET_ADDR) = FPGA_BASE_ADDR|BR_PS|BR_MSEL|BR_V;//32bit,UPMA
	//*(volatile unsigned *)(immr_base_addr+BR5_OFFSET_ADDR) = FPGA_BASE_ADDR|0x1801;//32bit,GPCM
	US_DELAY(10);
#ifdef FPGA_DEBUG
	printf("set BR5 regist addr 0x%08x ,value is 0x%08x\n ",
			immr_base_addr + BR5_OFFSET_ADDR, *(volatile unsigned *)(immr_base_addr + BR5_OFFSET_ADDR));	
#endif

	//*(volatile unsigned *)(immr_base_addr+LBCR_OFFSET_ADDR) = 0x00200000;
	//US_DELAY(10);
#ifdef FPGA_DEBUG
	printf("----after setting----\n");
	printf("OR5 = %08x    BR5 = %08x\n",*(volatile unsigned *)(immr_base_addr+OR5_OFFSET_ADDR),*(volatile unsigned *)(immr_base_addr+BR5_OFFSET_ADDR));
	printf("LBCR = %08x   LCRR = %08x\n",*(volatile unsigned *)(immr_base_addr+LBCR_OFFSET_ADDR),*(volatile unsigned *)(immr_base_addr+LCRR_OFFSET_ADDR));
#endif

	}

unsigned int fpga_read_reg(int reg)
{
	volatile unsigned int* pAddr32 = fpga_virt_base + FPGA_REG_OFFSET;
	return pAddr32[reg];
}

void fpga_write_reg(int reg,unsigned int data)
{
	volatile unsigned int* pAddr32 = fpga_virt_base + FPGA_REG_OFFSET;
	pAddr32[reg] = data;
	
}

static void fpga_reg_test(void)
{
	int i,Data,j;
	
	printf("Reg Test Start.\n");
	for(j=0;j<10;j++){
	//for(j=0;j<25000;j++){
		for (i = 2; i < 7; i++){
			fpga_write_reg(i,i);
			fpga_write_reg(i+1,i+1);
			Data = fpga_read_reg(i);
			if(Data != i)
				DEBUG_INFO("%d reg write 0x%08x,while read 0x%08x\n", i, i, fpga_read_reg(i));
	  }
	}
	printf("Reg Test End.\n");
}

/*int5 intterupt handler*/
void fpga_interrupt5(void)
{
	char date=0;
	volatile unsigned int  Data32;
	
	Data32 =*SEPNR;
	Data32 |= IRQ5_MASK;     /*clear IRQ5*/
	*SEPNR =Data32;
	
	/*logMsg("\t1 irq *SEPNR = 0x%x\n",*SEPNR,0,0,0,0,0);*/
	logMsg("Receive an interrupt5 ! \n",0,0,0,0,0,0);
}

/*int6 intterupt handler*/
void fpga_interrupt6(void)
{
	char date=0;
	volatile unsigned int  Data32;
	
	Data32 =*SEPNR;
	Data32 |= IRQ6_MASK;     /*clear IRQ6*/
	*SEPNR =Data32;
	
	/*logMsg("\t1 irq *SEPNR = 0x%x\n",*SEPNR,0,0,0,0,0);*/
	logMsg("Receive an interrupt6 ! \n",0,0,0,0,0,0);
}

/*int7 intterupt handler*/
void fpga_interrupt7(void)
{
	char date=0;
	volatile unsigned int  Data32;
	
	Data32 =*SEPNR;
	Data32 |= IRQ7_MASK;     /*clear IRQ7*/
	*SEPNR =Data32;
	
	/*logMsg("\t1 irq *SEPNR = 0x%x\n",*SEPNR,0,0,0,0,0);*/
	logMsg("Receive an interrupt7 ! \n",0,0,0,0,0,0);
}

int fpga_ext_int_init(void)
{
	volatile unsigned int  Data32;
	volatile unsigned long *sicrh;
		
	/*config the io pin to the interrupt*/
	sicrh = (unsigned long *)CFG_SICRH;	
	*sicrh &= ~CFG_FPGA_MASK;

	/*high-to-low gernerate the interrupt*/
	Data32 = *SECNR;
	Data32|= (IRQ_MASK>>16);
	*SECNR=Data32;
	
	/*unmask the interrupts*/
	#if 1
	if(ERROR == intConnect(INUM_TO_IVEC(IRQ_NUM5), (VOIDFUNCPTR)fpga_interrupt5, (int)NULL))
		{
			/* if connnect error */
			printf("intConnect For IRQ5 Failed.\n");
			return ERROR;
		} 
	if(ERROR == intConnect(INUM_TO_IVEC(IRQ_NUM6), (VOIDFUNCPTR)fpga_interrupt6, (int)NULL))
		{
			/* if connnect error */
			printf("intConnect For IRQ6 Failed.\n");
			return ERROR;
		}
	if(ERROR == intConnect(INUM_TO_IVEC(IRQ_NUM7), (VOIDFUNCPTR)fpga_interrupt7, (int)NULL))
		{
			/* if connnect error */
			printf("intConnect For IRQ7 Failed.\n");
			return ERROR;
		}
	
	FPGAInt_Connected = 1;

	Data32=*SEMSR;
	Data32|= IRQ_MASK;
	*SEMSR=Data32;
	
	intEnable(IRQ_NUM5);
	intEnable(IRQ_NUM6);
	intEnable(IRQ_NUM7);
	
#endif

	printf("Init fpga interrupt is OK!\n");
	return 0;
}

static int dma_show_buf(struct fpga_controller *pport,int channel)
{
	int i;
	volatile unsigned int * pAddr32;
	if(!channel)
	{
	pAddr32 = (volatile unsigned int *)pport->pInBuf;
	printf("pInBuf addr is 0x%08x \n",(unsigned int)pport->pInBuf);
	for(i = 0;i < BUF_SIZE/4;i++)
	{
		printf("0x%08x ", pAddr32[i]);
				if(i!=0 && i%10==0)
					printf("\n");
	}
	printf("\n");
	}else{
		printf("pOutBuf addr is 0x%08x \n",(unsigned int)pport->pOutBuf);
		pAddr32 = (volatile unsigned int *)pport->pOutBuf;
		for(i = 0;i < BUF_SIZE/4;i++)
		{
			printf("0x%08x ", pAddr32[i]);
				if(i!=0 && i%10==0)
					printf("\n");
		}
		printf("\n");
		}
	return 0;
}

int fpga_create(struct fpga_controller * pport,char * name,int mode)
{
	logMsg("---- fpga_create.\n",1,2,3,4,5,6);
	return (OK);
}
int fpga_open(struct fpga_controller * pport,char * name,int mode)
{
	pport->pInBuf = cacheDmaMalloc(BUF_SIZE);
	pport->pOutBuf = cacheDmaMalloc(BUF_SIZE);
	if(pport->pInBuf == NULL)
		return (ERROR);
	if(pport->pOutBuf == NULL)
		return (ERROR);
	memset(pport->pInBuf,0xff,BUF_SIZE);
	memset(pport->pOutBuf,0xff,BUF_SIZE);
	pport->read_wanted = 0;
	pport->write_status = 0;
#ifdef FPGA_DEBUG
	logMsg("---- fpga opened ----\n",1,2,3,4,5,6);
	logMsg("pInBuf  addr is 0x%08x \n",(unsigned int)pport->pInBuf,2,3,4,5,6);
	logMsg("pOutBuf addr is 0x%08x \n",(unsigned int)pport->pOutBuf,2,3,4,5,6);
	//dma_show_buf(pport,0);
	//dma_show_buf(pport,1);
#endif
	return ((int)pport);
}
int fpga_close(struct fpga_controller * pport)
{
#ifdef FPGA_DEBUG
	logMsg("---- fpga closed ----.\n",1,2,3,4,5,6);
#endif	
	cacheDmaFree(pport->pInBuf);
	cacheDmaFree(pport->pOutBuf);
	return(OK);
}
int fpga_write(struct fpga_controller * pport ,char * buf,int count)
{
	if(count>BUF_SIZE)
		count = BUF_SIZE;
		
	//printf("write_offset = 0x%08x\n",pport->write_offset);
	pport->write_status = 1;
	memcpy(pport->pOutBuf,buf,count);
#ifdef DMA_DEBUG
	dma_show_buf(pport,1);
#endif	
	dma_write(pport->pOutBuf,pport->write_offset,count);
	pport->write_status = 0;
	
	return count;
}
int fpga_read (struct fpga_controller * pport ,char * buf,int count)
{
		
	if(count > BUF_SIZE)
		count = BUF_SIZE;
	//wait dma_read;
	//printf("read offset = 0x%08x\n",pport->read_offset);
	pport->read_wanted = 1;
	dma_read(pport->pInBuf,pport->read_offset,count);
	pport->read_wanted = 0;
#ifdef DMA_DEBUG
	dma_show_buf(pport,0);
#endif
	memcpy(buf,pport->pInBuf,count);

	return count;
}
int fpga_ioctl(struct fpga_controller * pport,int cmd, int data)
{
	//logMsg("---- fpga_ioctl.\n",1,2,3,4,5,6);
	
	switch(cmd){
		case FPGA_IOCTL_CMD_SET_ROFFSET:
				pport->read_offset = data;
				break;
		case FPGA_IOCTL_CMD_SET_WOFFSET:
				pport->write_offset = data;
				break;
		case FPGA_IOCTL_CMD_INT_ENABLE:
				if(FPGAInt_Connected){
					intEnable(IRQ_NUM5);
					intEnable(IRQ_NUM6);
					intEnable(IRQ_NUM7);
				}else
					fpga_ext_int_init();
				
				break;
		case FPGA_IOCTL_CMD_INT_DISABLE:
				intDisable(IRQ_NUM5);
				intDisable(IRQ_NUM6);
				intDisable(IRQ_NUM7);
				break;
		default:
				printf("invalid cmd %d.\n",cmd);
				break;
	}
	
	return (OK);
}

int fpga_drv_install(void)
{
	int drvNum;
	struct fpga_controller *p;
		
	if(FPGA_Installed)
	{
		logMsg("FPGA driver already installed.\n",1,2,3,4,5,6);
		return (OK);
	}
	subboard_reset();
	board_bus_init();
	fpga_virt_base = (volatile unsigned char *)FPGA_BASE_ADDR;
	fpga_upma_prog();//write patterns into the RAM array;
	p = &fpga_var;
	p->io_addr = (volatile unsigned char *)FPGA_BASE_ADDR;
	p->port_name = "/fpga";
	drvNum = iosDrvInstall(fpga_create,(FUNCPTR)NULL,fpga_open,fpga_close,fpga_read,fpga_write,fpga_ioctl);
	if(ERROR == drvNum)
		return(ERROR);
	if(iosDevAdd(&p->devHdr,p->port_name,drvNum) == ERROR)
	{
		logMsg("err : add device %s failed\n",p->port_name,2,3,4,5,6);
		return(ERROR);
	}
	fpga_reg_test();
	dma_init();
#if 0
	fpga_ext_int_init();
#endif
	printf("Entering FPGA module.\n");
	printf("ioremap FPGA_BASE_ADDR 0x%08x to 0x%08x\n",(unsigned int)FPGA_BASE_ADDR,(unsigned int)fpga_virt_base);

	FPGA_Installed = 1;

	return (OK);
}

int dma_cleanup_module(void)
{
	//free_irq(DMA_IRQ_VECTOR,NULL);
	/*iounmap((void *)fpga_virt_base);
	release_mem_region(FPGA_BASE_ADDR, FPGA_PHY_SIZE);*/
	semDelete(dma_sync[DMA_READ]);
	semDelete(dma_sync[DMA_WRITE]);
	intDisable(DMA_IRQ_VECTOR);
	return 0;
}


int TestFPGA(void)
{
	volatile unsigned int *pAddr32,Data32;
		
	pAddr32 = fpga_virt_base;
	
	while(1){
	printf("Board Addr 0 = 0x%08x\n",*pAddr32);
	printf("Board Addr 1 = 0x%08x\n",pAddr32[1]);
	printf("Board Addr 2 = 0x%08x\n",pAddr32[2]);
	printf("Board Addr 3 = 0x%08x\n",pAddr32[3]);
	taskDelay(60);
}	
}

/* end of file */


下面是对应的app程序(其中有两部分,一部分时测试速率的,一部分就是对dma进行全方位的测试)
#include "vxworks.h"
#include "taskLib.h"
#include "ioLib.h"
#include "iosLib.h"
#include "logLib.h"
#include "stdio.h"

#define FPGA_IOCTL_CMD_SET_ROFFSET	1
#define FPGA_IOCTL_CMD_SET_WOFFSET	2
#define FPGA_IOCTL_CMD_INT_ENABLE 	3
#define FPGA_IOCTL_CMD_INT_DISABLE 	4

#define FPGA_DMA_CNT	1024*4
#define	WR_DMA_CNT		10

STATUS fpga_test(void);
STATUS fpga_test_read(void);
STATUS fpga_test_write(void);

#if 0
STATUS fpga_test(void)
{
	unsigned int buf[16];
	int i,ret;
	int fd;
	
	fd = open("/fpga",O_RDWR,0644);
	if(fd<0)
		{
		printf("open fpga error.\n");
		return ERROR;
		}
		
	printf("Start Read FPGA SRAM\n");
	
	printf("Start Read SRAM ============================\n");
	ret = ioctl(fd, FPGA_IOCTL_CMD_SET_ROFFSET, 0); /* set read offset */
	ret = read(fd, buf, 64);
	if(ret != 64)
		printf("read error.\n");
	printf("\n");
	for(i=0; i<16; i++){
		if(i!=0 && i%4==0)
			printf("\n");
		printf("0x%08x ", buf[i]);
	}
	printf("\n");
	
	printf("Start Write SRAM ============================\n");
	
	for(i=0; i<16; i++){
		buf[i]= i;
	}
	ret = ioctl(fd, FPGA_IOCTL_CMD_SET_WOFFSET, 0); /* set read offset */
	ret = write(fd, buf, 64);
	if(ret != 64)
		printf("write error.\n");
		
	printf("Start Read SRAM ============================\n");
	
	for(i=0; i<16; i++){
		buf[i]= 0;
	}
	ret = read(fd, buf, 64);
	if(ret != 64)
		printf("read error.\n");
	for(i=0; i<16; i++){
		if(i!=0 && i%4==0)
			printf("\n");
		printf("0x%08x ", buf[i]);
	}
	printf("\n");
	printf("Start Write SRAM ============================\n");
	
	for(i=0; i<16; i++){
		buf[i]= 16 - i;
	}
	ret = ioctl(fd, FPGA_IOCTL_CMD_SET_WOFFSET, 0); /* set read offset */
	ret = write(fd, buf, 64);
	if(ret != 64)
		printf("write error.\n");
		
	printf("Start Read SRAM ============================\n");
	
	for(i=0; i<16; i++){
		buf[i]= 0;
	}
	ret = read(fd, buf, 64);
	if(ret != 64)
		printf("read error.\n");
	for(i=0; i<16; i++){
		if(i!=0 && i%4==0)
			printf("\n");
		printf("0x%08x ", buf[i]);
	}
	printf("\n");
	
	
	printf("Start Read FPGA Reg\n");
	
	printf("Start Read Reg ============================\n");
	ret = ioctl(fd, FPGA_IOCTL_CMD_SET_ROFFSET, 0x200000); /* set read offset */
	ret = read(fd, buf, 32);
	if(ret != 32)
		printf("read error.\n");
	printf("\n");
	for(i=0; i<8; i++){
		if(i!=0 && i%4==0)
			printf("\n");
		printf("0x%08x ", buf[i]);
	}
	printf("\n");
	
	printf("Start Write Reg ============================\n");
	
	for(i=0; i<8; i++){
		buf[i]= i;
	}
	ret = ioctl(fd, FPGA_IOCTL_CMD_SET_WOFFSET, 0x200000); /* set read offset */
	ret = write(fd, buf, 32);
	if(ret != 32)
		printf("write error.\n");
		
	printf("Start Read Reg ============================\n");
	
	for(i=0; i<8; i++){
		buf[i]= 0;
	}
	ret = read(fd, buf, 32);
	if(ret != 32)
		printf("read error.\n");
	for(i=0; i<8; i++){
		if(i!=0 && i%4==0)
			printf("\n");
		printf("0x%08x ", buf[i]);
	}
	printf("\n");
	printf("Start Write Reg ============================\n");
	
	for(i=0; i<8; i++){
		buf[i]= 8 - i;
	}
	ret = ioctl(fd, FPGA_IOCTL_CMD_SET_WOFFSET, 0x200000); /* set read offset */
	ret = write(fd, buf, 32);
	if(ret != 32)
		printf("write error.\n");
		
	printf("Start Read Reg ============================\n");
	
	for(i=0; i<8; i++){
		buf[i]= 0;
	}
	ret = read(fd, buf, 32);
	if(ret != 32)
		printf("read error.\n");
	for(i=0; i<8; i++){
		if(i!=0 && i%4==0)
			printf("\n");
		printf("0x%08x ", buf[i]);
	}
	printf("\n");
	
	close(fd);
	return (OK);
}

#else

//test speed of write
STATUS fpga_test(void)
{
	unsigned int write_buf[FPGA_DMA_CNT];
	unsigned int read_buf[FPGA_DMA_CNT];
	unsigned long wr_tick_start;
	unsigned long wr_tick_end;
	unsigned long rd_tick_start;
	unsigned long rd_tick_end;
	int ret;
	int fd;
	unsigned long i;

	memset(write_buf,0x03, FPGA_DMA_CNT* sizeof(unsigned char));
	
	fd = open("/fpga",O_RDWR,0644);
	if(fd<0)
	{
		printf("open fpga error.\n");
		return ERROR;
	}

	//taskSpawn(char * name, int priority, int options, int stackSize, FUNCPTR entryPt, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, int arg10)
	
	ret = ioctl(fd, FPGA_IOCTL_CMD_SET_WOFFSET, 0); /* set write offset */
	while(1){
		BDLED_SetLED(0,0);
		for(i=0; i<WR_DMA_CNT; i++){
			ret = write(fd, write_buf, FPGA_DMA_CNT);
			if(ret != FPGA_DMA_CNT){
				printf("the Write ret is %d\n",ret);
				printf("write error.\n");
			}
		}

		BDLED_SetLED(0,1);
		for(i=0; i<200000; i++)
			;
	}
	close(fd);
	return (OK);
}


//test speed of read
STATUS fpga_test1(void)
{
	unsigned int write_buf[FPGA_DMA_CNT];
	unsigned int read_buf[FPGA_DMA_CNT];
	unsigned long wr_tick_start;
	unsigned long wr_tick_end;
	unsigned long rd_tick_start;
	unsigned long rd_tick_end;
	int ret;
	int fd;
	unsigned long i;


	memset(read_buf,0x03, FPGA_DMA_CNT* sizeof(unsigned char));
	
	
	fd = open("/fpga",O_RDWR,0644);
	if(fd<0)
	{
		printf("open fpga error.\n");
		return ERROR;
	}

	ret = ioctl(fd, FPGA_IOCTL_CMD_SET_ROFFSET, 0); /* set read offset */
	while(1){
		BDLED_SetLED(0,0);
		for(i=0; i<WR_DMA_CNT; i++){
			ret = read(fd, read_buf, FPGA_DMA_CNT);
			if(ret != FPGA_DMA_CNT){
				printf("the Write ret is %d\n",ret);
				printf("read error.\n");
			}
		}
		BDLED_SetLED(0,1);
		for(i=0; i<200000; i++)
			;
	}
	close(fd);
	return (OK);
}
#endif

STATUS fpga_IntStart(void)
{	
	unsigned int buf[16];
	int i,ret;
	int fd;
	
	fd = open("/fpga",O_RDWR,0644);
	if(fd<0)
		{
		printf("open fpga error.\n");
		return ERROR;
		}
		
	ret = ioctl(fd, FPGA_IOCTL_CMD_INT_ENABLE, 0); 
	close(fd);
	return (OK);
}

STATUS fpga_IntEnd(void)
{
	unsigned int buf[16];
	int i,ret;
	int fd;
	
	fd = open("/fpga",O_RDWR,0644);
	if(fd<0)
		{
		printf("open fpga error.\n");
		return ERROR;
		}
		
	ret = ioctl(fd, FPGA_IOCTL_CMD_INT_DISABLE, 0); 
	close(fd);
	return (OK);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值