|
2 | 2 | //! |
3 | 3 | //! Storage traits to allow on and off board storage devices to read and write |
4 | 4 | //! data. |
5 | | -//! |
6 | | -//! Implementation based on `Cuervo`s great work in |
7 | | -//! https://www.ecorax.net/as-above-so-below-1/ and |
8 | | -//! https://www.ecorax.net/as-above-so-below-2/ |
9 | 5 |
|
10 | 6 | #![no_std] |
11 | 7 | #![deny(missing_docs)] |
12 | 8 | #![deny(unsafe_code)] |
13 | 9 |
|
14 | | -use core::ops::{Add, Sub}; |
15 | | -use heapless::{consts::*, Vec}; |
16 | | -use nb; |
17 | | - |
18 | 10 | /// Currently contains [`OverlapIterator`] |
19 | 11 | pub mod iter; |
20 | | - |
21 | | -/// An address denotes the read/write address of a single word. |
22 | | -#[derive(Default, Copy, Clone, Debug, PartialOrd, PartialEq, Eq, Ord)] |
23 | | -pub struct Address(pub u32); |
24 | | - |
25 | | -impl Add<usize> for Address { |
26 | | - type Output = Self; |
27 | | - |
28 | | - fn add(self, rhs: usize) -> Self::Output { |
29 | | - Address(self.0 + rhs as u32) |
30 | | - } |
31 | | -} |
32 | | - |
33 | | -impl Add<isize> for Address { |
34 | | - type Output = Self; |
35 | | - |
36 | | - fn add(self, rhs: isize) -> Self::Output { |
37 | | - Address((self.0 as isize + rhs) as u32) |
38 | | - } |
39 | | -} |
40 | | -impl Sub<usize> for Address { |
41 | | - type Output = Self; |
42 | | - |
43 | | - fn sub(self, rhs: usize) -> Self::Output { |
44 | | - Address(self.0 - rhs as u32) |
45 | | - } |
46 | | -} |
47 | | - |
48 | | -impl Sub<isize> for Address { |
49 | | - type Output = Self; |
50 | | - |
51 | | - fn sub(self, rhs: isize) -> Self::Output { |
52 | | - Address((self.0 as isize - rhs) as u32) |
53 | | - } |
54 | | -} |
55 | | - |
56 | | -impl Sub<Address> for Address { |
57 | | - type Output = Self; |
58 | | - |
59 | | - fn sub(self, rhs: Address) -> Self::Output { |
60 | | - Address(self.0 - rhs.0) |
61 | | - } |
62 | | -} |
| 12 | +/// Technology specific traits for NOR Flashes |
| 13 | +pub mod nor_flash; |
63 | 14 |
|
64 | 15 | /// A region denotes a contiguous piece of memory between two addresses. |
65 | 16 | pub trait Region { |
66 | 17 | /// Check if `address` is contained in the region of `Self` |
67 | | - fn contains(&self, address: Address) -> bool; |
| 18 | + fn contains(&self, address: u32) -> bool; |
68 | 19 | } |
69 | 20 |
|
70 | 21 | /// Transparent storage trait |
71 | | -pub trait ReadWriteStorage { |
| 22 | +pub trait Storage { |
72 | 23 | /// An enumeration of storage errors |
73 | 24 | type Error; |
74 | 25 |
|
75 | 26 | /// Read a slice of data from the storage peripheral, starting the read |
76 | 27 | /// operation at the given address, and reading until end address |
77 | 28 | /// (`self.range().1`) or buffer length, whichever comes first. |
78 | | - fn try_read(&mut self, address: Address, bytes: &mut [u8]) -> nb::Result<(), Self::Error>; |
| 29 | + fn try_read(&mut self, address: u32, bytes: &mut [u8]) -> Result<(), Self::Error>; |
79 | 30 |
|
80 | 31 | /// Write a slice of data to the storage peripheral, starting the write |
81 | 32 | /// operation at the given address. |
82 | | - fn try_write(&mut self, address: Address, bytes: &[u8]) -> nb::Result<(), Self::Error>; |
83 | | - |
84 | | - /// The range of possible addresses within the peripheral. |
85 | 33 | /// |
86 | | - /// (start_addr, end_addr) |
87 | | - fn range(&self) -> (Address, Address); |
88 | | - |
89 | | - /// Erase the given storage range, clearing all data within `[from..to]`. |
90 | | - fn try_erase(&mut self, from: Address, to: Address) -> nb::Result<(), Self::Error>; |
91 | | -} |
92 | | - |
93 | | -/// NOR flash region trait. |
94 | | -pub trait NorFlashRegion { |
95 | | - /// The range of possible addresses within the region. |
| 34 | + /// **NOTE:** |
| 35 | + /// This function will automatically erase any pages necessary to write the given data, |
| 36 | + /// and might as such do RMW operations at an undesirable performance impact. |
96 | 37 | /// |
97 | | - /// (start_addr, end_addr) |
98 | | - fn range(&self) -> (Address, Address); |
99 | | - /// Maximum number of bytes that can be written at once. |
100 | | - fn page_size(&self) -> usize; |
101 | | - /// List of avalable erase sizes in this region. |
102 | | - /// Should be sorted in ascending order. |
103 | | - /// Currently limited to 5 sizes, but could be increased if necessary. |
104 | | - fn erase_sizes(&self) -> Vec<usize, U5>; |
105 | | -} |
106 | | - |
107 | | -/// Blanket implementation for all types implementing [`NorFlashRegion`] |
108 | | -impl<T: NorFlashRegion> Region for T { |
109 | | - fn contains(&self, address: Address) -> bool { |
110 | | - let (start, end) = self.range(); |
111 | | - address.0 >= start.0 && address.0 < end.0 |
112 | | - } |
113 | | -} |
114 | | - |
115 | | -/// NOR flash storage trait |
116 | | -pub trait NorFlash { |
117 | | - /// An enumeration of storage errors |
118 | | - type Error; |
119 | | - /// Region type |
120 | | - type Region: NorFlashRegion; |
121 | | - |
122 | | - /// Read a slice of data from the storage peripheral, starting the read |
123 | | - /// operation at the given address, and reading until end address |
124 | | - /// (`self.range().1`) or buffer length, whichever comes first. |
125 | | - fn try_read(&mut self, address: Address, bytes: &mut [u8]) -> nb::Result<(), Self::Error>; |
| 38 | + /// CONSIDERATIONS: |
| 39 | + /// - Should the address here be normalized (always start from zero?) |
| 40 | + fn try_write(&mut self, address: u32, bytes: &[u8]) -> Result<(), Self::Error>; |
126 | 41 |
|
127 | | - /// Write a slice of data to the storage peripheral, starting the write |
128 | | - /// operation at the given address. |
129 | | - /// |
130 | | - /// Since this is done on a NOR flash all bytes are anded with the current |
131 | | - /// content in the flash. This means no 0s can to turned into 1s this way. |
132 | | - fn try_write(&mut self, address: Address, bytes: &[u8]) -> nb::Result<(), Self::Error>; |
133 | | - |
134 | | - /// Erase the given storage range, clearing all data within `[from..to]`. |
135 | | - /// The given range will contain all 1s afterwards. |
136 | | - /// |
137 | | - /// This should return an error if the range is not aligned to a proper |
138 | | - /// erase resolution |
139 | | - fn try_erase(&mut self, from: Address, to: Address) -> nb::Result<(), Self::Error>; |
140 | | - |
141 | | - /// Get all distinct memory reagions. These must not overlap, but can be disjoint. |
142 | | - /// Most chips will return a single region, but some chips have regions with |
143 | | - /// different erase sizes. |
144 | | - /// Currently limited to 4 regions, but could be increased if necessary |
145 | | - fn regions(&self) -> Vec<Self::Region, U4>; |
146 | | -} |
147 | | - |
148 | | -/// Marker trait for NOR flashes with uniform erase and page sizes across the whole |
149 | | -/// address range |
150 | | -pub trait UniformNorFlash {} |
151 | | - |
152 | | -/// Blanket implementation for all types implementing [`NorFlash`] and [`UniformNorFlash`] |
153 | | -impl<T: NorFlash + UniformNorFlash> NorFlashRegion for T { |
154 | | - /// The range of possible addresses within the peripheral. |
155 | | - /// |
156 | | - /// (start_addr, end_addr) |
157 | | - fn range(&self) -> (Address, Address) { |
158 | | - self.regions()[0].range() |
159 | | - } |
160 | | - /// Maximum number of bytes that can be written at once. |
161 | | - fn page_size(&self) -> usize { |
162 | | - self.regions()[0].page_size() |
163 | | - } |
164 | | - /// List of avalable erase sizes in this region. |
165 | | - /// Should be sorted in ascending order. |
166 | | - /// Currently limited to 5 sizes, but could be increased if necessary. |
167 | | - fn erase_sizes(&self) -> Vec<usize, U5> { |
168 | | - self.regions()[0].erase_sizes() |
169 | | - } |
| 42 | + /// The capacity of the storage peripheral in bytes. |
| 43 | + fn capacity(&self) -> u32; |
170 | 44 | } |
0 commit comments