Skip to content

Commit

Permalink
Merge pull request #116 from rust-embedded-community/release/v0.7.0
Browse files Browse the repository at this point in the history
Release/v0.7.0
  • Loading branch information
thejpster authored Feb 9, 2024
2 parents d362a6a + afdcec7 commit 2f8303a
Show file tree
Hide file tree
Showing 25 changed files with 1,838 additions and 554 deletions.
29 changes: 28 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,32 @@ The format is based on [Keep a Changelog] and this project adheres to [Semantic

* None

## [Version 0.7.0] - 2024-02-04

## Changed

- __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.
- __Breaking Change__: Renamed the old types to `RawVolume`, `RawDirectory` and `RawFile`
- __Breaking Change__: Renamed `Error::FileNotFound` to `Error::NotFound`
- Fixed long-standing bug that caused an integer overflow when a FAT32 directory was longer than one cluster ([#74])
- You can now open directories multiple times without error
- Updated to [embedded-hal] 1.0

## Added

- `RawVolume`, `RawDirectory` and `RawFile` types (like the old `Volume`, `Directory` and `File` types)
- New method `make_dir_in_dir`
- Empty strings and `"."` convert to `ShortFileName::this_dir()`
- New API `change_dir` which changes a directory to point to some child directory (or the parent) without opening a new directory.
- Updated 'shell' example to support `mkdir`, `tree` and relative/absolute paths

## Removed

* None

[#74]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/issues/74
[embedded-hal]: https://crates.io/crates/embedded-hal

## [Version 0.6.0] - 2023-10-20

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

[Keep a Changelog]: http://keepachangelog.com/en/1.0.0/
[Semantic Versioning]: http://semver.org/spec/v2.0.0.html
[Unreleased]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.6.0...develop
[Unreleased]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.7.0...develop
[Version 0.7.0]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.7.0...v0.6.0
[Version 0.6.0]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.6.0...v0.5.0
[Version 0.5.0]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.5.0...v0.4.0
[Version 0.4.0]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.4.0...v0.3.0
Expand Down
16 changes: 9 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,24 @@ license = "MIT OR Apache-2.0"
name = "embedded-sdmmc"
readme = "README.md"
repository = "https://github.com/rust-embedded-community/embedded-sdmmc-rs"
version = "0.6.0"
version = "0.7.0"

[dependencies]
byteorder = {version = "1", default-features = false}
defmt = {version = "0.3", optional = true}
embedded-hal = "0.2.3"
embedded-hal = "1.0.0"
heapless = "0.7"
log = {version = "0.4", default-features = false, optional = true}

[dev-dependencies]
env_logger = "0.9"
hex-literal = "0.3"
flate2 = "1.0"
sha256 = "1.4"
chrono = "0.4"
embedded-hal-bus = "0.1.0"
env_logger = "0.10.0"
flate2 = "1.0"
hex-literal = "0.4.1"
sha2 = "0.10"

[features]
default = ["log"]
defmt-log = ["defmt"]
defmt-log = ["dep:defmt"]
log = ["dep:log"]
30 changes: 14 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ designed for readability and simplicity over performance.
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.

```rust
// Build an SD Card interface out of an SPI device, a chip-select pin and a delay object
// Build an SD Card interface out of an SPI device, a chip-select pin and the delay object
let sdcard = embedded_sdmmc::SdCard::new(sdmmc_spi, sdmmc_cs, delay);
// Get the card size (this also triggers card initialisation because it's not been done yet)
println!("Card size is {} bytes", sdcard.num_bytes()?);
Expand All @@ -20,29 +20,21 @@ println!("Card size is {} bytes", sdcard.num_bytes()?);
let mut volume_mgr = embedded_sdmmc::VolumeManager::new(sdcard, time_source);
// Try and access Volume 0 (i.e. the first partition).
// The volume object holds information about the filesystem on that volume.
// It doesn't hold a reference to the Volume Manager and so must be passed back
// to every Volume Manager API call. This makes it easier to handle multiple
// volumes in parallel.
let volume0 = volume_mgr.get_volume(embedded_sdmmc::VolumeIdx(0))?;
let mut volume0 = volume_mgr.open_volume(embedded_sdmmc::VolumeIdx(0))?;
println!("Volume 0: {:?}", volume0);
// Open the root directory (passing in the volume we're using).
let root_dir = volume_mgr.open_root_dir(&volume0)?;
// Open the root directory (mutably borrows from the volume).
let mut root_dir = volume0.open_root_dir()?;
// Open a file called "MY_FILE.TXT" in the root directory
let my_file = volume_mgr.open_file_in_dir(
root_dir,
"MY_FILE.TXT",
embedded_sdmmc::Mode::ReadOnly,
)?;
// This mutably borrows the directory.
let mut my_file = root_dir.open_file_in_dir("MY_FILE.TXT", embedded_sdmmc::Mode::ReadOnly)?;
// Print the contents of the file
while !volume_manager.file_eof(my_file).unwrap() {
while !my_file.is_eof() {
let mut buffer = [0u8; 32];
let num_read = volume_mgr.read(&volume0, &mut my_file, &mut buffer)?;
let num_read = my_file.read(&mut buffer)?;
for b in &buffer[0..num_read] {
print!("{}", *b as char);
}
}
volume_mgr.close_file(my_file)?;
volume_mgr.close_dir(root_dir)?;
```

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

## No-std usage
This repository houses no examples for no-std usage, however you can check out the following examples:
- [Pi Pico](https://github.com/rp-rs/rp-hal-boards/blob/main/boards/rp-pico/examples/pico_spi_sd_card.rs)
- [STM32H7XX](https://github.com/stm32-rs/stm32h7xx-hal/blob/master/examples/sdmmc_fat.rs)
- [atsamd(pygamer)](https://github.com/atsamd-rs/atsamd/blob/master/boards/pygamer/examples/sd_card.rs)

## Todo List (PRs welcome!)

* Create new dirs
Expand Down
10 changes: 4 additions & 6 deletions examples/append_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,11 @@ fn main() -> Result<(), embedded_sdmmc::Error<std::io::Error>> {
let lbd = LinuxBlockDevice::new(filename, print_blocks).map_err(Error::DeviceError)?;
let mut volume_mgr: VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4> =
VolumeManager::new_with_limits(lbd, Clock, 0xAA00_0000);
let volume = volume_mgr.open_volume(VolumeIdx(0))?;
let root_dir = volume_mgr.open_root_dir(volume)?;
let mut volume = volume_mgr.open_volume(VolumeIdx(0))?;
let mut root_dir = volume.open_root_dir()?;
println!("\nCreating file {}...", FILE_TO_APPEND);
let f = volume_mgr.open_file_in_dir(root_dir, FILE_TO_APPEND, Mode::ReadWriteAppend)?;
volume_mgr.write(f, b"\r\n\r\nThis has been added to your file.\r\n")?;
volume_mgr.close_file(f)?;
volume_mgr.close_dir(root_dir)?;
let mut f = root_dir.open_file_in_dir(FILE_TO_APPEND, Mode::ReadWriteAppend)?;
f.write(b"\r\n\r\nThis has been added to your file.\r\n")?;
Ok(())
}

Expand Down
39 changes: 39 additions & 0 deletions examples/big_dir.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
extern crate embedded_sdmmc;

mod linux;
use linux::*;

use embedded_sdmmc::{Error, VolumeManager};

fn main() -> Result<(), embedded_sdmmc::Error<std::io::Error>> {
env_logger::init();
let mut args = std::env::args().skip(1);
let filename = args.next().unwrap_or_else(|| "/dev/mmcblk0".into());
let print_blocks = args.find(|x| x == "-v").map(|_| true).unwrap_or(false);
let lbd = LinuxBlockDevice::new(filename, print_blocks).map_err(Error::DeviceError)?;
let mut volume_mgr: VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4> =
VolumeManager::new_with_limits(lbd, Clock, 0xAA00_0000);
let mut volume = volume_mgr
.open_volume(embedded_sdmmc::VolumeIdx(1))
.unwrap();
println!("Volume: {:?}", volume);
let mut root_dir = volume.open_root_dir().unwrap();

let mut file_num = 0;
loop {
file_num += 1;
let file_name = format!("{}.da", file_num);
println!("opening file {file_name} for writing");
let mut file = root_dir
.open_file_in_dir(
file_name.as_str(),
embedded_sdmmc::Mode::ReadWriteCreateOrTruncate,
)
.unwrap();
let buf = b"hello world, from rust";
println!("writing to file");
file.write(&buf[..]).unwrap();
println!("closing file");
drop(file);
}
}
10 changes: 4 additions & 6 deletions examples/create_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,14 @@ fn main() -> Result<(), embedded_sdmmc::Error<std::io::Error>> {
let lbd = LinuxBlockDevice::new(filename, print_blocks).map_err(Error::DeviceError)?;
let mut volume_mgr: VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4> =
VolumeManager::new_with_limits(lbd, Clock, 0xAA00_0000);
let volume = volume_mgr.open_volume(VolumeIdx(0))?;
let root_dir = volume_mgr.open_root_dir(volume)?;
let mut volume = volume_mgr.open_volume(VolumeIdx(0))?;
let mut root_dir = volume.open_root_dir()?;
println!("\nCreating file {}...", FILE_TO_CREATE);
// This will panic if the file already exists: use ReadWriteCreateOrAppend
// or ReadWriteCreateOrTruncate instead if you want to modify an existing
// file.
let f = volume_mgr.open_file_in_dir(root_dir, FILE_TO_CREATE, Mode::ReadWriteCreate)?;
volume_mgr.write(f, b"Hello, this is a new file on disk\r\n")?;
volume_mgr.close_file(f)?;
volume_mgr.close_dir(root_dir)?;
let mut f = root_dir.open_file_in_dir(FILE_TO_CREATE, Mode::ReadWriteCreate)?;
f.write(b"Hello, this is a new file on disk\r\n")?;
Ok(())
}

Expand Down
7 changes: 3 additions & 4 deletions examples/delete_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,11 @@ fn main() -> Result<(), embedded_sdmmc::Error<std::io::Error>> {
let lbd = LinuxBlockDevice::new(filename, print_blocks).map_err(Error::DeviceError)?;
let mut volume_mgr: VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4> =
VolumeManager::new_with_limits(lbd, Clock, 0xAA00_0000);
let volume = volume_mgr.open_volume(VolumeIdx(0))?;
let root_dir = volume_mgr.open_root_dir(volume)?;
let mut volume = volume_mgr.open_volume(VolumeIdx(0))?;
let mut root_dir = volume.open_root_dir()?;
println!("Deleting file {}...", FILE_TO_DELETE);
volume_mgr.delete_file_in_dir(root_dir, FILE_TO_DELETE)?;
root_dir.delete_file_in_dir(FILE_TO_DELETE)?;
println!("Deleted!");
volume_mgr.close_dir(root_dir)?;
Ok(())
}

Expand Down
28 changes: 12 additions & 16 deletions examples/list_dir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,24 +49,22 @@ fn main() -> Result<(), Error> {
let lbd = LinuxBlockDevice::new(filename, print_blocks).map_err(Error::DeviceError)?;
let mut volume_mgr: VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4> =
VolumeManager::new_with_limits(lbd, Clock, 0xAA00_0000);
let volume = volume_mgr.open_volume(VolumeIdx(0))?;
let root_dir = volume_mgr.open_root_dir(volume)?;
list_dir(&mut volume_mgr, root_dir, "/")?;
volume_mgr.close_dir(root_dir)?;
let mut volume = volume_mgr.open_volume(VolumeIdx(0))?;
let root_dir = volume.open_root_dir()?;
list_dir(root_dir, "/")?;
Ok(())
}

/// Recursively print a directory listing for the open directory given.
///
/// The path is for display purposes only.
fn list_dir(
volume_mgr: &mut VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4>,
directory: Directory,
mut directory: Directory<LinuxBlockDevice, Clock, 8, 8, 4>,
path: &str,
) -> Result<(), Error> {
println!("Listing {}", path);
let mut children = Vec::new();
volume_mgr.iterate_dir(directory, |entry| {
directory.iterate_dir(|entry| {
println!(
"{:12} {:9} {} {}",
entry.name,
Expand All @@ -78,23 +76,21 @@ fn list_dir(
""
}
);
if entry.attributes.is_directory() {
if entry.name != embedded_sdmmc::ShortFileName::parent_dir()
&& entry.name != embedded_sdmmc::ShortFileName::this_dir()
{
children.push(entry.name.clone());
}
if entry.attributes.is_directory()
&& entry.name != embedded_sdmmc::ShortFileName::parent_dir()
&& entry.name != embedded_sdmmc::ShortFileName::this_dir()
{
children.push(entry.name.clone());
}
})?;
for child_name in children {
let child_dir = volume_mgr.open_dir(directory, &child_name)?;
let child_dir = directory.open_dir(&child_name)?;
let child_path = if path == "/" {
format!("/{}", child_name)
} else {
format!("{}/{}", path, child_name)
};
list_dir(volume_mgr, child_dir, &child_path)?;
volume_mgr.close_dir(child_dir)?;
list_dir(child_dir, &child_path)?;
}
Ok(())
}
Expand Down
14 changes: 6 additions & 8 deletions examples/read_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,14 @@ fn main() -> Result<(), embedded_sdmmc::Error<std::io::Error>> {
let lbd = LinuxBlockDevice::new(filename, print_blocks).map_err(Error::DeviceError)?;
let mut volume_mgr: VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4> =
VolumeManager::new_with_limits(lbd, Clock, 0xAA00_0000);
let volume = volume_mgr.open_volume(VolumeIdx(0))?;
let root_dir = volume_mgr.open_root_dir(volume)?;
let mut volume = volume_mgr.open_volume(VolumeIdx(0))?;
let mut root_dir = volume.open_root_dir()?;
println!("\nReading file {}...", FILE_TO_READ);
let f = volume_mgr.open_file_in_dir(root_dir, FILE_TO_READ, Mode::ReadOnly)?;
volume_mgr.close_dir(root_dir)?;
while !volume_mgr.file_eof(f)? {
let mut f = root_dir.open_file_in_dir(FILE_TO_READ, Mode::ReadOnly)?;
while !f.is_eof() {
let mut buffer = [0u8; 16];
let offset = volume_mgr.file_offset(f)?;
let mut len = volume_mgr.read(f, &mut buffer)?;
let offset = f.offset();
let mut len = f.read(&mut buffer)?;
print!("{:08x} {:02x?}", offset, &buffer[0..len]);
while len < buffer.len() {
print!(" ");
Expand All @@ -74,7 +73,6 @@ fn main() -> Result<(), embedded_sdmmc::Error<std::io::Error>> {
}
println!("|");
}
volume_mgr.close_file(f)?;
Ok(())
}

Expand Down
Loading

0 comments on commit 2f8303a

Please sign in to comment.