cancel
Showing results for 
Search instead for 
Did you mean: 

NVIC and/or USART appears to hold pending requests stuck (Cortex-M0 in STM32L071)

AGrigoriev
Associate II

With STM32L071, I've been fighting a problem of losing UART RX characters. The RX path uses HAL_UART_ReceiveIT to queue a single character buffer, and then re-queues it from HAL_UART_RxCpltCallback. The received character is then stored in a software FIFO. The main loop reads from the software FIFO and echoes it back. The TX path uses DMA (TX is used for high volume debug output as well). Simple action of pasting a line to the terminal on UART5 (with echoing back) could cause it to drop a few characters. But one thing helped. After initiating the next RX operation (for a single byte buffer), check RXNE and set the interrupt pending:

 

 

 

// If RXNE is already set, request an immediate interrupt,
  // otherwise it may be lost and cause RX overrun
  if (READ_REG(huart->Instance->ISR) & USART_ISR_RXNE)
  {
    if (huart->Instance == USART4
      || huart->Instance == USART5)
    {
      NVIC_SetPendingIRQ(USART4_5_IRQn);
    }
    else if (huart->Instance == USART1)
    {
      NVIC_SetPendingIRQ(USART1_IRQn);
    }
    else if (huart->Instance == USART2)
    {
      NVIC_SetPendingIRQ(USART2_IRQn);
    }
  }

 

 

 

I then wrote additional test code to echo the data to another UART, get the TX looped back to its RX, and echoing back. Same as in previous example, The RX callback would queue the data, and then the main loop would read the data and transmit it. This was based on a different codebase, and TX DMA was NOT used. The main loop was checking if NVIC interrupt was pending, and/or RXNE bit was set in the UARTs. Surprisingly, once in a few tries, the test code managed to catch either RXNE or an interrupt pending bit set in NVIC. Some of those were caught for UART URQ, but also for SysTick IRQ and for RTC wakeup event IRQ. And it's not like the test loop was tight, it was doing some other stuff and turned about 1000 times a second. And by sampling NVIC pending register just 1000 times a second, it read interrupt pending.

WHAT'S HAPPENING?

One would have thought that code running with interrupts enabled would never see a pending interrupt or RXNE bit set (with RXNEIE also set), because these are supposed to cause an immediate interrupt to clear them. Yet here we are, catching them by sampling just 1000 times per second.

Yes, I've read the NVIC description. And honestly, when I encountered the phrase "Cortex-M0+ interrupts are both level-sensitive and pulse-sensitive. Pulse interrupts are also described as edge-triggered interrupts.", my first thought was "Uh oh, they probably screwed it up". And apparently they did.

12 REPLIES 12
Karl Yamashita
Lead III

Again, post your code. More than 95% of people posting that have issues with missing characters don't use HAL_UART_ReceiveIT  properly.

Tips and Tricks with TimerCallback https://www.youtube.com/@eebykarl
If you find my solution useful, please click the Accept as Solution so others see the solution.

It's pretty unlikely that there is some fundamental flaw in the USART/NVIC hardware. Note that these devices are extremely popular and used by many people, and L0 isn't exactly a new device. Unlikely a critical flaw exists in the USART peripheral (but possible, check the errata, it's certainly been spotted if it does exist).

Could be a HAL flaw, but software isn't going to cause NVIC requests to be held. Likely there's a deeper misunderstanding here that would be explained by seeing the code and how these functions are used.

If you feel a post has answered your question, please click "Accept as Solution".
KnarfB
Principal III

Think those observations are interesting, but would need more code/explanations.

The following shall hold:

  1. if the baud rate is high enough and a string is received, the IRQ handler is continuously executed (provided no higher prio interrupt interferes), and not a single instruction of the main loop will be executed in between
  2. if the string is long enough, an overrun error may happen. HAL does not include error recovery and anything can happen afterward

hth

KnarfB