diff options
| author | Damien George <damien@micropython.org> | 2025-06-29 22:14:52 +1000 |
|---|---|---|
| committer | Damien George <damien@micropython.org> | 2025-07-08 13:15:47 +1000 |
| commit | 0975255f863be2e2529d57fb67bc7ba841e81249 (patch) | |
| tree | caf6615da9fc24ef97eb5e26c80eec86e37047a5 | |
| parent | d5246cea616c9b783cfd88e5cd854b92953ed9d4 (diff) | |
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 <damien@micropython.org>
| -rw-r--r-- | ports/stm32/uart.c | 15 | ||||
| -rw-r--r-- | ports/stm32/uart.h | 4 |
2 files changed, 19 insertions, 0 deletions
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 |
