From 0975255f863be2e2529d57fb67bc7ba841e81249 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 29 Jun 2025 22:14:52 +1000 Subject: [PATCH] stm32/uart: Suppress additional RX idle IRQs on F4/L1. These MCUs only clear the RX idle IRQ if the data register is read, which won't occur if the only IRQ is the RX idle IRQ (because then reading and discarding the DR may lead to lost data). To work around this, explicitly suppress the RX idle IRQ so that it's only passed through to the Python callback once. Signed-off-by: Damien George --- ports/stm32/uart.c | 15 +++++++++++++++ ports/stm32/uart.h | 4 ++++ 2 files changed, 19 insertions(+) diff --git a/ports/stm32/uart.c b/ports/stm32/uart.c index 55fa62214..e3f8dc1f9 100644 --- a/ports/stm32/uart.c +++ b/ports/stm32/uart.c @@ -689,6 +689,10 @@ bool uart_init(machine_uart_obj_t *uart_obj, uart_obj->is_enabled = true; uart_obj->attached_to_repl = false; + #if defined(STM32F4) || defined(STM32L1) + uart_obj->suppress_idle_irq = true; + #endif + if (bits == UART_WORDLENGTH_9B && parity == UART_PARITY_NONE) { uart_obj->char_mask = 0x1ff; uart_obj->char_width = CHAR_WIDTH_9BIT; @@ -1274,6 +1278,9 @@ void uart_irq_handler(mp_uint_t uart_id) { self->uartx->CR1 &= ~USART_CR1_RXNEIE; } } + if (self->suppress_idle_irq) { + self->mp_irq_flags &= ~USART_SR_IDLE; + } #else self->uartx->ICR = self->mp_irq_flags & (USART_ICR_IDLECF | USART_ICR_ORECF); #endif @@ -1282,6 +1289,14 @@ void uart_irq_handler(mp_uint_t uart_id) { if (self->mp_irq_trigger & self->mp_irq_flags) { mp_irq_handler(self->mp_irq_obj); } + + #if defined(STM32F4) || defined(STM32L1) + if (did_clear_sr) { + self->suppress_idle_irq = false; + } else { + self->suppress_idle_irq = true; + } + #endif } static mp_uint_t uart_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) { diff --git a/ports/stm32/uart.h b/ports/stm32/uart.h index de4b70cde..d92434c64 100644 --- a/ports/stm32/uart.h +++ b/ports/stm32/uart.h @@ -26,6 +26,7 @@ #ifndef MICROPY_INCLUDED_STM32_UART_H #define MICROPY_INCLUDED_STM32_UART_H +#include "py/mphal.h" #include "shared/runtime/mpirq.h" typedef enum { @@ -63,6 +64,9 @@ typedef struct _machine_uart_obj_t { pyb_uart_t uart_id : 8; bool is_static : 1; bool is_enabled : 1; + #if defined(STM32F4) || defined(STM32L1) + bool suppress_idle_irq : 1; // whether the RX idle IRQ is suppressed (F4/L1 only) + #endif bool attached_to_repl; // whether the UART is attached to REPL byte char_width; // 0 for 7,8 bit chars, 1 for 9 bit chars uint16_t char_mask; // 0x7f for 7 bit, 0xff for 8 bit, 0x1ff for 9 bit