scsi works again, but has bugs

This commit is contained in:
2025-11-05 11:20:24 -07:00
parent 4ec5afbc65
commit 8290ec40a7
2 changed files with 43 additions and 29 deletions

View File

@@ -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

View File

@@ -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<CriticalSectionRawMutex, ()> = Signal::new();
static STOP_USB: Signal<CriticalSectionRawMutex, ()> = Signal::new();
static START_USB: Channel<CriticalSectionRawMutex, (), 1> = Channel::new();
static STOP_USB: Channel<CriticalSectionRawMutex, (), 1> = 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);
}