HAL IRQ Handler Bug: Stuck in ISR forever after initializing UART2 with floating pins - STM32WL5MOCH
- April 13, 2025
- 3 replies
- 1171 views
The UART2 IRQ Handler gets called consistently and never clears a few milliseconds after initialization.
If the debugger is not present on the RX line, the program always gets stuck in the IRQ Handler forever, until I touch the RX pin with my finger. Then the program begins executing normally.
On our STM32WL5MOCH-based board, the debug port (UART2) pins are left floating.
Here is the beginning of our main.c, which only uses default STM32CubeMX generated driver files, nothing custom. Please note the included project .ioc file in this post.
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC_Init();
MX_DAC_Init();
MX_LPUART1_UART_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
MX_TIM1_Init();
MX_RTC_Init();
MX_I2C2_Init();
MX_TIM16_Init();Basically, the program only gets down to MX_TIM16_Init() before it gets stuck in this ISR forever. The program gets stuck every time. If we touch any other pins, the program remains stuck. The only pin which actually breaks the loop is the RX pin for USART2.
The default IRQ handler is defined in the stm32wlxx_hal_uart.c file:
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
uint32_t isrflags = READ_REG(huart->Instance->ISR);
uint32_t cr1its = READ_REG(huart->Instance->CR1);
uint32_t cr3its = READ_REG(huart->Instance->CR3);
uint32_t errorflags;
uint32_t errorcode;
...At the break point, the variables usually evaluate as follows:
isrFlags = 0x6200F2
cr1its = 0x2D
cr3lits = 0x0
errorflags = 2
errorcode = <optimized out>When we define our own HAL_UART_ErrorCallback(), the callback is never executed. Since cr3lits is zero, and cr1lits does not correspond with any defined flags, none of the flags are cleared and none of the error callbacks are ever executed. So the ISR sits there looping around and around forever. This has to be a HAL ISR bug - because there are no valid states upon which the program can clear anything and recover.
If I touch the RX pin with my finger, the system fixes itself and proceeds with program execution - almost as if the UART error registers finally read acceptable values. When attached to a serial converter TX and RX, it never gets stuck on startup. It also never gets stuck when pulled up with a 10k resistor to VDD. Setting the internal pullup for the RX pin does not fix the issue in the function call MX_GPIO_Init();
/*Configure GPIO pin : PIN_USART2_RX_Pin */
GPIO_InitStruct.Pin = GPIO_PIN_3; // Replace with the actual RX pin number
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP; // Add pull-up resistor to RX pin
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // Replace GPIOA with the correct port
Conclusion
1. If the hardware can generate a condition upon which the IRQ handler cannot break out of the loop, then it means the HAL IRQ should have an additional exception / clearing function.
2. Also, I have never had a microcontroller which couldn't tolerate an open debug uart port before. Didn't expect it to be so sensitive! (we've made plenty of designs with Atmel, Microchip, TI, ARM, AVR, PIC, MSP, and more).
