stm32stm32f4

I'm missing some characters when I'm using UART interrupt method in STM32F407VET


I'm using UART1 of STM32F407VE in interrupt mode. The baudrate is 115200. I'm using docklight serial window to read the UART output. I'm sending 15 to 20 characters at a time. I have missing characters when I check with the loopback code as seen below.

I tried changing baudrates. But when I increase the number of characters, the same problem persists. This is my interrupt handler:

void USART1_IRQHandler(void) {
  uint8_t data;

  HAL_UART_IRQHandler(&huart1);
  __HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_RXNE);

  data = (uint8_t)(huart1.Instance->DR); //& (uint16_t)0x00FFU);

  HAL_UART_Transmit(&huart1, (uint8_t *)&data, 1, 10);
}

Solution

  • You are receiving a byte and putting that byte in the TDR register of your UART. It is probably running at the same baudrate so before a transfer is finished a new receive interrupt is received. The call to HAL_UART_Transmit is blocking and will check if a transfer is running. The statement if(huart->gState == HAL_UART_STATE_READY) will return false and as such will take the else path. This will result in a return value of HAL_BUSY. Which indicates that no transfer has happend because one was still ongoing.

    You'll need to add a circular buffer to fix this. Store the received byte in a storage container from within your interrupt handler and another part of your program needs to check if the storage container is not empty and transmit the contents if it isn't empty. You'll need to disable interrupts when you are updating your storage container because a race condition could occur.

    You could also add an end of transmission character to your transfer indicating that it is safe to echo it back to you, and as such avoiding the race condition. 0x04 is a great choice for this if you are using ASCII because it is defined as EOT (end of transmission).

    Another option would be to use HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) to receive a set amount of bytes in interrupt mode.

    The library code for the UART can be found inside: stm32f4xx_hal_uart.c. The HAL for the STMs is pretty readable and pretty informing, feel free to look inside. It can help in the future to find other bugs. (ST doesn't always make obvious or cooperative choices in their code)