Skip to content

Commit 8a220a9

Browse files
I can talk to the SD card.
But I had to do some Bad Things (tm). Implements a fake SPI device which the embedded_sdmmc object can then own. This fake device does the correct chip select operations and then performs the SPI transaction. Also have to downlock the SPI to 100 kHz because I don't have a clocks object inside struct Hardware with which to do the SPI re-clocking.
1 parent a7c2f09 commit 8a220a9

3 files changed

Lines changed: 81 additions & 8 deletions

File tree

Cargo.lock

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ mcp794xx = "0.3.0"
5050
shared-bus = "0.2"
5151
# Gets us compare-swap atomic operations
5252
atomic-polyfill = "1.0.2"
53+
# SD Card driver
54+
embedded-sdmmc = { version = "0.4", default-features = false, features = ["defmt-log"] }
5355

5456
[[bin]]
5557
name = "neotron-pico-bios"

src/main.rs

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,7 @@ impl Hardware {
702702
spi_bus: hal::Spi::new(spi).init(
703703
resets,
704704
clocks.peripheral_clock.freq(),
705-
4_000_000.Hz(),
705+
100_000.Hz(),
706706
&embedded_hal::spi::MODE_0,
707707
),
708708
delay,
@@ -1844,14 +1844,73 @@ pub extern "C" fn block_dev_get_info(device: u8) -> common::Option<common::block
18441844
let mut lock = HARDWARE.lock();
18451845
let hw = lock.as_mut().unwrap();
18461846

1847-
let media_present = match hw.card_state {
1848-
CardState::Unplugged => false,
1849-
CardState::Errored => false,
1847+
let card_size = match hw.card_state {
1848+
CardState::Unplugged => None,
1849+
CardState::Errored => None,
18501850
CardState::Uninitialised => {
18511851
// Init the card here
1852-
true
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
18531912
}
1854-
CardState::Online => true,
1913+
CardState::Online => None,
18551914
};
18561915

18571916
// This is our on-board card slot
@@ -1862,13 +1921,13 @@ pub extern "C" fn block_dev_get_info(device: u8) -> common::Option<common::block
18621921
// This is the standard for SD cards
18631922
block_size: 512,
18641923
// TODO: scan the card here
1865-
num_blocks: 0,
1924+
num_blocks: card_size.unwrap_or(0),
18661925
// No motorised eject
18671926
ejectable: false,
18681927
// But you can take the card out
18691928
removable: true,
18701929
// Pretend the card is out
1871-
media_present,
1930+
media_present: card_size.is_some(),
18721931
// Don't care about this value when card is out
18731932
read_only: false,
18741933
})

0 commit comments

Comments
 (0)