cancel
Showing results for 
Search instead for 
Did you mean: 

when uart over run happens by using stm32 hal lib, the system hang

roseanne qiu
Associate II

Dear Sir/Madam:

I use three uart of stm32f4 : uart1, uart2 and uart6

I have some problems . when uart1 has overrun error,

all system get stuck there. I read some websites about this.

they mention that in the hal lib, clear ORE does not work, they said, only reading uart data register , this bit will clear. I do that, still do not work:

void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)

{

...

 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))

 {

#if 1// I add this , but it does not work, system still hang/stuck when ore happens,

// any clue?

  uint8_t sysRxChar; // clear the regular interrupt

  sysRxChar = (uint8_t) huart->Instance->DR;

#endif

  // if does not really clear big

  __HAL_UART_CLEAR_OREFLAG(huart);

   

  huart->ErrorCode |= HAL_UART_ERROR_ORE;

 }

...

}

reference link is:

https://github.com/particle-iot/firmware/pull/796/commits/677b4b114b9b6503dcd10ddb83d128c9a65d6640

https://github.com/particle-iot/firmware/issues/776

thanks

roseanne

42 REPLIES 42
roseanne qiu
Associate II

Dear Clive:

this is a good idea for interrupt problem. I also have adc interrupt, I may also use this way to avoid adc interrupt has the same problems.

I am wondering that I also use timer interrupt, if timer interrupt also has the simillar problem, that will be terrible . and chip will be just useless.

thanks for the hint and help.

roseanne

roseanne qiu
Associate II

I think one more thing? how about systick interrupt priority compare with uart? if it is lower, it does not solve the system hang problem, in my case

I set all the uart interrupt as :  HAL_NVIC_SetPriority(USART1_IRQn, 2, 0);

 I read some paper, people say systick interrupt is lowerest priority, if that is the case , systick handler never got chance?

how could I set systick priority?

thanks

roseanne

roseanne qiu
Associate II

Dear Clive:

just found systick interrupt priority is 0x0FU, but in my configure uart, it is 2, obvious's uart interrupt priority is much higher than systick.

I would not change the systick priority to higher, because of its feature. am I wrong? if I am correct, by using systick seems not work?

any comments?

thanks

roseanne

For the HAL to function properly, and not lock up or get a priority inversion, the HAL_IncTick(); must be called from an interrupt that is the highest priority and preempt everything. All the timeout loops in the HAL depend on this because they presume the tick will advance. And code in callbacks is called under interrupt context, and will have similar expectations.

/**
  * @brief This function configures the source of the time base.
  *        The time source is configured  to have 1ms time base with a dedicated 
  *        Tick interrupt priority.
  * @note This function is called  automatically at the beginning of program after
  *       reset by HAL_Init() or at any time when clock is reconfigured  by HAL_RCC_ClockConfig().
  * @note In the default implementation, SysTick timer is the source of time base. 
  *       It is used to generate interrupts at regular time intervals. 
  *       Care must be taken if HAL_Delay() is called from a peripheral ISR process, 
  *       The SysTick interrupt must have higher priority (numerically lower)
  *       than the peripheral interrupt. Otherwise the caller ISR process will be blocked.
  *       The function is declared as __weak  to be overwritten  in case of other
  *       implementation  in user file.
  * @param TickPriority Tick interrupt priority.
  * @retval HAL status
  */
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
  /* Configure the SysTick to have interrupt in 1ms time basis*/
  if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
  {
    return HAL_ERROR;
  }
 
  /* Configure the SysTick IRQ priority */
  if (TickPriority < (1UL << __NVIC_PRIO_BITS))
  {
    HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
    uwTickPrio = TickPriority;
  }
  else
  {
    return HAL_ERROR;
  }
 
  /* Return function status */
  return HAL_OK;
}
#define  TICK_INT_PRIORITY            ((uint32_t)0x0) /*!< tick interrupt priority */
 
 HAL_InitTick (TICK_INT_PRIORITY);

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Pavel A.
Evangelist III

