cancel
Showing results for 
Search instead for 
Did you mean: 

UART_Start_Receive_IT error when using hardware flow control

gil_dobjanschi
Associate III

Hello,

 

I ran into an issue when testing a UART application on a STM32C562RE in loopback mode with RTS and CTS enabled. The app does the following:

1. Start receiving 1 character at a time by using HAL_UART_Receive_IT.

2. Send a string 

3. After the received character is printed out I issue another call HAL_UART_Receive_IT.

Everything works fine; the app prints out the string I sent.

 

I wanted to make sure the hardware flow control was running correctly so I placed a HAL_Delay(1) after I print out the character received and before I issue a new call  to HAL_UART_Receive_IT. This should stop the transmitter due to the CTS -> 1 (no more room in the Rx buffer) and it should restart it after I issue the HAL_UART_Receive_IT CTS -> 0 due to available room in the Rx buffer; and, it does. All the characters are received as expected however HAL_UART_Receive_IT returns HAL_ERROR. Everything seems normal except the error returned by HAL_UART_Receive_IT.

I debugged the code and it fails in UART_Start_Receive_IT:

  if (huart->rx_state != HAL_UART_RX_STATE_ACTIVE)
  {
    huart->p_rx_isr = NULL;
    return HAL_ERROR;
  }

The rx_state is HAL_UART_RX_STATE_IDLE and therefore the check above fails.

I also enabled 'Get last error' for UART in MX2 and the last_reception_error_codes is 0.

I cannot figure out why HAL_UART_Receive_IT returns an error.

I appreciate the help,

Gil

1 ACCEPTED SOLUTION

Accepted Solutions
Pavel A.
Super User

Aha so there's a race between HAL_UART_Receive_IT and a RX byte arriving and causing interrupt, thus satisfying your request for one byte.

TL;DR using HAL_UART_Receive_IT for anything practical isn't a good idea, especially for receiving bytes one by one. People use a continuous DMA with cyclical buffer, or something equivalent.

 

View solution in original post

7 REPLIES 7
Pavel A.
Super User

The rx_state field is assigned HAL_UART_RX_STATE_ACTIVE  here: https://github.com/STMicroelectronics/stm32c5xx-drivers/blob/79b901285a7efeaf87c4c25db81d24cb5d8c9465/hal/stm32c5xx_hal_uart.c#L4534

and the check is here https://github.com/STMicroelectronics/stm32c5xx-drivers/blob/79b901285a7efeaf87c4c25db81d24cb5d8c9465/hal/stm32c5xx_hal_uart.c#L7408

Somewhere between these points the value changes. Try to set a breakpoint on value change in debugger.

 

Hi @Pavel A. 

I traced it to the line before the check: LL_USART_EnableIT_RXNE_RXFNE(p_uartx). 

    if ((reg_temp & USART_CR1_PCE) != LL_USART_PARITY_NONE)
    {
      LL_USART_EnableIT_PE(p_uartx);
    }
    LL_USART_EnableIT_RXNE_RXFNE(p_uartx);
  }

  if (huart->rx_state != HAL_UART_RX_STATE_ACTIVE)
  {
    huart->p_rx_isr = NULL;
    return HAL_ERROR;
  }

 

When I execute the line: LL_USART_EnableIT_RXNE_RXFNE(p_uartx) my interrupt callback is executed (I had a breakpoint on it) and rx_state was set to HAL_UART_RX_STATE_IDLE.

 

Regards,

-Gil

 

Pavel A.
Super User

Aha so there's a race between HAL_UART_Receive_IT and a RX byte arriving and causing interrupt, thus satisfying your request for one byte.

TL;DR using HAL_UART_Receive_IT for anything practical isn't a good idea, especially for receiving bytes one by one. People use a continuous DMA with cyclical buffer, or something equivalent.

 

gil_dobjanschi
Associate III

Thank you for acknowledging the issue @Pavel A.!

 

I am writing a book about STM32 and I develop multiple examples on one topic. I start from the simplest scenario and advance to practical ones. This is why I was testing this mode.

 

Regards,

Gil

@gil_dobjanschi A book? could you tell something on the idea - is it about practical projects based on STM32? If so, which STM32 type (CM0, CM7? CM33), which kind of applications, do you use any RTOS and HMI?

gil_dobjanschi
Associate III

Hi @Pavel A. 

 

Yes, it is a book about practical projects for Nucleo-C562RE. I thought that the C5 series presents an opportunity to write about STM32CubeMX2 and use HAL2. The examples will be in C and will not use RTOS. RTOS is reserved for a followup book should the first one be interesting to readers. For the first book the intended audience is the experienced C programmers that wants to get into STM32 and learn its capabilities and programming techniques. I want to present interesting examples and explain behavior and visualize it for readers with the use of the oscilloscope. I will not write chapters about C programming and elementary embedded programming. 

I only started two months ago and I have a long road ahead. It's a lot of work to write the code, write the chapters, develop hardware that speeds up switching between projects and keep the quality of the material high. As I work on the book I learn new things, sometimes I find minor issues in HAL but that's what keeps it interesting.

 

Regards,

-Gil

gil_dobjanschi
Associate III

Hi,

 

Generally speaking it is not good to leave code that does not work properly in the main body of code even if it has minimal importance from a practical standpoint. This is to avoid to explain to those who encounter this issue in the future that the code in question does not work flawlessly when data is received on a byte-by-byte basis. If the code remains as is, maybe a comment in the documentation will need to state that the function should not be used to receive data byte-by-byte.

 

Regards,

-Gil