2025-05-29 3:05 AM - edited 2025-05-29 3:22 AM
Recently I have encountered a strange issue I cannot really explain...
I have a firmware that manages serial UART communication with a callback that has a state machine with 3 states.
In the first state, UART is set to perpetually expect 1 byte of data until a specific value is received. If the value is received, another byte is set to be read via UART_Receive_IT and SM proceeds to the next state.
In the second state, the received byte is considered message length and UART_Receive_IT is set to read the expected amount of bytes.
The third state is supposed to happen when the expected amount of bytes is received and all parsing is done... however, it is never triggered when the serial data is longer than 49 bytes.
I am sending data with RealTerm. Short messages work just fine, but then I need to send 147 bytes. In the debug, I can see from the state of huart2 handler that RxXferCount starts at 147 and decrements until 98. Then, UART_RxISR_8BIT is never called again, the state remains unchanged until firmware's timeout triggers and aborts the reception.
I tried to look at some other things. RTS and CTS pins are low at the time when timeout happens. The timeout was initially 0.02s, I raised it to 1s with no effect. Overrun flag is low as well. My buffer is larger than the message I am expecting. I tried to use UART_Receive_IT in batches of 32 bytes, but then the first batch is received correctly and the second batch freezes in the similar way as soon as the total amount of received bytes reaches 49. I am not supposed to reset something between UART_Receive_IT calls, correct?
Why UART might just stop receiving data? What else can I do to try debug this?
Solved! Go to Solution.
2025-05-29 7:18 AM
Hello everyone, thank you for the participation.
After a couple of tests I found out that Realterm v2.0.0.7 does not send more than 49 bytes in one go for some reason. I used a makeshift python script to send the data and it worked. Good grief, threw me for quite a loop.
2025-05-29 3:18 AM
A common STM32 bug: uncached memory or alignment issues if you use DMA with a non-DMA-safe buffer.
Check that your Rx buffer is:
__attribute__((aligned(4))) // Especially on Cortex-M7 or with DCache
uint8_t rx_buf[256];
Also, if using DMA, ensure buffer is in RAM region not cached, e.g., .dma_buffer section or DTCM.
2025-05-29 3:21 AM
Hello,
I have a similar issue in the past, in my case was regarding the "send" through UART. In my case when i wanted to send more bytes through UART, i had to increase the timeout for function:
HAL_UART_Transmit(&huart1, sendbuf, sizeof(sendbuf), 100);
When i wanted this function with a timeout of like, 10ms, it was sending few bytes, then i did increase the timeout and worked.
In the receiver what i do is a custom rutine to get byte by byte in each interrupt.
I do a similar "protocol" as you mentioned. Try to check in your stm32 device that you are trating the values as uint8_t and not as string, for example.
2025-05-29 3:27 AM
Hello, I am not using DMA, only IT.
I tried to add
__attribute__((aligned(4)))
before the declaration of my buffer but it did not resolve the issue.
2025-05-29 3:29 AM
Hello, my firmware does not use UART in polling mode and the problem is only with the reception. I transmit data using a serial terminal from my PC, RealTerm.
2025-05-29 3:39 AM
@MO94 wrote:I transmit data using a serial terminal from my PC, RealTerm.
How, exactly, do you do that?
Are you typing characters manually, one-by-one, or getting RealTerm to send them all together as a block?
If the latter, perhaps you are too slow in your receive handling, and you are getting UART overrun ... ?
If the former, you should be able to follow it in the debugger, and see what changes at 98 ...
2025-05-29 3:44 AM
I send the whole message package together by inserting the data and pressing Send Numbers.
As I mentioned in my post, I checked the overrun by reading __HAL_UART_GET_FLAG(&huart2, UART_FLAG_ORE) when the timeout happened and the value was 0.
In the debugger, I tried to follow the communication and saw only that past 98 counter value the interrupt is not called anymore.
2025-05-29 3:47 AM
how do you configure the: HAL_UART_Receive_IT? can you show the code that configure the IT?
2025-05-29 3:51 AM
@MO94 wrote:I send the whole message package together by inserting the data and pressing Send Numbers.
So try doing it manually; or perhaps RealTerm lets you put a delay between characters ...
2025-05-29 3:52 AM
My UART is initialized like this:
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}