cancel
Showing results for 
Search instead for 
Did you mean: 

Is this UART really busy?

hbarta2
Associate III
Posted on January 12, 2015 at 14:00

I'm baffled by a bit of code that results in a lockup in my application (On n STM32F429I-

DISCO) related to a UART receive ISR. The code receives characters one at a time as it needs to handle variable length messages. To do that it issues a read request within the receive data ISR:

[code]HAL_StatusTypeDef st;

void HAL_UART_RxCpltCallback( UART_HandleTypeDef * huart)

{

/* Character by character interrupt callback Ugh! HAL has no concept of

  receiving variable length messages so we do that at application level.

  Here the RxXferCount==0 means the 1 character receive buffer has been exhausted

  and the receiver disablked. We need to store the character and reissue the read.

  */

if( huart->State != HAL_UART_STATE_RESET) {

if(!huart->RxXferCount) { // character received?

                  RxBuffer[RxBufferHead] = *RxBufferIT; 

                  RxBufferHead = (RxBufferHead + 1) % RX_BUFFER_SIZE;

                  if((st=HAL_UART_Receive_IT(&UartHandle, (uint8_t *)RxBufferIT, 1)) != HAL_OK)

                  {

                    HAL_UART_Receive_IT(huart, (uint8_t *)RxBufferIT, 1);

                    Error_Handler();

                  }

}

}

}[/code]

(Error_Handler(); turns on an LED and goes into an infinite loop.)

I can break on the line prior to the call to Error_Handler() and find that the return status from HAL_UART_Receive_IT(); is HAL_BUSY. If I step through a second call to HAL_UART_Receive_IT(), all works well. If I program a loop to repeat the call to HAL_UART_Receive_IT() until it no longer returns HAL_BUSY it can repeat up to 100,000 times without ever returning a good status. 

Within HAL_UART_Receive_IT() I set a breakpoint on the line where it returns HAL_BUSY and execution never stops at the breakpoint. 

Woaking back up the call stack, HAL_UART_RxCpltCallback(huart); mis called from within this bit of code (in UART_Receive_IT(UART_HandleTypeDef *huart) in stm32f4xx_hal_uart.c):

[code]    if(--huart->RxXferCount == 0)

    {

      __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);

      /* Check if a transmit process is ongoing or not */

      if(huart->State == HAL_UART_STATE_BUSY_TX_RX) 

      {

        huart->State = HAL_UART_STATE_BUSY_TX;

      }

      else

      {

        /* Disable the UART Parity Error Interrupt */

        __HAL_UART_DISABLE_IT(huart, UART_IT_PE);

        /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */

        __HAL_UART_DISABLE_IT(huart, UART_IT_ERR);

        huart->State = HAL_UART_STATE_READY;

      }

      HAL_UART_RxCpltCallback(huart);

      return HAL_OK;

    }[/code]

It seems that the state (huart->State) should either be HAL_UART_STATE_BUSY_TX or HAL_UART_STATE_READY, neither of which should cause this path to be taken in the code.

All I can think of is that some memory access is being optimized away (Optimization within IAR EWARM set to low) but I cannot see where that would be happening.

The definition for the UART handle is:

UART_HandleTypeDef UartHandle;

and if I try to add the volatile keyword to it, the compiler spits out:

[code]Error[Pe147]: declaration is incompatible with ''struct <unnamed> volatile UartHandle'' (declared &#1;<SRCREF line=44&#1;>at line 44&#1;</SRCREF&#1;>) C:\STM32Cube_FW_F4_V1.3.0\Projects\STM32F429I-Discovery\Applications\STemWin\WiFi with STemWin_HelloWorld\Src\main.c 44 

[/code]

whicl leads me to believe it is already declared volatile through some magic I do not understand. (The typedef for UART_HandleTypeDef does not mention volatile) And since the handle is passed though the ISR chain as a pointer, I do not see how the volatile keyword would be honored unless the library code included it with the signature for the ISR related procedures.

I'm at a loss as to what to try to fix this since I cannot figure out what is causing it in the first place. Many thanks for suggestions on where to look!
3 REPLIES 3
Posted on January 13, 2015 at 14:08

Hi,

Concerning the HAL_UART_RxCpltCallback(), there is no need to call twice HAL_UART_Receive_IT() to have your application working:

if((st=HAL_UART_Receive_IT(&UartHandle, (uint8_t *)RxBufferIT, 1)) != HAL_OK)
{
HAL_UART_Receive_IT(huart, (uint8_t *)RxBufferIT, 1); 

// This Line is obsolete 
Error_Handler();
}

WithinHAL_UART_Receive_IT() I set a breakpoint on the line where it returns HAL_BUSY and execution never stops at the breakpoint.

This is a normal behavior when you call just one time the HAL_UART_Receive_IT() in the HAL_UART_RxCpltCallback(). Could you please confirm, this behavior is observed with how many calls? For the UART handler you don’t need to declare it as volatile, the “State�? parameter in the UART_HandleTypeDef is already declared as volatile (__IO) by the HAL UART driver

__IO HAL_UART_StateTypeDef State; /* UART communication state */

Conclusion: From our side this is a compiler issue, and here bellow some ways to be checked in your application:
  • What is the returned value in your st variable?
  • Please try to update this check as following :

if((st=HAL_UART_Receive_IT(&UartHandle, (uint8_t *)RxBufferIT, 1)) != HAL_OK)
{

By

st = HAL_UART_Receive_IT(&UartHandle, (uint8_t *)RxBufferIT, 1);
if(st != HAL_OK)
{

  • Try to use the EWARM Template project provided within STM32Cube_FW_F4 V1.3.0 package (keep the same settings)
Keep us informed about your finding. Regards, Heisenberg.
hbarta2
Associate III
Posted on January 13, 2015 at 20:41

Hi 

Heisenberg, 

Many thanks for the reply and suggestions. At present I'm working on another part of the system but I will get back to this and unless the issue magically goes away, I will be following your suggestions.

The extra call was there as a debugging aid BTW. I thought I could identify the problem by stepping through the code after the bad status had been returned. Unfortunately that turned out not to be the case.

Thanks,

hank (Not your brother-in-law ;) )
Posted on January 15, 2015 at 15:15

Hi Hank,

Thanks anyway.

Please continue providing valuable feedbacks.

Cheers,

Heisenberg.

PS: Not you brother-in-law too :D