Skip to content

Commit c13db45

Browse files
jonathanpallanteldruin
authored andcommitted
Fixup the README.
Also add the code from the README into an example so we can at least check it compiles.
1 parent b8e7f39 commit c13db45

File tree

2 files changed

+135
-10
lines changed

2 files changed

+135
-10
lines changed

README.md

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,29 @@ designed for readability and simplicity over performance.
1111
You will need something that implements the `BlockDevice` trait, which can read and write the 512-byte blocks (or sectors) from your card. If you were to implement this over USB Mass Storage, there's no reason this crate couldn't work with a USB Thumb Drive, but we only supply a `BlockDevice` suitable for reading SD and SDHC cards over SPI.
1212

1313
```rust
14-
// Build an SD Card interface out of an SPI device
15-
let sdcard = embedded_sdmmc::SdCard::new(sdmmc_spi, sdmmc_cs);
16-
write!(uart, "Card size is {} bytes", sdcard.num_bytes()?)?;
14+
// Build an SD Card interface out of an SPI device, a chip-select pin and a delay object
15+
let sdcard = embedded_sdmmc::SdCard::new(sdmmc_spi, sdmmc_cs, delay);
16+
// Get the card size (this also triggers card initialisation because it's not been done yet)
17+
println!("Card size is {} bytes", sdcard.num_bytes()?);
1718
// Now let's look for volumes (also known as partitions) on our block device.
18-
let mut cont = embedded_sdmmc::VolumeManager::new(sdcard, time_source);
19-
// Try and access Volume 0 (i.e. the first partition)
20-
let mut volume = cont.get_volume(embedded_sdmmc::VolumeIdx(0))?;
21-
writeln!(uart, "Volume 0: {:?}", v)?;
22-
// Open the root directory
19+
// To do this we need a Volume Manager. It will take ownership of the block device.
20+
let mut volume_mgr = embedded_sdmmc::VolumeManager::new(sdcard, time_source);
21+
// Try and access Volume 0 (i.e. the first partition).
22+
// The volume object holds information about the filesystem on that volume.
23+
// It doesn't hold a reference to the Volume Manager and so must be passed back
24+
// to every Volume Manager API call. This makes it easier to handle multiple
25+
// volumes in parallel.
26+
let mut volume0 = volume_mgr.get_volume(embedded_sdmmc::VolumeIdx(0))?;
27+
println!("Volume 0: {:?}", volume0);
28+
// Open the root directory (passing in the volume we're using).
2329
let root_dir = volume_mgr.open_root_dir(&volume0)?;
2430
// Open a file called "MY_FILE.TXT" in the root directory
2531
let mut my_file = volume_mgr.open_file_in_dir(
26-
&mut volume0, &root_dir, "MY_FILE.TXT", embedded_sdmmc::Mode::ReadOnly)?;
32+
&mut volume0,
33+
&root_dir,
34+
"MY_FILE.TXT",
35+
embedded_sdmmc::Mode::ReadOnly,
36+
)?;
2737
// Print the contents of the file
2838
while !my_file.eof() {
2939
let mut buffer = [0u8; 32];
@@ -33,7 +43,7 @@ while !my_file.eof() {
3343
}
3444
}
3545
volume_mgr.close_file(&volume0, my_file)?;
36-
volume_mgr.close_dir(&volume0, root_dir)?;
46+
volume_mgr.close_dir(&volume0, root_dir);
3747
```
3848

3949
### Open directories and files

