mirror of
https://github.com/LegitCamper/picocalc-os-rs.git
synced 2025-12-27 15:55:25 +00:00
scsi works again, but has bugs
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user