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 core::sync::atomic::{AtomicBool, Ordering};
|
||||||
use embassy_sync::lazy_lock::LazyLock;
|
use embassy_sync::lazy_lock::LazyLock;
|
||||||
|
use embassy_time::Timer;
|
||||||
use embassy_usb::Builder;
|
use embassy_usb::Builder;
|
||||||
use embassy_usb::driver::{Driver, EndpointIn, EndpointOut};
|
use embassy_usb::driver::{Driver, EndpointIn, EndpointOut};
|
||||||
use embedded_sdmmc::{Block, BlockIdx};
|
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
|
// indicates that a scsi transaction is occurring and is
|
||||||
// NOT safe to disable usb, or acquire sdcard
|
// 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
|
// number of blocks to read from sd at once
|
||||||
// higher is better, but is larger. Size is BLOCKS * 512 bytes
|
// 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]> =
|
static mut BLOCK_BUF: LazyLock<[Block; BLOCKS]> =
|
||||||
LazyLock::new(|| core::array::from_fn(|_| Block::new()));
|
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) {
|
pub async fn poll(&mut self) {
|
||||||
loop {
|
loop {
|
||||||
self.handle_cbw().await;
|
self.handle_cbw().await;
|
||||||
|
|
||||||
if self.temp_sd.is_some() {
|
Timer::after_millis(10).await;
|
||||||
let mut guard = SDCARD.get().lock().await;
|
|
||||||
guard.replace(self.temp_sd.take().unwrap()).unwrap();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,16 +82,6 @@ impl<'d, 's, D: Driver<'d>> MassStorageClass<'d, D> {
|
|||||||
if let Some(cbw) = CommandBlockWrapper::parse(&cbw_buf[..n]) {
|
if let Some(cbw) = CommandBlockWrapper::parse(&cbw_buf[..n]) {
|
||||||
SCSI_BUSY.store(true, Ordering::Release);
|
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);
|
let command = parse_cb(&cbw.CBWCB);
|
||||||
if self.handle_command(command).await.is_ok() {
|
if self.handle_command(command).await.is_ok() {
|
||||||
self.send_csw_success(cbw.dCBWTag).await
|
self.send_csw_success(cbw.dCBWTag).await
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
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_futures::{join::join, select::select};
|
||||||
use embassy_rp::{peripherals::USB, usb::Driver};
|
use embassy_rp::{peripherals::USB, usb::Driver};
|
||||||
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, signal::Signal};
|
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, channel::Channel};
|
||||||
use embassy_usb::{Builder, Config, UsbDevice};
|
use embassy_time::Timer;
|
||||||
|
use embassy_usb::{Builder, Config};
|
||||||
|
|
||||||
static START_USB: Signal<CriticalSectionRawMutex, ()> = Signal::new();
|
static START_USB: Channel<CriticalSectionRawMutex, (), 1> = Channel::new();
|
||||||
static STOP_USB: Signal<CriticalSectionRawMutex, ()> = Signal::new();
|
static STOP_USB: Channel<CriticalSectionRawMutex, (), 1> = Channel::new();
|
||||||
|
|
||||||
// for other tasks to query the status of usb (like ui)
|
// for other tasks to query the status of usb (like ui)
|
||||||
// this is read only for ALL other tasks
|
// 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();
|
let mut usb = builder.build();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
START_USB.wait().await;
|
START_USB.receiver().receive().await;
|
||||||
START_USB.reset();
|
|
||||||
#[cfg(feature = "defmt")]
|
#[cfg(feature = "defmt")]
|
||||||
|
scsi.take_sdcard().await;
|
||||||
defmt::info!("starting usb");
|
defmt::info!("starting usb");
|
||||||
select(
|
select(
|
||||||
// waits for cancellation signal, and then waits for
|
// waits for cancellation signal, and then waits for
|
||||||
// transfers to stop before dropping usb future
|
// transfers to stop before dropping usb future
|
||||||
async {
|
async {
|
||||||
STOP_USB.wait().await;
|
STOP_USB.receiver().receive().await;
|
||||||
STOP_USB.reset();
|
|
||||||
},
|
},
|
||||||
// runs the usb, until cancelled
|
// runs the usb, until cancelled
|
||||||
join(usb.run(), scsi.poll()),
|
join(usb.run(), scsi.poll()),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
while SCSI_BUSY.load(Ordering::Acquire) {
|
||||||
|
Timer::after_millis(100).await;
|
||||||
|
}
|
||||||
#[cfg(feature = "defmt")]
|
#[cfg(feature = "defmt")]
|
||||||
defmt::info!("disabling usb");
|
defmt::info!("disabling usb");
|
||||||
|
scsi.return_sdcard().await;
|
||||||
usb.disable().await;
|
usb.disable().await;
|
||||||
USB_ACTIVE.store(false, Ordering::Release);
|
USB_ACTIVE.store(false, Ordering::Release);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_usb() {
|
pub fn start_usb() {
|
||||||
STOP_USB.reset();
|
let _ = STOP_USB.receiver().try_receive();
|
||||||
START_USB.signal(());
|
let _ = START_USB.sender().try_send(());
|
||||||
USB_ACTIVE.store(true, Ordering::Release);
|
USB_ACTIVE.store(true, Ordering::Release);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stop_usb() {
|
pub fn stop_usb() {
|
||||||
START_USB.reset();
|
let _ = START_USB.receiver().try_receive();
|
||||||
STOP_USB.signal(());
|
let _ = STOP_USB.sender().try_send(());
|
||||||
USB_ACTIVE.store(false, Ordering::Release);
|
USB_ACTIVE.store(false, Ordering::Release);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user