2021-01-28 10:06 PM
MCU: STM32F072, clock: 48M
UART BR: 115200, clock: 48M
application: receive 20 bytes per second
issue: overrun happens sometimes, maybe after 3 hours or 1 day.
I think the clock is fast enough to handle the slow application, but overrun happens sometimes for my project. I'm wondering if the uart overrun is unavoidable?? If not, is there any way to 100% avoid the uart overrun??
2021-01-28 10:40 PM
How do you receive the data? Polling? interrupt? DMA? HAL? register level? Is the receiver 100% of the time "on"? Some code would also help.
2021-01-28 10:55 PM
Thanks for your reply. I use interrupt. Here is my code. Only USART1 and USART3 will be used. rb_write is for copying data to ring buffer.
Is the receiver 100% of the time "on"? Sorry, I'm not sure what you mean. Are you asking the received timing of 20 bytes in a second?
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_StatusTypeDef r;
char port;
if (huart->Instance == USART1) port = 0;
else if (huart->Instance == USART2) port = 1;
else if (huart->Instance == USART3) port = 2;
else if (huart->Instance == USART4) port = 3;
else return;
if (m_uart[port].rb_rx == NULL)
{
printf("port: %d, %s: rb is NULL\n", port, __func__);
}
else if (rb_is_full(*m_uart[port].rb_rx))
{
printf("port: %d, %s: rb_is_full\n", port, __func__);
}
else
{
rb_write((*m_uart[port].rb_rx), m_uart[port].ch);
}
r = HAL_UART_Receive_IT(huart, &m_uart[port].ch, 1);
}
#define rb_write(rb, c) \
do \
{ \
rb.data[rb.w] = c; \
rb.w = (rb.w + 1U) % rb.size; \
} while (0)
2021-01-28 11:59 PM
> 100% of the time "on"
If you receive one char per interrupt using HAL, there is some time from the beginning of the interrupt handler until your call of HAL_UART_Receive_IT for the next char. If this time is not short enough, overrun will happen. If this happens rarely (as in you case) the interrupt priority might not be high enough such that other interrupts (like SysTick) delay the UART interrupt handler.
Remedies:
For the DMA approch, check Tilen Majerle tutorials.
2021-01-29 10:24 AM
> r = HAL_UART_Receive_IT(huart, &m_uart[port].ch, 1);
As recently mentioned in other thread, HAL_UART_Receive_IT is not good for receiving by one byte - exactly because it enables RX interrupt only while in the function.
Between calls, the interrupt is disabled and overruns are expected.
UART of STM32F0 even does not have a FIFO.
So - roll your own "driver" where you keep the RX interrupt always enabled, or use DMA.
-- pa
2021-01-29 11:34 AM
The principles used in Tilen's example are usable also for interrupt mode, he just didn't implement it.
2021-01-29 11:37 AM
Even on L4 and F7 the USART peripheral doesn't have FIFO. It's a pretty new feature for STM32 MCUs. That said, it's a nice feature, but not a critical one.
2021-02-03 06:29 PM
Looks like LL driver solves my issue. HAL driver disables interrupt, but LL driver keeps interrupt enable. Is there any reason HAL has to disable interrupt? In other words, is there side effect when LL driver keeps interrupt enable?