Skip to main content
xmart
Associate II
October 1, 2020
Question

What is the best mode for uart in RTOS?

  • October 1, 2020
  • 5 replies
  • 1951 views

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

This topic has been closed for replies.

5 replies

Pavel A.
October 2, 2020

DMA

Nikita91
Lead II
October 2, 2020

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
October 2, 2020

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.

xmart
xmartAuthor
Associate II
October 14, 2020

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

underpickled
Associate
October 14, 2020

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
 }
}