Skip to content

Commit f6f0869

Browse files
committed
add async support using bisync crate
This moves the existing API into a `blocking` module and duplicates the API into a new `asynchronous` module, using `async fn` where applicable. Fixes #50
1 parent e7eef2a commit f6f0869

36 files changed

+943
-843
lines changed

CHANGELOG.md

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

99
### Changed
1010

11+
- __Breaking Change__: Existing API moved into `blocking` module. Adjust your imports from `embedded_sdmmc` to `embedded_sdmmc::blocking` to keep old code building.
1112
- __Breaking Change__: `VolumeManager` now uses interior-mutability (with a `RefCell`) and so most methods are now `&self`. This also makes it easier to open multiple `File`, `Directory` or `Volume` objects at once.
1213
- __Breaking Change__: The `VolumeManager`, `File`, `Directory` and `Volume` no longer implement `Send` or `Sync.
1314
- `VolumeManager` uses an interior block cache of 512 bytes, increasing its size by about 520 bytes but hugely reducing stack space required at run-time.
@@ -17,6 +18,7 @@ The format is based on [Keep a Changelog] and this project adheres to [Semantic
1718

1819
### Added
1920

21+
- Async API in `asynchronous` module
2022
- `File` now implements the `embedded-io` `Read`, `Write` and `Seek` traits.
2123
- New `iterate_dir_lfn` method on `VolumeManager` and `Directory` - provides decoded Long File Names as `Option<&str>`
2224

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,13 @@ version = "0.8.0"
1414
rust-version = "1.76"
1515

1616
[dependencies]
17+
bisync = "0.2.3"
1718
byteorder = {version = "1", default-features = false}
1819
defmt = {version = "0.3", optional = true}
1920
embedded-hal = "1.0.0"
21+
embedded-hal-async = "1.0.0"
2022
embedded-io = "0.6.1"
23+
embedded-io-async = "0.6.1"
2124
heapless = "^0.8"
2225
log = {version = "0.4", default-features = false, optional = true}
2326

examples/append_file.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,25 @@
55
//! $ cargo run --example append_file -- /dev/mmcblk0
66
//! ```
77
//!
8-
//! If you pass a block device it should be unmounted. No testing has been
9-
//! performed with Windows raw block devices - please report back if you try
10-
//! this! There is a gzipped example disk image which you can gunzip and test
11-
//! with if you don't have a suitable block device.
8+
//! If you pass a block device it should be unmounted. There is a gzipped
9+
//! example disk image which you can gunzip and test with if you don't have a
10+
//! suitable block device.
1211
//!
1312
//! ```bash
1413
//! zcat ./tests/disk.img.gz > ./disk.img
1514
//! $ cargo run --example append_file -- ./disk.img
1615
//! ```
1716
18-
extern crate embedded_sdmmc;
19-
2017
mod linux;
2118
use linux::*;
2219

2320
const FILE_TO_APPEND: &str = "README.TXT";
2421

25-
use embedded_sdmmc::{Error, Mode, VolumeIdx};
22+
use embedded_sdmmc::blocking::{Error, Mode, VolumeIdx};
2623

27-
type VolumeManager = embedded_sdmmc::VolumeManager<LinuxBlockDevice, Clock, 8, 4, 4>;
24+
type VolumeManager = embedded_sdmmc::blocking::VolumeManager<LinuxBlockDevice, Clock, 8, 4, 4>;
2825

