I have used EDMA3 on MCASP and RFIFO to acquire and sorts 4 channels coming from an ADC. The signal is stored in 2 buffers in flip flop mode. This works properly
Now, I want to use the EDMA on the same application to send data to a stereo DAC and using the WFIFO. And it does not work. The transmitter raiseserrors as if the WFIFO was never filled. To write by DMA in the WFIFO I use the same adress as for the RFIFO (0x01D02000). Is it Ok?
I have tried to force the 1st DMA transfer by setting the relevant bit int the ESR but nothing happens
I have tried also to write 1 time ine XBUF4 (transmitter that I used) at start of transmit but it does not change anything
My initializations for TX are described here :
//------ CONFIGURATION FOR TX
//program use of fifo
//Bit 16 : XENA : 0 Read fifo is disabled before programmaing
//Bit 15-8 : XNUMEVT : 2 Read word count per DMA event.
// When receive fifo contains 8 words then an AREVT (receive DMA event) is generated
//Bits 7-0 : XNUMDMA : 1 : Read word count per transfer 1 because only 1 serializer is active
aMcASPFifoRegs->WFIFOCTL = ((NB_CHANNEL_TX)<<8) | 1;
//Enable Tx FIFO
CSL_FINST(aMcASPFifoRegs->WFIFOCTL, AFIFO_WFIFOCTL_WENA, ENABLED);
while ((aMcASPFifoRegs->WFIFOCTL & CSL_AFIFO_WFIFOCTL_WENA_MASK)!= CSL_AFIFO_WFIFOCTL_WENA_MASK);
// Transmit format unit bit mask register : all the bits are transfered
MCASP->XMASK = 0xFFFFFFFF;
// Transmit bit stream format register
// Bits 0 à 2 : 000 XROT (right rotation value for receive) : no rotation
// Bit 3 :0 XBUSEL (select whether write to peripheral configuration port or DMA port) : write to DMA port
// Bits 4 à 7 : 1111 : XSSZ(transmit slot size) : 24 bits
// Bits 8 à 12 : 00000 : XPBIT (bit used to pad the extra bits) : 0
// Bits 13 à 14 : 00 XPAD (Pad value for extra bits not belonging to the word) : 0
// Bit 15 : 1 XRVRS (Transmit serial bitstream order) : bitstream in MSB first
// Bits 16-17 : 00 XDATDLY (Transmit bit delay) : 0 bit delay between frame sync and receive data bit
// Bits 18-31 : 0 Reserved
MCASP->XFMT = 0x000080F0; // MSB first, align left, slot=32bits, 0-bit delay, no rotation
// Receive Frame sync control register
//Bit 0 : 0 FSXP (transmit frame sync polarity) rising edge on frame sync
//Bit 1 : 1 FSXM (receive frame sync generation) internally generated transmit frame sync
//Bit 2-3 : 00 Reserved
//Bit 4 : 1 FXWID (Transmit frame sync width select bit) : single word
//Bits 5-6 : 00 Reserved
//Bits 7 to 15 : 2 XMOD (transmit frame sync mode select) 2 slot TDM
//Bits 16 to 31 : reserved
MCASP->AFSXCTL = 0x00000112;
//Transmit clock control register
//Bits 0 à 4 : 00011 CLKXDIV (Transmit bit clock divide ratio from AHCLKR to ACLKR) Divide by 4
//Bit 5 : 1 CLKXM (Transmit bit clock source) Internal
//Bit 6 : 1 ASYNC : Separate clock and frame sync used bu transmitter and receiver
//Bit 7 : 1 CLKXP (Transmit bit stream clock polarity) : shift out data on falling edge of serial clock
//Bits 8 to 31 : reserved
MCASP->ACLKXCTL = 0x000000E3; // rising edge, clkrm external, /1 CLKRDIV
//Transmit high frequency clock control register
//Bits 0 à 11 : 0 HCLKXDIV (Receive high frequency divide ratio from AUXCLK to AHCLKX) : 1
//Bits 12-13 : reserved
//Bits 14 : 0 HCLKXP (receive bitstream high frequency clock polarity) not inverted
//Bit 15 : 0 HCLKXM (receive high frequency clock source) external source
//bits 16 to 31 : reserved
MCASP->AHCLKXCTL = 0x00000000;
//transmit TDM time slot register
//Masks the time slot to transmit : 0 & 1
MCASP->XTDM = 0x00000003;
//Transmit interrupt control register
MCASP->XINTCTL = 0x00000000; // disabled because we use DMA
//transmit clock check control register
//Bits 0 to 3 : 0010 XPS (transmit clock check prescaler value): McASP system clock divided by 4
//Bits 4 to 7 : reserved
//Bits 8 to 15 : 0 XMIN (transmit clock minimum boundary) 0
//Bits 16 to 23 : FF XMAX (transmit clock maximum boundary)
//Bits 24 to 31 : 0 XCNT (transmit clock count value)
MCASP->XCLKCHK = 0x00FF0002;
//Enable the transmitter to the DAC
MCASP->SRCTL4 = 0x0009;
//Configure DMA for Tx
//It can be done 1 time at creation of McASP but we do not have pointers on Tx buffer
EDMA_ConfigureMcASPTx(m_poOutputBuffer, (int *)m_poOutputBuffer->GetAdressElement(0), (int *)m_poOutputBuffer->GetAdressElement(1), SIZE_BLOCK_AUDIO);
//Enable the audio clocks, verifying each bit is properly set.
SETBIT(MCASP->XGBLCTL, XHCLKRST);
while (!CHKBIT(MCASP->XGBLCTL, XHCLKRST)) {}
SETBIT(MCASP->XGBLCTL, XCLKRST);
while (!CHKBIT(MCASP->XGBLCTL, XCLKRST)) {}
//Start DMA
EDMA_StartMcASPTx();
//Clear all the status bits
MCASP->XSTAT = 0x0000FFFF; // Clear all
//Activate the serializer
SETBIT(MCASP->XGBLCTL, XSRCLR);
while (!CHKBIT(MCASP->XGBLCTL, XSRCLR)) {}
if(CHKBIT(MCASP->XSTAT, XDATA))
{
MCASP->XBUF4 = 0;
}
//Reset the state machine of transmitter
SETBIT(MCASP->XGBLCTL, XSMRST);
while (!CHKBIT(MCASP->XGBLCTL, XSMRST)) {}
//Reset frame sync generator
SETBIT(MCASP->XGBLCTL, XFRST);
while (!CHKBIT(MCASP->XGBLCTL, XFRST)) {}
The class EDMA constructor realizes the following initializations
//Use DMA control channel 0
aEdmaccRegs = (CSL_Edma3ccRegsOvly)(CSL_EDMA30CC_0_REGS);
//McASP0 Control Registers
mcaspRegs = (CSL_McaspRegsOvly) CSL_MCASP_0_CTRL_REGS; //OMAP-L138 McASP Configuration Register Pointer Instance
//McASP AFIFO Control Registers
afifoRegs = (CSL_AfifoRegsOvly) CSL_MCASP_0_FIFO_REGS;
//McASP DMA Port Registers
adataRegs = (CSL_AdataRegsOvly) CSL_MCASP_0_DATA_REGS;
// Write EMCR, CCEERCLR, ECR registers to clear the EMR, CCERR, ER
// EMCR = 0xFFFFFFFF; CCERRCLR = 0xFFFFFFFF; ECR = 0xFFFFFFFF;
// Clear all the Event in the event Register
// Disable all the events
aEdmaccRegs->EECR = 0xffffffff; // clear events 0 -> 31
aEdmaccRegs->ECR = 0xffffffff; // clear events 0 -> 31
// Clear all the events in the secondary Event Register
aEdmaccRegs->SECR = 0xffffffff; // clear secondary events 0 -> 31
//Clear all the events in the event interrupt enable register
aEdmaccRegs->IECR = 0xffffffff; // disable all interrupts
//Clear all the pending interrupts
aEdmaccRegs->ICR = 0xffffffff; // clear all pending interrupts
// We use shadow region 1 because it it is this region which is linked to interruption
// and we use DMA 0 and 1
// Enable Channel 0 - 1 to DSP (Region 1 )
aEdmaccRegs->DRA[CSL_EDMA3_REGION_1].DRAE =
CSL_FMKT(EDMA3CC_DRAE_E0, ENABLE)|
CSL_FMKT(EDMA3CC_DRAE_E1, ENABLE);
// Assign Channel 0 - 1 to Queue 0
aEdmaccRegs->DMAQNUM[1] =
CSL_FMKT(EDMA3CC_DMAQNUM_E0, Q0) |
CSL_FMKT(EDMA3CC_DMAQNUM_E1, Q0);
Then, the following method configures he DMA
voidEDMA::ConfigureMcASPTx(TypeFifoOfBlocksOutputAudio* poOutputBuffer, int * piBufOutputPing, int * piBufOutputPong, int iSizeBlock)
{
// Save pointer on circular buffer to increment index after each DMA read
m_poOutputBuffer = poOutputBuffer;
CSL_FINST(aEdmaccRegs->EECR, EDMA3CC_EECR_E1, CLEAR);
CSL_FINST(aEdmaccRegs->ECR, EDMA3CC_ECR_E1, CLEAR);
CSL_FINST(aEdmaccRegs->SECR, EDMA3CC_SECR_E1, CLEAR);
CSL_FINST(aEdmaccRegs->IECR, EDMA3CC_IECR_I1, CLEAR);
CSL_FINST(aEdmaccRegs->ICR, EDMA3CC_ICR_I1, CLEAR);
// Initialize PaRAM Transfer Context for Events 1 (Tx)
InitializeParamMcASPTxEvent1(piBufOutputPing, piBufOutputPong, iSizeBlock);
Task_sleep(20); // if no wait minimum 20 sometimes does not start : 0 in the buffer received by DMA
}
voidEDMA::InitializeParamMcASPTxEvent1 (int * piBufOutputPing, int * piBufOutputPong, int iSizeBlock)
{
// Reset EDMA PaRAM OPT Register
aEdmaccRegs->PARAMSET[EDMA_EVENT1].OPT = CSL_EDMA3CC_OPT_RESETVAL;
// Config PaRAM OPT
// Intermediate transfer compete interrupt disable
// Transfer complete chaining disable
// Intermediate transfer completion interrupt disable
// Transfer complete interrupt enable
// Transfer complete code : 0 unused
// Transfer complete code mode 0 : A transfer is complete after the data has been transfered
// FIFO width : 8 bits
// STATIC : 0 PaRAM set is not static. ParAm is updated or linked after Tr is submitted
// SYNCDIM : 1 AB synchronized because we use FIFO of McASP
// DAM : destination adress mode : 0 non constant addressing mode because not supported by C674x
// SAM : source adress mode : 0 non constant addressing mode because not supported by C674x
aEdmaccRegs->PARAMSET[EDMA_EVENT1].OPT =
CSL_FMKT(EDMA3CC_OPT_TCINTEN, ENABLE) |
CSL_FMKT(EDMA3CC_OPT_SYNCDIM, ABSYNC) |
CSL_FMK(EDMA3CC_OPT_TCC, EDMA_EVENT1);
// Initialize EDMA Event Src (Adress of RFIFO) and Dst Addresses (input pointer)
aEdmaccRegs->PARAMSET[EDMA_EVENT1].DST = (Uint32) piBufOutputPing;
aEdmaccRegs->PARAMSET[EDMA_EVENT1].SRC = CSL_MCASP_0_DATA_REGS;
// Set EDMA Event PaRAM A,B,C CNT
aEdmaccRegs->PARAMSET[EDMA_EVENT1].A_B_CNT =
CSL_FMK(EDMA3CC_A_B_CNT_ACNT, NUMBER_OF_BYTES_PER_SAMPLE) | //0004h
CSL_FMK(EDMA3CC_A_B_CNT_BCNT, NB_CHANNEL_TX); //2 arrays (channels) in a frame
aEdmaccRegs->PARAMSET[EDMA_EVENT1].CCNT = iSizeBlock; // Size of a block = 32
// Set EDMA Event PaRAM SRC/DST BIDX
aEdmaccRegs->PARAMSET[EDMA_EVENT1].SRC_DST_BIDX =
CSL_FMK(EDMA3CC_SRC_DST_BIDX_SRCBIDX, (iSizeBlock*NUMBER_OF_BYTES_PER_SAMPLE)) | // The source address between 2 channel is incremented from sizeBlock*4
CSL_FMK(EDMA3CC_SRC_DST_BIDX_DSTBIDX, 0); //The destination adress is always the same
// Set EDMA Event PaRAM SRC/DST CIDX
aEdmaccRegs->PARAMSET[EDMA_EVENT1].SRC_DST_CIDX =
CSL_FMK(EDMA3CC_SRC_DST_CIDX_SRCCIDX, NUMBER_OF_BYTES_PER_SAMPLE) | // after each read of a sample we go to the next sample, 4 bytes later
CSL_FMK(EDMA3CC_SRC_DST_CIDX_DSTCIDX, 0); //the destination is always the same the WFIFO
// Set EDMA Event PaRAM LINK to param 34 and BCNTRLD
aEdmaccRegs->PARAMSET[EDMA_EVENT1].LINK_BCNTRLD =
CSL_FMK(EDMA3CC_LINK_BCNTRLD_LINK, (Uint32)&aEdmaccRegs->PARAMSET[EDMA_PARAMETER_SET34] & 0xFFFFu);
//************** Parameter Set 34 *******************//
//The parameters are identical of those of channel 1
// Reset EDMA PaRAM OPT Register
aEdmaccRegs->PARAMSET[EDMA_PARAMETER_SET34].OPT = CSL_EDMA3CC_OPT_RESETVAL;
// Config PaRAM OPT (Identical of parameters of channel 0
aEdmaccRegs->PARAMSET[EDMA_PARAMETER_SET34].OPT = aEdmaccRegs->PARAMSET[EDMA_EVENT1].OPT ;
// Initialize EDMA Event Src and Dst Addresses
aEdmaccRegs->PARAMSET[EDMA_PARAMETER_SET34].SRC = aEdmaccRegs->PARAMSET[EDMA_EVENT1].SRC;
aEdmaccRegs->PARAMSET[EDMA_PARAMETER_SET34].DST = (Uint32) piBufOutputPong;
// Set EDMA Event PaRAM A,B,C CNT
aEdmaccRegs->PARAMSET[EDMA_PARAMETER_SET34].A_B_CNT = aEdmaccRegs->PARAMSET[EDMA_EVENT1].A_B_CNT;
aEdmaccRegs->PARAMSET[EDMA_PARAMETER_SET34].CCNT = aEdmaccRegs->PARAMSET[EDMA_EVENT1].CCNT;
// Set EDMA Event PaRAM SRC/DST BIDX
aEdmaccRegs->PARAMSET[EDMA_PARAMETER_SET34].SRC_DST_BIDX = aEdmaccRegs->PARAMSET[EDMA_EVENT1].SRC_DST_BIDX;
// Set EDMA Event PaRAM SRC/DST CIDX
aEdmaccRegs->PARAMSET[EDMA_PARAMETER_SET34].SRC_DST_CIDX = aEdmaccRegs->PARAMSET[EDMA_EVENT1].SRC_DST_CIDX;
// Set EDMA Event PaRAM LINK and BCNTRLD
aEdmaccRegs->PARAMSET[EDMA_PARAMETER_SET34].LINK_BCNTRLD =
CSL_FMK(EDMA3CC_LINK_BCNTRLD_LINK, (Uint32)&aEdmaccRegs->PARAMSET[EDMA_PARAMETER_SET35] & 0xFFFFu); // | // CSL_FMK(EDMA3CC_LINK_BCNTRLD_LINK, (Uint32)&edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET64] & 0xFFFFu) |
//************** Parameter Set 35 *******************//
//The parameters are identical of those of channel 1
// Reset EDMA PaRAM OPT Register
aEdmaccRegs->PARAMSET[EDMA_PARAMETER_SET35].OPT = CSL_EDMA3CC_OPT_RESETVAL;
// Config PaRAM OPT (Identical of parameters of channel 0
aEdmaccRegs->PARAMSET[EDMA_PARAMETER_SET35].OPT = aEdmaccRegs->PARAMSET[EDMA_EVENT1].OPT ;
// Initialize EDMA Event Src and Dst Addresses
aEdmaccRegs->PARAMSET[EDMA_PARAMETER_SET35].SRC = aEdmaccRegs->PARAMSET[EDMA_EVENT1].SRC;
aEdmaccRegs->PARAMSET[EDMA_PARAMETER_SET35].DST = (Uint32) piBufOutputPing;
// Set EDMA Event PaRAM A,B,C CNT
aEdmaccRegs->PARAMSET[EDMA_PARAMETER_SET35].A_B_CNT = aEdmaccRegs->PARAMSET[EDMA_EVENT1].A_B_CNT;
aEdmaccRegs->PARAMSET[EDMA_PARAMETER_SET35].CCNT = aEdmaccRegs->PARAMSET[EDMA_EVENT1].CCNT;
// Set EDMA Event PaRAM SRC/DST BIDX
aEdmaccRegs->PARAMSET[EDMA_PARAMETER_SET35].SRC_DST_BIDX = aEdmaccRegs->PARAMSET[EDMA_EVENT1].SRC_DST_BIDX;
// Set EDMA Event PaRAM SRC/DST CIDX
aEdmaccRegs->PARAMSET[EDMA_PARAMETER_SET35].SRC_DST_CIDX = aEdmaccRegs->PARAMSET[EDMA_EVENT1].SRC_DST_CIDX;
// Set EDMA Event PaRAM LINK and BCNTRLD
aEdmaccRegs->PARAMSET[EDMA_PARAMETER_SET35].LINK_BCNTRLD =
CSL_FMK(EDMA3CC_LINK_BCNTRLD_LINK, (Uint32)&aEdmaccRegs->PARAMSET[EDMA_PARAMETER_SET34] & 0xFFFFu); // | // CSL_FMK(EDMA3CC_LINK_BCNTRLD_LINK, (Uint32)&edma3ccRegs->PARAMSET[EDMA_PARAMETER_SET64] & 0xFFFFu) |
}
Finally, I call this method to start the transfer
voidEDMA::StartMcASPTx(void)
{
// Enable channel 1 by event enable set register
CSL_FINST(aEdmaccRegs->EESR, EDMA3CC_EESR_E1, SET);
// Enable interrupt for channel 1
CSL_FINST(aEdmaccRegs->IESR, EDMA3CC_IESR_I1, SET);
}