Hi,
we have a problem with edma3 and mcbsp in a dsp-bios application.
The tdm stream in composed by 64 slot, 8 bit, external clock and frame sync (2.048MHz and 4KHz respectively). Data and FS are posedge aligned with clock
we use CSL in C6455_default_package to configure EDMA and MCBSP.
We started with "edma_ping_pong_xfer_gbl_reg" example, then we added mcbsp configuration and we used dsp bios to manage hw int from edma
we divide each ping-buffer in 64 buffer of 40 byte for each slot
We notice that in transmit direction, the data output of the mcbsp is one slot in advance (so the data of first buffer is trasmitted in the slot before the frame sync, the data of the second buffer is trasmitted in the same slot of FS and so on)
In the receive direction, instead, we have a similar problem but with an opposite effect. The data received form the mcbsp are one slot in later.
this is my toolchain:
CCS 3.3.46.1
BIOS 5.31.02
CSL 03.00.10.02
this is my mcbsp configuration:
/* Receive data setup */
CSL_McbspDataSetup rcvDataCfg = {
CSL_MCBSP_PHASE_SINGLE,
CSL_MCBSP_WORDLEN_8,
64, /* FRMLEN1 */
CSL_MCBSP_WORDLEN_8, /* Default value for phase2*/
0, /* FRMLEN2 */
CSL_MCBSP_FRMSYNC_IGNORE,
//CSL_MCBSP_FRMSYNC_DETECT,
CSL_MCBSP_COMPAND_OFF_MSB_FIRST,
CSL_MCBSP_DATADELAY_0_BIT,
CSL_MCBSP_RJUSTDXENA_RJUST_RZF,
CSL_MCBSP_INTMODE_ON_FSYNC,
//CSL_MCBSP_INTMODE_ON_READY,
CSL_MCBSP_32BIT_REVERS_DISABLE
};
/* Transmit data setup */
CSL_McbspDataSetup xmtDataCfg = {
CSL_MCBSP_PHASE_SINGLE,
CSL_MCBSP_WORDLEN_8,
64, /* FRMLEN1 */
CSL_MCBSP_WORDLEN_8, /* Default value */
0, /* FRMLEN2 */
CSL_MCBSP_FRMSYNC_IGNORE,
//CSL_MCBSP_FRMSYNC_DETECT,
CSL_MCBSP_COMPAND_OFF_MSB_FIRST,
CSL_MCBSP_DATADELAY_0_BIT,
CSL_MCBSP_RJUSTDXENA_DXENA_OFF,
CSL_MCBSP_INTMODE_ON_FSYNC,
//CSL_MCBSP_INTMODE_ON_READY,
CSL_MCBSP_32BIT_REVERS_DISABLE
};
/* Mcbsp clock setup */
CSL_McbspClkSetup clkCfg = {
CSL_MCBSP_FSCLKMODE_EXTERNAL,//CSL_MCBSP_FSCLKMODE_INTERNAL, /* XMT Frame-sync */
CSL_MCBSP_FSCLKMODE_EXTERNAL,//CSL_MCBSP_FSCLKMODE_INTERNAL, /* RCV Frame-sync */
CSL_MCBSP_TXRXCLKMODE_EXTERNAL,//CSL_MCBSP_TXRXCLKMODE_INTERNAL, /* XMT clock */
CSL_MCBSP_TXRXCLKMODE_EXTERNAL,//CSL_MCBSP_TXRXCLKMODE_INTERNAL, /* RCV clock */
CSL_MCBSP_FSPOL_ACTIVE_HIGH, /* XMT Frame-sync Active High */
CSL_MCBSP_FSPOL_ACTIVE_HIGH, /* RCV Frame-sync Active High */
CSL_MCBSP_CLKPOL_TX_RISING_EDGE, /* XMT clock Rising Edge */
CSL_MCBSP_CLKPOL_RX_FALLING_EDGE,/* RCV clock Falling Edge */
1, /* Frame-sync pulse width=2 CLKG periods */
64, /* Frame-sync pulse period = 1024 CLKG periods */
1, /* CLKGDIV = 1 means divide by input clock by 2 */
CSL_MCBSP_SRGCLK_CLKCPU, /* SCLKME = 0, CLKSM = 1 */
CSL_MCBSP_CLKPOL_SRG_RISING_EDGE, /* CLKS pin signal Rising Edge */
CSL_MCBSP_TXFSMODE_DXRCOPY, /* If FSGM = 1, XMT Frame-sync driven by
sample rate generater, FSG signal */
CSL_MCBSP_CLKGSYNCMODE_OFF /* GSYNC = 0 means no clock synchronisation */
};
/* Multichannel setup */
CSL_McbspMulChSetup mulChCfg = {
(CSL_McbspPartMode)CSL_MCBSP_PARTMODE_2PARTITION,
(CSL_McbspPartMode)CSL_MCBSP_PARTMODE_2PARTITION,
(Uint16)0, /* Receive multichannel selection enable */
(Uint16)0, /* Transmit multichannel selection enable */
(CSL_McbspPABlk)CSL_MCBSP_PABLK_0,
(CSL_McbspPBBlk)CSL_MCBSP_PBBLK_1,
(CSL_McbspPABlk)CSL_MCBSP_PABLK_0,
(CSL_McbspPBBlk)CSL_MCBSP_PBBLK_1
};
/* Mcbsp hwsetup */
CSL_McbspHwSetup myHwSetup = {
&gblCfg,
&rcvDataCfg,
&xmtDataCfg,
&clkCfg,
&mulChCfg,
CSL_MCBSP_EMU_FREERUN,
NULL
};
/* Initialize the MCBSP CSL module */
status = CSL_mcbspInit(&pContext);
/* Open the CSL module */
hMcbsp = CSL_mcbspOpen (&mcbspObj, CSL_MCBSP_0, NULL, &status);
/* Program MCBSP control registers */
status = CSL_mcbspHwSetup(hMcbsp, &myHwSetup);
/* Put SRG, Frame-sync, XMT and RCV in reset */
ctrlMask = CSL_MCBSP_CTRL_SRG_DISABLE
| CSL_MCBSP_CTRL_FSYNC_DISABLE
| CSL_MCBSP_CTRL_TX_DISABLE
| CSL_MCBSP_CTRL_RX_DISABLE;
status = CSL_mcbspHwControl(hMcbsp, CSL_MCBSP_CMD_RESET_CONTROL, &ctrlMask);
WAIT_FOR_1_CLK;
this is my edma3 configuration:
#define NUMBYTE 40
#define NUMCHAN 64
#define FRAME_INDEX (-(((NUMCHAN-1)*NUMBYTE)-1))
C64_enableIER(EDMA_INT_FLAG);//HW INT 4
/* Module initialization */
status = CSL_edma3Init(&context);
/* Module level open */
hModule = CSL_edma3Open(&edmaObj,CSL_EDMA3,NULL,&status);
/* Module setup */
dmahwSetup.paramNum = 0;
dmahwSetup.que = CSL_EDMA3_QUE_0;
hwSetup.dmaChaSetup = &dmahwSetup;
hwSetup.qdmaChaSetup = NULL;
status = CSL_edma3HwSetup(hModule,&hwSetup);
/* --- Setup Transmit Channel (McBSP0 transmit, param 12) --- */
/* Channel open */
chAttr.regionNum = CSL_EDMA3_REGION_GLOBAL;
chAttr.chaNum = CSL_EDMA3_CHA_XEVT0;
hChannelXmt = CSL_edma3ChannelOpen(&chObj, CSL_EDMA3, &chAttr, &status);
/* Get Param Handle Basic*/
hParamBasic = CSL_edma3GetParamHandle(hChannelXmt,12,NULL);
/* Get Param Handle Ping*/
hParamPing = CSL_edma3GetParamHandle(hChannelXmt,67,NULL);
/* Get Param Handle Pong*/
hParamPong = CSL_edma3GetParamHandle(hChannelXmt,66,NULL);
/* Set up parameter block 67 as EDMA transmit ping reload */
myParamSetup.option = CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_DIS, \
CSL_EDMA3_TCCH_DIS, \
CSL_EDMA3_ITCINT_DIS, \
CSL_EDMA3_TCINT_EN, \
CSL_EDMA3_CHA_XEVT0,CSL_EDMA3_TCC_NORMAL,\
CSL_EDMA3_FIFOWIDTH_NONE, \
CSL_EDMA3_STATIC_DIS, \
CSL_EDMA3_SYNC_A, \
CSL_EDMA3_ADDRMODE_INCR, \
CSL_EDMA3_ADDRMODE_INCR );
myParamSetup.srcAddr = (Uint32)gBufferXmtPing;
myParamSetup.aCntbCnt = CSL_EDMA3_CNT_MAKE(1,64);
myParamSetup.dstAddr = (Uint32)CSL_MCBSP_0_TX_EDMA_REGS;
myParamSetup.srcDstBidx = CSL_EDMA3_BIDX_MAKE(40,0);
myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(hParamPong,64);
myParamSetup.srcDstCidx = CSL_EDMA3_CIDX_MAKE(FRAME_INDEX,0);
myParamSetup.cCnt = 40;
/* Set up channel and queue relationships */
CSL_edma3HwChannelSetupParam(hChannelXmt, 12);
CSL_edma3HwChannelSetupQue(hChannelXmt, CSL_EDMA3_QUE_1);
status = CSL_edma3ParamSetup(hParamPing,&myParamSetup);
/* Set up parameter block 12 as EDMA transmit (start with copy of ping) */
status = CSL_edma3ParamSetup(hParamBasic,&myParamSetup);
/* Set up parameter block 66 as EDMA transmit pong reload */
myParamSetup.srcAddr = (Uint32)gBufferXmtPong;
myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(hParamPing,64);
status = CSL_edma3ParamSetup(hParamPong,&myParamSetup);
/* --- Setup Receive Chan vnel (McBSP0 receive, param 13) --- */
/* Channel open */
chAttrRcv.regionNum = CSL_EDMA3_REGION_GLOBAL;
chAttrRcv.chaNum = CSL_EDMA3_CHA_REVT0;
hChannelRcv = CSL_edma3ChannelOpen(&chObjRcv, CSL_EDMA3, &chAttrRcv, &status);
/* Get Param Handle Basic*/
hParamBasicRcv = CSL_edma3GetParamHandle(hChannelRcv,13,NULL);
/* Get Param Handle Ping*/
hParamPingRcv = CSL_edma3GetParamHandle(hChannelRcv,65,NULL);
/* Get Param Handle Pong*/
hParamPongRcv = CSL_edma3GetParamHandle(hChannelRcv,64,NULL);
/* Set up parameter block 65 as EDMA transmit ping reload */
myParamSetup.option = CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_DIS, \
CSL_EDMA3_TCCH_DIS, \
CSL_EDMA3_ITCINT_DIS, \
CSL_EDMA3_TCINT_EN, \
CSL_EDMA3_CHA_REVT0,CSL_EDMA3_TCC_NORMAL,\
CSL_EDMA3_FIFOWIDTH_NONE, \
CSL_EDMA3_STATIC_DIS, \
CSL_EDMA3_SYNC_A, \
CSL_EDMA3_ADDRMODE_INCR, \
CSL_EDMA3_ADDRMODE_INCR );
myParamSetup.srcAddr = (Uint32)CSL_MCBSP_0_RX_EDMA_REGS;
myParamSetup.aCntbCnt = CSL_EDMA3_CNT_MAKE(1,64);
myParamSetup.dstAddr = (Uint32)gBufferRcvPing;
myParamSetup.srcDstBidx = CSL_EDMA3_BIDX_MAKE(0,40);
myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(hParamPongRcv,64);
myParamSetup.srcDstCidx = CSL_EDMA3_CIDX_MAKE(0, FRAME_INDEX);
myParamSetup.cCnt = 40;
/* Set up channel and queue relationships */
CSL_edma3HwChannelSetupParam(hChannelRcv, 13);
CSL_edma3HwChannelSetupQue(hChannelRcv, CSL_EDMA3_QUE_1);
status = CSL_edma3ParamSetup(hParamPingRcv,&myParamSetup);
/* Set up parameter block 13 as EDMA receive (start with copy of ping) */
status = CSL_edma3ParamSetup(hParamBasicRcv,&myParamSetup);
/* Set up parameter block 64 as EDMA receive pong reload */
myParamSetup.dstAddr = (Uint32)gBufferRcvPong;
myParamSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAKE(hParamPingRcv,64);
status = CSL_edma3ParamSetup(hParamPongRcv,&myParamSetup);
/* Interrupt enable for the global region interrupts */
regionIntr.region = CSL_EDMA3_REGION_GLOBAL ;
regionIntr.intr = 0x3000 ;
regionIntr.intrh = 0x0000 ;
CSL_edma3HwControl(hModule,CSL_EDMA3_CMD_INTR_ENABLE,®ionIntr);
/* Transmit event clear and enable */
CSL_edma3HwChannelControl(hChannelXmt,CSL_EDMA3_CMD_CHANNEL_CLEAR,NULL);
CSL_edma3HwChannelControl(hChannelXmt,CSL_EDMA3_CMD_CHANNEL_ENABLE,NULL);
/* Receive event clear and enable */
CSL_edma3HwChannelControl(hChannelRcv,CSL_EDMA3_CMD_CHANNEL_CLEAR,NULL);
CSL_edma3HwChannelControl(hChannelRcv,CSL_EDMA3_CMD_CHANNEL_ENABLE,NULL);
/* Clear CPU interrupt event 24 (EVTCLR0) */
*((Uint32*)0x1800040) = 0x01000000;
/* Enable CPU interrupt event 24 (EVTMASK0) */
*((Uint32*)0x1800080) = 0x01000000;
/* clear the error registers */
chErrClear.missed = TRUE;
chErrClear.secEvt = TRUE;
CSL_edma3HwChannelControl (hChannelXmt, CSL_EDMA3_CMD_CHANNEL_CLEARERR, &chErrClear);
CSL_edma3HwChannelControl (hChannelRcv, CSL_EDMA3_CMD_CHANNEL_CLEARERR, &chErrClear);
/* Trigger Channel */
CSL_edma3HwChannelControl(hChannelXmt,CSL_EDMA3_CMD_CHANNEL_SET,NULL);
CSL_edma3HwChannelControl(hChannelRcv,CSL_EDMA3_CMD_CHANNEL_SET,NULL);
at the end, re-enable int e start mcbsp:
/* Re-enable global interrupts */
HWI_enable();
/* Enable MCBSP0 transmit and receive */
ctrlMask = CSL_MCBSP_CTRL_TX_ENABLE | CSL_MCBSP_CTRL_RX_ENABLE;
CSL_mcbspHwControl(hMcbsp, CSL_MCBSP_CMD_RESET_CONTROL, &ctrlMask);
this is the routine for EDMA interrupt called by BIOS:
void edmaHwi(void)
{
Uint32 intr, j;
static Uint32 pingOrPong = PING;
static Int16 xmtdone = 0, rcvdone = 0;
Bool gpioEn;
/* Check for pending EDMA event interrupts (IPR) */
intr = *((Uint32*)0x02a01068);
if (intr & 0x1000)
{
xmtdone = 1;
}
if (intr & 0x2000)
{
rcvdone = 1;
}
if (xmtdone && rcvdone)
{
if (pingOrPong == PING)
{
pingOrPong = PONG;
SWI_or(&processBufferSwi, PING);
}
else
{
pingOrPong = PING;
SWI_or(&processBufferSwi, PONG);
}
rcvdone = 0;
xmtdone = 0;
}
/* Clear CPU interrupt event 24 (EVTCLR0) */
*((Uint32*)0x1800040) = 0x01000000;
/* Clear processed EDMA event interrupts (ICR) */
*((Uint32*)0x02a01070) = intr;
}