下面是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);
}
MPC8377_dma的驱动程序
最新推荐文章于 2026-06-13 16:31:27 发布
本文介绍了一个针对 MPC8377 核心 CPU 板的 DMA (直接内存访问) 驱动程序实现细节。该驱动程序支持 VxWorks 6.6 操作系统,并通过 FPGA 进行数据传输。文中详细描述了 DMA 控制器的初始化过程、DMA 读写操作、中断处理以及 FPGA 的配置方法。

1257

被折叠的 条评论
为什么被折叠?



