Skip to content

Commit 36dd5dd

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 rust-embedded-community#50
1 parent a17e0bc commit 36dd5dd

36 files changed

+866
-784
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.3.0"
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: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ use linux::*;
1919

2020
const FILE_TO_APPEND: &str = "README.TXT";
2121

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

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

2626
fn main() -> Result<(), Error<std::io::Error>> {
2727
env_logger::init();

examples/big_dir.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121
mod linux;
2222
use linux::*;
2323

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

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

2828
fn main() -> Result<(), Error<std::io::Error>> {
2929
env_logger::init();

examples/create_file.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ use linux::*;
1919

2020
const FILE_TO_CREATE: &str = "CREATE.TXT";
2121

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

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

2626
fn main() -> Result<(), Error<std::io::Error>> {
2727
env_logger::init();

examples/delete_file.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ use linux::*;
2222

2323
const FILE_TO_DELETE: &str = "README.TXT";
2424

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

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

2929
fn main() -> Result<(), Error<std::io::Error>> {
3030
env_logger::init();

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: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@
3434
mod linux;
3535
use linux::*;
3636

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

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

41-
type Directory<'a> = embedded_sdmmc::Directory<'a, LinuxBlockDevice, Clock, 8, 4, 4>;
42-
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>;
4343

4444
fn main() -> Result<(), Error> {
4545
env_logger::init();

examples/read_file.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ use linux::*;
3636

3737
const FILE_TO_READ: &str = "README.TXT";
3838

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

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

4343
fn main() -> Result<(), Error<std::io::Error>> {
4444
env_logger::init();

examples/readme_test.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
use core::cell::RefCell;
99

10-
use embedded_sdmmc::{Error, SdCardError, TimeSource, Timestamp};
10+
use embedded_sdmmc::blocking::{Error, SdCardError, TimeSource, Timestamp};
1111

1212
pub struct DummyCsPin;
1313

@@ -121,7 +121,7 @@ fn main() -> Result<(), MyError> {
121121
let time_source = FakeTimesource();
122122
// END Fake stuff that will be replaced with real peripherals
123123

124-
use embedded_sdmmc::{Mode, SdCard, VolumeIdx, VolumeManager};
124+
use embedded_sdmmc::blocking::{Mode, SdCard, VolumeIdx, VolumeManager};
125125
// Build an SD Card interface out of an SPI device, a chip-select pin and the delay object
126126
let sdcard = SdCard::new(sdmmc_spi, delay);
127127
// Get the card size (this also triggers card initialisation because it's not been done yet)

examples/shell.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,12 @@
8585
8686
use std::{cell::RefCell, io::prelude::*};
8787

88-
use embedded_sdmmc::{
88+
use embedded_sdmmc::blocking::{
8989
Error as EsError, LfnBuffer, Mode, RawDirectory, RawVolume, ShortFileName, VolumeIdx,
9090
};
9191

92-
type VolumeManager = embedded_sdmmc::VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4>;
93-
type Directory<'a> = embedded_sdmmc::Directory<'a, LinuxBlockDevice, Clock, 8, 8, 4>;
92+
type VolumeManager = embedded_sdmmc::blocking::VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4>;
93+
type Directory<'a> = embedded_sdmmc::blocking::Directory<'a, LinuxBlockDevice, Clock, 8, 8, 4>;
9494

9595
use crate::linux::{Clock, LinuxBlockDevice};
9696

src/blockdevice.rs renamed to src/inner/blockdevice.rs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
//! Generic code for handling block devices, such as types for identifying
44
//! a particular block on a block device by its index.
55
6+
use super::super::bisync;
7+
68
/// A standard 512 byte block (also known as a sector).
79
///
810
/// IBM PC formatted 5.25" and 3.5" floppy disks, IDE/SATA Hard Drives up to
@@ -75,15 +77,16 @@ impl Default for Block {
7577

7678
/// A block device - a device which can read and write blocks (or
7779
/// sectors). Only supports devices which are <= 2 TiB in size.
80+
#[bisync]
7881
pub trait BlockDevice {
7982
/// The errors that the `BlockDevice` can return. Must be debug formattable.
8083
type Error: core::fmt::Debug;
8184
/// Read one or more blocks, starting at the given block index.
82-
fn read(&self, blocks: &mut [Block], start_block_idx: BlockIdx) -> Result<(), Self::Error>;
85+
async fn read(&self, blocks: &mut [Block], start_block_idx: BlockIdx) -> Result<(), Self::Error>;
8386
/// Write one or more blocks, starting at the given block index.
84-
fn write(&self, blocks: &[Block], start_block_idx: BlockIdx) -> Result<(), Self::Error>;
87+
async fn write(&self, blocks: &[Block], start_block_idx: BlockIdx) -> Result<(), Self::Error>;
8588
/// Determine how many blocks this device can hold.
86-
fn num_blocks(&self) -> Result<BlockCount, Self::Error>;
89+
async fn num_blocks(&self) -> Result<BlockCount, Self::Error>;
8790
}
8891

8992
/// A caching layer for block devices
@@ -96,6 +99,7 @@ pub struct BlockCache<D> {
9699
block_idx: Option<BlockIdx>,
97100
}
98101

102+
#[bisync]
99103
impl<D> BlockCache<D>
100104
where
101105
D: BlockDevice,
@@ -110,42 +114,42 @@ where
110114
}
111115

112116
/// Read a block, and return a reference to it.
113-
pub fn read(&mut self, block_idx: BlockIdx) -> Result<&Block, D::Error> {
117+
pub async fn read(&mut self, block_idx: BlockIdx) -> Result<&Block, D::Error> {
114118
if self.block_idx != Some(block_idx) {
115119
self.block_idx = None;
116-
self.block_device.read(&mut self.block, block_idx)?;
120+
self.block_device.read(&mut self.block, block_idx).await?;
117121
self.block_idx = Some(block_idx);
118122
}
119123
Ok(&self.block[0])
120124
}
121125

122126
/// Read a block, and return a reference to it.
123-
pub fn read_mut(&mut self, block_idx: BlockIdx) -> Result<&mut Block, D::Error> {
127+
pub async fn read_mut(&mut self, block_idx: BlockIdx) -> Result<&mut Block, D::Error> {
124128
if self.block_idx != Some(block_idx) {
125129
self.block_idx = None;
126-
self.block_device.read(&mut self.block, block_idx)?;
130+
self.block_device.read(&mut self.block, block_idx).await?;
127131
self.block_idx = Some(block_idx);
128132
}
129133
Ok(&mut self.block[0])
130134
}
131135

132136
/// Write back a block you read with [`Self::read_mut`] and then modified.
133-
pub fn write_back(&mut self) -> Result<(), D::Error> {
137+
pub async fn write_back(&mut self) -> Result<(), D::Error> {
134138
self.block_device.write(
135139
&self.block,
136140
self.block_idx.expect("write_back with no read"),
137-
)
141+
).await
138142
}
139143

140144
/// Write back a block you read with [`Self::read_mut`] and then modified, but to two locations.
141145
///
142146
/// This is useful for updating two File Allocation Tables.
143-
pub fn write_back_with_duplicate(&mut self, duplicate: BlockIdx) -> Result<(), D::Error> {
147+
pub async fn write_back_with_duplicate(&mut self, duplicate: BlockIdx) -> Result<(), D::Error> {
144148
self.block_device.write(
145149
&self.block,
146150
self.block_idx.expect("write_back with no read"),
147-
)?;
148-
self.block_device.write(&self.block, duplicate)?;
151+
).await?;
152+
self.block_device.write(&self.block, duplicate).await?;
149153
Ok(())
150154
}
151155

@@ -256,7 +260,7 @@ impl BlockCount {
256260
/// How many blocks are required to hold this many bytes.
257261
///
258262
/// ```
259-
/// # use embedded_sdmmc::BlockCount;
263+
/// # use embedded_sdmmc::blocking::BlockCount;
260264
/// assert_eq!(BlockCount::from_bytes(511), BlockCount(1));
261265
/// assert_eq!(BlockCount::from_bytes(512), BlockCount(1));
262266
/// assert_eq!(BlockCount::from_bytes(513), BlockCount(2));

src/fat/bpb.rs renamed to src/inner/fat/bpb.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Boot Parameter Block
22
3-
use crate::{
3+
use super::super::{
44
blockdevice::BlockCount,
55
fat::{FatType, OnDiskDirEntry},
66
};

src/fat/info.rs renamed to src/inner/fat/info.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{BlockCount, BlockIdx, ClusterId};
1+
use super::super::{BlockCount, BlockIdx, ClusterId};
22
use byteorder::{ByteOrder, LittleEndian};
33

44
/// Indentifies the supported types of FAT format

src/fat/mod.rs renamed to src/inner/fat/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ pub use volume::{parse_volume, FatVolume, VolumeName};
3333
#[cfg(test)]
3434
mod test {
3535

36+
use super::super::{Attributes, BlockIdx, ClusterId, DirEntry, ShortFileName, Timestamp};
3637
use super::*;
37-
use crate::{Attributes, BlockIdx, ClusterId, DirEntry, ShortFileName, Timestamp};
3838

3939
fn parse(input: &str) -> Vec<u8> {
4040
let mut output = Vec::new();

src/fat/ondiskdirentry.rs renamed to src/inner/fat/ondiskdirentry.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! Directory Entry as stored on-disk
22
3-
use crate::{fat::FatType, Attributes, BlockIdx, ClusterId, DirEntry, ShortFileName, Timestamp};
3+
use super::super::{
4+
fat::FatType, Attributes, BlockIdx, ClusterId, DirEntry, ShortFileName, Timestamp,
5+
};
46
use byteorder::{ByteOrder, LittleEndian};
57

68
/// A 32-byte directory entry as stored on-disk in a directory file.

0 commit comments

Comments
 (0)