From 917f1d1f4de6f7e25f483561001a9b5b36cbce7e Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Sun, 27 Oct 2024 09:55:00 +0100 Subject: [PATCH] This fixes 2 issues where STM32 BXCAN would hang 1. If one received frames under an `interrupt_free` section, in my case `init` in RTIC, the RX IRQ will fire and clear it's enable bit after `interrupt_free` is complete. There is no frame to read so RX is now unconditionally disabled forever. 2. On clearing of RX IRQ, TX stops silently. This happens due to the use of `write` instead of `modify` when modifying IRQ enable bits. Solution 1: Enable RX IRQs on every call to `try_read` that return no data. This solution also solves the issue of very delayed handling of the RX IRQ which would cause the same issue. Solution 2: Use `modify` instead of `write`. --- embassy-stm32/src/can/bxcan/mod.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/src/can/bxcan/mod.rs b/embassy-stm32/src/can/bxcan/mod.rs index baa4bee79..19f1cea29 100644 --- a/embassy-stm32/src/can/bxcan/mod.rs +++ b/embassy-stm32/src/can/bxcan/mod.rs @@ -893,7 +893,7 @@ impl RxMode { RxFifo::Fifo0 => 0usize, RxFifo::Fifo1 => 1usize, }; - T::regs().ier().write(|w| { + T::regs().ier().modify(|w| { w.set_fmpie(fifo_idx, false); }); waker.wake(); @@ -936,18 +936,22 @@ impl RxMode { Self::NonBuffered(_) => { let registers = &info.regs; if let Some(msg) = registers.receive_fifo(RxFifo::Fifo0) { - registers.0.ier().write(|w| { + registers.0.ier().modify(|w| { w.set_fmpie(0, true); }); Ok(msg) } else if let Some(msg) = registers.receive_fifo(RxFifo::Fifo1) { - registers.0.ier().write(|w| { + registers.0.ier().modify(|w| { w.set_fmpie(1, true); }); Ok(msg) } else if let Some(err) = registers.curr_error() { Err(TryReadError::BusError(err)) } else { + registers.0.ier().modify(|w| { + w.set_fmpie(0, true); + w.set_fmpie(1, true); + }); Err(TryReadError::Empty) } }