This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28335: Ping pong buffering, half buffering problem

Part Number: TMS320F28335


Hello,

I am developing an audio application where I am using DMA to receive and transmit STEREO  audio data. I have based my configuration in one of your examples for audio and aic23b. I am able to process and receive data correctly in that way, but I decided to change the interrupt transfer size for receiving, so I don´t need to wait for the whole reception in order to start procesing data. The resulting configuration of the DMA in that way is the following:

void dma_init(){

   EALLOW;
   DmaRegs.DMACTRL.bit.HARDRESET = 1;
   asm("     NOP");

   DmaRegs.PRIORITYCTRL1.bit.CH1PRIORITY = 0;
   // DMA Channel 1 - McBSP-A Receive
   DmaRegs.CH1.BURST_SIZE.all = 1;   // 2 16-bit words/burst (1 32-bit word per RRDY) - memory address bumped up by 1 internally
   DmaRegs.CH1.SRC_BURST_STEP = 1;   // DRR2 must be read first & then DRR1. Increment by 1. Hence a value of +1. (This is a 2's C #)
   DmaRegs.CH1.DST_BURST_STEP = -1;   // Copy DRR2 data to address N+1 and DRR1 data to N. Hence -1 (32-bit read= read addr N+1 as MSB, then N as LSB)
   DmaRegs.CH1.TRANSFER_SIZE = (BUFFER_SIZE>>1)-1;   // HERE IS THE CHANGE!!! Interrupt every    (n+1) bursts. McBSP handles 16-bit data only (DRR2 and DRR1 are 16-bit registers) 

   DmaRegs.CH1.SRC_TRANSFER_STEP = -1; // Decrement source address by 1 (from DRR1 back to DRR2) after processing a burst of data
   DmaRegs.CH1.DST_TRANSFER_STEP = (BUFFER_SIZE+1); // After copying L-C data, move down (up más bien) to R-C data in a given buffer

   DmaRegs.CH1.SRC_ADDR_SHADOW = (Uint32) &McbspaRegs.DRR2.all;  // First read from DRR2
   DmaRegs.CH1.SRC_BEG_ADDR_SHADOW = (Uint32) &McbspaRegs.DRR2.all;
   DmaRegs.CH1.DST_ADDR_SHADOW = ping_buff_offset;               // First write to ping_buffer[1]
   DmaRegs.CH1.DST_BEG_ADDR_SHADOW = ping_buff_offset;

   DmaRegs.CH1.DST_WRAP_SIZE = 1;     // After LEFT(1) and then RIGHT(2), go back to LEFT buffer
   DmaRegs.CH1.SRC_WRAP_SIZE = 0xFFFF; // Arbitary large value. We'll never hit this.....
   DmaRegs.CH1.DST_WRAP_STEP = 2;      // From starting address, move down (up más bien) 2 16-bit addresses to write nxt 32-bit word

   DmaRegs.CH1.CONTROL.bit.PERINTCLR = 1;      // Clears peripheral interrupt, sync and sycn error flags
   DmaRegs.CH1.CONTROL.bit.SYNCCLR = 1;
   DmaRegs.CH1.CONTROL.bit.ERRCLR = 1;

   DmaRegs.CH1.MODE.bit.CHINTE = 1;         // Channel Interrupt Enable
   DmaRegs.CH1.MODE.bit.CHINTMODE = 0;         // Generates Interrupt at beginning of transfer
   DmaRegs.CH1.MODE.bit.PERINTE = 1;         // Peripheral Interrupt Enable
   DmaRegs.CH1.MODE.bit.PERINTSEL = 15;      // McBSP MREVTA
   DmaRegs.CH1.MODE.bit.CONTINUOUS = 1;      // Continuous mode

   // DMA Channel 2 - McBSP-A Transmit
   DmaRegs.CH2.BURST_SIZE.all = 1;   // 2 16-bit words/burst (1 32-bit word per XRDY) - value bumped up by 1 internally
   DmaRegs.CH2.SRC_BURST_STEP = -1;   // Copy data at address N+1 to DXR2 first then data at N to DXR1. Hence -1
   DmaRegs.CH2.DST_BURST_STEP = 1;   // DXR2 must be written to first & then DXR1. Increment by 1. Hence a value of +1. (This is a 2's C #)
   DmaRegs.CH2.TRANSFER_SIZE = (BUFFER_SIZE-1);   // Interrupt every 1024 (n+1) 16-bit words. McBSP still handles 16-bit data only in registers

   DmaRegs.CH2.SRC_TRANSFER_STEP = (BUFFER_SIZE+1); // After copying L-C data, move down to R-C data in a given buffer
   DmaRegs.CH2.DST_TRANSFER_STEP = -1;   // Decrement dest. address by 1 (DXR1 back to DXR2) after processing a burst of data

   DmaRegs.CH2.SRC_ADDR_SHADOW = ping_buff_offset;               // First read from ping_buffer[1]
   DmaRegs.CH2.SRC_BEG_ADDR_SHADOW = ping_buff_offset;
   DmaRegs.CH2.DST_ADDR_SHADOW = (Uint32) &McbspaRegs.DXR2.all;  // First write to DXR2
   DmaRegs.CH2.DST_BEG_ADDR_SHADOW = (Uint32) &McbspaRegs.DXR2.all;

   DmaRegs.CH2.SRC_WRAP_SIZE = 1;        // After LEFT(1) and then RIGHT(2), go back to LEFT buffer
   DmaRegs.CH2.DST_WRAP_SIZE = 0xFFFF;      // Arbitary large value. We'll never hit this.....
   DmaRegs.CH2.SRC_WRAP_STEP = 2;         // From starting address, move down 2 16-bit addresses to read next 32-bit word

   DmaRegs.CH2.CONTROL.bit.PERINTCLR = 1;      // Clears peripheral interrupt, sync and sync error flags
   DmaRegs.CH2.CONTROL.bit.SYNCCLR = 1;
   DmaRegs.CH2.CONTROL.bit.ERRCLR = 1;

   DmaRegs.CH2.MODE.bit.CHINTE = 1;         // Channel Interrupt Enable
   DmaRegs.CH2.MODE.bit.CHINTMODE = 0;         // Generates Interrupt at beginning of transfer
   DmaRegs.CH2.MODE.bit.PERINTE = 1;         // Peripheral Interrupt Enable
   DmaRegs.CH2.MODE.bit.PERINTSEL = 14;      // McBSP MXEVTA
   DmaRegs.CH2.MODE.bit.CONTINUOUS = 1;      // Continuous mode
   EDIS;

   EALLOW;
   DmaRegs.CH1.CONTROL.bit.RUN = 1;         // Starts up Channel 1
   EDIS;
}

However, I am having a problem when receiving the second half of the buffer. So, is that configuration correct? Is it possible to have 2 interrupts for reception while having 1 for transmission? I hope it is. 

Thanks in advance

Ignacio

  • Hi Ignacio,

    I can't find the original example that you mention, so it's not really clear to me what you've changed. Did you essentially halve the transfer size? At the beginning of the transfer, it's going to reset the transfer address back to the beginning address. Are you doing something in the ISR to switch the begin address so it will continue filling the second half of of the buffer instead of restarting?

    Or am I completely misunderstanding what you're trying to do?

    Thanks,
    Whitney
  • You understood it correctly. I was not updating the transfer address in the ISR correctly. Now it works.

    Thank you!