examples/readme_test.rs

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
//! This is the code from the README.md file.
2+
//!
3+
//! We add enough stuff to make it compile, but it won't run because our fake
4+
//! SPI doesn't do any replies.
5+
6+
struct FakeSpi();
7+
8+
impl embedded_hal::blocking::spi::Transfer<u8> for FakeSpi {
9+
type Error = core::convert::Infallible;
10+
fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
11+
Ok(words)
12+
}
13+
}
14+
15+
impl embedded_hal::blocking::spi::Write<u8> for FakeSpi {
16+
type Error = core::convert::Infallible;
17+
fn write<'w>(&mut self, _words: &'w [u8]) -> Result<(), Self::Error> {
18+
Ok(())
19+
}
20+
}
21+
22+
struct FakeCs();
23+
24+
impl embedded_hal::digital::v2::OutputPin for FakeCs {
25+
type Error = core::convert::Infallible;
26+
fn set_low(&mut self) -> Result<(), Self::Error> {
27+
Ok(())
28+
}
29+
30+
fn set_high(&mut self) -> Result<(), Self::Error> {
31+
Ok(())
32+
}
33+
}
34+
35+
struct FakeDelayer();
36+
37+
impl embedded_hal::blocking::delay::DelayUs<u8> for FakeDelayer {
38+
fn delay_us(&mut self, us: u8) {
39+
std::thread::sleep(std::time::Duration::from_micros(u64::from(us)));
40+
}
41+
}
42+
43+
struct FakeTimesource();
44+
45+
impl embedded_sdmmc::TimeSource for FakeTimesource {
46+
fn get_timestamp(&self) -> embedded_sdmmc::Timestamp {
47+
embedded_sdmmc::Timestamp {
48+
year_since_1970: 0,
49+
zero_indexed_month: 0,
50+
zero_indexed_day: 0,
51+
hours: 0,
52+
minutes: 0,
53+
seconds: 0,
54+
}
55+
}
56+
}
57+
58+
#[derive(Debug, Clone)]
59+
enum Error {
60+
Filesystem(embedded_sdmmc::Error<embedded_sdmmc::SdCardError>),
61+
Disk(embedded_sdmmc::SdCardError),
62+
}
63+
64+
impl From<embedded_sdmmc::Error<embedded_sdmmc::SdCardError>> for Error {
65+
fn from(value: embedded_sdmmc::Error<embedded_sdmmc::SdCardError>) -> Error {
66+
Error::Filesystem(value)
67+
}
68+
}
69+
70+
impl From<embedded_sdmmc::SdCardError> for Error {
71+
fn from(value: embedded_sdmmc::SdCardError) -> Error {
72+
Error::Disk(value)
73+
}
74+
}
75+
76+
fn main() -> Result<(), Error> {
77+
let sdmmc_spi = FakeSpi();
78+
let sdmmc_cs = FakeCs();
79+
let delay = FakeDelayer();
80+
let time_source = FakeTimesource();
81+
// Build an SD Card interface out of an SPI device, a chip-select pin and the delay object
82+
let sdcard = embedded_sdmmc::SdCard::new(sdmmc_spi, sdmmc_cs, delay);
83+
// Get the card size (this also triggers card initialisation because it's not been done yet)
84+
println!("Card size is {} bytes", sdcard.num_bytes()?);
85+
// Now let's look for volumes (also known as partitions) on our block device.
86+
// To do this we need a Volume Manager. It will take ownership of the block device.
87+
let mut volume_mgr = embedded_sdmmc::VolumeManager::new(sdcard, time_source);
88+
// Try and access Volume 0 (i.e. the first partition).
89+
// The volume object holds information about the filesystem on that volume.
90+
// It doesn't hold a reference to the Volume Manager and so must be passed back
91+
// to every Volume Manager API call. This makes it easier to handle multiple
92+
// volumes in parallel.
93+
let mut volume0 = volume_mgr.get_volume(embedded_sdmmc::VolumeIdx(0))?;
94+
println!("Volume 0: {:?}", volume0);
95+
// Open the root directory (passing in the volume we're using).
96+
let root_dir = volume_mgr.open_root_dir(&volume0)?;
97+
// Open a file called "MY_FILE.TXT" in the root directory
98+
let mut my_file = volume_mgr.open_file_in_dir(
99+
&mut volume0,
100+
&root_dir,
101+
"MY_FILE.TXT",
102+
embedded_sdmmc::Mode::ReadOnly,
103+
)?;
104+
// Print the contents of the file
105+
while !my_file.eof() {
106+
let mut buffer = [0u8; 32];
107+
let num_read = volume_mgr.read(&volume0, &mut my_file, &mut buffer)?;
108+
for b in &buffer[0..num_read] {
109+
print!("{}", *b as char);
110+
}
111+
}
112+
volume_mgr.close_file(&volume0, my_file)?;
113+
volume_mgr.close_dir(&volume0, root_dir);
114+
Ok(())
115+
}

0 commit comments

Comments
 (0)