2024-09-19 06:22 AM - last edited on 2024-09-24 09:05 AM by SofLit
Hello, during my tests I have come across a strange issue. During the initializing phase, my application was hitting a WWDG reset (after ~400ms) constantly. This only happened after a couple resets (toggling the NRST pin LOW).
I have concluded during debugging, that when this repeated resetting of the WWDG state occured, it is because the program is hanging on the autogenerated (via STM32CubeIDE) init function:
HAL_UART_Init(&huart2)
Looking further, it actually finishes most of the function code but hangs on the last function:
return (UART_CheckIdleState(huart));
It specifically hangs when doing the below check:
if (UART_WaitOnFlagUntilTimeout(huart, USART_ISR_TEACK, RESET, tickstart, HAL_UART_TIMEOUT_VALUE) != HAL_OK)
What baffles me, is how this is not repeatable behaviour. Most of the times I restart the MCU, it proceeds as intentioned. But sometimes it starts doing this infinite game of checking TEACK so long that WWDG resets it.
Before this code is executed, only other peripheral initilaization code is performed.
Any ideas?
Edit: Adding my current auto-generated USART parameters from the usart.c file
void MX_USART2_UART_Init(void)
{
/* USER CODE BEGIN USART2_Init 0 */
/* USER CODE END USART2_Init 0 */
/* USER CODE BEGIN USART2_Init 1 */
/* USER CODE END USART2_Init 1 */
huart2.Instance = USART2;
huart2.Init.BaudRate = 1000000;
huart2.Init.WordLength = UART_WORDLENGTH_9B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_EVEN;
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.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_RXOVERRUNDISABLE_INIT;
huart2.AdvancedInit.OverrunDisable = UART_ADVFEATURE_OVERRUN_DISABLE;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart2, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart2, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART2_Init 2 */
/* USER CODE END USART2_Init 2 */
}
:)
2024-09-19 06:45 AM - edited 2024-09-19 06:49 AM
How are clocks set up? What's the UART's kernel clock?
Is there some signal on the Rx pin?
Do you really set baud on 1MBaud?
Read out and check/post UART registers.
JW
2024-09-19 07:48 AM - edited 2024-09-19 07:50 AM
Hi @waclawek.jan , I added the CLK setup in the post attachments. There is a signal pretty frequently on the RX Pin. The UART Registers seem to be in order as far as I can tell (most of it is in the default reset value).
Yes, I really do set the baud to 1Mbaud.
2024-09-19 12:47 PM
I don't have answers for you, but as you are pushing things at the edge, with the highest possible baudrate and an unusually high APB divider... maybe you tapped into a genuine marginal hardware bug?
One way to tackle this might be simply ignoring TEACK, which would require to modify the Cube function or write your own - but that's easy, as you've said, most of the UART registers are at their reset values.
JW
2024-09-20 01:55 AM
Reducing the Baudrate has seemed to not impact anything, I will try to play around with the dividers and see. However maybe it would be worth to get an ST person involved. I'll reply if I get any results with reconfiguring the clock settings. Thanks! @waclawek.jan
2024-09-20 03:59 AM
Reconfiguring the clocks in various ways yielded no results. When commenting out the HAL these code blocks, it worked every time for me:
/* Check if the Transmitter is enabled */
if ((huart->Instance->CR1 & USART_CR1_TE) == USART_CR1_TE)
{
/* Wait until TEACK flag is set */
if (UART_WaitOnFlagUntilTimeout(huart, USART_ISR_TEACK, RESET, tickstart, HAL_UART_TIMEOUT_VALUE) != HAL_OK)
{
/* Disable TXE interrupt for the interrupt process */
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE_TXFNFIE));
huart->gState = HAL_UART_STATE_READY;
__HAL_UNLOCK(huart);
/* Timeout occurred */
return HAL_TIMEOUT;
}
}
/* Check if the Receiver is enabled */
if ((huart->Instance->CR1 & USART_CR1_RE) == USART_CR1_RE)
{
/* Wait until REACK flag is set */
if (UART_WaitOnFlagUntilTimeout(huart, USART_ISR_REACK, RESET, tickstart, HAL_UART_TIMEOUT_VALUE) != HAL_OK)
{
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error)
interrupts for the interrupt process */
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE));
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
huart->RxState = HAL_UART_STATE_READY;
__HAL_UNLOCK(huart);
/* Timeout occurred */
return HAL_TIMEOUT;
}
}
From the HAL_StatusTypeDef UART_CheckIdleState(UART_HandleTypeDef *huart) function.
I will also add the proof of undesired behaviour as an attachment (acquired via oscilloscope). The blue channel is the NRST line. We can see how after a couple resets (towards the end), the WWDG is physically resetting the NRST line, and this goes on indefinitely.
2024-09-24 07:26 AM
Hello @StefanInfi,
For the moment I couldn't reproduce this behavior
What I tried to do (using same usart2/ clock config) is very simple:
while (1)
{
/* USER CODE END WHILE */
SET_BIT(huart2.Instance->CR1, USART_CR1_TE);
uint32_t tickstart = HAL_GetTick();
uint32_t timeout = 1000; // 1 second timeout
HAL_StatusTypeDef status = UART_WaitOnFlagUntilTimeout(&huart2, USART_ISR_TEACK, RESET, tickstart, timeout);
if (status == HAL_OK)
{
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // Toggle an LED to indicate TEACK flag is set
}
else
{
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_6); // Toggle another LED to indicate TEACK flag is not set within timeout
}
In this case the TEACK flag is successfully set (LED5 toggles)
Will you be able to share the project reproducing the issue to investigate more!
Thank you!
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2024-09-25 03:09 AM
Hi @Sarra.S , thank you for trying to reproduce the issue!
However, I think you should also then have the uart RX pin receive a 10 byte stream (1Mbaud, even parity) every 50ms. I forgot to mention I also have even parity enabled (which is probably not relevant). This should be done by another MCU.
I would use the HAL functions included in the cubeMX generated files to do the UART init, since it more accurately replicates my setup.
If nothing is able to reproduce the issue, I would share my code with you but please then lets be in touch via email.
2024-09-25 07:39 AM
Hi @StefanInfi
Indeed, as mentioned by @waclawek.jan, handling a 1Mbaud with a 16Mhz clock source is the limit. To relax this on RX, could you try to initialize your USART2 with OverSampling_8 configuration :
huart2.Init.OverSampling = UART_OVERSAMPLING_8;
Regards
2024-09-29 11:13 PM
Sorry for the long wait @Guenael Cadier . During my testing I had also done this, and also toyed with other clock configurations but it seemed to have no effect.