Skip to content

Commit 4cb5ccc

Browse files
committed
Cache the SD card state.
A second call to block_dev_get_info now goes much faster because the card isn't re-initialised.
1 parent 8a220a9 commit 4cb5ccc

1 file changed

Lines changed: 107 additions & 97 deletions

File tree

src/main.rs

Lines changed: 107 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -112,16 +112,23 @@ type I2cPins = (
112112
type SpiBus = hal::Spi<hal::spi::Enabled, pac::SPI0, 8>;
113113

114114
/// What state our SD Card can be in
115-
#[derive(defmt::Format, Debug, Copy, Clone, PartialEq, Eq)]
115+
#[derive(defmt::Format, Debug, Clone, PartialEq, Eq)]
116116
enum CardState {
117117
Unplugged,
118118
Uninitialised,
119119
#[allow(unused)]
120-
Online,
120+
Online(CardInfo),
121121
#[allow(unused)]
122122
Errored,
123123
}
124124

125+
/// Describes an SD card we've discovered
126+
#[derive(defmt::Format, Debug, Clone, PartialEq, Eq)]
127+
struct CardInfo {
128+
/// Number of blocks on the SD card
129+
num_blocks: u64,
130+
}
131+
125132
/// All the hardware we use on the Pico
126133
struct Hardware {
127134
/// All the pins we use on the Raspberry Pi Pico
@@ -723,13 +730,6 @@ impl Hardware {
723730
)
724731
}
725732

726-
// i2c_sda: {
727-
//
728-
// },
729-
// i2c_scl: {
730-
//
731-
// },
732-
733733
/// Perform some SPI operation with the I/O chip selected.
734734
///
735735
/// You are required to have called `self.release_cs_lines()` previously,
@@ -961,7 +961,7 @@ impl Hardware {
961961
if was_inserted { "inserted" } else { "removed" }
962962
);
963963

964-
self.card_state = match (self.card_state, was_inserted) {
964+
self.card_state = match (&self.card_state, was_inserted) {
965965
// Eject events
966966
(CardState::Unplugged, false) => {
967967
defmt::warn!("Spurious unplug event");
@@ -971,7 +971,7 @@ impl Hardware {
971971
defmt::info!("SD Card removed");
972972
CardState::Unplugged
973973
}
974-
(CardState::Online, false) => {
974+
(CardState::Online(_), false) => {
975975
defmt::warn!("Active SD Card removed!");
976976
CardState::Unplugged
977977
}
@@ -1189,6 +1189,77 @@ impl Hardware {
11891189
}
11901190
Ok(bytes_in_fifo as usize)
11911191
}
1192+
1193+
fn sdcard_poll(&mut self) {
1194+
match self.card_state {
1195+
CardState::Uninitialised => {
1196+
// Init the card here
1197+
use embedded_sdmmc::BlockDevice;
1198+
struct FakeSpi<'a>(&'a mut Hardware);
1199+
struct FakeCs();
1200+
static IS_CS_LOW: AtomicBool = AtomicBool::new(false);
1201+
impl<'a> embedded_hal::blocking::spi::Transfer<u8> for FakeSpi<'a> {
1202+
type Error = core::convert::Infallible;
1203+
fn transfer<'w>(
1204+
&mut self,
1205+
words: &'w mut [u8],
1206+
) -> Result<&'w [u8], Self::Error> {
1207+
if IS_CS_LOW.load(Ordering::SeqCst) {
1208+
defmt::info!("out: {:?}", words);
1209+
self.0.with_bus_cs(1, |spi, _buffer| {
1210+
spi.transfer(words).unwrap();
1211+
});
1212+
defmt::info!("in: {:?}", words);
1213+
Ok(words)
1214+
} else {
1215+
// Select a slot we don't use so the SD card won't be activated
1216+
defmt::info!("out: {:?}", words);
1217+
self.0.with_bus_cs(7, |spi, _buffer| {
1218+
spi.transfer(words).unwrap();
1219+
});
1220+
defmt::info!("in: {:?}", words);
1221+
Ok(words)
1222+
}
1223+
}
1224+
}
1225+
impl embedded_hal::digital::v2::OutputPin for FakeCs {
1226+
type Error = core::convert::Infallible;
1227+
fn set_low(&mut self) -> Result<(), Self::Error> {
1228+
IS_CS_LOW.store(true, Ordering::SeqCst);
1229+
Ok(())
1230+
}
1231+
1232+
fn set_high(&mut self) -> Result<(), Self::Error> {
1233+
IS_CS_LOW.store(true, Ordering::SeqCst);
1234+
Ok(())
1235+
}
1236+
}
1237+
// Downclock SPI to 100 kHz
1238+
// hw.spi_bus.set_baudrate(hw.clocks, todo!());
1239+
let spi = FakeSpi(self);
1240+
let cs = FakeCs();
1241+
let mut spi_interface = embedded_sdmmc::SdMmcSpi::new(spi, cs);
1242+
let num_blocks = match spi_interface.acquire() {
1243+
Ok(card) => {
1244+
defmt::info!("Found card size!");
1245+
card.num_blocks()
1246+
}
1247+
Err(e) => {
1248+
defmt::warn!("Failed to acquire SD card: {:?}", e);
1249+
Err(e)
1250+
}
1251+
};
1252+
if let Ok(num_blocks) = num_blocks {
1253+
self.card_state = CardState::Online(CardInfo {
1254+
num_blocks: num_blocks.0 as u64,
1255+
});
1256+
}
1257+
// Bring SPI clock back up again
1258+
// hw.spi_bus.set_baudrate(hw.clocks, todo!());
1259+
}
1260+
CardState::Unplugged | CardState::Errored | CardState::Online(_) => {}
1261+
}
1262+
}
11921263
}
11931264

