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.

AM2634: Uart receive interrupt in DMA mode

Part Number: AM2634


Tool/software:

Hi Team,

I'm working on AM2634 eval board, and try to receive data on UART in DMA mode, its working fine with existing code example but it run only one time,

I want to use it continuously, please let me know the best way to do

I tried this also but not working

DMA receive callback function.

void RxCallback(UART_Handle handle, UART_Transaction *trans)
{

/* Read 8 chars */
gNumBytesRead = 0U;
trans->buf = &gUartReceiveBuffer[0U];
trans->count = APP_UART_RECEIVE_BUFSIZE;
UART_Transaction_init(trans);
CacheP_wbInv((void *)&gUartReceiveBuffer[0U], APP_UART_RECEIVE_BUFSIZE, CacheP_TYPE_ALL);
transferOKrx = UART_read(gUartHandle[CONFIG_UART_CONSOLE], trans);
APP_UART_ASSERT_ON_FAILURE(transferOKrx, trans);
}

  • Hi Rohal,

    Can you please explain what is "continuously" means here, using while loop for UART_read API?

    Regards,

    Anil

  • continuously mean after getting 8 byte (threshold set value) it should be get ready to receive next 8 byte and so on, because existing example code works only one time I need it for finitely.

    And Please let me know how to receive variable length data on UART, because as per my application USER can send variable size of data means some times he can send 10, 20 or 50 bytes   

  • Hi Rohal,

    continuously mean after getting 8 byte (threshold set value) it should be get ready to receive next 8 byte and so on, because existing example code works only one time I need it for finitely.

    Right now the application is designed to take 8B input from user, then echo back the same 8B and exit the application, You will have to modify the application to keep receiving data (for e.g. in a While loop, keep receiving data).

    Regards,
    Shaunak

  • I tried that also but its not receiving any interrupt after getting 8 bytes, So do we need to clear any interrupt flag to make it run again

     CacheP_wbInv((void *)&gUartReceiveBuffer[0U], APP_UART_RECEIVE_BUFSIZE, CacheP_TYPE_ALL); 

    above api blocking my process, please let me know how to remove Cache and get the interrupt on every receive the byte 

    Can we use DMA with Interrupt mean for transmission get interrupt after sending the all data and for reception get interrupt after getting data(all transmission and reception happen by DMA only) 

  • Hi Rohal,

    I believe the same question is being asked here by your colleague: https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1479707/am2634-uart-dma-receive-callback-reinitialization
    I have given the code snippet which I was able to test multiple UART reads and writes.

    And Please let me know how to receive variable length data on UART, because as per my application USER can send variable size of data means some times he can send 10, 20 or 50 bytes   

    Regarding this, let me get back in some time with steps.

    Regards,
    Shaunak

  • Yes, please look into this ASAP,

    one more issue noticed here,

    I configure 5 byte receive interrupt in DMA mode and its working fine for 5 bytes only, if user send more than 5 bytes lets 6, it's stopped receiving interrupt, 

    i'm share the code also please check

    /*
     *  Copyright (C) 2021 Texas Instruments Incorporated
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /* This example demonstrates the UART RX and TX operation by echoing char
     * that it recieves in blocking, interrupt mode of operation.
     * When user types 'quit', the application ends.
     */
    
    #include <string.h>
    #include <kernel/dpl/DebugP.h>
    #include "ti_drivers_config.h"
    #include "ti_drivers_open_close.h"
    #include "ti_board_open_close.h"
    
    
    #define APP_UART_BUFSIZE              (200U)
    #define APP_UART_RECEIVE_BUFSIZE      (20U)
    
    uint8_t gUartBuffer[APP_UART_BUFSIZE] __attribute__((aligned(CacheP_CACHELINE_ALIGNMENT)));
    uint8_t gUartReceiveBuffer[APP_UART_RECEIVE_BUFSIZE] __attribute__((aligned(CacheP_CACHELINE_ALIGNMENT)));
    volatile uint32_t gNumBytesRead = 0U, gNumBytesWritten = 0U;
    
    #define APP_UART_ASSERT_ON_FAILURE(transferOK, transaction) \
        do { \
            if((SystemP_SUCCESS != (transferOK)) || (UART_TRANSFER_STATUS_SUCCESS != transaction.status)) \
            { \
                DebugP_assert(FALSE); /* UART TX/RX failed!! */ \
            } \
        } while(0) \
    
    
    static SemaphoreP_Object gUartWriteDoneSem;
    static SemaphoreP_Object gUartReadDoneSem;
    static uint8_t rxcomplete=0;
    void uart_echo_dma(void *args)
    {
        int32_t          transferOK, status;
        UART_Transaction trans;
        UART_Transaction transRx;
    
        Drivers_open();
        Board_driversOpen();
    
        DebugP_log("[UART] Echo example DMA mode started ...\r\n");
    
        status = SemaphoreP_constructBinary(&gUartWriteDoneSem, 0);
        DebugP_assert(SystemP_SUCCESS == status);
    
        status = SemaphoreP_constructBinary(&gUartReadDoneSem, 0);
        DebugP_assert(SystemP_SUCCESS == status);
        UART_Transaction_init(&trans);
        UART_Transaction_init(&transRx);
    
        /* Send entry string */
        gNumBytesWritten = 0U;
        trans.buf   = &gUartBuffer[0U];
        strncpy(trans.buf,"This is uart echo test DMA blocking mode\r\nReceives 8 characters then echo's back. Please input..\r\n", APP_UART_BUFSIZE);
        trans.count = strlen(trans.buf);
        CacheP_wb((void *)trans.buf, trans.count, CacheP_TYPE_ALL);
        transferOK = UART_write(gUartHandle[CONFIG_UART_CONSOLE], &trans);
    
        APP_UART_ASSERT_ON_FAILURE(transferOK, trans);
        SemaphoreP_pend(&gUartWriteDoneSem, SystemP_NO_WAIT);
    
        CacheP_wbInv((void *)&gUartReceiveBuffer[0U], APP_UART_RECEIVE_BUFSIZE, CacheP_TYPE_ALL);
        /* Read 8 chars */
        gNumBytesRead = 0U;
        transRx.buf   = &gUartReceiveBuffer[0U];
        transRx.count = 5;
        transferOK = UART_read(gUartHandle[CONFIG_UART_CONSOLE], &transRx);
        APP_UART_ASSERT_ON_FAILURE(transferOK, transRx);
        SemaphoreP_pend(&gUartReadDoneSem, SystemP_NO_WAIT);
    
        /* Echo chars entered */
    
        while(1)
        {
            if(rxcomplete==1)
            {
                gNumBytesWritten = 0U;
                trans.buf   = &gUartReceiveBuffer[0U];
                trans.count = transRx.count;
                transferOK = UART_write(gUartHandle[CONFIG_UART_CONSOLE], &trans);
                APP_UART_ASSERT_ON_FAILURE(transferOK, trans);
                SemaphoreP_pend(&gUartWriteDoneSem, SystemP_NO_WAIT);
                rxcomplete=0;
    
                gNumBytesRead = 0U;
                transRx.buf   = &gUartReceiveBuffer[0U];
                transRx.count = 5;
                transferOK = UART_read(gUartHandle[CONFIG_UART_CONSOLE], &transRx);
                APP_UART_ASSERT_ON_FAILURE(transferOK, transRx);
                SemaphoreP_pend(&gUartReadDoneSem, SystemP_NO_WAIT);
            }
        }
        /* Send exit string */
    
        return;
    }
    void RxCallback(UART_Handle handle, UART_Transaction *transaction)
    {
        DebugP_assertNoLog(UART_TRANSFER_STATUS_SUCCESS == transaction->status);
        gNumBytesRead = transaction->count;
        SemaphoreP_post(&gUartReadDoneSem);
        rxcomplete=1;
    //        (void)RTI_counterEnable(CONFIG_RTI0_BASE_ADDR, RTI_TMR_CNT_BLK_INDEX_0);
    
    
    }
    
    void TxCallBack(UART_Handle handle, UART_Transaction *transaction)
    {
        DebugP_assertNoLog(UART_TRANSFER_STATUS_SUCCESS == transaction->status);
           gNumBytesWritten = transaction->count;
           SemaphoreP_post(&gUartWriteDoneSem);
    }
    uint8_t timer1ms;
    void TimerCallback()
    {
        timer1ms++;
    //    rxcomplete = 1;
        (void)RTI_counterDisable(CONFIG_RTI0_BASE_ADDR, RTI_TMR_CNT_BLK_INDEX_0);
    
    }
    
     

    Please suggest how to handle Uart Errors also (Frame error and over run error)

  • Hi Rohal,

    One question,

    What is the value you have configured in your UART module in example.syscfg? By default, the trigger level is set to 8

    This means that as soon as Rx FIFO has 8Bytes, it will trigger an interrupt.

    Regards,
    Shaunak