Because of the Thanksgiving holiday in the U.S., TI E2E™ design support forum responses may be delayed from November 25 through December 2. Thank you for your patience.

AM2634: I want to use UART in DMA mode using Interrupt.

Part Number: AM2634

Tool/software:

Hello,

I am trying to use UART in DMA mode with interrupts, and I am referring to the following resources: (1. UART Echo DMA, 2. UART Echo Callback). However, I am encountering a problem where the main function gets stuck in the uart_echo_dma function, waiting for the read and write operations to complete.

Here is a snippet of my code:

int main(void)
{
System_init();
Board_init();

uart_echo_dma(NULL);  // stuck here.

GPIO_setDirMode(LED_BASE_ADDR, LED_PIN, LED_DIR);
while(1)
{
GPIO_pinWriteHigh(LED_BASE_ADDR, LED_PIN);
ClockP_sleep(1);
GPIO_pinWriteLow(LED_BASE_ADDR, LED_PIN);
ClockP_sleep(1);
}


Board_deinit();
System_deinit();

return 0;
}

I am sharing my system configuration snapshot for reference.

 

i am sharing my uart_echo_dma file code, check i am doing right or wrong:

/*
 * uart0_echo_dma.c
 *
 *  Created on: 04-Nov-2024
 *      Author: SahilShakilMalpekar
 */



#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      (8U)

uint8_t gUartBuffer[APP_UART_BUFSIZE];
uint8_t gUartReceiveBuffer[APP_UART_RECEIVE_BUFSIZE];
volatile uint32_t gNumBytesRead = 0U, gNumBytesWritten = 0U;

/* Semaphore to indicate Write/Read completion used in callback api's */
static SemaphoreP_Object gUartWriteDoneSem;
static SemaphoreP_Object gUartReadDoneSem;

#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) \

void uart_echo_dma(void *args) {
  int32_t transferOK, status;
  UART_Transaction trans;

  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);

  /* Send entry string */
  gNumBytesWritten = 0U;
  trans.buf = &gUartBuffer[0U];
  strncpy(trans.buf,
          "This is uart echo test DMA callback mode\r\nReceives 8 characters "
          "then echoes 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);

  /* Wait for write completion */
  SemaphoreP_pend(&gUartWriteDoneSem, SystemP_WAIT_FOREVER);
  DebugP_assert(gNumBytesWritten == strlen(trans.buf));

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

  /* Wait for read completion */
  SemaphoreP_pend(&gUartReadDoneSem, SystemP_WAIT_FOREVER);
  DebugP_assert(gNumBytesRead == APP_UART_RECEIVE_BUFSIZE);

  /* Transmit received data on RFID_READER2 UART */
  gNumBytesWritten = 0U;
  trans.buf = &gUartReceiveBuffer[0U];
  trans.count = APP_UART_RECEIVE_BUFSIZE;
  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);

  DebugP_log("[UART] Transmitting to RFID_READER2 ...\r\n");
  /* Wait for write completion */
  SemaphoreP_pend(&gUartWriteDoneSem, SystemP_WAIT_FOREVER);
  DebugP_assert(gNumBytesWritten == APP_UART_RECEIVE_BUFSIZE);

  /* Echo chars entered back to the SERVICE_PORT */
  gNumBytesWritten = 0U;
  trans.buf = &gUartReceiveBuffer[0U];
  trans.count = APP_UART_RECEIVE_BUFSIZE;
  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);

  /* Wait for write completion */
  SemaphoreP_pend(&gUartWriteDoneSem, SystemP_WAIT_FOREVER);
  DebugP_assert(gNumBytesWritten == APP_UART_RECEIVE_BUFSIZE);

  /* Send exit string */
  gNumBytesWritten = 0U;
  trans.buf = &gUartBuffer[0U];
  strncpy(trans.buf, "\r\nAll tests have passed!!\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);

  /* Wait for write completion */
  SemaphoreP_pend(&gUartWriteDoneSem, SystemP_WAIT_FOREVER);
  DebugP_assert(gNumBytesWritten == strlen(trans.buf));

  DebugP_log("All tests have passed!!\r\n");

  Board_driversClose();
  Drivers_close();

  return;
}


void uart_echo_write_callback(UART_Handle handle, UART_Transaction *trans)
{
    DebugP_assertNoLog(UART_TRANSFER_STATUS_SUCCESS == trans->status);
    gNumBytesWritten = trans->count;
    SemaphoreP_post(&gUartWriteDoneSem);

    return;
}

void uart_echo_read_callback(UART_Handle handle, UART_Transaction *trans)
{
    DebugP_assertNoLog(UART_TRANSFER_STATUS_SUCCESS == trans->status);
    gNumBytesRead = trans->count;
    SemaphoreP_post(&gUartReadDoneSem);

    return;
}

If anyone knows how I can resolve this issue, please help me.

Thank you!

  • Hi Sahil,

    In your UART code, when you run the application, can you place breakpoints at the following points and verify what you see in the buffers:

    1. Line no. 73. If your buffer has the expected correct data,

    2. Line no. 103. Do you see this log on your UART Console?

    3. Line no. 116.

    Knowing where exactly the program crashes would help. Do you enter the 8 characters in the correct COM port console for the UART? 

    Also, in case you have configured GPIO interrupt, can you share what is the priority of the GPIO interrupt and as well as the UART interrupt prioirity.

    Regards,
    Shaunak

  • no i'm not using interrupt for GPIO simple LED toggle in main function but it start after entering 8 character. i want to run my main independently. 

    i want to send the UART data in DMA mode but it's not working as general DMA because semaphore is blocking our process that means it is no sense to us DMA in that way.

    sending data by the DMAcould be a different process (parallel process) processor should not block to send the data.

    so please let me know how to remove semaphore to fulfill our requirement.   

    can i get any idea how i can achieve my requirement. 

  • Hi Sahil,

    I am a bit confused here.

    You are using semaphores, which are posted (execution resumes) only in the callback function. The read and write operations Pend (halt the execution until semaphore is posted). The comments express the same. Right now the code is written in blocking calls.

    I recommend going through the below documentation to understand the modes of operation.

    https://software-dl.ti.com/mcu-plus-sdk/esd/AM263X/latest/exports/docs/api_guide_am263x/DRIVERS_UART_HLD_PAGE.html

    The above documentation also has code snippets for the write and read operations with the callback functions.

    Your syscfg settings seem correct to me. Just the code needs to be refactored from using blocking semaphores to non-blocking mutexes.

    Regards,
    Shaunak