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: Questions on DMA setting in MCBSP demo code

Part Number: TMS320F28335


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.

  • From your description it looks like McBSP hasn't triggered MXREVTB event. Please check CONTROL.PERINTFLG? If this is not set McBSP hasn't fired MXREVTB event.

  • I have checked the value of DMACH1_CONTROL is 0x0100, which means CONTROL.PERINTFLG is 1. I think the MXREVTB event has been occured. But I got nothing in DXR1 reg.

    1. The working flow of my code is:

    init_dma_xmit(); // is there anything missing or wrong?

    while( McbspbRegs.SPCR2.bit.XRDY ==0); //wait for transmitter ready  ->  IS this step necessary?

    start_dma_xmit();

    //McbspBTransmit();  //transmit 512 bytes values   -> I shield this fucntion cz I think DMA has already move the data to DXR1, it is same as McbspBTransmit() function

    local_D_INTCH1_ISR(); // enter dma ISR

    2. In DMA ISR, "DmaRegs.CH1.CONTROL.bit.HALT = 1 ;"

     2.1 The "HALT"  I think when HALT =1, the dma channl 1 will be blocked until the current transmission done . Am I right?

    3. I want to make sure the how the MXREVTB  event trigger the DMA. Here below is what I know about working flow

       3.1 I need send 512-byte and 2 bytes/burst. first fill SendDATA[] and MXREVTB event occurs -> trigger DMA to tansmit 2 bytes from Senddata[] to DXR1 ->then MCBSP start SPI transmission -> repeat 256 times (256 bursts/transfer) -> then enter DMA ISR

  • Li,

    Are all the transfer count registers at their initialized state, that is the DMA has not done any transfers to the McBSP?  Let's try to write to the PERINTFRC bit in the Control reg to get the DMA started.  After this it should continue when the McBSP fires its ISR signal, but I'm thinking we have to initiate the first one.

    Best,

    Matthew

  • I set a global variable "dma_xmit" , and  init "dma_xmit =0 " then set it to 2 in DMA_XMIT_ISR. After my application finished running, the dma_xmit=2. It means the DMA has already done  512 times burst/transfer and triggered the ISR.

    When my application finished, The values of DMA registers are :

    DMACTRL	                    0x0000	DMA Control Register [Memory Mapped]	
    DEBUGCTRL	                0x0000	Debug Control Register [Memory Mapped]	
    REVISION	                0x0000	Peripheral Revision Register [Memory Mapped]	
    PRIORITYCTRL1	            0x0000	Priority Control Register 1 [Memory Mapped]	
    PRIORITYSTAT	            0x0000	Priority Status Register [Memory Mapped]	
    DMACH1_MODE	                0x8310	DMA Channel 1 Mode Register [Memory Mapped]	
    DMACH1_CONTROL	            0x0100	DMA Channel 1 Control Register [Memory Mapped]	
    DMACH1_BURST_SIZE	        0x0000	DMA Channel 1 Burst Size Register [Memory Mapped]	
    DMACH1_BURST_COUNT	        0x0000	DMA Channel 1 Burst Count Register [Memory Mapped]	
    DMACH1_SRC_BURST_STEP	    0x0000	DMA Channel 1 Source Burst Step Size Register [Memory Mapped]	
    DMACH1_DST_BURST_STEP	    0x0000	DMA Channel 1 Destination Burst Step Size Register [Memory Mapped]	
    DMACH1_TRANSFER_SIZE	    0x00FF	DMA Channel 1 Transfer Size Register [Memory Mapped]	
    DMACH1_TRANSFER_COUNT	    0x0000	DMA Channel 1 Transfer Count Register [Memory Mapped]	
    DMACH1_SRC_TRANSFER_STEP	0x0001	DMA Channel 1 Source Transfer Step Size Register [Memory Mapped]	
    DMACH1_DST_TRANSFER_STEP	0x0000	DMA Channel 1 Destination Transfer Step Size Register [Memory Mapped]	
    DMACH1_SRC_WRAP_SIZE	    0xFFFF	DMA Channel 1 Source Wrap Size Register [Memory Mapped]	
    DMACH1_SRC_WRAP_COUNT	    0xFEFF	DMA Channel 1 Source Wrap Count Register [Memory Mapped]	
    DMACH1_SRC_WRAP_STEP	    0x0000	DMA Channel 1 Source Wrap Step Size Register [Memory Mapped]	
    DMACH1_DST_WRAP_SIZE	    0xFFFF	DMA Channel 1 Destination Wrap Size Register [Memory Mapped]	
    DMACH1_DST_WRAP_COUNT	    0xFEFF	DMA Channel 1 Destination Wrap Count Register [Memory Mapped]	
    DMACH1_DST_WRAP_STEP	    0x0000	DMA Channel 1 Destination Wrap Step Size Register [Memory Mapped]	
    DMACH1_SRC_BEG_ADDR_SHADOW	0x0000C280	DMA Channel 1 Shadow Source Begin Register [Memory Mapped]	
    DMACH1_SRC_ADDR_SHADOW	    0x0000C280	DMA Channel 1 Shadow Source Current Address Register [Memory Mapped]	
    DMACH1_SRC_BEG_ADDR_ACTIVE	0x0000C280	DMA Channel 1 Active Source Begin Register [Memory Mapped]	
    DMACH1_SRC_ADDR_ACTIVE	    0x0000C380	DMA Channel 1 Active Source Current Address Register [Memory Mapped]	
    DMACH1_DST_BEG_ADDR_SHADOW	0x00005003	DMA Channel 1 Shadow Destination Begin Register [Memory Mapped]	
    DMACH1_DST_ADDR_SHADOW	    0x00005003	DMA Channel 1 Shadow Destination Current Address Register [Memory Mapped]	
    

    1. Is DMA move 1 byte SendData[] to DXR1 each burst , then MCBSP transmit it through spi bus?

    2. In Mcbsp-spi, if I want to transmit one byte, the only thing I need to do is fill the DXR register?

  • The DXR1 value has nothing to change whenever I set both RUN bit  and PERINTFRC bit to 1.

    I also use Oscilloscope to catch the signal, but when I start DMA, nothing happen on MVBSP_SPI bus.

    The MCBSP_SPI I set is 8-bit length, is that matter?

  • Li,

    You are correct, all that needs to happen is writing to the DXR1 register and the transfer should start.

    I re-looked at your DMA settings, I think the DST ADDR should be 0x6003 not 0x5003 for McBSPA DXR1.  Can you change to 0x6003 and see if this fixes things?

    Best,

    Matthew

  • Matthew,

        I checked my DMA setting and noticed that the MCBSP I used is MCBSPB but not MCBSPA. When I changed the McbspaRegs.DXR1.all to McbspbRegs.DXR1.all, then DMA works.

        However, I find a question that:

       The xmit flow is :

        init_dma_xmit();

        start_dma_xmit();

        // do 512 times transfer;  Here need wait until 512 data done; otherwise the DMA will transfer CRC

       McbspBTransmit(CRC_High); McbspBTransmit(CRC_Low);

      In this case, what should I do to wait until the transmission done ?

  • Li,

    After all transfers are complete(256 times of 2 word bursts), the DMA will set its RUNSTS bit = 0, which will effectively halt the DMA until it is re-enabled.  The DMA will also issue it ISR to indicate the above, you can use this to wait until you are ready to transfer again setting RUNSTST = 1 to begin the next round of transfers.

    Best,
    Matthew