From 427862d54b84a6e56cc208695abc1eea0129624b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 29 Apr 2026 22:03:33 +0200 Subject: [PATCH] possible fixes for async SPI --- vorago-shared-hal/src/spi/asynch.rs | 47 ++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/vorago-shared-hal/src/spi/asynch.rs b/vorago-shared-hal/src/spi/asynch.rs index 7e97150..663b2aa 100644 --- a/vorago-shared-hal/src/spi/asynch.rs +++ b/vorago-shared-hal/src/spi/asynch.rs @@ -33,13 +33,15 @@ pub fn on_interrupt(peripheral: super::Bank) { let idx = peripheral as usize; let interrupt_enabled = spi.read_interrupt_control(); let isr = spi.read_interrupt_status(); - // IRQ is not related. - if interrupt_enabled.raw_value() == 0 { - return; - } + spi.write_interrupt_clear(InterruptClear::ALL); // Prevent spurious interrupts from messing with out logic here. spi.write_interrupt_control(InterruptControl::DISABLE_ALL); - spi.write_interrupt_clear(InterruptClear::ALL); + // IRQ is not related. + if interrupt_enabled.raw_value() == 0 { + reset_trigger_levels(&mut spi); + spi.write_fifo_clear(FifoClear::ALL); + return; + } let mut context = critical_section::with(|cs| { let context_ref = TRANSFER_CONTEXTS[idx].borrow(cs); *context_ref.borrow() @@ -175,6 +177,7 @@ fn on_interrupt_transfer_in_place( isr_finish_handler(idx, spi, context, transfer_len) } +#[inline] fn calculate_read_len( spi: &mut super::regs::MmioSpi<'static>, isr: InterruptStatus, @@ -201,46 +204,60 @@ fn isr_finish_handler( ) { // Transfer finish condition. if context.rx_progress == context.tx_progress && context.rx_progress == transfer_len { - finish_transfer(idx, context, spi); + finish_transfer(spi, idx, context); return; } - - unfinished_transfer(spi, transfer_len, context.rx_progress); - // If the transfer is done, the context structure was already written back. // Write back updated context structure. critical_section::with(|cs| { let context_ref = TRANSFER_CONTEXTS[idx].borrow(cs); *context_ref.borrow_mut() = *context; }); + unfinished_transfer(spi, transfer_len, context); } fn finish_transfer( + spi: &mut super::regs::MmioSpi<'static>, idx: usize, context: &mut TransferContext, - spi: &mut super::regs::MmioSpi<'static>, ) { // Write back updated context structure. critical_section::with(|cs| { let context_ref = TRANSFER_CONTEXTS[idx].borrow(cs); *context_ref.borrow_mut() = *context; }); - spi.write_rx_fifo_trigger(TriggerLevel::new(u5::new(0x08))); - spi.write_tx_fifo_trigger(TriggerLevel::new(u5::new(0x00))); + // Clean up, restore clean state. + reset_trigger_levels(spi); + spi.write_fifo_clear(FifoClear::ALL); // Interrupts were already disabled and cleared. DONE[idx].store(true, core::sync::atomic::Ordering::Relaxed); WAKERS[idx].wake(); } +#[inline] fn unfinished_transfer( spi: &mut super::regs::MmioSpi<'static>, transfer_len: usize, - rx_progress: usize, + context: &TransferContext, ) { - let new_trig_level = core::cmp::min(super::FIFO_DEPTH, transfer_len - rx_progress); + let new_trig_level = core::cmp::min(super::FIFO_DEPTH, transfer_len - context.rx_progress); spi.write_rx_fifo_trigger(TriggerLevel::new(u5::new(new_trig_level as u8))); + // Re-enable interrupts with the new RX FIFO trigger level. - spi.write_interrupt_control(InterruptControl::ENABLE_ALL); + spi.write_interrupt_control( + InterruptControl::builder() + .with_tx(context.tx_progress < transfer_len) + .with_rx(true) + .with_rx_timeout(true) + .with_rx_overrun(true) + .build(), + ); +} + +#[inline] +fn reset_trigger_levels(spi: &mut super::regs::MmioSpi<'static>) { + spi.write_rx_fifo_trigger(TriggerLevel::new(u5::new(0x08))); + spi.write_tx_fifo_trigger(TriggerLevel::new(u5::new(0x00))); } #[derive(Debug, Clone, Copy)] -- 2.43.0