Skip to main content
Visitor II
October 21, 2025
Solved

Possible bug in HAL_UART_DeInit()

  • October 21, 2025
  • 2 replies
  • 284 views

Hello all,


There might be a possible bug in HAL_UART_DeInit(). When calling HAL_UART_DeInit() when it is already initialized could lead to CPU starvation. Assume that an interrupt fires after calling __HAL_UART_DISABLE(huart); and before huart->Instance->CR1 = 0x0U; the interrupt is going to keep firing provided that some conditions are met. I was able to run a debug session and saw that only the interrupt was firing.
From the ref. manual -> Note: If TE bit is reset and no transmission is on going, the TC bit is immediately set.
This means that the TC bit is always going to be set and the interrupt is constantly going to fire regardless of clearing the TCF in ICR. The reference manual also mentions to ensure TC bit is being set before calling  __HAL_UART_DISABLE(huart).
I am running into this issue when TE is reset and TXIE is set after calling  __HAL_UART_DISABLE(huart). This happens extremely rarely but I am able to reproduce by adding 5-10 no-ops between __HAL_UART_DISABLE(huart) and huart->Instance->CR1 = 0x0U.

Possible fix is to remove __HAL_UART_DISABLE(huart) and directly call huart->Instance->CR1=0x0U or make those two lines atomic. I know that it can also be avoided by fixing it in the ISR itself but the HAL should not let this happen in the first place. Let me know if this is a valid bug or if you have seen this before. Thank you!

/**
 * @brief DeInitialize the UART peripheral.
 * @PAram huart UART handle.
 * @retval HAL status
 */
HAL_StatusTypeDef HAL_UART_DeInit(UART_HandleTypeDef *huart)
{
 /* Check the UART handle allocation */
 if (huart == NULL)
 {
 return HAL_ERROR;
 }

 /* Check the parameters */
 assert_param((IS_UART_INSTANCE(huart->Instance)) || (IS_LPUART_INSTANCE(huart->Instance)));

 huart->gState = HAL_UART_STATE_BUSY;

 __HAL_UART_DISABLE(huart); // Sets bit 0 of CR1 to 0 and disables UART peripheral
 // ----> Interrupt fires here
 huart->Instance->CR1 = 0x0U; // Disables Interupt
 huart->Instance->CR2 = 0x0U;
 huart->Instance->CR3 = 0x0U;

 

 

    This topic has been closed for replies.
    Best answer by Saket_Om

    Hello @bala- 

    Thank you for bringing this issue to our attention.

    I reported this internally.

    Internal ticket number: 220098 (This is an internal tracking number and is not accessible or usable by customers).

     

    2 replies

    Saket_OmAnswer
    Technical Moderator
    October 21, 2025

    Hello @bala- 

    Thank you for bringing this issue to our attention.

    I reported this internally.

    Internal ticket number: 220098 (This is an internal tracking number and is not accessible or usable by customers).

     

    bala-Author
    Visitor II
    October 21, 2025

    @Saket_Om Since this was accepted as a solution I am assuming that it is indeed a bug? Please let me know what the internal team thinks though.

    bala-Author
    Visitor II
    November 5, 2025

    @Saket_Om Bumping this. Any update from the team?