summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2025-06-29 22:14:52 +1000
committerDamien George <damien@micropython.org>2025-07-08 13:15:47 +1000
commit0975255f863be2e2529d57fb67bc7ba841e81249 (patch)
treecaf6615da9fc24ef97eb5e26c80eec86e37047a5
parentd5246cea616c9b783cfd88e5cd854b92953ed9d4 (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.c15
-rw-r--r--ports/stm32/uart.h4
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