Hi all:
The goal I want to realize is to use DMA channel to move "SendData[512] -> &McbspaRegs.DXR1.all" and "&McbspaRegs.DRR1.all -> RecvData[512]" in MCBSP clock stop mode. I have realized the MCBSP clock mode and can communicate with SD card successfully but something wrong with DMA setting.
1. I need move 512 bytes values from SendData[] to McbspaRegs.DXR1.all, so I want to set 2 words/brust, and 256 bursts/transfer. In this case, the DMA could transfer 512 bytes in one transmission. Also the MCBSP in spi mode is 16-bit wide so that The DMA setting is below:
void init_dma_xmit(Uint16* xmitbuff)
{
EALLOW;
DmaRegs.DMACTRL.bit.HARDRESET = 1;
__asm(" NOP"); // Only 1 NOP needed per Design
// Channel 1, McBSPA transmit
// Burst step is the used for updating the address within a burst. In this example, since we use 1 word per burst, it does not make any difference.
// Multiple bursts form a transfer (in this case, 256 bursts in one transfer) and the address is updated using the TRANSFER_STEP value. In the example you can see that SRC_TRANSFER_STEP is set as 1.
DmaRegs.CH1.MODE.bit.CHINTE = 0;
DmaRegs.CH1.BURST_SIZE.all = 1; // 2 words/burst
DmaRegs.CH1.SRC_BURST_STEP = 0; // no effect when using 1 word/burst
DmaRegs.CH1.DST_BURST_STEP = 0; // no effect when using 1 word/burst
// Interrupt every frame (256 bursts/transfer)
DmaRegs.CH1.TRANSFER_SIZE = 255;
// Move to next word in buffer after each word in a burst
DmaRegs.CH1.SRC_TRANSFER_STEP = 2; //移位到下一个word 告诉DSP下次brust传输的源首地址,是在上次burst傳輸的最后一個源數據的地址上進行偏移
DmaRegs.CH1.DST_TRANSFER_STEP = 0; // Don't move destination address
//DmaRegs.CH1.SRC_ADDR_SHADOW = (Uint32) &Senddata[0]; // Start address = buffer 源地址的首地址
DmaRegs.CH1.SRC_ADDR_SHADOW =(Uint32)xmitbuff;
// Not needed unless using wrap function
//DmaRegs.CH1.SRC_BEG_ADDR_SHADOW = (Uint32) &Senddata[0];
DmaRegs.CH1.SRC_BEG_ADDR_SHADOW = (Uint32)xmitbuff;
// Start address = McBSPA DXR
DmaRegs.CH1.DST_ADDR_SHADOW = (Uint32) &McbspaRegs.DXR1.all; //目的地的首地址
// Not needed unless using wrap function
DmaRegs.CH1.DST_BEG_ADDR_SHADOW = (Uint32) &McbspaRegs.DXR1.all;
// Clear peripheral interrupt event flag
DmaRegs.CH1.CONTROL.bit.PERINTCLR = 1; // Clear peripheral interrupt event flag
DmaRegs.CH1.CONTROL.bit.SYNCCLR = 1; // Clear sync flag
DmaRegs.CH1.CONTROL.bit.ERRCLR = 1; // Clear sync error flag
// Put to maximum - don't want destination wrap
DmaRegs.CH1.DST_WRAP_SIZE = 0xFFFF;
// Put to maximum - don't want source wrap
DmaRegs.CH1.SRC_WRAP_SIZE = 0xFFFF;
DmaRegs.CH1.MODE.bit.SYNCE = 0; // No sync signal
DmaRegs.CH1.MODE.bit.SYNCSEL = 0; // No sync signal
DmaRegs.CH1.MODE.bit.CHINTE = 1; // Enable channel interrupt
DmaRegs.CH1.MODE.bit.CHINTMODE = 1; // Interrupt at end of transfer
DmaRegs.CH1.MODE.bit.PERINTE = 1; // Enable peripheral interrupt event
// Peripheral interrupt select
DmaRegs.CH1.MODE.bit.PERINTSEL = DMA_MXREVTB;
DmaRegs.CH1.CONTROL.bit.PERINTCLR = 1;// Clear any spurious interrupt flags
EDIS;
}
void start_dma_xmit(void)
{
EALLOW;
DmaRegs.CH1.CONTROL.bit.RUN = 1; // Start DMA Transmit from McBSP-B
EDIS;
}
Uint16 McbspBTransmit(Uint16 nData)
{
Uint16 McbspBTimeout = McbspB_TIMEOUT;
McbspbRegs.DXR2.all = 0; // transmit buffer - high word
McbspbRegs.DXR1.all = nData; // transmit buffer - low word
while(McbspbRegs.SPCR1.bit.RRDY == 0 && McbspB_TIMEOUT > 0) // wait until RX data are ready
{
McbspBTimeout--;
}
return McbspbRegs.DRR1.all; // return RX data
}
// local_D_INTCH1_ISR - DMA Ch1 (INT7.1)
__interrupt void local_D_INTCH1_ISR(void)
{
EALLOW; // NEED TO EXECUTE EALLOW INSIDE ISR !!!
//
// Re-enable DMA CH1. Should be done every transfer
//
DmaRegs.CH1.CONTROL.bit.HALT = 1 ;
//
// To receive more interrupts from this PIE group, acknowledge
// this interrupt
//
PieCtrlRegs.PIEACK.all = PIEACK_GROUP7;
EDIS;
return;
}
I am not very sure that whether I need change the "DmaRegs.CH1.SRC_BURST_STEP = 0"; In my mind, the work flow should be when I fill the SendData[], at the same time the DXR1.all is ready ,then DMA move SendData[0] and SendData[1] to DXR1.all, then MCBSP will do data transfer.
The logic is :
init_dma_xmit();
start_dma_xmit();
McbspBTransmit(); // do 512 times
//After 256 bursts finished ,enter DMA interrupt
local_D_INTCH1_ISR();
Could someone tell me whether I miss something? Cz in my configuration, I can not send anything with MCBSP-spi.