2020-10-01 09:14 AM
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
2020-10-02 11:45 AM
DMA
2020-10-02 02:42 PM
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.
2020-10-02 03:46 PM
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.
2020-10-14 08:05 AM
Did you mean to receive character -by-character in interrupt mode? Do you have a simple example?
2020-10-14 10:53 AM
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
}
}