I'm sure that I will recognize this as a "Doh!" question when I find the answer... I am unable to get the EDMA3 to respond to MCASP transmit events in my 6424 application.
I have MCASP0 configured for 4 output serializers, transmitting 16-bit data padded to 32-bits in I2S output format. The EDMA3 should constantly dump the contents of 4 sets of ping-pong buffers to the 4 serializers, using 2 linked parameter RAM sets.
My setup code is below, but the flow is
- Place MCASP0 in reset
- Configure MCASP0
- Request the MCASP0 XEVT EDMA3 channel
- Request a link channel
- Configure the parameter RAM sets and link them to each other
- Enable the EDMA3 transfer with an event trigger
- Take MCASP0 out of reset
After this, I see that the MCASP clocks are configured as I want them, the parameter RAM entries for the XEVT0 channel (12) and the link channel (64) look correct, and I see CH12 enabled in the EER, and TCC 12 enabled in the IER. In MCASP0 XSTAT, I see XDATA = 1, which should generate an EDMA3 sync event. What I don't see are any EDMA3 transfers from RAM to the MCASP :(.
QDMA transfers are working, so I think all the EDMA3 LLD configuration structures are OK.
Like I said, I'm sure the problem is obvious, but I have obviously overlooked it. Any help would be appreciated.
The setup portion of my code follows:
// set up MCASP0
// First, reset the peripheral
mcasp0Regs->GBLCTL = 0L; // 0 is reset default, resets everything
// Set the pin directions
mcasp0Regs->PDIR = CSL_FMKT( MCASP_PDIR_AFSX, OUTPUT )
| CSL_FMKT( MCASP_PDIR_ACLKX, OUTPUT )
| CSL_FMKT( MCASP_PDIR_AXR3, OUTPUT )
| CSL_FMKT( MCASP_PDIR_AXR2, OUTPUT )
| CSL_FMKT( MCASP_PDIR_AXR1, OUTPUT )
| CSL_FMKT( MCASP_PDIR_AXR0, OUTPUT );
mcasp0Regs->XMASK = 0xFFFF; // MPEG2 decoder puts out 16-bit samples
// Transmit bit stream format Register (XFMT)
mcasp0Regs->XFMT = CSL_FMKT( MCASP_XFMT_XDATDLY, 0BIT )
| CSL_FMKT( MCASP_XFMT_XRVRS, MSBFIRST )
| CSL_FMKT( MCASP_XFMT_XSSZ, 32BITS )
| CSL_FMKT( MCASP_XFMT_XBUSEL, VBUSP )
| CSL_FMKT( MCASP_XFMT_XROT, 16BITS );
// Transmit Frame Sync Control Register (AFSXCTL)
mcasp0Regs->AFSXCTL = CSL_FMK( MCASP_AFSXCTL_XMOD, 2 ) // TDM mode
| CSL_FMKT( MCASP_AFSXCTL_FXWID, WORD )
| CSL_FMKT( MCASP_AFSXCTL_FSXM, INTERNAL );
// Transmit clock control register (ACLKXCTL)
mcasp0Regs->ACLKXCTL = CSL_FMKT( MCASP_ACLKXCTL_CLKXP, RISING )
| CSL_FMKT( MCASP_ACLKXCTL_ASYNC, ASYNC )
| CSL_FMKT( MCASP_ACLKXCTL_CLKXM, INTERNAL )
| CSL_FMK( MCASP_ACLKXCTL_CLKXDIV, 9 );
// MCASP bit clock is (SYSCLK3/(AHCLKDIV+1))/(CLKDIV+1)
// Configure MCASP bit clock for 3.3 MHz
// Transmit HF Clock Control Register (AHCLKXCTL)
// AHCLKX (and AHCLKR) must be < 40 MHz
// AHCLKX = SYSCLK3/(AHCLKXDIV+1)
mcasp0Regs->AHCLKXCTL = CSL_FMKT( MCASP_AHCLKXCTL_HCLKXM, INTERNAL )
| CSL_FMKT( MCASP_AHCLKXCTL_HCLKXP, RISING )
| CSL_FMK( MCASP_AHCLKXCTL_HCLKXDIV, 2 );
// AHCLK will be 33 MHz for SYSCLK1 = 594 MHz
// // Transmitter DMA Event Control Register (XEVCTL)
// mcasp0Regs->XEVTCTL = CSL_FMKT( MCASP_XEVTCTL_XDATDMA, ENABLE );
// // default value
mcasp0Regs->XINTCTL = CSL_FMKT( MCASP_XINTCTL_XDATA, ENABLE );
// Serializer control registers 0-3
CSL_FINST( mcasp0Regs->SRCTL0, MCASP_SRCTL0_SRMOD, INACTIVE );
CSL_FINST( mcasp0Regs->SRCTL1, MCASP_SRCTL1_SRMOD, INACTIVE );
CSL_FINST( mcasp0Regs->SRCTL2, MCASP_SRCTL2_SRMOD, INACTIVE );
CSL_FINST( mcasp0Regs->SRCTL3, MCASP_SRCTL3_SRMOD, INACTIVE );
// Request the MCBSP1 TX EDMA channel
edmaAudioOutChPing = EDMA3_DRV_HW_CHANNEL_MCASP0_TX;
// Also a link channel - get a link PaRAM set
edmaAudioOutChPong = EDMA3_DRV_LINK_CHANNEL;
// Request the ping channel first
edma3Result = EDMA3_DRV_requestChannel( hEdma, &edmaAudioOutChPing, &edmaTccPing,
(EDMA3_RM_EventQueue)1, &callback2, NULL );
if( edma3Result != EDMA3_DRV_SOK )
{
LOG_printf( &LOG_User, "EDMA3_DRV_requestChannel failed: %d",
edma3Result );
goto end;
}
// Request the link channel
edma3Result = EDMA3_DRV_requestChannel( hEdma, &edmaAudioOutChPong, &edmaTccPong,
(EDMA3_RM_EventQueue)0, &callback2, NULL );
// Configure the EDMA3 channels
// First, initialize structures in RAM to contain the configuration
// Channel options are the same for the primary and the link channel
// except for the TCC value
// channel options are:
// no chaining
// no intermediate transfer complete interrupt
// interrupt on transfer complete
// normal TC interrupt (not early)
// 32-bit output fifo
// parameter set isn't static
// use AB synchronization
// increment dest address across MCASP XBUFn
// increment source address
edma3PaRAMValsPing.OPT = CSL_FMKT( EDMA3CC_OPT_ITCCHEN, DISABLE )
| CSL_FMKT( EDMA3CC_OPT_TCCHEN, DISABLE )
| CSL_FMKT( EDMA3CC_OPT_ITCINTEN, DISABLE )
| CSL_FMKT( EDMA3CC_OPT_TCINTEN, ENABLE )
| CSL_FMK( EDMA3CC_OPT_TCC, edmaTccPing )
| CSL_FMKT( EDMA3CC_OPT_TCCMOD, NORMAL )
| CSL_FMKT( EDMA3CC_OPT_FWID, RESETVAL )
| CSL_FMKT( EDMA3CC_OPT_STATIC, NORMAL )
| CSL_FMKT( EDMA3CC_OPT_SYNCDIM, ABSYNC )
| CSL_FMKT( EDMA3CC_OPT_DAM, CONST )
| CSL_FMKT( EDMA3CC_OPT_SAM, INCR );
edma3PaRAMValsPong.OPT = CSL_FMKT( EDMA3CC_OPT_ITCCHEN, DISABLE )
| CSL_FMKT( EDMA3CC_OPT_TCCHEN, DISABLE )
| CSL_FMKT( EDMA3CC_OPT_ITCINTEN, DISABLE )
| CSL_FMKT( EDMA3CC_OPT_TCINTEN, ENABLE )
| CSL_FMK( EDMA3CC_OPT_TCC, edmaTccPong )
| CSL_FMKT( EDMA3CC_OPT_TCCMOD, NORMAL )
| CSL_FMKT( EDMA3CC_OPT_FWID, RESETVAL )
| CSL_FMKT( EDMA3CC_OPT_STATIC, NORMAL )
| CSL_FMKT( EDMA3CC_OPT_SYNCDIM, ABSYNC )
| CSL_FMKT( EDMA3CC_OPT_DAM, CONST )
| CSL_FMKT( EDMA3CC_OPT_SAM, INCR );
// Set the starting address for the transfers
// this starts with the PING buffer
edma3PaRAMValsPing.SRC = ( Uint32 )&output0SyncPing;
// This one starts with the PONG buffer
edma3PaRAMValsPong.SRC = ( Uint32 )&output0SyncPong;
// Each MCASP EDMA transmit event moves 2 bytes per channel (ACNT)
// for each of 4 channels (BCNT)
edma3PaRAMValsPing.A_B_CNT = CSL_FMK( EDMA3CC_A_B_CNT_ACNT, 2 )
| CSL_FMK( EDMA3CC_A_B_CNT_BCNT, 4 );
edma3PaRAMValsPong.A_B_CNT = edma3PaRAMValsPing.A_B_CNT;
// Transfer starts with MCASP0_XBUF0
edma3PaRAMValsPing.DST = CSL_MCASP_TXBUF_ADDR;
edma3PaRAMValsPong.DST = CSL_MCASP_TXBUF_ADDR;
// source and destination B indices
// These are the distance in bytes between the start of
// B-dimension transfers
edma3PaRAMValsPing.SRC_DST_BIDX =
CSL_FMK( EDMA3CC_SRC_DST_BIDX_DSTBIDX, 0 )
| CSL_FMK( EDMA3CC_SRC_DST_BIDX_SRCBIDX,
(Uint16)(sizeof( tAudioSync ) + sizeof( output0BufferPing )));
edma3PaRAMValsPong.SRC_DST_BIDX = edma3PaRAMValsPing.SRC_DST_BIDX;
// Get the physical address of the PING parameter RAM set
edma3Result = EDMA3_DRV_getPaRAMPhyAddr( hEdma, edmaAudioOutChPing,
&paRAMSetPingAddress );
if( edma3Result != EDMA3_DRV_SOK )
{
LOG_printf( &LOG_User, "Getting PING paRAM address failed, %d",
edma3Result );
goto end;
}
// Get the physical address of the PONG parameter RAM set
edma3Result = EDMA3_DRV_getPaRAMPhyAddr( hEdma, edmaAudioOutChPong,
&paRAMSetPongAddress );
if( edma3Result != EDMA3_DRV_SOK )
{
LOG_printf( &LOG_User, "Getting PONG paRAM address failed, %d",
edma3Result );
goto end;
}
// Link the PARAM sets - PING to PONG, PONG to PING
edma3PaRAMValsPing.LINK_BCNTRLD = CSL_FMK( EDMA3CC_LINK_BCNTRLD_BCNTRLD, 4 )
| CSL_FMK( EDMA3CC_LINK_BCNTRLD_LINK, (Uint16)paRAMSetPongAddress );
edma3PaRAMValsPong.LINK_BCNTRLD = CSL_FMK( EDMA3CC_LINK_BCNTRLD_BCNTRLD, 4 )
| CSL_FMK( EDMA3CC_LINK_BCNTRLD_LINK, (Uint16)paRAMSetPingAddress );
// Set the source and destination C indices
// C index is the distance between the beginning of consecutive frames
// in the AB synchronized transfer
edma3PaRAMValsPing.SRC_DST_CIDX = CSL_FMK( EDMA3CC_SRC_DST_CIDX_SRCCIDX, 4 )
| CSL_FMK( EDMA3CC_SRC_DST_CIDX_DSTCIDX, 0 );
edma3PaRAMValsPong.SRC_DST_CIDX = edma3PaRAMValsPing.SRC_DST_CIDX;
edma3PaRAMValsPing.CCNT = ((( FRAME_LEN * MAX_CHANNELS)/sizeof(CT_int16))
+ (( sizeof( tAudioSync )/sizeof( Uint16 ))));
edma3PaRAMValsPong.CCNT = edma3PaRAMValsPing.CCNT;
LOG_printf( &LOG_User, "EDMA3_DRV_requestChannel succeeded." );
// Now, configure the actual EDMA PARAM sets
edma3Result = EDMA3_DRV_setPaRAM( hEdma, edmaAudioOutChPing,
( const EDMA3_DRV_PaRAMRegs *)&edma3PaRAMValsPing );
if( edma3Result != EDMA3_DRV_SOK )
{
LOG_printf( &LOG_User, "Configuring PING PARAM failed, %d",
edma3Result );
goto end;
}
edma3Result = EDMA3_DRV_setPaRAM( hEdma, edmaAudioOutChPong,
( EDMA3_DRV_PaRAMRegs *)&edma3PaRAMValsPong );
if( edma3Result != EDMA3_DRV_SOK )
{
LOG_printf( &LOG_User, "Configuring PONG PARAM failed, %d",
edma3Result );
goto end;
}
// Link the two parameter sets to each other
edma3Result = EDMA3_DRV_linkChannel( hEdma,
edmaAudioOutChPing,
edmaAudioOutChPong );
if( edma3Result != EDMA3_DRV_SOK )
{
LOG_printf( &LOG_User, "Linking PONG to PING failed, %d",
edma3Result );
goto end;
}
edma3Result = EDMA3_DRV_linkChannel( hEdma,
edmaAudioOutChPong,
edmaAudioOutChPing );
if( edma3Result != EDMA3_DRV_SOK )
{
LOG_printf( &LOG_User, "Linking PING to PONG failed, %d",
edma3Result );
goto end;
}
// Clear any error flags from XSTAT
mcasp0Regs->XSTAT = CSL_FMKT( MCASP_XSTAT_XERR, ERROR )
| CSL_FMKT( MCASP_XSTAT_XDMAERR, ERROR )
| CSL_FMKT( MCASP_XSTAT_XSTAFRM, YES )
| CSL_FMKT( MCASP_XSTAT_XDATA, YES )
| CSL_FMKT( MCASP_XSTAT_XCKFAIL,YES )
| CSL_FMKT( MCASP_XSTAT_XSYNCERR, YES )
| CSL_FMKT( MCASP_XSTAT_XUNDRN, YES );
EDMA3_DRV_enableTransfer( hEdma, edmaAudioOutChPing, EDMA3_DRV_TRIG_MODE_EVENT );
// Take the Serializers out of reset
CSL_FINST( mcasp0Regs->SRCTL0, MCASP_SRCTL0_SRMOD, XMT );
CSL_FINST( mcasp0Regs->SRCTL1, MCASP_SRCTL1_SRMOD, XMT );
CSL_FINST( mcasp0Regs->SRCTL2, MCASP_SRCTL2_SRMOD, XMT );
CSL_FINST( mcasp0Regs->SRCTL3, MCASP_SRCTL3_SRMOD, XMT );
// Take the MCASP out of reset and let it run
mcasp0Regs->XGBLCTL = CSL_FMKT( MCASP_XGBLCTL_XFRST, ACTIVE )
| CSL_FMKT( MCASP_XGBLCTL_XSMRST, ACTIVE )
| CSL_FMKT( MCASP_XGBLCTL_XSRCLR, ACTIVE )
| CSL_FMKT( MCASP_XGBLCTL_XHCLKRST, ACTIVE )
| CSL_FMKT( MCASP_XGBLCTL_XCLKRST, ACTIVE );