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.

MSP432E411Y: I want to know the timing of DMA transfer start through QSSI module.

Part Number: MSP432E411Y

Hello,

I have questions about DMA and QSSI setting.

I referred to the following documentation, but I couldn't find an answer.

MSP432E4 DriverLib API Guide

http://software-dl.ti.com/simplelink/esd/simplelink_msp432e4_sdk/4.20.00.12/docs/driverlib/msp432e4/api_guide/html/group__udma__api.html#ga1020903cbcc5a03434c3f5c13f252a72

http://software-dl.ti.com/simplelink/esd/simplelink_msp432e4_sdk/4.20.00.1MSP432E4%20DriverLib%20API%20Guide/docs/driverlib/msp432e4/api_guide/html/group__ssi__api.html#ga897bf9d2d751cb23cdef74c222ed141e

 

I want to know the timing of DMA transfer start through QSSI module.

In my situation, when uDMAChannelAssign() is called, DMATXRIS is set.

① Does DMA transfer start when uDMAChannelAssign () is called?

②  If SSIEnable () is called before assigning to a channel, will DMA start forwarding immediately after the assignment?

③  Does DMA start forwarding only when uDMAChannelEnabe () is called?

④ Is it okay to call SSIDMAEnable () at any time before calling uDMAChannelEnabe ()?

Best Regards,