29-
fn main() -> Result<(), embedded_sdmmc::Error<std::io::Error>> {
26+
fn main() -> Result<(), Error<std::io::Error>> {
3027
env_logger::init();
3128
let mut args = std::env::args().skip(1);
3229
let filename = args.next().unwrap_or_else(|| "/dev/mmcblk0".into());

examples/big_dir.rs

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,38 @@
1-
extern crate embedded_sdmmc;
1+
//! Big Directory Example.
2+
//!
3+
//! Attempts to create an infinite number of files in the root directory of the
4+
//! first volume of the given block device. This is basically to see what
5+
//! happens when the root directory runs out of space.
6+
//!
7+
//! ```bash
8+
//! $ cargo run --example big_dir -- ./disk.img
9+
//! $ cargo run --example big_dir -- /dev/mmcblk0
10+
//! ```
11+
//!
12+
//! If you pass a block device it should be unmounted. There is a gzipped
13+
//! example disk image which you can gunzip and test with if you don't have a
14+
//! suitable block device.
15+
//!
16+
//! ```bash
17+
//! zcat ./tests/disk.img.gz > ./disk.img
18+
//! $ cargo run --example big_dir -- ./disk.img
19+
//! ```
220
321
mod linux;
422
use linux::*;
523

6-
use embedded_sdmmc::Error;
24+
use embedded_sdmmc::blocking::{Error, Mode, VolumeIdx};
725

8-
type VolumeManager = embedded_sdmmc::VolumeManager<LinuxBlockDevice, Clock, 8, 4, 4>;
26+
type VolumeManager = embedded_sdmmc::blocking::VolumeManager<LinuxBlockDevice, Clock, 8, 4, 4>;
927

10-
fn main() -> Result<(), embedded_sdmmc::Error<std::io::Error>> {
28+
fn main() -> Result<(), Error<std::io::Error>> {
1129
env_logger::init();
1230
let mut args = std::env::args().skip(1);
1331
let filename = args.next().unwrap_or_else(|| "/dev/mmcblk0".into());
1432
let print_blocks = args.find(|x| x == "-v").map(|_| true).unwrap_or(false);
1533
let lbd = LinuxBlockDevice::new(filename, print_blocks).map_err(Error::DeviceError)?;
1634
let volume_mgr: VolumeManager = VolumeManager::new_with_limits(lbd, Clock, 0xAA00_0000);
17-
let volume = volume_mgr
18-
.open_volume(embedded_sdmmc::VolumeIdx(1))
19-
.unwrap();
35+
let volume = volume_mgr.open_volume(VolumeIdx(0)).unwrap();
2036
println!("Volume: {:?}", volume);
2137
let root_dir = volume.open_root_dir().unwrap();
2238

@@ -26,10 +42,7 @@ fn main() -> Result<(), embedded_sdmmc::Error<std::io::Error>> {
2642
let file_name = format!("{}.da", file_num);
2743
println!("opening file {file_name} for writing");
2844
let file = root_dir
29-
.open_file_in_dir(
30-
file_name.as_str(),
31-
embedded_sdmmc::Mode::ReadWriteCreateOrTruncate,
32-
)
45+
.open_file_in_dir(file_name.as_str(), Mode::ReadWriteCreateOrTruncate)
3346
.unwrap();
3447
let buf = b"hello world, from rust";
3548
println!("writing to file");

examples/create_file.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,25 @@
55
//! $ cargo run --example create_file -- /dev/mmcblk0
66
//! ```
77
//!
8-
//! If you pass a block device it should be unmounted. No testing has been
9-
//! performed with Windows raw block devices - please report back if you try
10-
//! this! There is a gzipped example disk image which you can gunzip and test
11-
//! with if you don't have a suitable block device.
8+
//! If you pass a block device it should be unmounted. There is a gzipped
9+
//! example disk image which you can gunzip and test with if you don't have a
10+
//! suitable block device.
1211
//!
1312
//! ```bash
1413
//! zcat ./tests/disk.img.gz > ./disk.img
1514
//! $ cargo run --example create_file -- ./disk.img
1615
//! ```
1716
18-
extern crate embedded_sdmmc;
19-
2017
mod linux;
2118
use linux::*;
2219

2320
const FILE_TO_CREATE: &str = "CREATE.TXT";
2421

25-
use embedded_sdmmc::{Error, Mode, VolumeIdx};
22+
use embedded_sdmmc::blocking::{Error, Mode, VolumeIdx};
2623

27-
type VolumeManager = embedded_sdmmc::VolumeManager<LinuxBlockDevice, Clock, 8, 4, 4>;
24+
type VolumeManager = embedded_sdmmc::blocking::VolumeManager<LinuxBlockDevice, Clock, 8, 4, 4>;
2825

29-
fn main() -> Result<(), embedded_sdmmc::Error<std::io::Error>> {
26+
fn main() -> Result<(), Error<std::io::Error>> {
3027
env_logger::init();
3128
let mut args = std::env::args().skip(1);
3229
let filename = args.next().unwrap_or_else(|| "/dev/mmcblk0".into());

examples/delete_file.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,25 @@
88
//! NOTE: THIS EXAMPLE DELETES A FILE CALLED README.TXT. IF YOU DO NOT WANT THAT
99
//! FILE DELETED FROM YOUR DISK IMAGE, DO NOT RUN THIS EXAMPLE.
1010
//!
11-
//! If you pass a block device it should be unmounted. No testing has been
12-
//! performed with Windows raw block devices - please report back if you try
13-
//! this! There is a gzipped example disk image which you can gunzip and test
14-
//! with if you don't have a suitable block device.
11+
//! If you pass a block device it should be unmounted. There is a gzipped
12+
//! example disk image which you can gunzip and test with if you don't have a
13+
//! suitable block device.
1514
//!
1615
//! ```bash
1716
//! zcat ./tests/disk.img.gz > ./disk.img
1817
//! $ cargo run --example delete_file -- ./disk.img
1918
//! ```
2019
21-
extern crate embedded_sdmmc;
22-
2320
mod linux;
2421
use linux::*;
2522

2623
const FILE_TO_DELETE: &str = "README.TXT";
2724

28-
use embedded_sdmmc::{Error, VolumeIdx};
25+
use embedded_sdmmc::blocking::{Error, VolumeIdx};
2926

30-
type VolumeManager = embedded_sdmmc::VolumeManager<LinuxBlockDevice, Clock, 8, 4, 4>;
27+
type VolumeManager = embedded_sdmmc::blocking::VolumeManager<LinuxBlockDevice, Clock, 8, 4, 4>;
3128

32-
fn main() -> Result<(), embedded_sdmmc::Error<std::io::Error>> {
29+
fn main() -> Result<(), Error<std::io::Error>> {
3330
env_logger::init();
3431
let mut args = std::env::args().skip(1);
3532
let filename = args.next().unwrap_or_else(|| "/dev/mmcblk0".into());

examples/linux/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Helpers for using embedded-sdmmc on Linux
22
33
use chrono::Timelike;
4-
use embedded_sdmmc::{Block, BlockCount, BlockDevice, BlockIdx, TimeSource, Timestamp};
4+
use embedded_sdmmc::blocking::{Block, BlockCount, BlockDevice, BlockIdx, TimeSource, Timestamp};
55
use std::cell::RefCell;
66
use std::fs::{File, OpenOptions};
77
use std::io::prelude::*;

examples/list_dir.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,9 @@
2222
//! $
2323
//! ```
2424
//!
25-
//! If you pass a block device it should be unmounted. No testing has been
26-
//! performed with Windows raw block devices - please report back if you try
27-
//! this! There is a gzipped example disk image which you can gunzip and test
28-
//! with if you don't have a suitable block device.
25+
//! If you pass a block device it should be unmounted. There is a gzipped
26+
//! example disk image which you can gunzip and test with if you don't have a
27+
//! suitable block device.
2928
//!
3029
//! ```bash
3130
//! zcat ./tests/disk.img.gz > ./disk.img
@@ -35,12 +34,12 @@
3534
mod linux;
3635
use linux::*;
3736

38-
use embedded_sdmmc::{ShortFileName, VolumeIdx};
37+
use embedded_sdmmc::blocking::{ShortFileName, VolumeIdx};
3938

40-
type Error = embedded_sdmmc::Error<std::io::Error>;
39+
type Error = embedded_sdmmc::blocking::Error<std::io::Error>;
4140

42-
type Directory<'a> = embedded_sdmmc::Directory<'a, LinuxBlockDevice, Clock, 8, 4, 4>;
43-
type VolumeManager = embedded_sdmmc::VolumeManager<LinuxBlockDevice, Clock, 8, 4, 4>;
41+
type Directory<'a> = embedded_sdmmc::blocking::Directory<'a, LinuxBlockDevice, Clock, 8, 4, 4>;
42+
type VolumeManager = embedded_sdmmc::blocking::VolumeManager<LinuxBlockDevice, Clock, 8, 4, 4>;
4443

4544
fn main() -> Result<(), Error> {
4645
env_logger::init();

examples/read_file.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,28 +22,25 @@
2222
//! 00000100 [54, 0a, 0d] |T...............|
2323
//! ```
2424
//!
25-
//! If you pass a block device it should be unmounted. No testing has been
26-
//! performed with Windows raw block devices - please report back if you try
27-
//! this! There is a gzipped example disk image which you can gunzip and test
28-
//! with if you don't have a suitable block device.
25+
//! If you pass a block device it should be unmounted. There is a gzipped
26+
//! example disk image which you can gunzip and test with if you don't have a
27+
//! suitable block device.
2928
//!
3029
//! ```bash
3130
//! zcat ./tests/disk.img.gz > ./disk.img
3231
//! $ cargo run --example read_file -- ./disk.img
3332
//! ```
3433
35-
extern crate embedded_sdmmc;
36-
3734
mod linux;
3835
use linux::*;
3936

4037
const FILE_TO_READ: &str = "README.TXT";
4138

42-
use embedded_sdmmc::{Error, Mode, VolumeIdx};
39+
use embedded_sdmmc::blocking::{Error, Mode, VolumeIdx};
4340

44-
type VolumeManager = embedded_sdmmc::VolumeManager<LinuxBlockDevice, Clock, 8, 4, 4>;
41+
type VolumeManager = embedded_sdmmc::blocking::VolumeManager<LinuxBlockDevice, Clock, 8, 4, 4>;
4542

46-
fn main() -> Result<(), embedded_sdmmc::Error<std::io::Error>> {
43+
fn main() -> Result<(), Error<std::io::Error>> {
4744
env_logger::init();
4845
let mut args = std::env::args().skip(1);
4946
let filename = args.next().unwrap_or_else(|| "/dev/mmcblk0".into());

examples/readme_test.rs

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
use core::cell::RefCell;
99

10+
use embedded_sdmmc::blocking::{Error, SdCardError, TimeSource, Timestamp};
11+
1012
pub struct DummyCsPin;
1113

1214
impl embedded_hal::digital::ErrorType for DummyCsPin {
@@ -80,9 +82,9 @@ impl embedded_hal::delay::DelayNs for FakeDelayer {
8082

8183
struct FakeTimesource();
8284

83-
impl embedded_sdmmc::TimeSource for FakeTimesource {
84-
fn get_timestamp(&self) -> embedded_sdmmc::Timestamp {
85-
embedded_sdmmc::Timestamp {
85+
impl TimeSource for FakeTimesource {
86+
fn get_timestamp(&self) -> Timestamp {
87+
Timestamp {
8688
year_since_1970: 0,
8789
zero_indexed_month: 0,
8890
zero_indexed_day: 0,
@@ -94,47 +96,48 @@ impl embedded_sdmmc::TimeSource for FakeTimesource {
9496
}
9597

9698
#[derive(Debug, Clone)]
97-
enum Error {
98-
Filesystem(embedded_sdmmc::Error<embedded_sdmmc::SdCardError>),
99-
Disk(embedded_sdmmc::SdCardError),
99+
enum MyError {
100+
Filesystem(Error<SdCardError>),
101+
Disk(SdCardError),
100102
}
101103

102-
impl From<embedded_sdmmc::Error<embedded_sdmmc::SdCardError>> for Error {
103-
fn from(value: embedded_sdmmc::Error<embedded_sdmmc::SdCardError>) -> Error {
104-
Error::Filesystem(value)
104+
impl From<Error<SdCardError>> for MyError {
105+
fn from(value: Error<SdCardError>) -> MyError {
106+
MyError::Filesystem(value)
105107
}
106108
}
107109

108-
impl From<embedded_sdmmc::SdCardError> for Error {
109-
fn from(value: embedded_sdmmc::SdCardError) -> Error {
110-
Error::Disk(value)
110+
impl From<SdCardError> for MyError {
111+
fn from(value: SdCardError) -> MyError {
112+
MyError::Disk(value)
111113
}
112114
}
113115

114-
fn main() -> Result<(), Error> {
116+
fn main() -> Result<(), MyError> {
115117
// BEGIN Fake stuff that will be replaced with real peripherals
116118
let spi_bus = RefCell::new(FakeSpiBus());
117119
let delay = FakeDelayer();
118120
let sdmmc_spi = embedded_hal_bus::spi::RefCellDevice::new(&spi_bus, DummyCsPin, delay).unwrap();
119121
let time_source = FakeTimesource();
120122
// END Fake stuff that will be replaced with real peripherals
121123

124+
use embedded_sdmmc::blocking::{Mode, SdCard, VolumeIdx, VolumeManager};
122125
// Build an SD Card interface out of an SPI device, a chip-select pin and the delay object
123-
let sdcard = embedded_sdmmc::SdCard::new(sdmmc_spi, delay);
126+
let sdcard = SdCard::new(sdmmc_spi, delay);
124127
// Get the card size (this also triggers card initialisation because it's not been done yet)
125128
println!("Card size is {} bytes", sdcard.num_bytes()?);
126129
// Now let's look for volumes (also known as partitions) on our block device.
127130
// To do this we need a Volume Manager. It will take ownership of the block device.
128-
let volume_mgr = embedded_sdmmc::VolumeManager::new(sdcard, time_source);
131+
let volume_mgr = VolumeManager::new(sdcard, time_source);
129132
// Try and access Volume 0 (i.e. the first partition).
130133
// The volume object holds information about the filesystem on that volume.
131-
let volume0 = volume_mgr.open_volume(embedded_sdmmc::VolumeIdx(0))?;
134+
let volume0 = volume_mgr.open_volume(VolumeIdx(0))?;
132135
println!("Volume 0: {:?}", volume0);
133136
// Open the root directory (mutably borrows from the volume).
134137
let root_dir = volume0.open_root_dir()?;
135138
// Open a file called "MY_FILE.TXT" in the root directory
136139
// This mutably borrows the directory.
137-
let my_file = root_dir.open_file_in_dir("MY_FILE.TXT", embedded_sdmmc::Mode::ReadOnly)?;
140+
let my_file = root_dir.open_file_in_dir("MY_FILE.TXT", Mode::ReadOnly)?;
138141
// Print the contents of the file, assuming it's in ISO-8859-1 encoding
139142
while !my_file.is_eof() {
140143
let mut buffer = [0u8; 32];
@@ -143,6 +146,7 @@ fn main() -> Result<(), Error> {
143146
print!("{}", *b as char);
144147
}
145148
}
149+
146150
Ok(())
147151
}
148152

0 commit comments

Comments
 (0)