2025-02-22 10:36 AM - edited 2025-02-22 10:39 AM
Hello,
I'm facing a bizarre issue with USART2 in STM32H7 chip.
My H7 is connected to 8 F072 chips via UART. Communication with each chip uses a dedicated UART from 1 to 8.
All the data exchanges in both RX and TX work fine during normal operativity of my product even exchanging lots of data. I dont use any RTOS, I set priority in the NVIC table to manage concurrency.
-----
The problem starts when from the H7 I manage to transmit to the F0s a new version of their software to be installed by a bootloader. Once again during the data transmission and even the copy by the boot everything is fine. At the end of the installation process inside the F0s, when the main application is launched by the boot, that sends 3 bytes of "welcome" to the H7 to confirm the process has completed successfully.
For UART 1 and from 3 to 8 the welcome bytes are sent and received correctly. for UART2 I see an overrun error on the RX of the peripheral. Please keep in made that the whole process is repeated 8 times sequentially and the implementation is exactly the same, both inside the F0 and the H7.
Checking the registers of USART2 I see that in the RDR there is the first byte of the welcome message but the RXNE bit is in fact set. The ORE bit is also set. So according to my understanding the second byte of the welcome message arrives in the shift register before the first is red from the RDR. I really can't understand why only UART2 and only in this specific transfer is suffering this communication issue.
Some more implementation info:
1) the UARTs in both F0 and H7 are all set and receiving in async
2) all the UART configs are absolutely the same! (or at least this is what it looks like form CubeMX view)
3) this is the code in the callback on the H7
//rb_USART_CHxx_rx is a cyrcular FIFO buffer
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART1)
{
HAL_UART_Receive_IT(&huart1, &uart1_data, 1);
bufferWrite2(&rb_USART_CH1_rx, uart1_data);
isUartCh1Rx = true;
}
else if(huart->Instance == USART2)
{
HAL_UART_Receive_IT(&huart2, &uart2_data, 1);
bufferWrite2(&rb_USART_CH2_rx, uart2_data);
isUartCh2Rx = true;
}
else if(huart->Instance == USART3)
{
HAL_UART_Receive_IT(&huart3, &uart3_data, 1);
bufferWrite2(&rb_USART_CH3_rx, uart3_data);
isUartCh3Rx = true;
}
else if(huart->Instance == UART5)
{
HAL_UART_Receive_IT(&huart5, &uart4_data, 1);
bufferWrite2(&rb_USART_CH4_rx, uart4_data);
isUartCh4Rx = true;
}
else if(huart->Instance == USART6)
{
HAL_UART_Receive_IT(&huart6, &uart5_data, 1);
bufferWrite2(&rb_USART_CH5_rx, uart5_data);
isUartCh5Rx = true;
}
else if(huart->Instance == UART7)
{
HAL_UART_Receive_IT(&huart7, &uart6_data, 1);
bufferWrite2(&rb_USART_CH6_rx, uart6_data);
isUartCh6Rx = true;
}
else if(huart->Instance == UART9)
{
HAL_UART_Receive_IT(&huart9, &uart7_data, 1);
bufferWrite2(&rb_USART_CH7_rx, uart7_data);
isUartCh7Rx = true;
}
else if(huart->Instance == UART8)
{
HAL_UART_Receive_IT(&huart8, &uart8_data, 1);
bufferWrite2(&rb_USART_CH8_rx, uart8_data);
isUartCh8Rx = true;
}
else if(huart->Instance == UART4)
{
HAL_UART_Receive_IT(&huart4, &uartMST_data, 1);
bufferWrite2(&rb_USART_MST_rx, uartMST_data);
isUartMSTRx = true;
}
}
4) i have tried to switch the communication of different F0s from USART1 (working) to USART2 (not working) and viceversa and the result is the same.
What it seems to me is that for some reason on USART2 the call back is not running in this situation or the reading function is not working HAL_UART_Receive_IT(&huart2, &uart2_data, 1);
Any idea to point me in some direction? Here I'm getting crazy.
Thanks,
Filo
2025-02-22 2:37 PM
If RXNE and ORE are set, the interrupt wasn't handled fast enough, as you said.
There are a limited number of reasons an interrupt isn't running, so check each of them:
If all those check out, perhaps the interrupt is ran but due to some other bug (e.g. out of bounds write) the uart handle is corrupted and the HAL handler doesn't behave as expected.
It sure sounds like the interrupt just wasn't handled quickly enough. I'd look at other parts of your code, particularly interrupt handlers, which may be taking longer than allowed. You can shuffle priorities to ensure USART2 is handled first as a debug measure.
2025-02-22 7:48 PM
You create race issues by passing an active buffer to a secondary routine.
HAL_UART_Receive_IT(&huart1, &uart1_data, 1); // you make uart1_data volatile/hot
bufferWrite2(&rb_USART_CH1_rx, uart1_data);
Should perhaps swap these around
>>Here I'm getting crazy
Don't view the UART registers in the debugger, it will interfere, you're NOT looking at MEMORY cells, but a portal to combinational logic
2025-02-23 7:23 AM - edited 2025-02-23 7:25 AM
Thanks for the points Tesla. Interesting indeed. I will try to swap and let you know.
However, I have some doubt due to the fact that I made several tests, at this point, and what i see are very consistent results: for USART1 and 3, 4 , 5 , 6 , 7 , 8 -> 100% of the tests are fine. For USART 2 -> 100% of the tests are faulty. I mean, if there is a variable which becomes volatile by definition I would expect to see some inconsistent results...
Having said the above do you mind if I ask the following? Given, as you have seen in my code, to be in a call back for RX USART, given to have a circular buffer to feed and finally given to have to read the data in the RDR how would you do it to avoid the potential issue you mentioned?
Thanks again so much
Filo
2025-02-23 9:38 AM
Thanks TDK i will check for sure and bring the screenshots.
Cheers
Filo
2025-02-28 12:32 AM
Hello Tesla,
I tried inverting the 2 statements but no way... same issue
Cheers
Filippo
2025-02-28 1:03 AM - edited 2025-02-28 1:24 AM
..