Skip to content

Commit 2f8303a

Browse files
authored
Merge pull request #116 from rust-embedded-community/release/v0.7.0
Release/v0.7.0
2 parents d362a6a + afdcec7 commit 2f8303a

25 files changed

+1838
-554
lines changed

CHANGELOG.md

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,32 @@ The format is based on [Keep a Changelog] and this project adheres to [Semantic
88

99
* None
1010

11+
## [Version 0.7.0] - 2024-02-04
12+
13+
## Changed
14+
15+
- __Breaking Change__: `Volume`, `Directory` and `File` are now smart! They hold references to the thing they were made from, and will clean themselves up when dropped. The trade-off is you can can't open multiple volumes, directories or files at the same time.
16+
- __Breaking Change__: Renamed the old types to `RawVolume`, `RawDirectory` and `RawFile`
17+
- __Breaking Change__: Renamed `Error::FileNotFound` to `Error::NotFound`
18+
- Fixed long-standing bug that caused an integer overflow when a FAT32 directory was longer than one cluster ([#74])
19+
- You can now open directories multiple times without error
20+
- Updated to [embedded-hal] 1.0
21+
22+
## Added
23+
24+
- `RawVolume`, `RawDirectory` and `RawFile` types (like the old `Volume`, `Directory` and `File` types)
25+
- New method `make_dir_in_dir`
26+
- Empty strings and `"."` convert to `ShortFileName::this_dir()`
27+
- New API `change_dir` which changes a directory to point to some child directory (or the parent) without opening a new directory.
28+
- Updated 'shell' example to support `mkdir`, `tree` and relative/absolute paths
29+
30+
## Removed
31+
32+
* None
33+
34+
[#74]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/issues/74
35+
[embedded-hal]: https://crates.io/crates/embedded-hal
36+
1137
## [Version 0.6.0] - 2023-10-20
1238

1339
### Changed
@@ -111,7 +137,8 @@ The format is based on [Keep a Changelog] and this project adheres to [Semantic
111137

112138
[Keep a Changelog]: http://keepachangelog.com/en/1.0.0/
113139
[Semantic Versioning]: http://semver.org/spec/v2.0.0.html
114-
[Unreleased]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.6.0...develop
140+
[Unreleased]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.7.0...develop
141+
[Version 0.7.0]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.7.0...v0.6.0
115142
[Version 0.6.0]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.6.0...v0.5.0
116143
[Version 0.5.0]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.5.0...v0.4.0
117144
[Version 0.4.0]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.4.0...v0.3.0

Cargo.toml

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,24 @@ license = "MIT OR Apache-2.0"
88
name = "embedded-sdmmc"
99
readme = "README.md"
1010
repository = "https://github.com/rust-embedded-community/embedded-sdmmc-rs"
11-
version = "0.6.0"
11+
version = "0.7.0"
1212

1313
[dependencies]
1414
byteorder = {version = "1", default-features = false}
1515
defmt = {version = "0.3", optional = true}
16-
embedded-hal = "0.2.3"
16+
embedded-hal = "1.0.0"
1717
heapless = "0.7"
1818
log = {version = "0.4", default-features = false, optional = true}
1919

2020
[dev-dependencies]
21-
env_logger = "0.9"
22-
hex-literal = "0.3"
23-
flate2 = "1.0"
24-
sha256 = "1.4"
2521
chrono = "0.4"
22+
embedded-hal-bus = "0.1.0"
23+
env_logger = "0.10.0"
24+
flate2 = "1.0"
25+
hex-literal = "0.4.1"
26+
sha2 = "0.10"
2627

2728
[features]
2829
default = ["log"]
29-
defmt-log = ["defmt"]
30+
defmt-log = ["dep:defmt"]
31+
log = ["dep:log"]

README.md

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ 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, a chip-select pin and a delay object
14+
// Build an SD Card interface out of an SPI device, a chip-select pin and the delay object
1515
let sdcard = embedded_sdmmc::SdCard::new(sdmmc_spi, sdmmc_cs, delay);
1616
// Get the card size (this also triggers card initialisation because it's not been done yet)
1717
println!("Card size is {} bytes", sdcard.num_bytes()?);
@@ -20,29 +20,21 @@ println!("Card size is {} bytes", sdcard.num_bytes()?);
2020
let mut volume_mgr = embedded_sdmmc::VolumeManager::new(sdcard, time_source);
2121
// Try and access Volume 0 (i.e. the first partition).
2222
// 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 volume0 = volume_mgr.get_volume(embedded_sdmmc::VolumeIdx(0))?;
23+
let mut volume0 = volume_mgr.open_volume(embedded_sdmmc::VolumeIdx(0))?;
2724
println!("Volume 0: {:?}", volume0);
28-
// Open the root directory (passing in the volume we're using).
29-
let root_dir = volume_mgr.open_root_dir(&volume0)?;
25+
// Open the root directory (mutably borrows from the volume).
26+
let mut root_dir = volume0.open_root_dir()?;
3027
// Open a file called "MY_FILE.TXT" in the root directory
31-
let my_file = volume_mgr.open_file_in_dir(
32-
root_dir,
33-
"MY_FILE.TXT",
34-
embedded_sdmmc::Mode::ReadOnly,
35-
)?;
28+
// This mutably borrows the directory.
29+
let mut my_file = root_dir.open_file_in_dir("MY_FILE.TXT", embedded_sdmmc::Mode::ReadOnly)?;
3630
// Print the contents of the file
37-
while !volume_manager.file_eof(my_file).unwrap() {
31+
while !my_file.is_eof() {
3832
let mut buffer = [0u8; 32];
39-
let num_read = volume_mgr.read(&volume0, &mut my_file, &mut buffer)?;
33+
let num_read = my_file.read(&mut buffer)?;
4034
for b in &buffer[0..num_read] {
4135
print!("{}", *b as char);
4236
}
4337
}
44-
volume_mgr.close_file(my_file)?;
45-
volume_mgr.close_dir(root_dir)?;
4638
```
4739

4840
### Open directories and files
@@ -66,6 +58,12 @@ let mut cont: VolumeManager<_, _, 6, 12, 4> = VolumeManager::new_with_limits(blo
6658
* Iterate sub-directories
6759
* Log over defmt or the common log interface (feature flags).
6860

61+
## No-std usage
62+
This repository houses no examples for no-std usage, however you can check out the following examples:
63+
- [Pi Pico](https://github.com/rp-rs/rp-hal-boards/blob/main/boards/rp-pico/examples/pico_spi_sd_card.rs)
64+
- [STM32H7XX](https://github.com/stm32-rs/stm32h7xx-hal/blob/master/examples/sdmmc_fat.rs)
65+
- [atsamd(pygamer)](https://github.com/atsamd-rs/atsamd/blob/master/boards/pygamer/examples/sd_card.rs)
66+
6967
## Todo List (PRs welcome!)
7068

7169
* Create new dirs

examples/append_file.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,11 @@ fn main() -> Result<(), embedded_sdmmc::Error<std::io::Error>> {
3232
let lbd = LinuxBlockDevice::new(filename, print_blocks).map_err(Error::DeviceError)?;
3333
let mut volume_mgr: VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4> =
3434
VolumeManager::new_with_limits(lbd, Clock, 0xAA00_0000);
35-
let volume = volume_mgr.open_volume(VolumeIdx(0))?;
36-
let root_dir = volume_mgr.open_root_dir(volume)?;
35+
let mut volume = volume_mgr.open_volume(VolumeIdx(0))?;
36+
let mut root_dir = volume.open_root_dir()?;
3737
println!("\nCreating file {}...", FILE_TO_APPEND);
38-
let f = volume_mgr.open_file_in_dir(root_dir, FILE_TO_APPEND, Mode::ReadWriteAppend)?;
39-
volume_mgr.write(f, b"\r\n\r\nThis has been added to your file.\r\n")?;
40-
volume_mgr.close_file(f)?;
41-
volume_mgr.close_dir(root_dir)?;
38+
let mut f = root_dir.open_file_in_dir(FILE_TO_APPEND, Mode::ReadWriteAppend)?;
39+
f.write(b"\r\n\r\nThis has been added to your file.\r\n")?;
4240
Ok(())
4341
}
4442

examples/big_dir.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
extern crate embedded_sdmmc;
2+
3+
mod linux;
4+
use linux::*;
5+
6+
use embedded_sdmmc::{Error, VolumeManager};
7+
8+
fn main() -> Result<(), embedded_sdmmc::Error<std::io::Error>> {
9+
env_logger::init();
10+
let mut args = std::env::args().skip(1);
11+
let filename = args.next().unwrap_or_else(|| "/dev/mmcblk0".into());
12+
let print_blocks = args.find(|x| x == "-v").map(|_| true).unwrap_or(false);
13+
let lbd = LinuxBlockDevice::new(filename, print_blocks).map_err(Error::DeviceError)?;
14+
let mut volume_mgr: VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4> =
15+
VolumeManager::new_with_limits(lbd, Clock, 0xAA00_0000);
16+
let mut volume = volume_mgr
17+
.open_volume(embedded_sdmmc::VolumeIdx(1))
18+
.unwrap();
19+
println!("Volume: {:?}", volume);
20+
let mut root_dir = volume.open_root_dir().unwrap();
21+
22+
let mut file_num = 0;
23+
loop {
24+
file_num += 1;
25+
let file_name = format!("{}.da", file_num);
26+
println!("opening file {file_name} for writing");
27+
let mut file = root_dir
28+
.open_file_in_dir(
29+
file_name.as_str(),
30+
embedded_sdmmc::Mode::ReadWriteCreateOrTruncate,
31+
)
32+
.unwrap();
33+
let buf = b"hello world, from rust";
34+
println!("writing to file");
35+
file.write(&buf[..]).unwrap();
36+
println!("closing file");
37+
drop(file);
38+
}
39+
}

examples/create_file.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,14 @@ fn main() -> Result<(), embedded_sdmmc::Error<std::io::Error>> {
3232
let lbd = LinuxBlockDevice::new(filename, print_blocks).map_err(Error::DeviceError)?;
3333
let mut volume_mgr: VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4> =
3434
VolumeManager::new_with_limits(lbd, Clock, 0xAA00_0000);
35-
let volume = volume_mgr.open_volume(VolumeIdx(0))?;
36-
let root_dir = volume_mgr.open_root_dir(volume)?;
35+
let mut volume = volume_mgr.open_volume(VolumeIdx(0))?;
36+
let mut root_dir = volume.open_root_dir()?;
3737
println!("\nCreating file {}...", FILE_TO_CREATE);
3838
// This will panic if the file already exists: use ReadWriteCreateOrAppend
3939
// or ReadWriteCreateOrTruncate instead if you want to modify an existing
4040
// file.
41-
let f = volume_mgr.open_file_in_dir(root_dir, FILE_TO_CREATE, Mode::ReadWriteCreate)?;
42-
volume_mgr.write(f, b"Hello, this is a new file on disk\r\n")?;
43-
volume_mgr.close_file(f)?;
44-
volume_mgr.close_dir(root_dir)?;
41+
let mut f = root_dir.open_file_in_dir(FILE_TO_CREATE, Mode::ReadWriteCreate)?;
42+
f.write(b"Hello, this is a new file on disk\r\n")?;
4543
Ok(())
4644
}
4745

examples/delete_file.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,11 @@ fn main() -> Result<(), embedded_sdmmc::Error<std::io::Error>> {
3535
let lbd = LinuxBlockDevice::new(filename, print_blocks).map_err(Error::DeviceError)?;
3636
let mut volume_mgr: VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4> =
3737
VolumeManager::new_with_limits(lbd, Clock, 0xAA00_0000);
38-
let volume = volume_mgr.open_volume(VolumeIdx(0))?;
39-
let root_dir = volume_mgr.open_root_dir(volume)?;
38+
let mut volume = volume_mgr.open_volume(VolumeIdx(0))?;
39+
let mut root_dir = volume.open_root_dir()?;
4040
println!("Deleting file {}...", FILE_TO_DELETE);
41-
volume_mgr.delete_file_in_dir(root_dir, FILE_TO_DELETE)?;
41+
root_dir.delete_file_in_dir(FILE_TO_DELETE)?;
4242
println!("Deleted!");
43-
volume_mgr.close_dir(root_dir)?;
4443
Ok(())
4544
}
4645

examples/list_dir.rs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -49,24 +49,22 @@ fn main() -> Result<(), Error> {
4949
let lbd = LinuxBlockDevice::new(filename, print_blocks).map_err(Error::DeviceError)?;
5050
let mut volume_mgr: VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4> =
5151
VolumeManager::new_with_limits(lbd, Clock, 0xAA00_0000);
52-
let volume = volume_mgr.open_volume(VolumeIdx(0))?;
53-
let root_dir = volume_mgr.open_root_dir(volume)?;
54-
list_dir(&mut volume_mgr, root_dir, "/")?;
55-
volume_mgr.close_dir(root_dir)?;
52+
let mut volume = volume_mgr.open_volume(VolumeIdx(0))?;
53+
let root_dir = volume.open_root_dir()?;
54+
list_dir(root_dir, "/")?;
5655
Ok(())
5756
}
5857

5958
/// Recursively print a directory listing for the open directory given.
6059
///
6160
/// The path is for display purposes only.
6261
fn list_dir(
63-
volume_mgr: &mut VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4>,
64-
directory: Directory,
62+
mut directory: Directory<LinuxBlockDevice, Clock, 8, 8, 4>,
6563
path: &str,
6664
) -> Result<(), Error> {
6765
println!("Listing {}", path);
6866
let mut children = Vec::new();
69-
volume_mgr.iterate_dir(directory, |entry| {
67+
directory.iterate_dir(|entry| {
7068
println!(
7169
"{:12} {:9} {} {}",
7270
entry.name,
@@ -78,23 +76,21 @@ fn list_dir(
7876
""
7977
}
8078
);
81-
if entry.attributes.is_directory() {
82-
if entry.name != embedded_sdmmc::ShortFileName::parent_dir()
83-
&& entry.name != embedded_sdmmc::ShortFileName::this_dir()
84-
{
85-
children.push(entry.name.clone());
86-
}
79+
if entry.attributes.is_directory()
80+
&& entry.name != embedded_sdmmc::ShortFileName::parent_dir()
81+
&& entry.name != embedded_sdmmc::ShortFileName::this_dir()
82+
{
83+
children.push(entry.name.clone());
8784
}
8885
})?;
8986
for child_name in children {
90-
let child_dir = volume_mgr.open_dir(directory, &child_name)?;
87+
let child_dir = directory.open_dir(&child_name)?;
9188
let child_path = if path == "/" {
9289
format!("/{}", child_name)
9390
} else {
9491
format!("{}/{}", path, child_name)
9592
};
96-
list_dir(volume_mgr, child_dir, &child_path)?;
97-
volume_mgr.close_dir(child_dir)?;
93+
list_dir(child_dir, &child_path)?;
9894
}
9995
Ok(())
10096
}

examples/read_file.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,14 @@ fn main() -> Result<(), embedded_sdmmc::Error<std::io::Error>> {
4949
let lbd = LinuxBlockDevice::new(filename, print_blocks).map_err(Error::DeviceError)?;
5050
let mut volume_mgr: VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4> =
5151
VolumeManager::new_with_limits(lbd, Clock, 0xAA00_0000);
52-
let volume = volume_mgr.open_volume(VolumeIdx(0))?;
53-
let root_dir = volume_mgr.open_root_dir(volume)?;
52+
let mut volume = volume_mgr.open_volume(VolumeIdx(0))?;
53+
let mut root_dir = volume.open_root_dir()?;
5454
println!("\nReading file {}...", FILE_TO_READ);
55-
let f = volume_mgr.open_file_in_dir(root_dir, FILE_TO_READ, Mode::ReadOnly)?;
56-
volume_mgr.close_dir(root_dir)?;
57-
while !volume_mgr.file_eof(f)? {
55+
let mut f = root_dir.open_file_in_dir(FILE_TO_READ, Mode::ReadOnly)?;
56+
while !f.is_eof() {
5857
let mut buffer = [0u8; 16];
59-
let offset = volume_mgr.file_offset(f)?;
60-
let mut len = volume_mgr.read(f, &mut buffer)?;
58+
let offset = f.offset();
59+
let mut len = f.read(&mut buffer)?;
6160
print!("{:08x} {:02x?}", offset, &buffer[0..len]);
6261
while len < buffer.len() {
6362
print!(" ");
@@ -74,7 +73,6 @@ fn main() -> Result<(), embedded_sdmmc::Error<std::io::Error>> {
7473
}
7574
println!("|");
7675
}
77-
volume_mgr.close_file(f)?;
7876
Ok(())
7977
}
8078

0 commit comments

Comments
 (0)