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.

MSP432P401R: DMA gather scatter setup question, please clear

Part Number: MSP432P401R


Hello collegues,

I have following hw setup in my project .

MSP432 is communicating through 2 UARTS UART0 and UART2 to other components.

One of the scenario MSP has to ask through UATRT0 and answer through UART2.

So far, is clear. I try to do this with DMA, exactly with DMA scatter gather.

My first attempt fails..

I define an array DMA control table.. this way

DMA_ControlTable configExchange[2] =
{
    DMA_TaskStructEntry(HEADER_LENGTH + CONFIG_PAYLOAD_LENGTH, UDMA_SIZE_8,
                        UDMA_SRC_INC_8, txBuff,
                        UDMA_DST_INC_NONE, &EUSCI_A0->TXBUF,
                        UDMA_ARB_1, UDMA_MODE_BASIC),

    DMA_TaskStructEntry(HEADER_LENGTH + CONFIG_PAYLOAD_LENGTH, UDMA_SIZE_8,
                        UDMA_SRC_INC_NONE, &EUSCI_A2->RXBUF,
                        UDMA_DST_INC_8, rxBuff,
                        UDMA_ARB_1, UDMA_MODE_BASIC)
};

And how must I set DMA gath scatt. ? What DMA channel I have to assign?

DMA_setChannelScatterGather(/*DMA_CHANNEL*/,1,(void*),configExchange,1);


Rest of DMA setting is obvious and I have no question there. Only this one above..

