From c2648780af45743e3a7e83c2f179a5be02d5b752 Mon Sep 17 00:00:00 2001 From: xoviat Date: Fri, 7 Aug 2026 11:07:30 -0500 Subject: [PATCH 1/2] stm32/spi: clear errors on restart --- embassy-stm32/src/spi/ringbuffered.rs | 37 ++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/src/spi/ringbuffered.rs b/embassy-stm32/src/spi/ringbuffered.rs index ce1033d109..aac64cb7c4 100644 --- a/embassy-stm32/src/spi/ringbuffered.rs +++ b/embassy-stm32/src/spi/ringbuffered.rs @@ -9,8 +9,6 @@ use embassy_hal_internal::Peri; use embedded_io_async::ReadReady; use futures_util::future::select; -use super::mode::Slave; -use super::{Config, Error, Info, RegsExt, Spi, Word, check_error_flags, reconfigure, set_rxdmaen}; use crate::dma::ReadableRingBuffer; use crate::exti::{Channel, ExtiInput, InterruptHandler}; use crate::gpio::{Flex, Pin}; @@ -19,6 +17,10 @@ use crate::mode::Async; use crate::rcc::WakeGuard; #[cfg(any(spi_v4, spi_v5, spi_v6))] use crate::spi::SlaveSelectPolarity; +use crate::spi::mode::Slave; +use crate::spi::{ + Config, Error, Info, Regs, RegsExt, Spi, Word, check_error_flags, flush_rx_fifo, reconfigure, set_rxdmaen, +}; use crate::time::Hertz; /// Rx-only Ring-buffered SPI Driver @@ -190,7 +192,9 @@ impl<'d, W: Word> RingBufferedSpiRx<'d, W> { fn start_or_check_errors(&mut self) -> Result<(), Error> { let r = self.info.regs; - check_error_flags(r.sr().read(), true)?; + let sr = r.sr().read(); + clear_spi_errors(r); + check_error_flags(sr, true)?; if !self.ring_buf.is_running() { self.start(); @@ -334,3 +338,30 @@ impl ReadReady for RingBufferedSpiRx<'_, W> { Ok(len > 0) } } + +/// Clear sticky SPI error flags and flush any stale RX FIFO data. +/// +/// On SPI v4/v5/v6 (H7), OVR/UDR/MODF/CRCE/TIFRE are cleared via IFCR. +/// On older SPI, OVR is cleared by reading SR then DR. +fn clear_spi_errors(r: Regs) { + #[cfg(any(spi_v4, spi_v5, spi_v6))] + { + // Write 1s to all flag-clear bits in IFCR + r.ifcr().write(|w| w.0 = 0xffff_ffff); + flush_rx_fifo(r); + } + #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] + { + // OVR is cleared by reading SR then DR. + // MODF is cleared by reading SR then writing CR1. + let sr = r.sr().read(); + if sr.modf() { + r.cr1().modify(|w| w.set_spe(false)); + r.cr1().modify(|w| w.set_spe(true)); + } + #[cfg(not(spi_v3))] + let _ = r.dr().read(); + #[cfg(spi_v3)] + let _ = r.dr16().read(); + } +} From 14e38d025682f3e485d7d239124752fa86856892 Mon Sep 17 00:00:00 2001 From: xoviat Date: Fri, 7 Aug 2026 11:11:18 -0500 Subject: [PATCH 2/2] fmt --- embassy-stm32/src/spi/ringbuffered.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/src/spi/ringbuffered.rs b/embassy-stm32/src/spi/ringbuffered.rs index aac64cb7c4..6e2450fef0 100644 --- a/embassy-stm32/src/spi/ringbuffered.rs +++ b/embassy-stm32/src/spi/ringbuffered.rs @@ -15,12 +15,10 @@ use crate::gpio::{Flex, Pin}; use crate::interrupt::typelevel::Binding; use crate::mode::Async; use crate::rcc::WakeGuard; -#[cfg(any(spi_v4, spi_v5, spi_v6))] -use crate::spi::SlaveSelectPolarity; use crate::spi::mode::Slave; -use crate::spi::{ - Config, Error, Info, Regs, RegsExt, Spi, Word, check_error_flags, flush_rx_fifo, reconfigure, set_rxdmaen, -}; +use crate::spi::{Config, Error, Info, Regs, RegsExt, Spi, Word, check_error_flags, reconfigure, set_rxdmaen}; +#[cfg(any(spi_v4, spi_v5, spi_v6))] +use crate::spi::{SlaveSelectPolarity, flush_rx_fifo}; use crate::time::Hertz; /// Rx-only Ring-buffered SPI Driver