Skip to main content
Visitor II
October 1, 2020
Question

What is the best mode for uart in RTOS?

  • October 1, 2020
  • 3 replies
  • 1905 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.

    3 replies

    Super User
    October 2, 2020

    DMA

    Explorer 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.

    Visitor II
    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.

    xmartAuthor
    Visitor II
    October 14, 2020

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

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