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 for different codebase 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 main loop is tight, it’s turning 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 before. 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.