Skip to content

Commit 02caa6a

Browse files
committed
Use embedded-storage BlockDevice trait.
This will allow both the SD card driver and the FAT32 implementation to be used with filesystem or block device drivers respectively.
1 parent 1b9fa5c commit 02caa6a

File tree

10 files changed

+343
-337
lines changed

10 files changed

+343
-337
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ byteorder = {version = "1", default-features = false}
1515
defmt = {version = "0.3", optional = true}
1616
embedded-hal = "1.0.0"
1717
embedded-io = "0.6.1"
18+
embedded-storage = { git = "https://github.com/qwandor/embedded-storage", branch = "block" }
1819
heapless = "^0.8"
1920
log = {version = "0.4", default-features = false, optional = true}
2021

examples/linux/mod.rs

+10-10
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::{Block, BlockDevice, TimeSource, Timestamp, BLOCK_LEN_U64};
55
use std::cell::RefCell;
66
use std::fs::{File, OpenOptions};
77
use std::io::prelude::*;
@@ -34,35 +34,35 @@ impl LinuxBlockDevice {
3434
impl BlockDevice for LinuxBlockDevice {
3535
type Error = std::io::Error;
3636

37-
fn read(&self, blocks: &mut [Block], start_block_idx: BlockIdx) -> Result<(), Self::Error> {
37+
fn read(&mut self, first_block_index: u64, blocks: &mut [Block]) -> Result<(), Self::Error> {
3838
self.file
3939
.borrow_mut()
40-
.seek(SeekFrom::Start(start_block_idx.into_bytes()))?;
40+
.seek(SeekFrom::Start(first_block_index * BLOCK_LEN_U64))?;
4141
for block in blocks.iter_mut() {
42-
self.file.borrow_mut().read_exact(&mut block.contents)?;
42+
self.file.borrow_mut().read_exact(block)?;
4343
if self.print_blocks {
44-
println!("Read block {:?}: {:?}", start_block_idx, &block);
44+
println!("Read block {:?}: {:?}", first_block_index, &block);
4545
}
4646
}
4747
Ok(())
4848
}
4949

50-
fn write(&self, blocks: &[Block], start_block_idx: BlockIdx) -> Result<(), Self::Error> {
50+
fn write(&mut self, first_block_index: u64, blocks: &[Block]) -> Result<(), Self::Error> {
5151
self.file
5252
.borrow_mut()
53-
.seek(SeekFrom::Start(start_block_idx.into_bytes()))?;
53+
.seek(SeekFrom::Start(first_block_index * BLOCK_LEN_U64))?;
5454
for block in blocks.iter() {
55-
self.file.borrow_mut().write_all(&block.contents)?;
55+
self.file.borrow_mut().write_all(block)?;
5656
if self.print_blocks {
5757
println!("Wrote: {:?}", &block);
5858
}
5959
}
6060
Ok(())
6161
}
6262

63-
fn num_blocks(&self) -> Result<BlockCount, Self::Error> {
63+
fn block_count(&self) -> Result<u64, Self::Error> {
6464
let num_blocks = self.file.borrow().metadata().unwrap().len() / 512;
65-
Ok(BlockCount(num_blocks as u32))
65+
Ok(num_blocks)
6666
}
6767
}
6868

src/blockdevice.rs

+29-84
Original file line numberDiff line numberDiff line change
@@ -3,88 +3,27 @@
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 embedded_storage::BlockDevice;
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
911
/// about 2 TiB, and almost all SD/MMC cards have 512 byte blocks.
1012
///
1113
/// This library does not support devices with a block size other than 512
1214
/// bytes.
13-
#[derive(Clone)]
14-
pub struct Block {
15-
/// The 512 bytes in this block (or sector).
16-
pub contents: [u8; Block::LEN],
17-
}
15+
pub type Block = [u8; BLOCK_LEN];
1816

19-
impl Block {
20-
/// All our blocks are a fixed length of 512 bytes. We do not support
21-
/// 'Advanced Format' Hard Drives with 4 KiB blocks, nor weird old
22-
/// pre-3.5-inch floppy disk formats.
23-
pub const LEN: usize = 512;
17+
/// All our blocks are a fixed length of 512 bytes. We do not support
18+
/// 'Advanced Format' Hard Drives with 4 KiB blocks, nor weird old
19+
/// pre-3.5-inch floppy disk formats.
20+
pub const BLOCK_LEN: usize = 512;
2421

25-
/// Sometimes we want `LEN` as a `u32` and the casts don't look nice.
26-
pub const LEN_U32: u32 = 512;
22+
/// Sometimes we want `LEN` as a `u32` and the casts don't look nice.
23+
pub const BLOCK_LEN_U32: u32 = 512;
2724

28-
/// Create a new block full of zeros.
29-
pub fn new() -> Block {
30-
Block {
31-
contents: [0u8; Self::LEN],
32-
}
33-
}
34-
}
35-
36-
impl core::ops::Deref for Block {
37-
type Target = [u8; 512];
38-
fn deref(&self) -> &[u8; 512] {
39-
&self.contents
40-
}
41-
}
42-
43-
impl core::ops::DerefMut for Block {
44-
fn deref_mut(&mut self) -> &mut [u8; 512] {
45-
&mut self.contents
46-
}
47-
}
48-
49-
impl core::fmt::Debug for Block {
50-
fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
51-
writeln!(fmt, "Block:")?;
52-
for line in self.contents.chunks(32) {
53-
for b in line {
54-
write!(fmt, "{:02x}", b)?;
55-
}
56-
write!(fmt, " ")?;
57-
for &b in line {
58-
if (0x20..=0x7F).contains(&b) {
59-
write!(fmt, "{}", b as char)?;
60-
} else {
61-
write!(fmt, ".")?;
62-
}
63-
}
64-
writeln!(fmt)?;
65-
}
66-
Ok(())
67-
}
68-
}
69-
70-
impl Default for Block {
71-
fn default() -> Self {
72-
Self::new()
73-
}
74-
}
75-
76-
/// A block device - a device which can read and write blocks (or
77-
/// sectors). Only supports devices which are <= 2 TiB in size.
78-
pub trait BlockDevice {
79-
/// The errors that the `BlockDevice` can return. Must be debug formattable.
80-
type Error: core::fmt::Debug;
81-
/// 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>;
83-
/// Write one or more blocks, starting at the given block index.
84-
fn write(&self, blocks: &[Block], start_block_idx: BlockIdx) -> Result<(), Self::Error>;
85-
/// Determine how many blocks this device can hold.
86-
fn num_blocks(&self) -> Result<BlockCount, Self::Error>;
87-
}
25+
/// Sometimes we want `LEN` as a `u64` and the casts don't look nice.
26+
pub const BLOCK_LEN_U64: u64 = 512;
8827

8928
/// A caching layer for block devices
9029
///
@@ -93,7 +32,7 @@ pub trait BlockDevice {
9332
pub struct BlockCache<D> {
9433
block_device: D,
9534
block: [Block; 1],
96-
block_idx: Option<BlockIdx>,
35+
block_idx: Option<u64>,
9736
}
9837

9938
impl<D> BlockCache<D>
@@ -104,26 +43,26 @@ where
10443
pub fn new(block_device: D) -> BlockCache<D> {
10544
BlockCache {
10645
block_device,
107-
block: [Block::new()],
46+
block: [[0; BLOCK_LEN]],
10847
block_idx: None,
10948
}
11049
}
11150

11251
/// Read a block, and return a reference to it.
113-
pub fn read(&mut self, block_idx: BlockIdx) -> Result<&Block, D::Error> {
52+
pub fn read(&mut self, block_idx: u64) -> Result<&Block, D::Error> {
11453
if self.block_idx != Some(block_idx) {
11554
self.block_idx = None;
116-
self.block_device.read(&mut self.block, block_idx)?;
55+
self.block_device.read(block_idx, &mut self.block)?;
11756
self.block_idx = Some(block_idx);
11857
}
11958
Ok(&self.block[0])
12059
}
12160

12261
/// Read a block, and return a reference to it.
123-
pub fn read_mut(&mut self, block_idx: BlockIdx) -> Result<&mut Block, D::Error> {
62+
pub fn read_mut(&mut self, block_idx: u64) -> Result<&mut Block, D::Error> {
12463
if self.block_idx != Some(block_idx) {
12564
self.block_idx = None;
126-
self.block_device.read(&mut self.block, block_idx)?;
65+
self.block_device.read(block_idx, &mut self.block)?;
12766
self.block_idx = Some(block_idx);
12867
}
12968
Ok(&mut self.block[0])
@@ -132,13 +71,13 @@ where
13271
/// Write back a block you read with [`Self::read_mut`] and then modified.
13372
pub fn write_back(&mut self) -> Result<(), D::Error> {
13473
self.block_device.write(
135-
&self.block,
13674
self.block_idx.expect("write_back with no read"),
75+
&self.block,
13776
)
13877
}
13978

14079
/// Access a blank sector
141-
pub fn blank_mut(&mut self, block_idx: BlockIdx) -> &mut Block {
80+
pub fn blank_mut(&mut self, block_idx: u64) -> &mut Block {
14281
self.block_idx = Some(block_idx);
14382
for b in self.block[0].iter_mut() {
14483
*b = 0;
@@ -173,7 +112,7 @@ impl BlockIdx {
173112
/// volume. Useful if your underlying block device actually works in
174113
/// bytes, like `open("/dev/mmcblk0")` does on Linux.
175114
pub fn into_bytes(self) -> u64 {
176-
(u64::from(self.0)) * (Block::LEN as u64)
115+
u64::from(self.0) * BLOCK_LEN_U64
177116
}
178117

179118
/// Create an iterator from the current `BlockIdx` through the given
@@ -183,6 +122,12 @@ impl BlockIdx {
183122
}
184123
}
185124

125+
impl From<BlockIdx> for u64 {
126+
fn from(value: BlockIdx) -> Self {
127+
value.0.into()
128+
}
129+
}
130+
186131
impl core::ops::Add<BlockCount> for BlockIdx {
187132
type Output = BlockIdx;
188133
fn add(self, rhs: BlockCount) -> BlockIdx {
@@ -254,8 +199,8 @@ impl BlockCount {
254199
/// assert_eq!(BlockCount::from_bytes(1025), BlockCount(3));
255200
/// ```
256201
pub const fn from_bytes(byte_count: u32) -> BlockCount {
257-
let mut count = byte_count / Block::LEN_U32;
258-
if (count * Block::LEN_U32) != byte_count {
202+
let mut count = byte_count / BLOCK_LEN_U32;
203+
if (count * BLOCK_LEN_U32) != byte_count {
259204
count += 1;
260205
}
261206
BlockCount(count)
@@ -264,7 +209,7 @@ impl BlockCount {
264209
/// Take a number of blocks and increment by the integer number of blocks
265210
/// required to get to the block that holds the byte at the given offset.
266211
pub fn offset_bytes(self, offset: u32) -> Self {
267-
BlockCount(self.0 + (offset / Block::LEN_U32))
212+
BlockCount(self.0 + (offset / BLOCK_LEN_U32))
268213
}
269214
}
270215

0 commit comments

Comments
 (0)