diff --git a/kernel/src/scsi/mod.rs b/kernel/src/scsi/mod.rs index 594fa56..f941335 100644 --- a/kernel/src/scsi/mod.rs +++ b/kernel/src/scsi/mod.rs @@ -1,5 +1,6 @@ use core::sync::atomic::{AtomicBool, Ordering}; use embassy_sync::lazy_lock::LazyLock; +use embassy_time::Timer; use embassy_usb::Builder; use embassy_usb::driver::{Driver, EndpointIn, EndpointOut}; use embedded_sdmmc::{Block, BlockIdx}; @@ -15,11 +16,11 @@ const BULK_ENDPOINT_PACKET_SIZE: usize = 64; // indicates that a scsi transaction is occurring and is // NOT safe to disable usb, or acquire sdcard -static SCSI_BUSY: AtomicBool = AtomicBool::new(false); +pub static SCSI_BUSY: AtomicBool = AtomicBool::new(false); // number of blocks to read from sd at once // higher is better, but is larger. Size is BLOCKS * 512 bytes -const BLOCKS: usize = 32; +const BLOCKS: usize = 1; static mut BLOCK_BUF: LazyLock<[Block; BLOCKS]> = LazyLock::new(|| core::array::from_fn(|_| Block::new())); @@ -47,14 +48,30 @@ impl<'d, 's, D: Driver<'d>> MassStorageClass<'d, D> { } } + // Take sdcard to increase speed + pub async fn take_sdcard(&mut self) { + if self.temp_sd.is_none() { + let mut guard = SDCARD.get().lock().await; + if let Some(sd) = guard.take() { + self.temp_sd = Some(sd); + } else { + panic!("Tried to take SDCARD but it was already taken"); + } + } + } + + pub async fn return_sdcard(&mut self) { + if self.temp_sd.is_some() { + let mut guard = SDCARD.get().lock().await; + guard.replace(self.temp_sd.take().unwrap()).unwrap(); + } + } + pub async fn poll(&mut self) { loop { self.handle_cbw().await; - if self.temp_sd.is_some() { - let mut guard = SDCARD.get().lock().await; - guard.replace(self.temp_sd.take().unwrap()).unwrap(); - } + Timer::after_millis(10).await; } } @@ -65,16 +82,6 @@ impl<'d, 's, D: Driver<'d>> MassStorageClass<'d, D> { if let Some(cbw) = CommandBlockWrapper::parse(&cbw_buf[..n]) { SCSI_BUSY.store(true, Ordering::Release); - // Take sdcard to increase speed - if self.temp_sd.is_none() { - let mut guard = SDCARD.get().lock().await; - if let Some(sd) = guard.take() { - self.temp_sd = Some(sd); - } else { - panic!("Tried to take SDCARD but it was already taken"); - } - } - let command = parse_cb(&cbw.CBWCB); if self.handle_command(command).await.is_ok() { self.send_csw_success(cbw.dCBWTag).await diff --git a/kernel/src/usb.rs b/kernel/src/usb.rs index 9140a40..885a0f1 100644 --- a/kernel/src/usb.rs +++ b/kernel/src/usb.rs @@ -1,13 +1,17 @@ use core::sync::atomic::{AtomicBool, Ordering}; -use crate::{scsi::MassStorageClass, storage::SdCard}; +use crate::{ + scsi::{MassStorageClass, SCSI_BUSY}, + storage::SdCard, +}; use embassy_futures::{join::join, select::select}; use embassy_rp::{peripherals::USB, usb::Driver}; -use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, signal::Signal}; -use embassy_usb::{Builder, Config, UsbDevice}; +use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, channel::Channel}; +use embassy_time::Timer; +use embassy_usb::{Builder, Config}; -static START_USB: Signal = Signal::new(); -static STOP_USB: Signal = Signal::new(); +static START_USB: Channel = Channel::new(); +static STOP_USB: Channel = Channel::new(); // for other tasks to query the status of usb (like ui) // this is read only for ALL other tasks @@ -40,36 +44,39 @@ pub async fn usb_handler(driver: Driver<'static, USB>) { let mut usb = builder.build(); loop { - START_USB.wait().await; - START_USB.reset(); + START_USB.receiver().receive().await; #[cfg(feature = "defmt")] + scsi.take_sdcard().await; defmt::info!("starting usb"); select( // waits for cancellation signal, and then waits for // transfers to stop before dropping usb future async { - STOP_USB.wait().await; - STOP_USB.reset(); + STOP_USB.receiver().receive().await; }, // runs the usb, until cancelled join(usb.run(), scsi.poll()), ) .await; + while SCSI_BUSY.load(Ordering::Acquire) { + Timer::after_millis(100).await; + } #[cfg(feature = "defmt")] defmt::info!("disabling usb"); + scsi.return_sdcard().await; usb.disable().await; USB_ACTIVE.store(false, Ordering::Release); } } pub fn start_usb() { - STOP_USB.reset(); - START_USB.signal(()); + let _ = STOP_USB.receiver().try_receive(); + let _ = START_USB.sender().try_send(()); USB_ACTIVE.store(true, Ordering::Release); } pub fn stop_usb() { - START_USB.reset(); - STOP_USB.signal(()); + let _ = START_USB.receiver().try_receive(); + let _ = STOP_USB.sender().try_send(()); USB_ACTIVE.store(false, Ordering::Release); }