Skip to content

Commit 44fff98

Browse files
committed
Re-clock SD Card and enable HDD LED
1 parent 034459e commit 44fff98

File tree

2 files changed

+76
-40
lines changed

2 files changed

+76
-40
lines changed

src/main.rs

Lines changed: 48 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ struct CardInfo {
129129
/// Number of blocks on the SD card
130130
num_blocks: u64,
131131
/// Type of card
132-
card_type: embedded_sdmmc::sdcard::CardType
132+
card_type: embedded_sdmmc::sdcard::CardType,
133133
}
134134

135135
/// All the hardware we use on the Pico
@@ -161,10 +161,12 @@ struct Hardware {
161161
rtc: rtc::Rtc,
162162
/// The time we started up at, in microseconds since the Neotron epoch
163163
bootup_at: Duration,
164-
/// A Timer
164+
/// A 1 MHz Timer
165165
timer: hal::timer::Timer,
166166
/// the state of our SD Card
167167
card_state: CardState,
168+
/// Tracks all the clocks in the RP2040
169+
clocks: ClocksManager,
168170
}
169171

170172
/// Flips between true and false so we always send a unique read request
@@ -488,6 +490,12 @@ fn main() -> ! {
488490
}
489491

490492
impl Hardware {
493+
/// How fast can the I/O chip SPI CLK input go?
494+
const CLOCK_IO: fugit::Rate<u32, 1, 1> = fugit::Rate::<u32, 1, 1>::Hz(10_000_000);
495+
496+
/// How fast can the BMC SPI CLK input go?
497+
const CLOCK_BMC: fugit::Rate<u32, 1, 1> = fugit::Rate::<u32, 1, 1>::Hz(2_000_000);
498+
491499
/// How many nano seconds per clock cycle (at 126 MHz)?
492500
const NS_PER_CLOCK_CYCLE: u32 = 1_000_000_000 / 126_000_000;
493501

@@ -711,12 +719,12 @@ impl Hardware {
711719
// We are in SPI MODE 0. This means we change the COPI pin on the
712720
// CLK falling edge, and we sample the CIPO pin on the CLK rising
713721
// edge.
714-
715-
// Set SPI up for 4 MHz clock, 8 data bits.
722+
//
723+
// SPI clock speed here is irrelevant - we change it depending on the device.
716724
spi_bus: hal::Spi::new(spi).init(
717725
resets,
718726
clocks.peripheral_clock.freq(),
719-
100_000.Hz(),
727+
2_000_000.Hz(),
720728
&embedded_hal::spi::MODE_0,
721729
),
722730
delay,
@@ -732,6 +740,7 @@ impl Hardware {
732740
bootup_at: Duration::from_ticks(ticks_at_boot_us as u64),
733741
timer,
734742
card_state: CardState::Unplugged,
743+
clocks,
735744
},
736745
hal_pins.gpio20.into_pull_up_input(),
737746
)
@@ -746,6 +755,9 @@ impl Hardware {
746755
where
747756
F: FnOnce(&mut hal::Spi<hal::spi::Enabled, pac::SPI0, 8_u8>) -> T,
748757
{
758+
self.spi_bus
759+
.set_baudrate(self.clocks.peripheral_clock.freq(), Self::CLOCK_IO);
760+
749761
// Select MCP23S17
750762
self.pins.nspi_cs_io.set_low().unwrap();
751763
// Setup time
@@ -827,7 +839,7 @@ impl Hardware {
827839
///
828840
/// Activates a specific chip-select line, runs the closure (passing in the
829841
/// SPI bus object), then de-activates the CS pin.
830-
fn with_bus_cs<F>(&mut self, cs: u8, func: F)
842+
fn with_bus_cs<F>(&mut self, cs: u8, clock_speed: fugit::Rate<u32, 1, 1>, func: F)
831843
where
832844
F: FnOnce(&mut hal::Spi<hal::spi::Enabled, pac::SPI0, 8_u8>, &mut [u8]),
833845
{
@@ -846,6 +858,9 @@ impl Hardware {
846858
// Setup time
847859
cortex_m::asm::delay(Self::CS_BUS_SETUP_CPU_CLOCKS);
848860

861+
self.spi_bus
862+
.set_baudrate(self.clocks.peripheral_clock.freq(), clock_speed);
863+
849864
// Call function
850865
func(&mut self.spi_bus, &mut self.bmc_buffer);
851866

@@ -1052,7 +1067,7 @@ impl Hardware {
10521067
let expected_response_len = buffer.as_ref().map(|b| b.len()).unwrap_or(0) + 2;
10531068
defmt::debug!("req: {=[u8; 4]:02x}", req_bytes);
10541069
let mut latency = 0;
1055-
self.with_bus_cs(0, |spi, borrowed_buffer| {
1070+
self.with_bus_cs(0, Self::CLOCK_BMC, |spi, borrowed_buffer| {
10561071
// Send the request
10571072
spi.write(&req_bytes).unwrap();
10581073
for retry in 0..MAX_LATENCY {
@@ -1200,25 +1215,26 @@ impl Hardware {
12001215
fn sdcard_poll(&mut self) {
12011216
match self.card_state {
12021217
CardState::Uninitialised => {
1203-
// Downclock SPI to 100 kHz
1204-
// hw.spi_bus.set_baudrate(hw.clocks, todo!());
12051218
use embedded_sdmmc::BlockDevice;
1206-
let spi = sdcard::FakeSpi(self);
1219+
// Downclock SPI to initialisation speed
1220+
let spi = sdcard::FakeSpi(self, true);
12071221
let cs = sdcard::FakeCs();
12081222
let delayer = sdcard::FakeDelayer();
12091223
let sdcard = embedded_sdmmc::SdCard::new(spi, cs, delayer);
12101224
// Talk to the card to trigger a scan if its type
12111225
let num_blocks = sdcard.num_blocks();
12121226
let card_type = sdcard.get_card_type();
1213-
defmt::info!("Found card size {:?} blocks, type {:?}", num_blocks, card_type);
1227+
defmt::info!(
1228+
"Found card size {:?} blocks, type {:?}",
1229+
num_blocks,
1230+
card_type
1231+
);
12141232
if let (Ok(num_blocks), Some(card_type)) = (num_blocks, card_type) {
12151233
self.card_state = CardState::Online(CardInfo {
12161234
num_blocks: num_blocks.0 as u64,
1217-
card_type
1235+
card_type,
12181236
});
12191237
}
1220-
// Bring SPI clock back up again
1221-
// hw.spi_bus.set_baudrate(hw.clocks, todo!());
12221238
}
12231239
CardState::Unplugged | CardState::Errored | CardState::Online(_) => {}
12241240
}
@@ -1884,7 +1900,9 @@ pub extern "C" fn block_dev_get_info(device: u8) -> common::Option<common::block
18841900
let mut lock = HARDWARE.lock();
18851901
let hw = lock.as_mut().unwrap();
18861902

1903+
hw.set_hdd_led(true);
18871904
hw.sdcard_poll();
1905+
hw.set_hdd_led(false);
18881906

18891907
match &hw.card_state {
18901908
CardState::Unplugged | CardState::Uninitialised | CardState::Errored => {
@@ -1953,32 +1971,33 @@ pub extern "C" fn block_read(
19531971
if data.data_len != usize::from(num_blocks) * 512 {
19541972
return common::Result::Err(common::Error::UnsupportedConfiguration(0));
19551973
}
1956-
match device {
1974+
let mut lock = HARDWARE.lock();
1975+
let hw = lock.as_mut().unwrap();
1976+
hw.set_hdd_led(true);
1977+
let result = match device {
19571978
0 => {
1958-
let mut lock = HARDWARE.lock();
1959-
let hw = lock.as_mut().unwrap();
19601979
hw.sdcard_poll();
19611980
let info = match &hw.card_state {
1962-
CardState::Online(info) => {
1963-
info.clone()
1964-
}
1965-
_ => return common::Result::Err(common::Error::NoMediaFound)
1981+
CardState::Online(info) => info.clone(),
1982+
_ => return common::Result::Err(common::Error::NoMediaFound),
19661983
};
1967-
let spi = sdcard::FakeSpi(hw);
1984+
// Run card at full speed
1985+
let spi = sdcard::FakeSpi(hw, false);
19681986
let cs = sdcard::FakeCs();
19691987
let delayer = sdcard::FakeDelayer();
19701988
let sdcard = embedded_sdmmc::SdCard::new(spi, cs, delayer);
19711989
unsafe {
19721990
sdcard.mark_card_as_init(info.card_type);
19731991
}
19741992
let blocks = unsafe {
1975-
core::slice::from_raw_parts_mut(data.data as *mut embedded_sdmmc::Block, data.data_len / 512)
1993+
core::slice::from_raw_parts_mut(
1994+
data.data as *mut embedded_sdmmc::Block,
1995+
data.data_len / 512,
1996+
)
19761997
};
19771998
let start_block_idx = embedded_sdmmc::BlockIdx(block.0 as u32);
19781999
match sdcard.read(blocks, start_block_idx, "bios") {
1979-
Ok(_) => {
1980-
common::Result::Ok(())
1981-
}
2000+
Ok(_) => common::Result::Ok(()),
19822001
Err(e) => {
19832002
defmt::warn!("SD error reading {}: {:?}", block.0, e);
19842003
common::Result::Err(common::Error::DeviceError(0))
@@ -1989,7 +2008,9 @@ pub extern "C" fn block_read(
19892008
// Nothing else supported by this BIOS
19902009
common::Result::Err(common::Error::InvalidDevice)
19912010
}
1992-
}
2011+
};
2012+
hw.set_hdd_led(false);
2013+
result
19932014
}
19942015

19952016
/// Verify one or more sectors on a block device (that is read them and

src/sdcard.rs

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,46 @@ use atomic_polyfill::{AtomicBool, Ordering};
44

55
use super::Hardware;
66

7-
pub(crate) struct FakeSpi<'a>(pub(crate) &'a mut Hardware);
7+
pub(crate) struct FakeSpi<'a>(pub(crate) &'a mut Hardware, pub bool);
88

99
pub(crate) struct FakeCs();
1010

1111
pub(crate) struct FakeDelayer();
1212

13+
/// How fast can the SD Card SPI CLK input go?
14+
const CLOCK_SD_CARD: fugit::Rate<u32, 1, 1> = fugit::Rate::<u32, 1, 1>::Hz(10_000_000);
15+
16+
/// How fast can the SD Card SPI CLK input go during the card init phase?
17+
const CLOCK_SD_CARD_INIT: fugit::Rate<u32, 1, 1> = fugit::Rate::<u32, 1, 1>::Hz(400_000);
18+
1319
static IS_CS_LOW: AtomicBool = AtomicBool::new(false);
1420

1521
impl<'a> embedded_hal::blocking::spi::Transfer<u8> for FakeSpi<'a> {
1622
type Error = core::convert::Infallible;
1723
fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
18-
if IS_CS_LOW.load(Ordering::SeqCst) {
24+
let result = if IS_CS_LOW.load(Ordering::SeqCst) {
1925
defmt::debug!("SD out: {:02x}", words);
20-
self.0.with_bus_cs(1, |spi, _buffer| {
21-
spi.transfer(words).unwrap();
22-
});
26+
self.0.with_bus_cs(
27+
1,
28+
if self.1 {
29+
CLOCK_SD_CARD_INIT
30+
} else {
31+
CLOCK_SD_CARD
32+
},
33+
|spi, _buffer| {
34+
spi.transfer(words).unwrap();
35+
},
36+
);
2337
defmt::debug!("SD: {:02x}", words);
24-
Ok(words)
38+
words
2539
} else {
2640
// Select a slot we don't use so the SD card won't be activated
27-
self.0.with_bus_cs(7, |spi, _buffer| {
41+
self.0.with_bus_cs(7, CLOCK_SD_CARD_INIT, |spi, _buffer| {
2842
spi.transfer(words).unwrap();
2943
});
30-
Ok(words)
31-
}
44+
words
45+
};
46+
Ok(result)
3247
}
3348
}
3449

@@ -46,8 +61,8 @@ impl embedded_hal::digital::v2::OutputPin for FakeCs {
4661
}
4762

4863
impl embedded_hal::blocking::delay::DelayUs<u8> for FakeDelayer {
49-
fn delay_us(&mut self, us: u8) {
50-
// It doesn't have to be accurate. Just within an order of magnitude is fine.
51-
cortex_m::asm::delay(u32::from(us) * 150)
52-
}
64+
fn delay_us(&mut self, us: u8) {
65+
// It doesn't have to be accurate. Just within an order of magnitude is fine.
66+
cortex_m::asm::delay(u32::from(us) * 150)
67+
}
5368
}

0 commit comments

Comments
 (0)