From eb41170fa27cf0529e16dcedee95bcec7ca0d88a Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 1 May 2026 13:54:43 +0200 Subject: [PATCH] more robustness improvements for async SPI --- vorago-shared-hal/src/spi/asynch.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/vorago-shared-hal/src/spi/asynch.rs b/vorago-shared-hal/src/spi/asynch.rs index eb95a87..6537073 100644 --- a/vorago-shared-hal/src/spi/asynch.rs +++ b/vorago-shared-hal/src/spi/asynch.rs @@ -46,6 +46,7 @@ pub fn on_interrupt(peripheral: super::Bank) { let mut spi = unsafe { peripheral.steal_regs() }; let index = peripheral as usize; let enabled_irqs = spi.read_interrupt_control(); + let interrupt_status = spi.read_interrupt_status(); spi.write_interrupt_clear(InterruptClear::ALL); // Prevent spurious interrupts from messing with out logic here. spi.write_interrupt_control(InterruptControl::DISABLE_ALL); @@ -55,7 +56,7 @@ pub fn on_interrupt(peripheral: super::Bank) { spi.write_fifo_clear(FifoClear::ALL); return; } - if spi.read_interrupt_status().rx_overrun() { + if interrupt_status.rx_overrun() { // Not sure how to otherwise handle this cleanly.. return handle_rx_overrun(&mut spi, index); } @@ -257,7 +258,9 @@ fn unfinished_transfer( context: &TransferContext, enabled_irqs: InterruptControl, ) { - let new_trig_level = core::cmp::min(super::FIFO_DEPTH, transfer_len - context.rx_progress); + // Take 8 as a conservative value to make sure that the FIFO does not overflow even if there + // is a significant delay between the interrupt being triggered and the handler being executed. + let new_trig_level = core::cmp::min(8, transfer_len - context.rx_progress); spi.write_rx_fifo_trigger(TriggerLevel::new(u5::new(new_trig_level as u8))); // If TX was already enabled and the transfer is finished, stop enabling it. Otherwise, we can @@ -335,7 +338,7 @@ impl<'spi> SpiFuture<'spi> { spi.regs.write_data(Data::new_with_raw_value(0)); }); - Self::set_triggers(spi, write_index, words.len()); + Self::set_triggers(spi, words.len()); critical_section::with(|cs| { let context_ref = TRANSFER_CONTEXTS[bank as usize].borrow(cs); @@ -414,7 +417,7 @@ impl<'spi> SpiFuture<'spi> { spi.regs.write_data(Data::new_with_raw_value(value as u32)); } - Self::set_triggers(spi, fifo_prefill, full_write_len); + Self::set_triggers(spi, full_write_len); critical_section::with(|cs| { let context_ref = TRANSFER_CONTEXTS[index].borrow(cs); @@ -494,14 +497,13 @@ impl<'spi> SpiFuture<'spi> { .write_data(Data::new_with_raw_value(write[idx] as u32)); }); - Self::set_triggers(spi, write_idx, write.len()); + Self::set_triggers(spi, write.len()); write_idx } - fn set_triggers(spi: &mut super::Spi, write_idx: usize, write_len: usize) { - // This should never fail because it is never larger than the FIFO depth. + fn set_triggers(spi: &mut super::Spi, write_len: usize) { spi.regs - .write_rx_fifo_trigger(TriggerLevel::new(u5::new(write_idx as u8))); + .write_rx_fifo_trigger(TriggerLevel::new(u5::new(8))); // We want to re-fill the TX FIFO before it is completely empty if the full transfer size // is larger than the FIFO depth. Otherwise, set it to 0. Not exactly sure what that does, // but we do not enable interrupts anyway.