cancel
Showing results for 
Search instead for 
Did you mean: 

What is the best mode for uart in RTOS?

xmart
Associate II

Hi

I ask

What is the best mode for the uart in RTOS to send at command and receive it?

I think polling is inappropriate because it adopts systick

5 REPLIES 5
Pavel A.
Evangelist III

DMA

Nikita91
Lead II

It may depends on the UART baudrate and the MCU core frequency. At low baudrate, interrupt is convenient.

At high baudrate DMA may be more efficient for emit. For receive DMA can be tricky id you don't know the command size to receive.

underpickled
Associate II

I think it depends on what you're using it for. I'm using for debug prints and CLI, so for RX I just use Receive_IT mode for 1 character and the callback puts it in a buffer until it gets a newline character, and then it sends the buffer in a queue to a terminal task (I'm using FreeRTOS) and it gets processed by the terminal task and handled by FreeRTOS CLI.

For print I just replaced __putchar with a blocking 1 byte TX so I could use printf. It works well enough for what I need, but if you've got really tight timing you might want to use DMA for prints, or have a more strict command length so you don't have to process one char at a time on the input.

Did you mean to receive character -by-character in interrupt mode? Do you have a simple example?

Yes, exactly. When you're ready to start running the terminal/command prompt, you start listening for a single character in IT mode. In the callback, you store the character and start listening again. In my code (not shown below), if I received a command to process, I start listening again after that command has completed. Here's my callback for reference:

static void uart_rx_cb(UART_HandleTypeDef *huart)
{
    static char rx_buffer[COMMAND_LENGTH_MAX]; // Local holding buffer to build line, w/NUL
    static int rx_index = 0;
 
    char rx = (char)(huart->Instance->RDR & 0xFF);
    if ((rx == '\r') || (rx == '\n')) // Look for end-of-line
    {
        if (rx_index != 0) // Check that line has contents
        {
            osMessageQueuePut(xCommandQueue, rx_buffer, 0, 0); // Copy to queue from live dynamic receive buffer
        }
        rx_index = 0; // Reset content pointer
        memset(rx_buffer, 0, sizeof(rx_buffer));
    }
    else if (rx_index < COMMAND_LENGTH_MAX) // add to the buffer as long as we're not overflowing
    {
        rx_buffer[rx_index++] = rx; // Copy to buffer and increment
        HAL_UART_Receive_IT(&huart4, &rxByte, 1);   // Keep listening
    }
    else // clear the buffer if we're going to overflow
    {
        rx_index = 0;
        memset(rx_buffer, 0, sizeof(rx_buffer));
        HAL_UART_Receive_IT(&huart4, &rxByte, 1);   // Keep listening
    }
}