cancel
Showing results for 
Search instead for 
Did you mean: 

USART overrun after receive timeout interrupt is enabled

YosemiteJohn
Associate

USART1 is configured using code generated by CubeMX to run at 9600 8N1 in FIFO mode with Rx FIFO threshold set to 7/8 full. Receive is done via interrupts into an 80-byte buffer and callbacks are used to transfer data out of the 80-byte buffer. Everything seems to run as expected here.

Then I configure receive timeout and enable the interrupt. That's when I observe (using a GPIO toggle) the USART1 ISR running every 1.5 us or so even when no data is being received. When I break execution with a debugger, the overrun flag is set.

Why is it that when receive timeout is enabled, I get rx overruns?

I noted that the overruns start about 4 UART bytes after a call to HAL_UART_Receive_IT(). Without receive timeout interrupt enabled, the ISR runs every 7 UART bytes, which is expected for a 7/8 Rx FIFO threshold.

This is using stm32h7xx HAL v1.6.0.

Thanks! (code and scope trace are below)

#define RX_BUF_SZ    80
static unsigned char      rx_buf[RX_BUF_SZ];
static void MX_USART1_UART_Init(void)
{
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 9600;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_7_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_EnableFifoMode(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
 
  // USART overruns when the following code is commented out
  //HAL_UART_ReceiverTimeout_Config(&huart1, 100);
  //HAL_UART_EnableReceiverTimeout(&huart1);
 
  HAL_UART_RegisterCallback(&huart1, HAL_UART_RX_COMPLETE_CB_ID, uart_rx_cb);
  HAL_UART_RegisterCallback(&huart1, HAL_UART_ERROR_CB_ID, uart_rx_cb);
 
  HAL_UART_Receive_IT(&huart1, rx_buf, RX_BUF_SZ);
}
 
static void uart_rx_cb(UART_HandleTypeDef *huart)
{
    if (huart->ErrorCode & HAL_UART_ERROR_RTO)
    {
        HAL_GPIO_TogglePin(LED_RED_GPIO_Port, LED_RED_Pin);
    }
    else
    {
    	HAL_GPIO_TogglePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin);
    }
    HAL_UART_Receive_IT(&huart1, rx_buf, RX_BUF_SZ);
}
 
void USART1_IRQHandler(void)
{
  HAL_GPIO_TogglePin(LED_BLUE_GPIO_Port, LED_BLUE_Pin);
  HAL_UART_IRQHandler(&huart1);
}

 0690X00000Bv0d6QAB.png

1 REPLY 1
maple
Associate II

This is very late non-answer, sorry.

We had some RTOF code working differently for two engineers. They had different versions of HAL downloaded. Upon investigation it turned out that there were some changes in the HAL recently, that look like they were made by someone who had not a slightest idea what RTOF is for. They basically treat it as an error, breaking totally normal communication for no reason.