Koki

  • Hello,

    Do you have any update?

    Thanks,

    Koki

  • 1. DMA will start forwarding only when uDMAChannelEnabe () is called. You can see this in the DMA transmit example.

    2. About this one "Is it okay to call SSIDMAEnable () at any time before calling uDMAChannelEnabe ()?", I think yes. But I advice you test it by yourself.

  • Hi,

    I ran the sample code below.

    DMATXRIS is set when uDMAChannelAssign is called.

    So If I call IntEnable, an interrupt occurs even though the DMA transfer is not yet complete.

    Why DMATXRIS is interrupted after Assign and is there any workaround?

    The evaluation board is MSP42E411Y-BGAEUM Rev A.

     

    ==========================================================

    #include "ti/devices/msp432e4/driverlib/driverlib.h"

    uint8_t pui8ControlTable[1024] __attribute__ ((aligned(1024)));

     

    #ifdef DEBUG

    void __error__(char *pcFilename, uint32_t ui32Line)

    {

    }

    #endif

     

    int main(void)

    {

                         // Set System Clock

                    (void)SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |

                                                 SYSCTL_OSC_MAIN |

                                                 SYSCTL_USE_PLL |

                                                 SYSCTL_CFG_VCO_480), 120000000);

     

      // Enable UDMA

       SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);

       SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA);

       uDMAEnable();

     

                         // Enable SSI2

                         SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2);

                         SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_SSI2);

                        

                         // Set Parameter SSI2

                         SSIConfigSetExpClk(SSI2_BASE, 120000000, 3, 0, 25000000, 8);

                        

                         // Enable DMA Rx and DMA Tx

                         SSIDMAEnable(SSI2_BASE,(UART_DMA_RX | UART_DMA_TX));

                        

                         // Enable SSI2 Operation

                         SSIEnable(SSI2_BASE);

                        

                         // Channel Assign

                         uDMAChannelAssign(UDMA_CH13_SSI2TX);

      

                    while(true) {

                            // Do Nothing

                    }

    }

    ===================================================================

    Thanks,

    Koki

  • Hello,

    Do you have any update?

    Thanks,

    Koki

  • Sorry. I am on business travel, will be back in a week. Don't have board.

  • I've only used the DMA with the ADC, not the SSI, but based on TRM (SLAU723A) Sec 23.3.8 (first paragraph) the SSI will immediately issue a DMA request when the TXDMAE bit is set. Since the DMA control isn't set up, I expect it sees a "Stop" descriptor and stops with a completion interrupt.

    I suggest you not enable the SSI DMA until after the DMA descriptor(s) is initialized.

    [Edit: the 4th paragraph suggests that the "normal" usage is to keep TXDMAE=0 until you want to start a transaction, then clear it back to =0 after the transaction is over. I suspect it's fine to keep RXDMAE=1 all the time.]

  • Hi,

    >I suggest you not enable the SSI DMA until after the DMA descriptor(s) is initialized.

    Did I call uDMAChannelAssign () at the wrong time?

    I want you to tell me the right timing.

    Thanks,

    Koki

  • The code above is (part of) what I would expect to see in an initialization function. I recommend you Not call SSIDMAEnable() at all in that initialization function. I would expect the rest of that function would assign the DMA channel(s), and create the DMA descriptor(s) using uDMAChannelTransferSet().

    In a separate function which performs the actual data transfer, you would create the DMA descriptor(s) using uDMAChannelTransferSet()., then call SSIDMAEnable() to start the transaction. When the transaction is complete (perhaps in an Interrupt Service Routine), you would call SSIDMADisable() then SSIIntClear()..

    This is described in TRM Sec 23.4 (Step 6),, though the recommendation to set TXDMAEN (sub-step 3) then doesn't look right to me given what was said above.

    [Edit: I forgot about the transfer type -- uDMAChannelTransferSet() would normally be called in the read/write function, not the initialization function.]

  • In the API Guide contains a Programming Example.

    https://downloads.ti.com/simplelink/esd/simplelink_msp432e4_sdk/4.20.00.12/docs/driverlib/msp432e4/api_guide/html/group__udma__api.html

    The transfer start timing is described.

    When should SSIDMAEnable () be called in below?

    ==============================================

    Part of Programming Example in  the API Guide.    

                        :

                        :

    UDMA_MODE_AUTO, pui8SourceBuffer, pui8DestBuffer,
    sizeof(pui8DestBuffer));
    //
    // Finally, the channel must be enabled. Because this is a software-
    // initiated transfer, a request must also be made. The request starts the
    // transfer.
    //
    uDMAChannelEnable(UDMA_CHANNEL_SW);
    uDMAChannelRequest(UDMA_CHANNEL_SW);

    ==================================================

  • Hi,

    In the API guide, The transfer start timing is described.

    https://downloads.ti.com/simplelink/esd/simplelink_msp432e4_sdk/4.20.00.12/docs/driverlib/msp432e4/api_guide/html/group__udma__api.html

     

    When should SSIDMAEnable () be called?

     

    A part of Programming Example in API guide

    ====================================================

    :

    :

    uDMAChannelTransferSet(UDMA_CHANNEL_SW | UDMA_PRI_SELECT,

                           UDMA_MODE_AUTO, pui8SourceBuffer, pui8DestBuffer,

                           sizeof(pui8DestBuffer));

    uDMAChannelEnable(UDMA_CHANNEL_SW);

    uDMAChannelRequest(UDMA_CHANNEL_SW);

    ======================================================

  • SSIDMAEnable() would replace uDMAChannelRequest() in that example, since doing the (SSI) DMA enable (TXDMAEN) results in an immediate channel request from the SSI.

    There doesn't appear to be an example running the SSI with the DMA, but you might also want to glance over example adc0_singleended_multichannel_timertrigger_dmareq, starting about line 187:

    https://dev.ti.com/tirex/explore/node?node=AD2lu-FBfgxXTzSKEtIrZA__J4.hfJy__LATEST

  • > you might also want to glance over example adc0_singleended_multichannel_timertrigger_dmareq starting about  line 187:

    Line 187 is MAP_uDMAEnable () ;.

    I was talking about SSIDMAEnable () now, but do I need to change the timing of calling uDMAEnable()?

     

    Summary

    -The actual timing to call SSIDMAEnable () is in the transfer function.

    -SSIDMAEnable () is called in the DMA transfer function at the following timing.

    =====================

    uDMAChannelTransferSet ();

    uDMAChannelEnable ();

    SSIDMAEnable ();

    ======================

    Thanks,

  • I believe you can call uDMAChannelEnable() once, in the initialization step; however I expect that doing it for each transaction will not be wrong (perhaps unnecessary).

    I don't have any working examples, nor (apparently) does TI, but based on the TRM this fragment appears to be right. As a practical matter, the next step is probably for you to fill out the code and see what it does.

  • -SSIDMAEnable () is called in the DMA transfer function at the following timing.

    =====================

    uDMAChannelTransferSet ();

    uDMAChannelEnable ();

    SSIDMAEnable ();

    ======================

    Is the call timing of SSIDMAEnable() correct in this order?

  • Yes, this appears to be the correct sequence for these calls.

  • Hi,

    I have confirmed that the interrupt generation timing works properly.

    Thank you very much.

    Is it okay to understand that DMA transfer starts when SSIDMAEnable () is called?

    On what page of the technical reference is the description regarding ①?

    Please tell me why DMATXRIS was set before modifying the code. Is it a bug?

     Regarding (a) and (b) for determining the completion of DMA transfer

    (a). Obtain SSIMIS and check that DMATXMIS and DMARXMIS are set.

    (b). Call uDMAChannelModeGet () to get μDMA Transfer Mode and check that it is STOP

    Can you tell me which one is best for me?

    Thanks,

    Koki

  • 1) As a practical matter, setting TXDMAE (using SSIDMAEnable) causes the DMA to start. Strictly speaking, doing this (with the TX FIFO not-full, which is the usual case) causes an immediate request to the DMA unit; your earlier experiments show that this request will stay pending until the channel is assigned, but it will not wait for the DMA control words to be populated (this is an unsurprising result).

    2) This is described in TRM (SLAU723) Sec 23.3.8.

    3) The SSI issued the DMA request on setting TXDMAEN, but the DMA left it pending until it had a channel to use. When the channel was assigned, the DMA unit started the transfer, but the (uninitialized) DMA control word had a STOP(=0) transfer type, so the DMA stopped immediately. The TRM doesn't describe all possible interactions, but this one seems within the rules. The TRM does have a recommended sequence in Sec 23.4.

    4) For simple start/run/stop sequences such as what I expect you're doing, the two methods are equivalent. Where they diverge is when you use multiple-descriptor (notably Ping-Pong) sequences, where an interrupt may be triggered while the DMA is actually still active.

  • 1)

    >your earlier experiments show that this request will stay pending until the channel is assigned,

    >but it will not wait for the DMA control words to be populated (this is an unsurprising result).

    I'm sorry, I didn't understand.

    Please tell me in detail.

    3)

    > but the (uninitialized) DMA control word had a STOP(=0) transfer type, so the DMA stopped immediately. 

    Why is it a STOP transfer type?

    4)  

    > 1.simple start/run/stop sequences

    > 2.multiple-descriptor (notably Ping-Pong) sequences

    (a)1,2 is a transmit mode, right?

       Please tell me specifically what kind of transfer mode you say.

    (b) You said that 1 can be either (a) or (b).

    Which of (a) and (b) is recommended for 2?

  • 1) I recommend you follow the setup sequence in TRM Sec 23.4

    3) Stop=0 per TRM Tables 8-16/17. I know that byte is =0 since pui8ControlTable[] is set to =0 during C initialization.

    4)  Ping-Pong mode is described in TRM Sec 8.3.5.4. I expect you're not using that. (But that's just a guess since you haven't told us what you're trying to accomplish.) For Basic mode (TRM Sec 8.3.5.2) I suggest checking for the interrupt bit, since it's simpler. There are special requirements for the Tx interrupt with DMA -- see TRM Sec 23.3.8, 4th paragraph.

  • In summary, if I set TXDMAE before setting the transfer mode, DMA transfer will not work properly.

    If you set TXDMAE after setting the transfer mode, DMA transfer will be performed properly.

    1) Is this recognition correct?

    2) Why was DMATXRIS set when transferring in STOP mode in my earlier experiments ?

  • 1) Yes

    2) The DMA was considered (immediately) finished since the DMA unit fetched a descriptor with XFERMODE=Stop.

    As I said, the TRM doesn't describe all possible interactions. Some interactions can be determined through experiment (accidental or intentional). Your best bet is to follow the recommended setup (Sec 23.4).

  • Hi,

    >When the channel was assigned, the DMA unit started the transfer,

    >but the (uninitialized) DMA control word had a STOP(=0) transfer type, so the DMA stopped immediately. 

     

    The sample code I post in the before question does not call uDMAChannelEnable ().

    Will it still start DMA transfer after uDMAChannelAssign ()?

    ==========================================================

    #include "ti/devices/msp432e4/driverlib/driverlib.h"

    uint8_t pui8ControlTable[1024] __attribute__ ((aligned(1024)));

     

    #ifdef DEBUG

    void __error__(char *pcFilename, uint32_t ui32Line)

    {

    }

    #endif

     

    int main(void)

    {

                         // Set System Clock

                    (void)SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |

                                                 SYSCTL_OSC_MAIN |

                                                 SYSCTL_USE_PLL |

                                                 SYSCTL_CFG_VCO_480), 120000000);

     

      // Enable UDMA

       SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);

       SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA);

       uDMAEnable();

     

                         // Enable SSI2

                         SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2);

                         SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_SSI2);

                        

                         // Set Parameter SSI2

                         SSIConfigSetExpClk(SSI2_BASE, 120000000, 3, 0, 25000000, 8);

                        

                         // Enable DMA Rx and DMA Tx

                         SSIDMAEnable(SSI2_BASE,(UART_DMA_RX | UART_DMA_TX));

                        

                         // Enable SSI2 Operation

                         SSIEnable(SSI2_BASE);

                        

                         // Channel Assign

                         uDMAChannelAssign(UDMA_CH13_SSI2TX);

      

                    while(true) {

                            // Do Nothing

                    }

    }

    ===================================================================

    Thanks,

    Koki

  • This code sequence (still) requests the SSI to run a DMA transaction before either has been completely configured to do this. This sequence is not (as far as I know) described in the TRM, so any result is possible.

    If your goal is to successfully run an SSI transaction using the DMA, I recommend you follow the sequence described in the TRM.