AnsweredAssumed Answered

STM32F4 Cube HAL UART. Is it a bug or am I missing something?

Question asked by ns.rublag on Nov 6, 2015
Latest reply on Jun 20, 2017 by john gassel

I am using interrupt based UART IO (no DMA).

HAL_UART_Transmit_IT function sets EIE bit in CR3 register. According to STM32F407 datasheet (and real behaviour), this generates interrupt only in multi buffer mode (when DMAR bit is set). EIE enables interrupt generation for frame error (FE), overrun error (ORE), noise error (NE). This error, as I understand, only for receiving.

Part of HAL_UART_IRQHandler function:

tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_ORE);
tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR);
/* UART Over-Run interrupt occurred ----------------------------------------*/
if((tmp1 != RESET) && (tmp2 != RESET))
{
  __HAL_UART_CLEAR_OREFLAG(huart);
 
  huart->ErrorCode |= HAL_UART_ERROR_ORE;
}
 
if(huart->ErrorCode != HAL_UART_ERROR_NONE)
{
  /* Set the UART state ready to be able to start again the process */
  huart->State = HAL_UART_STATE_READY;
 
  HAL_UART_ErrorCallback(huart);
}

HAL_UART_IRQHandler checks for each error. If error occurred and EIE bit is set, it resets UART state, but doesn't reset interrupt enabling bits, so TXE interrupt will be always generated, but UART_Transmit_IT function treats state HAL_UART_STATE_READY as invalid and doesn't do anything. Infinite loop.

Part of UART_Transmit_IT function:

static HAL_StatusTypeDef UART_Transmit_IT(UART_HandleTypeDef *huart)
  {
  uint16_t* tmp;
  uint32_t tmp1 = 0;
 
  tmp1 = huart->State;
  if((tmp1 == HAL_UART_STATE_BUSY_TX) || (tmp1 == HAL_UART_STATE_BUSY_TX_RX))
  {
  }
  else
  {
    return HAL_BUSY;
  }
}

Is it a bug in Cube HAL?

Outcomes