Thanks
  • Yuliy,

       The "MODE" that you set in the tasks should also be scatter-gather except for the last one which can be basic.  

    Please find examples here:

    Regards,

    Chris

  • > The "MODE" that you set in the tasks should also be scatter-gather except for the last one which can be basic.
    Oh Yes, I did it already in the code...
    What about core question?
  • You could do this a couple of different ways.

    (1) You could have one channel triggered from RX(CH5) and another from TX (CH0).  This would mean that you would have to manually clear the txifg and then wait for the RX.  The task list triggered from the RX (CH5) would recieve the data based upon the peripheral scatter gather but the next to last byte recieved would use the memory scatter gather so that the next task which starts the transmit sequence would start automatically.  By writing to the TX buf the other dma channel (CH0) would start to move data into the TX as the TXBUF is available.  Please see the previously mentioned demo's on how to mix memory and peripheral scatter-gather.

    (2) You could have everything triggered from the RX (CH5).  You would still need to mix the memory and peripheral scatter gather to transition between the RX and TX.  The key is putting in 'dummy' tasks in the TX mechanism so that the DMA does not write to the TXBUF faster then it is actually transmitting data.

    Chris

  • Hello Chris,

    you wrote

    This would mean that you would have to manually clear the txifg and then wait for the RX.  The task list triggered from the RX (CH5) would recieve the data based upon the peripheral scatter gather but the next to last byte recieved would use the memory scatter gather so that the next task which starts the transmit sequence would start automatically.  By writing to the TX buf the other dma channel (CH0) would start to move data into the TX as the TXBUF is available


    Sorry did not get your advise

    >This would mean that you would have to manually clear the txifg and then wait for the RX

    manually, means CPU, menas no scatter gather automation. right?  

    >that the next task which starts the transmit sequence would start automaticallyGood,

    that is what I want, question, what channel must I use in 

    DMA_setChannelScatterGather? first param?

    will investigate examples,
    thanks
  • Yuli,
    When the eUSCI peripheral is released from reset (you hold in reset to configure), the TXIFG is automatically set. If you were to enable a DMA channel which is triggered from the TXIFG , then the DMA would automatically start moving data. So as part of the configuration the CPU would clear the TXIFG before setting up the DMAs. Hope that makes more sense.

    Chris

    MAP_DMA_setChannelScatterGather(DMA_CH4_EUSCIA2TX,TX_TASKS,(void*)&txData[0],false);
    MAP_DMA_setChannelScatterGather(DMA_CH1_EUSCIA0RX,RX_TASKS,(void*)&rxData[0],false);
  • Thank you Chris,

    i will investigate the issue but only at Wendsday, we have a holiday in Germany.

    Sorry for delay, I hope I do not make your balance of unanswerwed topics too much...

    :-)

  • just cuirious
    DMA_setChannelScatterGather(.., uint32_t isPeriphSG )
    last paramether is telling, according to documentation.... "The flag bIsPeriphSG should be used to indicate if scatter-gather should be configured for peripheral or memory operation."
    from other hand it is already defined in DMA_TaskStructEntry macro last param - UDMA_MODE_MEM_SCATTER_GATHER.

    Why? Or do I misunderstand the meaning of paramethers?
  • Hi Chris,

    another small question..

    from  ADC DMA example

        DMA_TaskStructEntry(1, UDMA_SIZE_8,
                    UDMA_SRC_INC_NONE, &EUSCI_B2_SPI->RXBUF,
                    UDMA_DST_INC_NONE, &dummyRX,
                    UDMA_ARB_4, (UDMA_MODE_MEM_SCATTER_GATHER+UDMA_MODE_ALT_SELECT)),
        /* Task2, Clear Chip select */
        DMA_TaskStructEntry(1, UDMA_SIZE_8,
                    UDMA_SRC_INC_NONE, &outputLow,
                    UDMA_DST_INC_NONE, &P3->OUT,
                    UDMA_ARB_4, (UDMA_MODE_MEM_SCATTER_GATHER+UDMA_MODE_ALT_SELECT)),
        /* Task3, load TX buffer to initiate SPI */
        DMA_TaskStructEntry(1, UDMA_SIZE_8,
                    UDMA_SRC_INC_NONE, &dummyTX,
                    UDMA_DST_INC_NONE, &EUSCI_B2_SPI->TXBUF,
                    UDMA_ARB_4, (UDMA_MODE_PER_SCATTER_GATHER+UDMA_MODE_ALT_SELECT)),

    When we read from periphery (UART) we use  UDMA_MODE_MEM_SCATTER_GATHER

    when we write po periphery we use  UDMA_MODE_PER_SCATTER_GATHER

    Why? it is clear the second, I do not understand first...Both works with periphery...

  • Hello Chris,

    have another question, sorry, last for today.
    Is it in theory possible in DMA task to switch UART settings?
    I mean, because of HW restriction UART TX can be done at 8 MHz, UART RX can be done at 1 MHz.
    So I have an idea of using one UART, but switch speed, and switch this in DMA setter gather task?
    Is it possible ?
  • Yuli,
    This is dependent upon if you want the task to be triggered from a peripheral trigger or auto-triggered. So for example, for the RX channel, each transfer from the uart to SRAM is triggered by the UART RX. Once all of the bytes are received a task should be auto-triggered to write to the TX buffer. Once that byte is moved into the shift register the TX ifg is set and triggers the other DMA channel to move another byte into the TX buffer and subsequent moves to the TXBUF are triggered by the TX ifg. Please keep in mind of which trigger you need and when (auto vs manual || memory vs peripheral).

    Yes, you can use the DMA to reconfigure the peripheral. Amit has an example of this here:

    dev.ti.com/.../

    In this example the tasks move between peripheral (ADC in this case) and memory. The memory tasks reconfigure the associated peripherals.

    /* 9. Transfer the 1024 samples of 40 KHz */
    DMA_TaskStructEntry(ABF_SAMPLES, UDMA_SIZE_32,
    UDMA_SRC_INC_NONE, &ADC14->MEM[1],
    UDMA_DST_INC_32, (void *)&ui32ABFArray[0],
    UDMA_ARB_1, UDMA_MODE_PER_SCATTER_GATHER
    ),
    /* 10. Stop the Timer-A0 */
    DMA_TaskStructEntry(1, UDMA_SIZE_16,
    UDMA_SRC_INC_NONE, (void *)&TimerStopCommand,
    UDMA_DST_INC_NONE, &TIMER_A0->CTL,
    UDMA_ARB_1, UDMA_MODE_MEM_SCATTER_GATHER
    ),
    /* 11. Re configure the Timer-A0 CCR for 400 KHz */
    DMA_TaskStructEntry(1, UDMA_SIZE_16,
    UDMA_SRC_INC_NONE, (void *)&TimerCCR1Update400K,
    UDMA_DST_INC_NONE, &TIMER_A0->CCR[0],
    UDMA_ARB_1, UDMA_MODE_MEM_SCATTER_GATHER
    ),
    /* 12. Stop the ADC */
    DMA_TaskStructEntry(1, UDMA_SIZE_32,
    UDMA_SRC_INC_NONE, (void *)&ADCStopCommand,
    UDMA_DST_INC_NONE, &ADC14->CTL0,
    UDMA_ARB_1, UDMA_MODE_MEM_SCATTER_GATHER
    ),

    Regards,
    Chris
  • Thank you Chris, you really help me.

    I hope others also will have good info out of our dialog.

    Another small question

    I see

    DMA_TaskStructEntry(1, UDMA_SIZE_8,
    UDMA_SRC_INC_NONE, &dummyTX,
    UDMA_DST_INC_NONE, &EUSCI_B2_SPI->TXBUF,
    UDMA_ARB_4, (UDMA_MODE_PER_SCATTER_GATHER+UDMA_MODE_ALT_SELECT))
     

    I am curious, why we use UDMA_MODE_PER_SCATTER_GATHER+UDMA_MODE_ALT_SELECT

    I mean '+' sign, usually we use logical or ..
  • Yuli,

        I am glad that this was helpful.  Coming from an MSP430 background I do not find the Scatter-gather very intuitive, but I think that is just because it is new to me.

      There is no reason to use the '+' instead of a logical or.  I think the logical or would be more appropriate in this context.  Moreover, the UDMA_MODE_ALT_SELECT is not needed because by definition the tasks are performed in the alternate channel while the primary channel is used to load the tasks into the alternate in the scatter-gather mode.  In more recent examples this definition is omitted.

    Regards,

    Chris 

  • >Moreover, the UDMA_MODE_ALT_SELECT is not needed because by definition the tasks are performed in the alternate channel..
    That is also a bit strange for me.

    Please do not close the thread?topic, since I am in a middle of this scatter-gather function probably will ask some advice.

    it won't take much time.
  • Hi Chris,

    have difficulties in implementation of HW pair

    MSP432  (UART TX with DMA gather-scatter) -----------> Tiva TM4C129 (UART RX TI Rtos DMA )

    test shows following problems

    RX receives first TX sending properly, but all subsequent with some amount of garbage. it looks like overlapping... first happens lost 2 or 4 bytes, then rest is overlapping or shifted..

    since I expect fixed TX Telegramm size. I see it clearly.. no random bytes but right byte but wrong place. I hope you understand what I mean.

    this is my DMA Task array

    static DMA_ControlTable dmaControlTablesConfigTX[1] =
    {
        DMA_TaskStructEntry(HEADER_LENGTH + CONFIG_PAYLOAD_LENGTH, UDMA_SIZE_8,
                            UDMA_SRC_INC_8, txBuff,
                            UDMA_DST_INC_NONE, &EUSCI_A0->TXBUF,
                            UDMA_ARB_1, UDMA_MODE_BASIC)
    };
    
    //this is my DMA set code 
    
    static void prepareDMA_scatter_gather()
    {
        MAP_DMA_enableModule();
        MAP_DMA_setControlBase(dmaControlTable);
    
        MAP_DMA_assignChannel(DMA_CH0_EUSCIA0TX);
        MAP_DMA_assignChannel(DMA_CH5_EUSCIA2RX);
        MAP_DMA_clearInterruptFlag(DMA_CHANNEL_0);
        MAP_DMA_clearInterruptFlag(DMA_CHANNEL_5);
    
        MAP_DMA_assignInterrupt         (INT_DMA_INT0, DMA_CHANNEL_0);
        MAP_DMA_assignInterrupt         (INT_DMA_INT0, DMA_CHANNEL_5);
        MAP_DMA_enableInterrupt         (INT_DMA_INT0);
    
        MAP_Interrupt_enableInterrupt   (INT_DMA_INT0);
    
        MAP_DMA_enableInterrupt         (INT_DMA_ERR);
        MAP_Interrupt_enableInterrupt   (INT_DMA_ERR);
    }
    
    //this is IRQ
    
    void DMA_INT0_IRQHandler(void)
    {
      const uint32_t dma_status = DMA_getInterruptStatus();
    
      if(dma_status & (1 << DMA_CHANNEL_0))
      {
          MAP_DMA_disableChannel        (DMA_CHANNEL_0);
          MAP_DMA_clearInterruptFlag    (DMA_CHANNEL_0);
          ch0Fn(true);
      }
    
      if(dma_status & (1 << DMA_CHANNEL_5))
      {
          MAP_DMA_disableChannel        (DMA_CHANNEL_5);
          MAP_DMA_clearInterruptFlag    (DMA_CHANNEL_5);
          ch5Fn(true);
      }
    }

    I have a feeling that I miss something related UART in IRQ handler..

     

  • and I send with following code



    MAP_DMA_setChannelScatterGather(DMA_CH0_EUSCIA0TX,1,(void*)dmaControlTablesConfigTX,1); MAP_DMA_enableChannel(DMA_CHANNEL_0);

**Attention** This is a public forum