Skip to content

Commit f9dd1de

Browse files
committed
Change implementation to use associated consts for read, write and erase sizes. Split traits into Read and ReadWrite versions
1 parent 3eb1428 commit f9dd1de

File tree

3 files changed

+57
-45
lines changed

3 files changed

+57
-45
lines changed

Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,4 @@ keywords = ["storage"]
1515
categories = ["embedded", "hardware-support", "no-std"]
1616

1717
[dependencies]
18-
nb = "1"
1918
heapless = "^0.5"

src/lib.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,22 @@ pub trait Region {
1818
fn contains(&self, address: u32) -> bool;
1919
}
2020

21-
/// Transparent storage trait
22-
pub trait Storage {
21+
/// Transparent read only storage trait
22+
pub trait ReadStorage {
2323
/// An enumeration of storage errors
2424
type Error;
25-
25+
2626
/// Read a slice of data from the storage peripheral, starting the read
2727
/// operation at the given address, and reading until end address
2828
/// (`self.range().1`) or buffer length, whichever comes first.
2929
fn try_read(&mut self, address: u32, bytes: &mut [u8]) -> Result<(), Self::Error>;
3030

31+
/// The capacity of the storage peripheral in bytes.
32+
fn capacity(&self) -> usize;
33+
}
34+
35+
/// Transparent read/write storage trait
36+
pub trait Storage: ReadStorage {
3137
/// Write a slice of data to the storage peripheral, starting the write
3238
/// operation at the given address.
3339
///
@@ -38,7 +44,4 @@ pub trait Storage {
3844
/// CONSIDERATIONS:
3945
/// - Should the address here be normalized (always start from zero?)
4046
fn try_write(&mut self, address: u32, bytes: &[u8]) -> Result<(), Self::Error>;
41-
42-
/// The capacity of the storage peripheral in bytes.
43-
fn capacity(&self) -> u32;
4447
}

src/nor_flash.rs

+48-38
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,32 @@
1-
use crate::{iter::IterableByOverlaps, Region, Storage};
1+
use crate::{iter::IterableByOverlaps, ReadStorage, Region, Storage};
22

3-
/// NOR flash trait.
4-
pub trait NorFlash {
3+
/// Read only NOR flash trait.
4+
pub trait ReadNorFlash {
55
/// An enumeration of storage errors
66
type Error;
77

8+
/// The minumum number of bytes the storage peripheral can read
9+
const READ_SIZE: usize;
10+
811
/// Read a slice of data from the storage peripheral, starting the read
912
/// operation at the given address, and reading `bytes.len()` bytes.
1013
///
1114
/// This should throw an error in case `bytes.len()` will be larger than
1215
/// the peripheral end address.
1316
fn try_read(&mut self, address: u32, bytes: &mut [u8]) -> Result<(), Self::Error>;
1417

18+
/// The capacity of the peripheral in bytes.
19+
fn capacity(&self) -> usize;
20+
}
21+
22+
/// NOR flash trait.
23+
pub trait NorFlash: ReadNorFlash {
24+
/// The minumum number of bytes the storage peripheral can write
25+
const WRITE_SIZE: usize;
26+
27+
/// The minumum number of bytes the storage peripheral can erase
28+
const ERASE_SIZE: usize;
29+
1530
/// Erase the given storage range, clearing all data within `[from..to]`.
1631
/// The given range will contain all 1s afterwards.
1732
///
@@ -28,15 +43,6 @@ pub trait NorFlash {
2843
/// It is not allowed to write to the same word twice.
2944
/// `address` and `bytes.len()` must both be multiples of `write_size()` and properly aligned.
3045
fn try_write(&mut self, address: u32, bytes: &[u8]) -> Result<(), Self::Error>;
31-
32-
/// The erase granularity of the storage peripheral
33-
fn erase_size(&self) -> u32;
34-
35-
/// The minumum write size of the storage peripheral
36-
fn write_size(&self) -> u32;
37-
38-
/// The capacity of the peripheral in bytes.
39-
fn capacity(&self) -> u32;
4046
}
4147

4248
/// Marker trait for NorFlash relaxing the restrictions on `write`.
@@ -51,28 +57,15 @@ pub trait NorFlash {
5157
/// - Rest of the bits in the page are guaranteed to be unchanged
5258
pub trait MultiwriteNorFlash: NorFlash {}
5359

54-
///
55-
pub struct RmwNorFlashStorage<S: NorFlash>(S);
56-
57-
// FIXME: Not sure how to do this correctly? Ideally we could have `const fn erase_size()` or some const generic?
58-
const MAX_PAGE_SIZE: usize = 2048;
59-
60-
impl<S: NorFlash> RmwNorFlashStorage<S> {
61-
/// Instantiate a new generic `Storage` from a `NorFlash` peripheral
62-
pub fn new(nor_flash: S) -> Self {
63-
Self(nor_flash)
64-
}
65-
}
66-
6760
struct Page {
6861
pub start: u32,
69-
pub size: u32,
62+
pub size: usize,
7063
}
7164

7265
impl Page {
73-
fn new(index: u32, size: u32) -> Self {
66+
fn new(index: u32, size: usize) -> Self {
7467
Self {
75-
start: index * size,
68+
start: index * size as u32,
7669
size,
7770
}
7871
}
@@ -89,26 +82,47 @@ impl Region for Page {
8982
}
9083
}
9184

92-
impl<S: NorFlash> Storage for RmwNorFlashStorage<S> {
85+
///
86+
pub struct RmwNorFlashStorage<S>(S);
87+
88+
impl<S> RmwNorFlashStorage<S> {
89+
/// Instantiate a new generic `Storage` from a `NorFlash` peripheral
90+
pub fn new(nor_flash: S) -> Self {
91+
Self(nor_flash)
92+
}
93+
}
94+
95+
impl<S> ReadStorage for RmwNorFlashStorage<S>
96+
where
97+
S: ReadNorFlash,
98+
{
9399
type Error = S::Error;
94100

95101
fn try_read(&mut self, address: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
96102
// Nothing special to be done for reads
97103
self.0.try_read(address, bytes)
98104
}
99105

106+
fn capacity(&self) -> usize {
107+
self.0.capacity()
108+
}
109+
}
110+
111+
impl<S> Storage for RmwNorFlashStorage<S>
112+
where
113+
S: NorFlash,
114+
{
100115
fn try_write(&mut self, address: u32, bytes: &[u8]) -> Result<(), Self::Error> {
101116
// Perform read/modify/write operations on the byte slice.
102-
let erase_size = self.0.erase_size();
103-
let last_page = (self.0.capacity() / erase_size) - 1;
117+
let last_page = (self.0.capacity() / S::ERASE_SIZE) - 1;
104118

105119
// `data` is the part of `bytes` contained within `page`,
106120
// and `addr` in the address offset of `page` + any offset into the page as requested by `address`
107-
for (data, page, addr) in (0..last_page)
108-
.map(move |i| Page::new(i, erase_size))
121+
for (data, page, addr) in (0..last_page as u32)
122+
.map(move |i| Page::new(i, S::ERASE_SIZE))
109123
.overlaps(bytes, address)
110124
{
111-
let merge_buffer = &mut [0u8; MAX_PAGE_SIZE][0..erase_size as usize];
125+
let merge_buffer = &mut [0u8; 2048];
112126
let offset_into_page = addr.saturating_sub(page.start) as usize;
113127

114128
self.try_read(page.start, merge_buffer)?;
@@ -124,10 +138,6 @@ impl<S: NorFlash> Storage for RmwNorFlashStorage<S> {
124138
}
125139
Ok(())
126140
}
127-
128-
fn capacity(&self) -> u32 {
129-
self.0.capacity()
130-
}
131141
}
132142

133143
// FIXME: Requires specialization to take advantage of MultiwriteNorFlash?

0 commit comments

Comments
 (0)