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.

CCS/TM4C1294NCPDT: A little help with DMA

Part Number: TM4C1294NCPDT

Tool/software: Code Composer Studio

i'm working over transferring the data from a array and the sending it to a UART port using the DMA method. I'm able to put it on the data register of UART 1 but unable to shown the same over the COM port.

how can i do this.... if i dont want to use any more arrays!!!

  • Hi Rohan,

    There is the udma_demo example program at Tivaware that you can review.

    -kel
  • yes i have seen that example and i'm wishing to make some changes into that example according to the requirement as mentioned.
  • Hello Rohan,

    I don't really understand what information you are missing based on your description, can you outline what steps you have taken, what the results are so far, and what is missing from what is currently working for you? And to that point, what about the udma_demo is not meeting your needs?
  • Hello Ralph,
    So what i want to do is to send a data from a memory location over the com port of my pc using the dma.
    so far i have not achieved any result in it, i can only update the memory register of the given UART port but cannot display it over the UART com port.

    Thank you
    Rohan Parvatiyar
  • Hello Rohan,

    What you would need to do is buffer the data and then use a UART print API to send it to the PC. If you are wanting to feed the UART print APIs direct from the DMA, that has not been implemented (to my knowledge) and wouldn't make much sense either as the UART printing would be slow compared the DMA transfers and you'd gain no tangible benefit as a result. The idea with DMA is to allow the CPU to transfer data during idle CPU clock cycles to improve efficiency. That wouldn't lend well to outputting data over the UART console which is a CPU clock cycle driven operation. What would make more sense is using the DMA to fill the next buffer while the UART print is outputting the current buffer in order to speed up the overall time it takes to receive data vs transmit it back out.
  • void
    InitUART1Transfer(void)
    {
        uint_fast16_t ui16Idx;
    
        //
        // Fill the TX buffer with a simple data pattern.
        //
        for(ui16Idx = 0; ui16Idx < UART_TXBUF_SIZE; ui16Idx++)
        {
            g_ui8TxBuf[ui16Idx] = ui16Idx;
        }
    
        //
        // Enable the UART peripheral, and configure it to operate even if the CPU
        // is in sleep.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART0);
    
        //
        // Configure the UART communication parameters.
        //
        ROM_UARTConfigSetExpClk(UART0_BASE, g_ui32SysClock, 115200,
                                UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                                UART_CONFIG_PAR_NONE);
    
        //
        // Set both the TX and RX trigger thresholds to 4.  This will be used by
        // the uDMA controller to signal when more data should be transferred.  The
        // uDMA TX and RX channels will be configured so that it can transfer 4
        // bytes in a burst when the UART is ready to transfer more data.
        //
        ROM_UARTFIFOLevelSet(UART0_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8);
    
        //
        // Enable the UART for operation, and enable the uDMA interface for both TX
        // and RX channels.
        //
        ROM_UARTEnable(UART0_BASE);
        ROM_UARTDMAEnable(UART0_BASE, UART_DMA_RX | UART_DMA_TX);
    
        //
        // This register write will set the UART to operate in loopback mode.  Any
        // data sent on the TX output will be received on the RX input.
        //
        HWREG(UART0_BASE + UART_O_CTL) |= UART_CTL_TXE|UART_CTL_RXE;
      
        
        //
        // Put the attributes in a known state for the uDMA UART0RX channel.  These
        // should already be disabled by default.
        //
        ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_UART0RX,
                                        UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
                                        UDMA_ATTR_HIGH_PRIORITY |
                                        UDMA_ATTR_REQMASK);
    
        //
        // Configure the control parameters for the primary control structure for
        // the UART RX channel.  The primary contol structure is used for the "A"
        // part of the ping-pong receive.  The transfer data size is 8 bits, the
        // source address does not increment since it will be reading from a
        // register.  The destination address increment is byte 8-bit bytes.  The
        // arbitration size is set to 4 to match the RX FIFO trigger threshold.
        // The uDMA controller will use a 4 byte burst transfer if possible.  This
        // will be somewhat more effecient that single byte transfers.
        //
        ROM_uDMAChannelControlSet(UDMA_CHANNEL_UART0RX | UDMA_PRI_SELECT,
                                  UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 |
                                  UDMA_ARB_4);
    
        
        ROM_uDMAChannelTransferSet(UDMA_CHANNEL_UART0RX | UDMA_PRI_SELECT,
        							UDMA_MODE_BASIC,
                                   (void *)(UART0_BASE + UART_O_DR),
                                   g_ui8RxBufA, sizeof(g_ui8RxBufA));
    
        //
        // Set up the transfer parameters for the UART RX alternate control
        // structure.  The mode is set to ping-pong, the transfer source is the
        // UART data register, and the destination is the receive "B" buffer.  The
        // transfer size is set to match the size of the buffer.
        //
       /* ROM_uDMAChannelTransferSet(UDMA_CHANNEL_UART0RX | UDMA_ALT_SELECT,
                                   UDMA_MODE_PINGPONG,
                                   (void *)(UART0_BASE + UART_O_DR),
                                   g_ui8RxBufB, sizeof(g_ui8RxBufB));*/
    
        //
        // Put the attributes in a known state for the uDMA UART0TX channel.  These
        // should already be disabled by default.
        //
        ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_UART0TX,
                                        UDMA_ATTR_ALTSELECT |
                                        UDMA_ATTR_HIGH_PRIORITY |
                                        UDMA_ATTR_REQMASK);
    
        //
        // Set the USEBURST attribute for the uDMA UART TX channel.  This will
        // force the controller to always use a burst when transferring data from
        // the TX buffer to the UART.  This is somewhat more effecient bus usage
        // than the default which allows single or burst transfers.
        //
        ROM_uDMAChannelAttributeEnable(UDMA_CHANNEL_UART0TX, UDMA_ATTR_USEBURST);
    
        //
        // Configure the control parameters for the UART TX.  The uDMA UART TX
        // channel is used to transfer a block of data from a buffer to the UART.
        // The data size is 8 bits.  The source address increment is 8-bit bytes
        // since the data is coming from a buffer.  The destination increment is
        // none since the data is to be written to the UART data register.  The
        // arbitration size is set to 4, which matches the UART TX FIFO trigger
        // threshold.
        //
       ROM_uDMAChannelControlSet(UDMA_CHANNEL_UART0TX | UDMA_PRI_SELECT,
                                  UDMA_SIZE_8 | UDMA_SRC_INC_8 |
                                  UDMA_DST_INC_NONE |
                                  UDMA_ARB_4);
    
        //
        // Set up the transfer parameters for the uDMA UART TX channel.  This will
        // configure the transfer source and destination and the transfer size.
        // Basic mode is used because the peripheral is making the uDMA transfer
        // request.  The source is the TX buffer and the destination is the UART
        // data register.
        //
        ROM_uDMAChannelTransferSet(UDMA_CHANNEL_UART0TX | UDMA_PRI_SELECT,
                                   UDMA_MODE_BASIC, g_ui8TxBuf,
                                   (void *)(UART0_BASE + UART_O_DR),
                                   sizeof(g_ui8TxBuf));
    
        printf("data %X \n",(void *)(UART0_BASE + UART_O_DR));
        //
        // Now both the uDMA UART TX and RX channels are primed to start a
        // transfer.  As soon as the channels are enabled, the peripheral will
        // issue a transfer request and the data transfers will begin.
        //
        ROM_uDMAChannelEnable(UDMA_CHANNEL_UART0RX);
        ROM_uDMAChannelEnable(UDMA_CHANNEL_UART0TX);
    
        //
        // Enable the UART DMA TX/RX interrupts.
        //
        ROM_UARTIntEnable(UART0_BASE, UART_INT_DMATX | UART_INT_DMATX);
    
        //
        // Enable the UART peripheral interrupts.
        //
        ROM_IntEnable(INT_UART0);
    }

    Hello Ralph,

    The basic idea was not to print the data only but yes it was just a part of the project.

    i'm trying to set a array of 0-256 and transmit it to the UART0 com port by using the DMA without using the print function.

    Thank  You!

  • Hello Rohan,

    The example you are working from used a loopback mode which included TX and RX setup due to nature of how loopback is done. For the example you are describing, you want to TX to the terminal. I see a lot of code that sets up RX though. I would recommend removing anything related to RX for now and first focus on getting TX working. If you need to process RX as well, then we add that piece on after, but it would simply the process of debugging if you could clean the code up by removing everything related to RX and see if you get any different behavior.
  • Hello Ralph,

    i tried removing all the RX component from this example enabling only the TX for sending the data over the COM Port but yet noting comes up over it.

    Thank You
    Rohan
  • Should it not be noted that the (failing UART0) has (only) been 'PARTIALLY INITIALIZED!'

    // Enable the UART peripheral, and configure it to operate even if the CPU is in sleep.

        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

        ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART0);

    Are not (additional) calls to the basic functions:

    • SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    and

    • GPIOPinConfigure(GPIO_PA0_U0RX);
    • GPIOPinConfigure(GPIO_PA1_U0TX);
    • GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    also required?     Is it sufficient to 'rely upon'  -  these calls being either 'default behavior'  - or made  (maybe)  elsewhere?

    As poster notes:  "Enabling only the TX for sending the data over the COM Port ... but yet noting comes up over it."    ('it'  being -  (the incompletely initialized)  'UART0!')

    The (always)  'uber Problem Resolving'  'KISS'  directs that,  'ALL of the EXCESS'  (not just the (already) excised RX code) be (temporarily removed) and that the MOST BASIC 'UART CODE EXAMPLE'  be instead  installed  -  and then Test/Verified.    

    If and Only when - that, 'MOST BASIC - YET  MOST VITAL of OPERATIONS IS CONFIRMED'  should (INDIVIDUAL PIECES) of the 'EXCESS' be added - and  individually  and  sequentially  tested -  ONE MEASURED/Confirmed  Step  (or piece)   at a time...

  • hello cb1
    the UART0 has been completely initialised with all the function mentioned above but i have not included that into the code shown
    if you'll look at the example then there is a function of UART config tat is for this function. i have removed the rx part from that function and have tried with enabling the rx also in that function.

    thank you
    rohan!!
  • Greetings - and thank you for your (so quick) response.

    Now few here could know that you've (selectively) provided (and removed) function calls - and the "FAR less Vital" 'Sleep Enable()'  WAS included - which  confounds!    (the VITAL is hidden - 'excess' included   - that's inconsistent - is it not?)     And ... time-wasting & Krazy-Making...

    As suggested - the code (shown ... unknown is what else lurks ... 'out of sight') adds complexity - and severely violates, 'KISS.'     Errors & clashes are 'INVITED' - which proves SO unwise!

    As earlier stated - the smallest, easiest code implementation - which succeeds in obtaining proper output from your UART - stands as my, 'Best, First and Only' recommendation!     (Should you (really) desire to, 'Slay your UART Dragon!'     (the added complexity and 'pitfalls' - introduced by CODE EXCESS - proves NOT your friend!      And no friend to your helper crüe - either...)

    As an ex US Army Officer - we were taught to, 'Limit the size/scope of our battle' - fighting against  'ALL  SIDES/DIRECTIONS'  - most always - does NOT 'end well.'    (such holds here ... as well.)

  • hello cb1

    i'm so sorry for not mentioning the name of the project well it is udma_demo for the board TM4C1294NCPDT in code composer studio. i hope now you can easily refer to this example and provide me with some good solution so that i can achieve the set of output required.

    thank you!!
    Rohan
  • Do read again - my posting - arriving '8 minutes' prior to yours! Debugging and Resolving 'en masse' - has long been proven - to be a 'minimally effective' Solution-Resolving method... 'Baby steps' - even as noted by the (first) moon-walker - make GREAT (and the BEST) SENSE!
  • hello Ralph,

    The basic requirement of ours is to make use of DMA to transfer the data to the UART peripheral without CPU intervention not to take the RX buffer out from DMA and then transfer it to UART which takes extra CPU cycles.
    We only want that our processed buffer can be transferred to the UART peripheral so that our code doesn't stuck on ISR for processing the data and sending to the UART. Please suggest how could we go with this demo code to get our requirements.

    thank you
    rohan
  • Hello Rohan,

    Can you please post the code with the RX functions removed so I can review it once more without all the RX-centric calls included?
  • void
    ConfigureUART(void)
    {
        //
        // Enable the GPIO Peripheral used by the UART.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Enable UART0
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        ROM_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART0);
    
        //
        // Configure GPIO Pins for UART mode.
        //
        //ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
        ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
        ROM_GPIOPinTypeUART(GPIO_PORTA_BASE,  GPIO_PIN_1);
    
        //
        // Initialize the UART for console I/O.
        //
        UARTStdioConfig(0, 115200, g_ui32SysClock);
    }
    
    void
    UART0IntHandler(void)
    {
        uint32_t ui32Status;
        uint32_t ui32Mode;
    
        //
        // Read the interrupt status of the UART.
        //
        ui32Status = ROM_UARTIntStatus(UART0_BASE, 1);
    
        //
        // Clear any pending status, even though there should be none since no UART
        // interrupts were enabled.  If UART error interrupts were enabled, then
        // those interrupts could occur here and should be handled.  Since uDMA is
        // used for both the RX and TX, then neither of those interrupts should be
        // enabled.
        //
        ROM_UARTIntClear(UART0_BASE, ui32Status);
    
        //
        // Check the DMA control table to see if the ping-pong "A" transfer is
        // complete.  The "A" transfer uses receive buffer "A", and the primary
        // control structure.
        //
        ui32Mode = ROM_uDMAChannelModeGet(UDMA_CHANNEL_UART0TX | UDMA_PRI_SELECT);
    
        //
        // If the primary control structure indicates stop, that means the "A"
        // receive buffer is done.  The uDMA controller should still be receiving
        // data into the "B" buffer.
        //
        if(ui32Mode == UDMA_MODE_STOP)
        {
            //
            // Increment a counter to indicate data was received into buffer A.  In
            // a real application this would be used to signal the main thread that
            // data was received so the main thread can process the data.
            //
            g_ui32RxBufACount++;
    
            //
            // Set up the next transfer for the "A" buffer, using the primary
            // control structure.  When the ongoing receive into the "B" buffer is
            // done, the uDMA controller will switch back to this one.  This
            // example re-uses buffer A, but a more sophisticated application could
            // use a rotating set of buffers to increase the amount of time that
            // the main thread has to process the data in the buffer before it is
            // reused.
            //
            ROM_uDMAChannelTransferSet(UDMA_CHANNEL_UART0TX | UDMA_PRI_SELECT,
            							UDMA_MODE_BASIC,
                                       (void *)(UART0_BASE + UART_O_DR),
                                       g_ui8RxBufA, sizeof(g_ui8RxBufA));
        }
    
           
        //
        // If the UART1 DMA TX channel is disabled, that means the TX DMA transfer
        // is done.
        //
        if(!ROM_uDMAChannelIsEnabled(UDMA_CHANNEL_UART0TX))
        {
            //
            // Start another DMA transfer to UART1 TX.
            //
            ROM_uDMAChannelTransferSet(UDMA_CHANNEL_UART0TX | UDMA_PRI_SELECT,
                                       UDMA_MODE_BASIC, g_ui8TxBuf,
                                       (void *)(UART0_BASE + UART_O_DR),
                                       sizeof(g_ui8TxBuf));
    
            //
            // The uDMA TX channel must be re-enabled.
            //
            ROM_uDMAChannelEnable(UDMA_CHANNEL_UART0TX);
        }

    i have mentioned the two of my function that has been configured in favour of UART0 with only TX enabled.

    thank you 

    rohan

  • Hello Rohan,

    Sorry for the delay but I decided it would be easier to make a CCS project example myself from udma_demo to do something a kin to what you are trying. It is hardly complete, but it definitely transfers UDMA data straight to the terminal. This will give you the UDMA setup code.

    Please compare the setup code for your project vs this one and see any differences. I know one thing I changed from your example is that in the UDMA_MODE_STOP if statement, I adjusted ROM_uDMAChannelTransferSet to use g_ui8TxBuf instead of g_ui8RxBufA.

    udma_demo_tx_only.zip

  • hello ralph,
    thank you so much for this help.... yet i have achieved the transfer to the com port via udma was doing some silly mistakes from basic.

    regards
    Rohan