• Not Answered

Using SSI0 with uDMA

I am having some issues getting the uDMA and SSI0 to work on the LM3S2B93. I have been able to get just SSI0 working as well as the UART0 with uDMA but when I attempt to make SSI0 transfers using the uDMA I keep getting errors in my uDMAErrorHandler ISR.  I have seen a couple of examples of how to set up the transfers and the other parameters and I have followed the examples.

What typically causes a peripheral uDMA error? Any insight on where I should look to troubleshoot this?

Thanks,

Matt

24 Replies

  • The uDMA error interrupt is essentially the same thing as a bus  fault.  It means the uDMA controller tried to access some memory that caused a bus fault.  Have you enabled the SSI0 peripheral?  Are the to/from addresses for your DMA transfer legal addresses?

  • In reply to Stellaris Joe:

    Hello Joe,

    Here is the code I am using to set it up (attached). My "locbuf" is a buffer I was previously sending directly to the SPI. Now I just load the data into the buffer and do the following;

     uDMAChannelEnable(UDMA_CHANNEL_SSI0TX);

    uDMAChannelEnable(UDMA_CHANNEL_SSI0RX);

     

    Thanks,

    Matt

  • In reply to Matthew Fratkin:

    For some reason my code didnt attach so here it is below:



    //Intialization routine

    #include "driverlib/udma.h"
    #include "inc/hw_types.h"
    #include "driverlib/ssi.h"
    #include "main.h"
    #include "ssi_udma.h"


    #include "inc/hw_ssi.h"


    extern volatile char locbuf;
    extern volatile char ssiRxBuf;

    #pragma DATA_ALIGN(ucControlTable, 1024)
    unsigned char ucControlTable[1024];


    void init_ssiDMA()
    {

       SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);

       uDMAEnable();

       uDMAControlBaseSet(ucControlTable);

       uDMAChannelSelectDefault(UDMA_DEF_SSI0TX_SEC_SSI1TX | UDMA_DEF_SSI0RX_SEC_SSI1RX);


       //SET UP SSI RX channel
       uDMAChannelAttributeDisable(UDMA_CHANNEL_SSI0RX,
                                               UDMA_ATTR_USEBURST |
                                   UDMA_ATTR_HIGH_PRIORITY |
                                   UDMA_ATTR_REQMASK);

       uDMAChannelAttributeEnable(UDMA_CHANNEL_SSI0RX, UDMA_ATTR_USEBURST);

       uDMAChannelControlSet(UDMA_CHANNEL_SSI0RX,
                             UDMA_SIZE_8       |
                             UDMA_SRC_INC_NONE |
                             UDMA_DST_INC_8    |
                             UDMA_ARB_8);

       uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT,
                                                          UDMA_MODE_BASIC,
                                       (void *)(SSI0_BASE + SSI_O_DR),
                                       (unsigned char*) ssiRxBuf, sizeof(ssiRxBuf));

       //SET UP SSI TX channel
       uDMAChannelAttributeDisable(UDMA_CHANNEL_SSI0TX,
                                    UDMA_ATTR_ALTSELECT |
                                    UDMA_ATTR_HIGH_PRIORITY |
                                    UDMA_ATTR_REQMASK);

       uDMAChannelAttributeEnable(UDMA_CHANNEL_SSI0TX, UDMA_ATTR_USEBURST);

       uDMAChannelControlSet(UDMA_CHANNEL_SSI0TX ,
                                    UDMA_SIZE_8         |
                                    UDMA_SRC_INC_8      |
                                    UDMA_DST_INC_NONE    |
                                    UDMA_ARB_4);

     

       uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT,
                                                       UDMA_MODE_BASIC,
                                    (unsigned char*) locbuf
                                    (void *)(SSI0_BASE + SSI_O_DR), sizeof(locbuf));


       SSIDMAEnable(SSI0_BASE, SSI_DMA_TX | SSI_DMA_RX);


    }

    //ISR for when a DMA request completes

    void ssi_txISRFxn(UArg argo)
    {
       txCntr++;

       unsigned long ulStatus;
       unsigned long ulMode;

       ulStatus = SSIIntStatus(SSI0_BASE, true);

       SSIIntClear(SSI0_BASE, true);

       ulMode = uDMAChannelModeGet(UDMA_CHANNEL_SSI0TX);


       uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT,
                                     UDMA_MODE_BASIC,
                                    (unsigned char*) locbuf
                                    (void *)(SSI0_BASE + SSI_O_DR), sizeof(locbuf));

       uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT,
                                                             UDMA_MODE_BASIC,
                                          (void *)(SSI0_BASE + SSI_O_DR),
                                          (unsigned char*) ssiRxBuf, sizeof(ssiRxBuf));

    }

  • In reply to Matthew Fratkin:

    First question, is the SSI peripheral enabled?  Somewhere you have a function call SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0)?

    Second question, have you been able to do any debug to see at what point the fault occurs?  For example is any transfer occurring or is the error happening immediately?  One way to test this is to put a pattern in the source buffer and clear the destination buffer before you start.  Then when the error occurs, use the debugger to examine the destination buffer and see if any of the pattern has been copied.

    Does the ssi_tx_ISRFxn() ever get triggered?

  • In reply to Stellaris Joe:

    Hello Joe,

    Yes, I do call the SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0) in another location (before I do the DMA SSI initialization).

    The TX ISR gets called the same number of times the uDMA Error ISR gets called.  I took a look in the RX buffer (destination buffer) and see only 8 bytes from my source buffer. I am trying to transfer 53 bytes at a time.

    Thanks,

    Matt

  • In reply to Matthew Fratkin:

    Hello Joe,

    I decided to just load 10 bytes into my TxBuf and try the DMA transfer. After I start the transfer I immediately get an error and do not see any of the expected bytes (remain 0x00) in the buffer.

    Thanks,

    Matt

  • In reply to Matthew Fratkin:

    Matt, I am sorry for the delay in getting back to you.  I can not tell what is wrong from what I see so far.  Is it possible for you to send me a .c file that I can build myself to see the problem?  If I can reproduce in my office I am sure I will be able to figure it out.  You can try to attach a file to the forum post.  If that doesnt work you can paste in the text (as you have already done).

  • In reply to Stellaris Joe:

    Hello Joe,

    Here is my attached .c file.

    3252.ssi_udma.c

    Thanks,

    Matt

  • In reply to Matthew Fratkin:

    Matt, I tried to build that but there is just too much missing.  I tried to hack in the missing pieces but at this point I am changing it so much I am not sure of the point.  It is missing a main(), there are several header files referenced that I dont have, some externs are referenced that are not defined.  There is also no int handler in this file.  Is it possible for you to collect the pieces into one file or a small set of files that I can successfully compile and that will show the problem?  That is going to be the fastest way for me to figure out what is wrong.

  • In reply to Stellaris Joe:

    I also noticed that the DMA control table is not aligned.  That will cause problems.  If this is how you are using it, that could explain the fault.