2
2
//!
3
3
//! This module provides a `Flash` struct that wraps a MultiwriteNorFlash device
4
4
//! and exposes async methods for queue-like operations on persistent storage.
5
+ use core:: { num:: NonZeroU32 , ops:: Deref } ;
5
6
6
- use embedded_storage_async:: nor_flash:: MultiwriteNorFlash ;
7
+ use embedded_storage_async:: nor_flash:: { ErrorType , MultiwriteNorFlash } ;
7
8
use sequential_storage:: {
8
- Error as SeqStorError ,
9
9
cache:: CacheImpl ,
10
- queue:: { self , QueueIterator } ,
10
+ queue:: { self , QueueIterator , QueueIteratorEntry } ,
11
11
} ;
12
12
13
+ use crate :: { Elem , NdlDataStorage , NdlElemIter , NdlElemIterNode , SerData , consts} ;
14
+
13
15
/// Owns a flash and the range reserved for the `StorageList`
14
16
pub struct Flash < T : MultiwriteNorFlash , C : CacheImpl > {
15
17
flash : T ,
16
18
range : core:: ops:: Range < u32 > ,
17
19
cache : C ,
18
20
}
19
21
22
+ /// An iterator over a [`Flash`]
23
+ pub struct FlashIter < ' flash , T : MultiwriteNorFlash , C : CacheImpl > {
24
+ iter : QueueIterator < ' flash , T , C > ,
25
+ }
26
+
27
+ /// A single position in the flash queue iterator
28
+ ///
29
+ /// This represents a well-decoded element, where `half` contains the decoded
30
+ /// contents that correspond with `qit`.
31
+ pub struct FlashNode < ' flash , ' iter , ' buf , T : MultiwriteNorFlash , C : CacheImpl > {
32
+ half : HalfElem ,
33
+ qit : QueueIteratorEntry < ' flash , ' buf , ' iter , T , C > ,
34
+ }
35
+
36
+ /// A partially decoded element
37
+ ///
38
+ /// This is a helper type that mimics [`Elem`], so we don't need to re-decode it
39
+ /// on every access.
40
+ #[ derive( Clone , Copy ) ]
41
+ enum HalfElem {
42
+ Start { seq_no : NonZeroU32 } ,
43
+ Data ,
44
+ End { seq_no : NonZeroU32 , calc_crc : u32 } ,
45
+ }
46
+
47
+ // ---- impl Flash ----
48
+
20
49
impl < T : MultiwriteNorFlash , C : CacheImpl > Flash < T , C > {
21
50
/// Creates a new Flash instance with the given flash device and address range.
22
51
///
23
52
/// # Arguments
24
53
/// * `flash` - The MultiwriteNorFlash device to use for storage operations
25
54
/// * `range` - The address range within the flash device reserved for this storage
55
+ /// * `cache` - the cache to use with this flash access
26
56
pub fn new ( flash : T , range : core:: ops:: Range < u32 > , cache : C ) -> Self {
27
57
Self {
28
58
flash,
@@ -35,36 +65,153 @@ impl<T: MultiwriteNorFlash, C: CacheImpl> Flash<T, C> {
35
65
pub fn flash ( & mut self ) -> & mut T {
36
66
& mut self . flash
37
67
}
68
+ }
69
+
70
+ impl < T : MultiwriteNorFlash + ' static , C : CacheImpl + ' static > NdlDataStorage for Flash < T , C > {
71
+ type Iter < ' this >
72
+ = FlashIter < ' this , T , C >
73
+ where
74
+ Self : ' this ;
75
+
76
+ type Error = sequential_storage:: Error < <T as ErrorType >:: Error > ;
77
+
78
+ async fn iter_elems < ' this > (
79
+ & ' this mut self ,
80
+ ) -> Result < Self :: Iter < ' this > , <Self :: Iter < ' this > as NdlElemIter >:: Error > {
81
+ Ok ( FlashIter {
82
+ iter : queue:: iter ( & mut self . flash , self . range . clone ( ) , & mut self . cache ) . await ?,
83
+ } )
84
+ }
85
+
86
+ async fn push ( & mut self , data : & Elem < ' _ > ) -> Result < ( ) , Self :: Error > {
87
+ // scratch buffer used if this is start/end
88
+ let mut buf = [ 0u8 ; 9 ] ;
89
+ let used = match data {
90
+ Elem :: Start { seq_no } => {
91
+ let buf = & mut buf[ ..5 ] ;
92
+ buf[ 0 ] = consts:: ELEM_START ;
93
+ buf[ 1 ..5 ] . copy_from_slice ( & seq_no. get ( ) . to_le_bytes ( ) ) ;
94
+ buf
95
+ }
96
+ Elem :: Data { data } => data. hdr_key_val ,
97
+ Elem :: End { seq_no, calc_crc } => {
98
+ buf[ 0 ] = consts:: ELEM_END ;
99
+ buf[ 1 ..5 ] . copy_from_slice ( & seq_no. get ( ) . to_le_bytes ( ) ) ;
100
+ buf[ 5 ..9 ] . copy_from_slice ( & calc_crc. to_le_bytes ( ) ) ;
101
+ buf. as_slice ( )
102
+ }
103
+ } ;
38
104
39
- /// Pushes data to the sequential storage queue.
40
- pub async fn push ( & mut self , data : & [ u8 ] ) -> Result < ( ) , SeqStorError < T :: Error > > {
105
+ // Push data to the underlying queue
41
106
queue:: push (
42
107
& mut self . flash ,
43
108
self . range . clone ( ) ,
44
109
& mut self . cache ,
45
- data ,
110
+ used ,
46
111
false ,
47
112
)
48
113
. await
49
114
}
115
+ }
116
+
117
+ // ---- impl FlashIter ----
50
118
51
- /// Creates an iterator over the sequential storage queue.
52
- pub async fn iter ( & mut self ) -> Result < QueueIterator < T , C > , SeqStorError < T :: Error > > {
53
- queue:: iter ( & mut self . flash , self . range . clone ( ) , & mut self . cache ) . await
119
+ impl < ' flash , T : MultiwriteNorFlash + ' static , C : CacheImpl + ' static > NdlElemIter
120
+ for FlashIter < ' flash , T , C >
121
+ {
122
+ type Item < ' this , ' buf >
123
+ = FlashNode < ' flash , ' this , ' buf , T , C >
124
+ where
125
+ Self : ' this ,
126
+ Self : ' buf ;
127
+
128
+ type Error = sequential_storage:: Error < <T as ErrorType >:: Error > ;
129
+
130
+ async fn next < ' iter , ' buf > (
131
+ & ' iter mut self ,
132
+ buf : & ' buf mut [ u8 ] ,
133
+ ) -> Result < Option < Option < Self :: Item < ' iter , ' buf > > > , Self :: Error >
134
+ where
135
+ Self : ' buf ,
136
+ Self : ' iter ,
137
+ {
138
+ // Attempt to get the next item
139
+ let nxt: Option < QueueIteratorEntry < ' flash , ' buf , ' iter , T , C > > =
140
+ self . iter . next ( buf) . await ?;
141
+
142
+ // No data? all done.
143
+ let Some ( nxt) = nxt else { return Ok ( None ) } ;
144
+
145
+ // Can we decode this as an element?
146
+ if let Some ( elem) = HalfElem :: from_bytes ( & nxt) {
147
+ Ok ( Some ( Some ( FlashNode {
148
+ half : elem,
149
+ qit : nxt,
150
+ } ) ) )
151
+ } else {
152
+ Ok ( Some ( None ) )
153
+ }
54
154
}
155
+ }
156
+
157
+ // ---- impl FlashIterNode ----
158
+
159
+ impl < T : MultiwriteNorFlash , C : CacheImpl > NdlElemIterNode for FlashNode < ' _ , ' _ , ' _ , T , C > {
160
+ type Error = sequential_storage:: Error < <T as ErrorType >:: Error > ;
55
161
56
- /// Pops data from the sequential storage queue.
57
- pub async fn pop < ' a > (
58
- & mut self ,
59
- data : & ' a mut [ u8 ] ,
60
- ) -> Result < Option < & ' a mut [ u8 ] > , SeqStorError < T :: Error > > {
61
- queue:: pop ( & mut self . flash , self . range . clone ( ) , & mut self . cache , data) . await
162
+ fn data ( & self ) -> Elem < ' _ > {
163
+ match self . half {
164
+ HalfElem :: Start { seq_no } => Elem :: Start { seq_no } ,
165
+ HalfElem :: Data => Elem :: Data {
166
+ data : SerData :: from_existing ( self . qit . deref ( ) ) . unwrap ( ) ,
167
+ } ,
168
+ HalfElem :: End { seq_no, calc_crc } => Elem :: End { seq_no, calc_crc } ,
169
+ }
170
+ }
171
+
172
+ async fn invalidate ( self ) -> Result < ( ) , Self :: Error > {
173
+ self . qit . pop ( ) . await ?;
174
+ Ok ( ( ) )
62
175
}
63
- /// Peeks at data from the sequential storage queue.
64
- pub async fn peek < ' a > (
65
- & mut self ,
66
- data : & ' a mut [ u8 ] ,
67
- ) -> Result < Option < & ' a mut [ u8 ] > , SeqStorError < T :: Error > > {
68
- queue:: peek ( & mut self . flash , self . range . clone ( ) , & mut self . cache , data) . await
176
+ }
177
+
178
+ // ---- impl HalfElem ----
179
+
180
+ impl HalfElem {
181
+ fn from_bytes ( data : & [ u8 ] ) -> Option < Self > {
182
+ let ( first, rest) = data. split_first ( ) ?;
183
+ match * first {
184
+ consts:: ELEM_START => {
185
+ if rest. len ( ) != 4 {
186
+ return None ;
187
+ }
188
+ let mut bytes = [ 0u8 ; 4 ] ;
189
+ bytes. copy_from_slice ( rest) ;
190
+ Some ( HalfElem :: Start {
191
+ seq_no : NonZeroU32 :: new ( u32:: from_le_bytes ( bytes) ) ?,
192
+ } )
193
+ }
194
+ consts:: ELEM_DATA => {
195
+ if rest. is_empty ( ) {
196
+ None
197
+ } else {
198
+ Some ( HalfElem :: Data )
199
+ }
200
+ }
201
+ consts:: ELEM_END => {
202
+ if rest. len ( ) != 8 {
203
+ return None ;
204
+ }
205
+ let mut seq_bytes = [ 0u8 ; 4 ] ;
206
+ seq_bytes. copy_from_slice ( & rest[ ..4 ] ) ;
207
+ let mut crc_bytes = [ 0u8 ; 4 ] ;
208
+ crc_bytes. copy_from_slice ( & rest[ 4 ..8 ] ) ;
209
+ Some ( HalfElem :: End {
210
+ seq_no : NonZeroU32 :: new ( u32:: from_le_bytes ( seq_bytes) ) ?,
211
+ calc_crc : u32:: from_le_bytes ( crc_bytes) ,
212
+ } )
213
+ }
214
+ _ => None ,
215
+ }
69
216
}
70
217
}
0 commit comments