The ST HAL does not have to use systick for its timer. freeRTOS wants systick for itself, so when CubeMx creates a project with freeRTOS it recommends to use a different timer for HAL. Maybe this could help for the OP's environment (particle-iot...) as well.

-- pa

henry.dick
Senior II

"I have some problems . when uart1 has overrun error,

all system get stuck there."

try to establish that - try to write a piece of code that shows

1) the system hangs when uart1 has ORE;

2) the system doesn't hang when uart2/6 have ORE.

" I read some websites about this.

they mention that in the hal lib, clear ORE does not work, they said, only reading uart data register , this bit will clear."

don't worry about anything said by some random dudes. always go back to the most authoritative source on this: the datasheet. What does the datasheet say about ORE?

" I do that, still do not work:"

again, you have to establish first that your inability to clear ORE is the reason; if that's proven, then focus on what ORE is set. Constantly clearing ORE in a timer routine is NOT the way moving forward: that means you are running the risk of losing incoming data.

uwTick needs to advance in a way immune to other interrupts and threads blocking, otherwise you're completely cooked. Smarter solutions would have used a free-running 32-bit timer register for this purpose, but if you're using a software based counter you'd better make sure it counts time properly, and carries all the code you've built around it that is dependent on it functioning properly. Otherwise you're going to see dead-locks, failure to timeout, and failure to meet deadlines.

You can add functionality to SysTick. You can have interrupts that don't cause the RTOS to yield.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
roseanne qiu
Associate II

Dear Clive:

I come back again. I use timer per 1 second to check interrupt counts based on your advice.

meanwhile I make this counter as highest priority , higher than uart interrupt.

once inside the timer, I found the count is extreamyly big, I clear interrupt.

but still same not clear uart., the uart 1 interrupt keep come back.

I do not know why, any wrong with my codes?

here is the codes:

...

timer_irq()

{

if (gbUart1Count > UART_STUCK_COUNT ) // this is 60000

 {// clean uart interrupt

 __HAL_UART_DISABLE_IT(&Uart1Handle, UART_IT_RXNE);

   

  /* Disable the UART Parity Error Interrupt */

  __HAL_UART_DISABLE_IT(&Uart1Handle, UART_IT_PE);

   

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

  __HAL_UART_DISABLE_IT(&Uart1Handle, UART_IT_ERR);

   

  /* Rx process is completed, restore huart->RxState to Ready */

  Uart1Handle.RxState = HAL_UART_STATE_READY;

  /* Disable the UART Transmit Complete Interrupt */   

  __HAL_UART_DISABLE_IT(&Uart1Handle, UART_IT_TC);

   

  /* Tx process is ended, restore huart->gState to Ready */

  Uart1Handle.gState = HAL_UART_STATE_READY;

  HAL_NVIC_ClearPendingIRQ(USART1_IRQn);

 __HAL_UART_FLUSH_DRREGISTER(&Uart1Handle); 

}

...

}

any clue?

thanks

roseanne

Sorry, really not going to wade into HAL/CubeMX library code implementation, and how you'd go about restarting it. One could burn hours of time on such things.

I think you really need to get to the bottom of why the USART is continually failing. This honestly isn't normal, and you should really be looking at the cause rather than addressing the symptoms.

Waiting a second is probably too long, and issues are likely to compound and start negatively impacting other peripherals and tasks.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
roseanne qiu
Associate II

continue:

here I use hardcode to create interrupt dead loop.

at the beginning of the interrupt:

I do not clear flags,just force interrupt routine running and test whether timer could disable interrupt.

void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)

{

 uint32_t tmp1 = 0U, tmp2 = 0U;

#if defined(RQIU_OUTINT_LOOP)

  

 if ( huart->Instance == USART1 )

  {

    

  gbUart1Count++;

  if ( gbDbInt == 1 ) <===============let interrupt keep to running when this flag is 1

   return;

  }

 else if ( huart->Instance == USART2 )

  gbUart2Count++;

 else if (huart->Instance == USART6 )

  gbUart6Count++;

  .....