我看了一个C55XX系列的DSP的DMA配置成ping-pong模式的例子,设置断点进行调试,理论上应该是先是ping,后是pong交替进行,但是在调试的时候并不是交替的,只有第一次是的,后面总是好几次pong后在是ping,要么就是好几次ping后再是pong,请问这是什么原因呢?请问还有没有相关的DMAping-pong的例子,有没有那种不是CSL编写的,谢谢!
Tony Tang:
Chunhua,
下面是我几年前做的C55的DMA的PING-PONG的例子,我想可以根据其大体思路对比看看你的程序的问题在哪吧。
#pragma DATA_ALIGN(gBufferRcvPing,128);#pragma DATA_ALIGN(gBufferRcvPong,128);#pragma DATA_ALIGN(gBufferXmtPing,128);#pragma DATA_ALIGN(gBufferXmtPong,128);#pragma DATA_ALIGN(gBufferXmtPingMic,128);#pragma DATA_ALIGN(gBufferXmtPongMic,128);
#pragma DATA_SECTION(gBufferRcvPing, ".gBufferRcvPing");#pragma DATA_SECTION(gBufferRcvPong, ".gBufferRcvPong");#pragma DATA_SECTION(gBufferXmtPing, ".gBufferXmtPing");#pragma DATA_SECTION(gBufferXmtPong, ".gBufferXmtPong");#pragma DATA_SECTION(gBufferXmtPingMic, ".gBufferXmtPingMic");#pragma DATA_SECTION(gBufferXmtPongMic, ".gBufferXmtPongMic"); short gBufferRcvPing[BUFFSIZE];short gBufferRcvPong[BUFFSIZE];short gBufferXmtPing[BUFFSIZE];short gBufferXmtPong[BUFFSIZE];short gBufferXmtPingMic[BUFFSIZE];short gBufferXmtPongMic[BUFFSIZE];
Uint16 eventIdRcv;Uint16 eventIdXmt;Uint16 eventIdXmtMic;
DMA_Handle hDmaXmt;DMA_Handle hDmaRcv;DMA_Handle hDmaXmtMic;
int pingOrPong = PING;int pingorpong = PING;int pingorpongMic = PING;Uint32 addr;Uint32 xmt_addr;Uint32 xmtmic_addr;ptr_MessageStr* ptr_Me;
RING_ID rdBuf;RING_ID rdBufMic;short *buffer;short *bufferMic;
DMA_Config gDmaConfigXmt = { DMA_DMACSDP_RMK( DMA_DMACSDP_DSTBEN_NOBURST, DMA_DMACSDP_DSTPACK_OFF, DMA_DMACSDP_DST_PERIPH, DMA_DMACSDP_SRCBEN_NOBURST, DMA_DMACSDP_SRCPACK_OFF, DMA_DMACSDP_SRC_DARAM, DMA_DMACSDP_DATATYPE_16BIT ), /* Source/Destination Register – DMACSDP */ DMA_DMACCR_RMK( DMA_DMACCR_DSTAMODE_CONST, DMA_DMACCR_SRCAMODE_POSTINC, DMA_DMACCR_ENDPROG_OFF, DMA_DMACCR_REPEAT_ALWAYS, DMA_DMACCR_AUTOINIT_ON, DMA_DMACCR_EN_STOP, DMA_DMACCR_PRIO_HI, DMA_DMACCR_FS_DISABLE, DMA_DMACCR_SYNC_XEVT1 ), /* Control Register – DMACCR */ DMA_DMACICR_RMK( DMA_DMACICR_BLOCKIE_ON, DMA_DMACICR_LASTIE_OFF, DMA_DMACICR_FRAMEIE_OFF, DMA_DMACICR_FIRSTHALFIE_OFF, DMA_DMACICR_DROPIE_OFF, DMA_DMACICR_TIMEOUTIE_OFF ), /* Interrupt Control Register – DMACICR */ 0, /* Lower Source Address – DMACSSAL */ 0, /* Upper Source Address – DMACSSAU */ 0, /* Lower Destination Address – DMACDSAL */ 0, /* Upper Destination Address – DMACDSAU */ BUFFSIZE, /* Element Number – DMACEN */ 1, /* Frame Number – DMACFN */ 0, /* Frame Index – DMACFI */ 0 /* Element Index – DMACEI */};
DMA_Config gDmaConfigRcv = { DMA_DMACSDP_RMK( DMA_DMACSDP_DSTBEN_NOBURST, DMA_DMACSDP_DSTPACK_OFF, DMA_DMACSDP_DST_DARAM, //OK DMA_DMACSDP_SRCBEN_NOBURST, //OK DMA_DMACSDP_SRCPACK_OFF, //OK DMA_DMACSDP_SRC_PERIPH, //OK DMA_DMACSDP_DATATYPE_16BIT //OK ), /* Source/Destination Register – DMACSDP */ DMA_DMACCR_RMK( DMA_DMACCR_DSTAMODE_POSTINC, DMA_DMACCR_SRCAMODE_CONST, DMA_DMACCR_ENDPROG_OFF, DMA_DMACCR_REPEAT_ALWAYS, DMA_DMACCR_AUTOINIT_ON, DMA_DMACCR_EN_STOP, DMA_DMACCR_PRIO_HI, DMA_DMACCR_FS_DISABLE, DMA_DMACCR_SYNC_REVT0 ), /* Control Register – DMACCR */ DMA_DMACICR_RMK( DMA_DMACICR_BLOCKIE_OFF, DMA_DMACICR_LASTIE_OFF, DMA_DMACICR_FRAMEIE_ON, DMA_DMACICR_FIRSTHALFIE_OFF, DMA_DMACICR_DROPIE_OFF, DMA_DMACICR_TIMEOUTIE_OFF ), /* Interrupt Control Register – DMACICR */ 0, /* Lower Source Address – DMACSSAL */ 0, /* Upper Source Address – DMACSSAU */ 0, /* Lower Destination Address – DMACDSAL */ 0, /* Upper Destination Address – DMACDSAU */ BUFFSIZE, /* Element Number – DMACEN */ 1, /* Frame Number – DMACFN */ 0, /* Frame Index – DMACFI */ 0 /* Element Index – DMACEI */};
DMA_Config gDmaConfigXmtMic = { DMA_DMACSDP_RMK( DMA_DMACSDP_DSTBEN_NOBURST, DMA_DMACSDP_DSTPACK_OFF, DMA_DMACSDP_DST_PERIPH, DMA_DMACSDP_SRCBEN_NOBURST, DMA_DMACSDP_SRCPACK_OFF, DMA_DMACSDP_SRC_DARAM, DMA_DMACSDP_DATATYPE_16BIT ), /* Source/Destination Register – DMACSDP */ DMA_DMACCR_RMK( DMA_DMACCR_DSTAMODE_CONST, DMA_DMACCR_SRCAMODE_POSTINC, DMA_DMACCR_ENDPROG_OFF, DMA_DMACCR_REPEAT_ALWAYS, DMA_DMACCR_AUTOINIT_ON, DMA_DMACCR_EN_STOP, DMA_DMACCR_PRIO_HI, DMA_DMACCR_FS_DISABLE, DMA_DMACCR_SYNC_XEVT0 ), /* Control Register – DMACCR */ DMA_DMACICR_RMK( DMA_DMACICR_BLOCKIE_ON, DMA_DMACICR_LASTIE_OFF, DMA_DMACICR_FRAMEIE_OFF, DMA_DMACICR_FIRSTHALFIE_OFF, DMA_DMACICR_DROPIE_OFF, DMA_DMACICR_TIMEOUTIE_OFF ), /* Interrupt Control Register – DMACICR */ 0, /* Lower Source Address – DMACSSAL */ 0, /* Upper Source Address – DMACSSAU */ 0, /* Lower Destination Address – DMACDSAL */ 0, /* Upper Destination Address – DMACDSAU */ BUFFSIZE, /* Element Number – DMACEN */ 1, /* Frame Number – DMACFN */ 0, /* Frame Index – DMACFI */ 0 /* Element Index – DMACEI */};
void initDma(){
ptr_Me = (ptr_MessageStr*)0xc0; buffer = (short*)0x1300; bufferMic = (short*)0x1400; // Open DMA channels hDmaXmt = DMA_open(0,DMA_OPEN_RESET); hDmaRcv = DMA_open(1,DMA_OPEN_RESET); hDmaXmtMic = DMA_open(2,DMA_OPEN_RESET); /* By default, the TMS320C55xx compiler assigns all data symbols word */ /* addresses. The DMA however, expects all addresses to be byte */ /* addresses. Therefore, we must shift the address in order to */ /* change the word address to a byte address for the DMA transfer. */ gDmaConfigXmt.dmacssal = (DMA_AdrPtr)(((Uint32)(&gBufferXmtPing)<<1)&0x00FFFF); /* Lower Source Address */ gDmaConfigXmt.dmacssau = (Uint16)((((Uint32)(&gBufferXmtPing)<<1)&0xFF0000) >> 16); /* Upper Source Address */
gDmaConfigXmt.dmacdsal = (DMA_AdrPtr)(((Uint32)(&_MCBSP_DXR11)<<1)&0x00FFFF); /* Lower Destination Address */ gDmaConfigXmt.dmacdsau = (Uint16)((((Uint32)(&_MCBSP_DXR11)<<1)&0xFF0000) >> 16); /* Upper Destination Address */ // Receive gDmaConfigRcv.dmacssal = (DMA_AdrPtr)(((Uint32)(&_MCBSP_DRR10)<<1)&0x00FFFF); /* Lower Source Address */ gDmaConfigRcv.dmacssau = (Uint16)((((Uint32)(&_MCBSP_DRR10)<<1)&0xFF0000) >> 16); /* Upper Source Address */
gDmaConfigRcv.dmacdsal = (DMA_AdrPtr)(((Uint32)(&gBufferRcvPing)<<1)&0x00FFFF); /* Lower Destination Address */ gDmaConfigRcv.dmacdsau = (Uint16)((((Uint32)(&gBufferRcvPing)<<1)&0xFF0000) >> 16); /* Upper Destination Address */
gDmaConfigXmtMic.dmacssal = (DMA_AdrPtr)(((Uint32)(&gBufferXmtPingMic)<<1)&0x00FFFF); /* Lower Source Address */ gDmaConfigXmtMic.dmacssau = (Uint16)((((Uint32)(&gBufferXmtPingMic)<<1)&0xFF0000) >> 16); /* Upper Source Address */
gDmaConfigXmtMic.dmacdsal = (DMA_AdrPtr)(((Uint32)(&_MCBSP_DXR10)<<1)&0x00FFFF); /* Lower Destination Address */ gDmaConfigXmtMic.dmacdsau = (Uint16)((((Uint32)(&_MCBSP_DXR10)<<1)&0xFF0000) >> 16); /* Upper Destination Address */
// Write values from DMA config structure to DMA channel control registers DMA_config(hDmaXmt, &gDmaConfigXmt); DMA_config(hDmaRcv, &gDmaConfigRcv); DMA_config(hDmaXmtMic,&gDmaConfigXmtMic); rdBuf = rngCreate(BUFFSIZE*10); if(!rdBuf) LOG_printf(&TestLOG, "rngCreate err!"); rngFlush (rdBuf); rdBufMic = rngCreate(BUFFSIZE*10); if(!rdBufMic) LOG_printf(&TestLOG, "rngMicCreate err!"); rngFlush (rdBufMic);} void processBuffer(void){ short pingPong;// Int16 switch2; // Read DIP switch 2// switch2 = DSK5510_DIP_get(2); // Get mailbox value pingPong = SWI_getmbox(); // Determine current pingPong state if(pingPong==PING){
ptr_Me->rcv_flag = 0x5555; CHIP_FSET(ST3_55, HINT, 0); CHIP_FSET(ST3_55, HINT, 1);
// copyData(gBufferRcvPing, gBufferXmtPing, BUFFSIZE);
// copyData(gBufferRcvPing, buffer, BUFFSIZE); // Reprogram config regs for PingL addr = ((Uint32)gBufferRcvPing) << 1; DMA_RSETH(hDmaRcv, DMACDSAL, addr & 0xffff); DMA_RSETH(hDmaRcv, DMACDSAU, (addr >> 16) & 0xffff);/* addr = ((Uint32)gBufferXmtPing) << 1; DMA_RSETH(hDmaXmt, DMACSSAL, addr & 0xffff); DMA_RSETH(hDmaXmt, DMACSSAU, (addr >> 16) & 0xffff); */ //LOG_printf(&TestLOG, "PING"); } else{ ptr_Me->rcv_flag = 0xaaaa; CHIP_FSET(ST3_55, HINT, 0); CHIP_FSET(ST3_55, HINT, 1);// copyData(gBufferRcvPong, gBufferXmtPong, BUFFSIZE);// copyData(gBufferRcvPing, buffer+BUFFSIZE, BUFFSIZE); // Reprogram config regs for PongL addr = ((Uint32)gBufferRcvPong) << 1; DMA_RSETH(hDmaRcv, DMACDSAL, addr & 0xffff); DMA_RSETH(hDmaRcv, DMACDSAU, (addr >> 16) & 0xffff);/* addr = ((Uint32)gBufferXmtPong) << 1; DMA_RSETH(hDmaXmt, DMACSSAL, addr & 0xffff); DMA_RSETH(hDmaXmt, DMACSSAU, (addr >> 16) & 0xffff); */ //LOG_printf(&TestLOG, "PONG"); }}
void dmaHwi(void){ // Read the DMA status registers to clear it so new interrupts will be seen DMA_RGETH(hDmaRcv, DMACSR); // Determine if current state is PING or PONG if(pingOrPong==PING){ // Post SWI thread to process PING data SWI_or(&processBufferSwi, PING); pingOrPong = PONG; } else{ // Post SWI thread to process PONG data SWI_or(&processBufferSwi, PONG); pingOrPong = PING; }}
void XmtprocessBuffer(void){ short pingPong; pingPong = SWI_getmbox(); if(pingPong==PING) { // DMA_start(hDmaXmt); if(!rngIsEmpty(rdBuf)) { rngBufGet(rdBuf,gBufferXmtPing,BUFFSIZE); } else LOG_printf(&TestLOG, "rng buf is empty!"); // DMA_RSETH(hDmaXmt,DMACEN,(Uint16)ptr_Me->xmt_length); xmt_addr = ((Uint32)gBufferXmtPing) << 1; DMA_RSETH(hDmaXmt, DMACSSAL, xmt_addr & 0xffff); DMA_RSETH(hDmaXmt, DMACSSAU, (xmt_addr >> 16) & 0xffff); // DMA_start(hDmaXmt); } else { // DMA_start(hDmaXmt); if(!rngIsEmpty(rdBuf)) { rngBufGet(rdBuf,gBufferXmtPong,BUFFSIZE); } else LOG_printf(&TestLOG, "rng buf is empty!"); // DMA_RSETH(hDmaXmt,DMACEN,(Uint16)ptr_Me->xmt_length); xmt_addr = ((Uint32)gBufferXmtPong) << 1; DMA_RSETH(hDmaXmt, DMACSSAL, xmt_addr & 0xffff); DMA_RSETH(hDmaXmt, DMACSSAU, (xmt_addr >> 16) & 0xffff); // DMA_start(hDmaXmt); }}
void XmtprocessBufferMic(void){ short pingPong; pingPong = SWI_getmbox(); if(pingPong==PING) { // DMA_start(hDmaXmt); if(!rngIsEmpty(rdBufMic)) rngBufGet(rdBufMic,gBufferXmtPingMic,BUFFSIZE); else LOG_printf(&TestLOG, "rng buf is empty!"); // DMA_RSETH(hDmaXmt,DMACEN,(Uint16)ptr_Me->xmt_length); xmtmic_addr = ((Uint32)gBufferXmtPingMic) << 1; DMA_RSETH(hDmaXmtMic, DMACSSAL, xmtmic_addr & 0xffff); DMA_RSETH(hDmaXmtMic, DMACSSAU, (xmtmic_addr >> 16) & 0xffff); // DMA_start(hDmaXmt); } else { // DMA_start(hDmaXmt); if(!rngIsEmpty(rdBufMic)) rngBufGet(rdBufMic,gBufferXmtPongMic,BUFFSIZE); else LOG_printf(&TestLOG, "rng buf is empty!"); // DMA_RSETH(hDmaXmt,DMACEN,(Uint16)ptr_Me->xmt_length); xmtmic_addr = ((Uint32)gBufferXmtPongMic) << 1; DMA_RSETH(hDmaXmtMic, DMACSSAL, xmtmic_addr & 0xffff); DMA_RSETH(hDmaXmtMic, DMACSSAU, (xmtmic_addr >> 16) & 0xffff); // DMA_start(hDmaXmt); }}
void hpiHwi(void){ if(!rngIsFull(rdBufMic)) { rngBufPut(rdBufMic,buffer,BUFFSIZE); // LOG_printf(&TestLOG, "hpHwi %d\n", rngNBytes(rdBufMic)); } else LOG_printf(&TestLOG, "rng buf is full!\n");
if(!rngIsFull(rdBuf)) { rngBufPut(rdBuf,buffer,BUFFSIZE); // LOG_printf(&TestLOG, "hpHwi %d\n", rngNBytes(rdBuf)); } else LOG_printf(&TestLOG, "rng buf is full!\n");}
void dmaXmtHwi(void){ DMA_RGETH(hDmaXmt, DMACSR); if(pingorpong==PING){ // Post SWI thread to process PING data SWI_or(&XmtprocessBufferSwi, PING); pingorpong = PONG; } else{ // Post SWI thread to process PONG data SWI_or(&XmtprocessBufferSwi, PONG); pingorpong = PING; }}
void dmaXmtMicHwi(void){ DMA_RGETH(hDmaXmtMic, DMACSR); if(pingorpongMic==PING){ // Post SWI thread to process PING data SWI_or(&XmtprocessBufferMicSwi, PING); pingorpongMic = PONG; } else{ // Post SWI thread to process PONG data SWI_or(&XmtprocessBufferMicSwi, PONG); pingorpongMic = PING; }}