11941265
fn sign_on() {
@@ -1844,93 +1915,32 @@ pub extern "C" fn block_dev_get_info(device: u8) -> common::Option<common::block
18441915
let mut lock = HARDWARE.lock();
18451916
let hw = lock.as_mut().unwrap();
18461917

1847-
let card_size = match hw.card_state {
1848-
CardState::Unplugged => None,
1849-
CardState::Errored => None,
1850-
CardState::Uninitialised => {
1851-
// Init the card here
1852-
use embedded_sdmmc::BlockDevice;
1853-
struct FakeSpi<'a>(&'a mut Hardware);
1854-
struct FakeCs();
1855-
static IS_CS_LOW: AtomicBool = AtomicBool::new(false);
1856-
impl<'a> embedded_hal::blocking::spi::Transfer<u8> for FakeSpi<'a> {
1857-
type Error = core::convert::Infallible;
1858-
fn transfer<'w>(
1859-
&mut self,
1860-
words: &'w mut [u8],
1861-
) -> Result<&'w [u8], Self::Error> {
1862-
if IS_CS_LOW.load(Ordering::SeqCst) {
1863-
defmt::info!("out: {:?}", words);
1864-
self.0.with_bus_cs(1, |spi, _buffer| {
1865-
spi.transfer(words).unwrap();
1866-
});
1867-
defmt::info!("in: {:?}", words);
1868-
Ok(words)
1869-
} else {
1870-
// Select a slot we don't use so the SD card won't be activated
1871-
defmt::info!("out: {:?}", words);
1872-
self.0.with_bus_cs(7, |spi, _buffer| {
1873-
spi.transfer(words).unwrap();
1874-
});
1875-
defmt::info!("in: {:?}", words);
1876-
Ok(words)
1877-
}
1878-
}
1879-
}
1880-
impl embedded_hal::digital::v2::OutputPin for FakeCs {
1881-
type Error = core::convert::Infallible;
1882-
fn set_low(&mut self) -> Result<(), Self::Error> {
1883-
IS_CS_LOW.store(true, Ordering::SeqCst);
1884-
Ok(())
1885-
}
1886-
1887-
fn set_high(&mut self) -> Result<(), Self::Error> {
1888-
IS_CS_LOW.store(true, Ordering::SeqCst);
1889-
Ok(())
1890-
}
1891-
}
1892-
// Downclock SPI to 100 kHz
1893-
// hw.spi_bus.set_baudrate(hw.clocks, todo!());
1894-
let spi = FakeSpi(hw);
1895-
let cs = FakeCs();
1896-
let mut spi_interface = embedded_sdmmc::SdMmcSpi::new(spi, cs);
1897-
let size = match spi_interface.acquire() {
1898-
Ok(card) => {
1899-
defmt::info!("Found card size!");
1900-
card.num_blocks()
1901-
.map(|block_count| block_count.0 as u64)
1902-
.ok()
1903-
}
1904-
Err(e) => {
1905-
defmt::warn!("Failed to acquire SD card: {:?}", e);
1906-
None
1907-
}
1908-
};
1909-
// Bring SPI clock back up again
1910-
// hw.spi_bus.set_baudrate(hw.clocks, todo!());
1911-
size
1918+
hw.sdcard_poll();
1919+
1920+
match &hw.card_state {
1921+
CardState::Unplugged | CardState::Uninitialised | CardState::Errored => {
1922+
common::Option::Some(common::block_dev::DeviceInfo {
1923+
name: common::types::ApiString::new("SdCard0"),
1924+
device_type: common::block_dev::DeviceType::SecureDigitalCard,
1925+
block_size: 0,
1926+
num_blocks: 0,
1927+
ejectable: false,
1928+
removable: true,
1929+
media_present: false,
1930+
read_only: false,
1931+
})
19121932
}
1913-
CardState::Online => None,
1914-
};
1915-
1916-
// This is our on-board card slot
1917-
common::Option::Some(common::block_dev::DeviceInfo {
1918-
// This is the built-in SD card slot
1919-
name: common::types::ApiString::new("SdCard0"),
1920-
device_type: common::block_dev::DeviceType::SecureDigitalCard,
1921-
// This is the standard for SD cards
1922-
block_size: 512,
1923-
// TODO: scan the card here
1924-
num_blocks: card_size.unwrap_or(0),
1925-
// No motorised eject
1926-
ejectable: false,
1927-
// But you can take the card out
1928-
removable: true,
1929-
// Pretend the card is out
1930-
media_present: card_size.is_some(),
1931-
// Don't care about this value when card is out
1932-
read_only: false,
1933-
})
1933+
CardState::Online(info) => common::Option::Some(common::block_dev::DeviceInfo {
1934+
name: common::types::ApiString::new("SdCard0"),
1935+
device_type: common::block_dev::DeviceType::SecureDigitalCard,
1936+
block_size: 512,
1937+
num_blocks: info.num_blocks,
1938+
ejectable: false,
1939+
removable: true,
1940+
media_present: true,
1941+
read_only: false,
1942+
}),
1943+
}
19341944
}
19351945
_ => {
19361946
// Nothing else supported by this BIOS

0 commit comments

Comments
 (0)