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.

[FAQ] AM62P-Q1: Continuous Data Streaming over UART using DMA

Part Number: AM62P-Q1

Continuous Data Streaming over UART is a use-case across different applications. Lets check the implementation and any additional pointers to take care of while implementing this.

This FAQ applies to other SoCs as well like AM62x, AM64x, AM62Ax, AM62Dx, AM275x, AM62Lx.

SDK Reference: www.ti.com/.../11.02.00.23

Drivers Reference: https://github.com/TexasInstruments/mcupsdk-core-k3/tree/k3_main/source/drivers/uart/v0

  • Prerequisite: MCU+ SDK UART Driver - Transfer Completion Behavior

    Summary

    The UART driver's UART_write() API behavior varies significantly depending on the transfer mode. Only Polled mode guarantees that data has been fully transmitted on the wire when the function returns. All other modes (Interrupt and DMA, both Blocking and Callback) only guarantee that data has been transferred to the UART TX FIFO, not that it has been transmitted on the physical TX line.

    Key Terminology

    Term

    Definition

    Transfer Complete

    Data moved from application buffer to UART TX FIFO

    On the Wire

    Data transmitted from TX FIFO → Shift Register → TX Pin

    TX FIFO Empty

    UART_LSR_TX_FIFO_E_MASK (bit 5 of LSR)

    TX Shift Register Empty

    UART_LSR_TX_SR_E_MASK (bit 6 of LSR)

    Detailed Mode Analysis

    Polled Mode

    Aspect

    Behavior

    UART_write() returns when

    All data transmitted on wire

    Data on wire guaranteed?

    YES

    Additional API needed?

    No

    Implementation: The driver busy-waits until both TX FIFO and Shift Register are empty before returning.

     

     

     

    Interrupt + Blocking Mode

    Aspect

    Behavior

    UART_write() returns when

    All data moved to TX FIFO

    Data on wire guaranteed?

    NO

    Additional API needed?

    UART_flushTxFifo()

    Implementation: Blocks on semaphore; ISR posts semaphore when last byte enters FIFO.

     

     

    Interrupt + Callback Mode

    Aspect

    Behavior

    UART_write() returns when

    Immediately after transfer initiated

    Callback fires when

    All data moved to TX FIFO

    Data on wire guaranteed?

    NO (not even at callback)

    Additional API needed?

    UART_flushTxFifo() after callback

    Implementation: Returns immediately; callback invoked when last byte enters FIFO.

     

     

     

    DMA + Blocking Mode

    Aspect

    Behavior

    UART_write() returns when

    DMA transfer complete (data in FIFO)

    Data on wire guaranteed?

    NO

    Additional API needed?

    UART_flushTxFifo()

    Implementation: Blocks on semaphore; DMA completion ISR posts semaphore.

     

     

     

    DMA + Callback Mode

    Aspect

    Behavior

    UART_write() returns when

    Immediately after DMA initiated

    Callback fires when

    DMA transfer complete (data in FIFO)

    Data on wire guaranteed?

    NO (not even at callback)

    Additional API needed?

    UART_flushTxFifo() after callback

    Implementation: Returns immediately; callback invoked on DMA completion.

     

     

    Summary Matrix:

    Mode

    Returns When

    Data on Wire?

    Action Required

    Polled

    TX complete

    YES

    None

    Interrupt + Blocking

    Data → FIFO

    NO

    Call UART_flushTxFifo()

    Interrupt + Callback

    Immediately

    NO

    Call UART_flushTxFifo() in callback

    DMA + Blocking

    Data → FIFO

    NO

    Call UART_flushTxFifo()

    DMA + Callback

    Immediately

    NO

    Call UART_flushTxFifo() in callback

    UART_flushTxFifo() Limitation

    UART_flushTxFifo() calls TaskP_yield() internally and is not safe to call from ISR/callback context. Doing so will cause undefined behaviour.

    Instead the following implementation can be used:

    /*
     * Wait for UART TX to complete - ISR safe version
     * Polls the Line Status Register directly without calling TaskP_yield()
     *
     * NOTE: UART_flushTxFifo() is NOT safe to call from ISR/callback context
     * because it calls TaskP_yield() internally, which causes a crash.
     */
    static void waitForTxComplete_IsrSafe(UART_Handle handle)
    {
        uint32_t baseAddr = UART_getBaseAddr(handle);
        uint32_t lineStatus;
    
        /*
         * Wait until both:
         * - TX FIFO is empty (bit 5: UART_LSR_TX_FIFO_E_MASK = 0x20)
         * - TX Shift Register is empty (bit 6: UART_LSR_TX_SR_E_MASK = 0x40)
         */
        do
        {
            lineStatus = UART_readLineStatus(baseAddr);
        }
        while ((lineStatus & (UART_LSR_TX_FIFO_E_MASK | UART_LSR_TX_SR_E_MASK))
               != (UART_LSR_TX_FIFO_E_MASK | UART_LSR_TX_SR_E_MASK));
    }


  • UART + DMA + Callback + Continuous Streaming:

    8081.uart_echo_callback.zip

    For Blocking + DMA + Continuous Mode:

    Use the following API "waitForTxComplete_IsrSafe", as mentioned above, just after UART_write API call.