From 837950cd7440460f0e1f89e1ab9607f1a9d656ab Mon Sep 17 00:00:00 2001 From: Peter Gibson Date: Wed, 14 Jun 2023 11:56:44 +1000 Subject: [PATCH 1/4] ensure DR is read to clear idle/overflow interrupt when they occur independently of the rxne --- embassy-stm32/src/usart/buffered.rs | 37 ++++++++++++++++------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index 613da567..f55123e1 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -21,27 +21,32 @@ impl interrupt::typelevel::Handler for Interrupt // RX unsafe { let sr = sr(r).read(); + // Reading DR clears the rxne, error and idle interrupt flags on v1. + let dr = if sr.ore() || sr.idle() || sr.rxne() { + Some(rdr(r).read_volatile()) + } + else { + None + }; clear_interrupt_flags(r, sr); + if sr.pe() { + warn!("Parity error"); + } + if sr.fe() { + warn!("Framing error"); + } + if sr.ne() { + warn!("Noise error"); + } + if sr.ore() { + warn!("Overrun error"); + } if sr.rxne() { - if sr.pe() { - warn!("Parity error"); - } - if sr.fe() { - warn!("Framing error"); - } - if sr.ne() { - warn!("Noise error"); - } - if sr.ore() { - warn!("Overrun error"); - } - let mut rx_writer = state.rx_buf.writer(); let buf = rx_writer.push_slice(); if !buf.is_empty() { - // This read also clears the error and idle interrupt flags on v1. - buf[0] = rdr(r).read_volatile(); + buf[0] = dr.unwrap(); rx_writer.push_done(1); } else { // FIXME: Should we disable any further RX interrupts when the buffer becomes full. @@ -54,7 +59,7 @@ impl interrupt::typelevel::Handler for Interrupt if sr.idle() { state.rx_waker.wake(); - }; + } } // TX From d23717904b283fa46a02525acfb42eb9f42e61e3 Mon Sep 17 00:00:00 2001 From: Peter Gibson Date: Thu, 15 Jun 2023 18:33:01 +1000 Subject: [PATCH 2/4] fix formatting --- embassy-stm32/src/usart/buffered.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index f55123e1..e04b3ea0 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -48,7 +48,8 @@ impl interrupt::typelevel::Handler for Interrupt if !buf.is_empty() { buf[0] = dr.unwrap(); rx_writer.push_done(1); - } else { + } + else { // FIXME: Should we disable any further RX interrupts when the buffer becomes full. } From d236f3dbf9b53c5e646020946d8da1458eb591a1 Mon Sep 17 00:00:00 2001 From: Peter Gibson Date: Thu, 15 Jun 2023 18:35:58 +1000 Subject: [PATCH 3/4] actually fix formatting --- embassy-stm32/src/usart/buffered.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index e04b3ea0..530760bd 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -24,8 +24,7 @@ impl interrupt::typelevel::Handler for Interrupt // Reading DR clears the rxne, error and idle interrupt flags on v1. let dr = if sr.ore() || sr.idle() || sr.rxne() { Some(rdr(r).read_volatile()) - } - else { + } else { None }; clear_interrupt_flags(r, sr); @@ -48,8 +47,7 @@ impl interrupt::typelevel::Handler for Interrupt if !buf.is_empty() { buf[0] = dr.unwrap(); rx_writer.push_done(1); - } - else { + } else { // FIXME: Should we disable any further RX interrupts when the buffer becomes full. } From b4f96e192cd8c86f437e1d155388a860dcd3e1fd Mon Sep 17 00:00:00 2001 From: Peter Gibson Date: Sun, 18 Jun 2023 08:45:58 +1000 Subject: [PATCH 4/4] Don't read data register to clear flags on usart v3 ^& v4 --- embassy-stm32/src/usart/buffered.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index 530760bd..086196a2 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -21,8 +21,10 @@ impl interrupt::typelevel::Handler for Interrupt // RX unsafe { let sr = sr(r).read(); - // Reading DR clears the rxne, error and idle interrupt flags on v1. - let dr = if sr.ore() || sr.idle() || sr.rxne() { + // On v1 & v2, reading DR clears the rxne, error and idle interrupt + // flags. Keep this close to the SR read to reduce the chance of a + // flag being set in-between. + let dr = if sr.rxne() || cfg!(any(usart_v1, usart_v2)) && (sr.ore() || sr.idle()) { Some(rdr(r).read_volatile()) } else { None