|
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