@@ -60,16 +60,18 @@ impl Default for Config {
60
60
#[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
61
61
#[ non_exhaustive]
62
62
pub enum Error {
63
+ OutOfBounds ,
63
64
// TODO add "not in data memory" error and check for it
64
65
}
65
66
66
- pub struct Qspi < ' d , T : Instance > {
67
+ pub struct Qspi < ' d , T : Instance , const FLASH_SIZE : usize > {
68
+ irq : T :: Interrupt ,
67
69
dpm_enabled : bool ,
68
70
phantom : PhantomData < & ' d mut T > ,
69
71
}
70
72
71
- impl < ' d , T : Instance > Qspi < ' d , T > {
72
- pub async fn new (
73
+ impl < ' d , T : Instance , const FLASH_SIZE : usize > Qspi < ' d , T , FLASH_SIZE > {
74
+ pub fn new (
73
75
_qspi : impl Unborrow < Target = T > + ' d ,
74
76
irq : impl Unborrow < Target = T :: Interrupt > + ' d ,
75
77
sck : impl Unborrow < Target = impl GpioPin > + ' d ,
@@ -79,7 +81,7 @@ impl<'d, T: Instance> Qspi<'d, T> {
79
81
io2 : impl Unborrow < Target = impl GpioPin > + ' d ,
80
82
io3 : impl Unborrow < Target = impl GpioPin > + ' d ,
81
83
config : Config ,
82
- ) -> Qspi < ' d , T > {
84
+ ) -> Qspi < ' d , T , FLASH_SIZE > {
83
85
unborrow ! ( irq, sck, csn, io0, io1, io2, io3) ;
84
86
85
87
let r = T :: regs ( ) ;
@@ -142,6 +144,7 @@ impl<'d, T: Instance> Qspi<'d, T> {
142
144
143
145
let mut res = Self {
144
146
dpm_enabled : config. deep_power_down . is_some ( ) ,
147
+ irq,
145
148
phantom : PhantomData ,
146
149
} ;
147
150
@@ -150,7 +153,7 @@ impl<'d, T: Instance> Qspi<'d, T> {
150
153
151
154
r. tasks_activate . write ( |w| w. tasks_activate ( ) . bit ( true ) ) ;
152
155
153
- res. wait_ready ( ) . await ;
156
+ res. blocking_wait_ready ( ) ;
154
157
155
158
res
156
159
}
@@ -173,8 +176,36 @@ impl<'d, T: Instance> Qspi<'d, T> {
173
176
) -> Result < ( ) , Error > {
174
177
let bomb = DropBomb :: new ( ) ;
175
178
179
+ let len = core:: cmp:: max ( req. len ( ) , resp. len ( ) ) as u8 ;
180
+ self . custom_instruction_start ( opcode, req, len) ?;
181
+
182
+ self . wait_ready ( ) . await ;
183
+
184
+ self . custom_instruction_finish ( resp) ?;
185
+
186
+ bomb. defuse ( ) ;
187
+
188
+ Ok ( ( ) )
189
+ }
190
+
191
+ pub fn blocking_custom_instruction (
192
+ & mut self ,
193
+ opcode : u8 ,
194
+ req : & [ u8 ] ,
195
+ resp : & mut [ u8 ] ,
196
+ ) -> Result < ( ) , Error > {
197
+ let len = core:: cmp:: max ( req. len ( ) , resp. len ( ) ) as u8 ;
198
+ self . custom_instruction_start ( opcode, req, len) ?;
199
+
200
+ self . blocking_wait_ready ( ) ;
201
+
202
+ self . custom_instruction_finish ( resp) ?;
203
+
204
+ Ok ( ( ) )
205
+ }
206
+
207
+ fn custom_instruction_start ( & mut self , opcode : u8 , req : & [ u8 ] , len : u8 ) -> Result < ( ) , Error > {
176
208
assert ! ( req. len( ) <= 8 ) ;
177
- assert ! ( resp. len( ) <= 8 ) ;
178
209
179
210
let mut dat0: u32 = 0 ;
180
211
let mut dat1: u32 = 0 ;
@@ -190,8 +221,6 @@ impl<'d, T: Instance> Qspi<'d, T> {
190
221
}
191
222
}
192
223
193
- let len = core:: cmp:: max ( req. len ( ) , resp. len ( ) ) as u8 ;
194
-
195
224
let r = T :: regs ( ) ;
196
225
r. cinstrdat0 . write ( |w| unsafe { w. bits ( dat0) } ) ;
197
226
r. cinstrdat1 . write ( |w| unsafe { w. bits ( dat1) } ) ;
@@ -210,9 +239,10 @@ impl<'d, T: Instance> Qspi<'d, T> {
210
239
let w = w. lfstop ( ) . bit ( false ) ;
211
240
w
212
241
} ) ;
242
+ Ok ( ( ) )
243
+ }
213
244
214
- self . wait_ready ( ) . await ;
215
-
245
+ fn custom_instruction_finish ( & mut self , resp : & mut [ u8 ] ) -> Result < ( ) , Error > {
216
246
let r = T :: regs ( ) ;
217
247
218
248
let dat0 = r. cinstrdat0 . read ( ) . bits ( ) ;
@@ -227,9 +257,6 @@ impl<'d, T: Instance> Qspi<'d, T> {
227
257
resp[ i] = ( dat1 >> ( i * 8 ) ) as u8 ;
228
258
}
229
259
}
230
-
231
- bomb. defuse ( ) ;
232
-
233
260
Ok ( ( ) )
234
261
}
235
262
@@ -246,12 +273,22 @@ impl<'d, T: Instance> Qspi<'d, T> {
246
273
. await
247
274
}
248
275
249
- pub async fn read ( & mut self , address : usize , data : & mut [ u8 ] ) -> Result < ( ) , Error > {
250
- let bomb = DropBomb :: new ( ) ;
276
+ fn blocking_wait_ready ( & mut self ) {
277
+ loop {
278
+ let r = T :: regs ( ) ;
279
+ if r. events_ready . read ( ) . bits ( ) != 0 {
280
+ break ;
281
+ }
282
+ }
283
+ }
251
284
285
+ fn start_read ( & mut self , address : usize , data : & mut [ u8 ] ) -> Result < ( ) , Error > {
252
286
assert_eq ! ( data. as_ptr( ) as u32 % 4 , 0 ) ;
253
287
assert_eq ! ( data. len( ) as u32 % 4 , 0 ) ;
254
288
assert_eq ! ( address as u32 % 4 , 0 ) ;
289
+ if address > FLASH_SIZE {
290
+ return Err ( Error :: OutOfBounds ) ;
291
+ }
255
292
256
293
let r = T :: regs ( ) ;
257
294
@@ -269,19 +306,20 @@ impl<'d, T: Instance> Qspi<'d, T> {
269
306
r. intenset . write ( |w| w. ready ( ) . set ( ) ) ;
270
307
r. tasks_readstart . write ( |w| w. tasks_readstart ( ) . bit ( true ) ) ;
271
308
272
- self . wait_ready ( ) . await ;
273
-
274
- bomb. defuse ( ) ;
275
-
276
309
Ok ( ( ) )
277
310
}
278
311
279
- pub async fn write ( & mut self , address : usize , data : & [ u8 ] ) -> Result < ( ) , Error > {
280
- let bomb = DropBomb :: new ( ) ;
281
-
312
+ fn start_write ( & mut self , address : usize , data : & [ u8 ] ) -> Result < ( ) , Error > {
313
+ //info!("start_write ptr {}", data.as_ptr() as u32);
282
314
assert_eq ! ( data. as_ptr( ) as u32 % 4 , 0 ) ;
315
+ //info!("start_write OK ptr");
283
316
assert_eq ! ( data. len( ) as u32 % 4 , 0 ) ;
317
+ //info!("start_write OK len");
284
318
assert_eq ! ( address as u32 % 4 , 0 ) ;
319
+ //info!("start_write OK addr");
320
+ if address > FLASH_SIZE {
321
+ return Err ( Error :: OutOfBounds ) ;
322
+ }
285
323
286
324
let r = T :: regs ( ) ;
287
325
r. write
@@ -298,17 +336,14 @@ impl<'d, T: Instance> Qspi<'d, T> {
298
336
r. intenset . write ( |w| w. ready ( ) . set ( ) ) ;
299
337
r. tasks_writestart . write ( |w| w. tasks_writestart ( ) . bit ( true ) ) ;
300
338
301
- self . wait_ready ( ) . await ;
302
-
303
- bomb. defuse ( ) ;
304
-
305
339
Ok ( ( ) )
306
340
}
307
341
308
- pub async fn erase ( & mut self , address : usize ) -> Result < ( ) , Error > {
309
- let bomb = DropBomb :: new ( ) ;
310
-
342
+ fn start_erase ( & mut self , address : usize ) -> Result < ( ) , Error > {
311
343
assert_eq ! ( address as u32 % 4096 , 0 ) ;
344
+ if address > FLASH_SIZE {
345
+ return Err ( Error :: OutOfBounds ) ;
346
+ }
312
347
313
348
let r = T :: regs ( ) ;
314
349
r. erase
@@ -320,15 +355,65 @@ impl<'d, T: Instance> Qspi<'d, T> {
320
355
r. intenset . write ( |w| w. ready ( ) . set ( ) ) ;
321
356
r. tasks_erasestart . write ( |w| w. tasks_erasestart ( ) . bit ( true ) ) ;
322
357
358
+ Ok ( ( ) )
359
+ }
360
+
361
+ pub async fn read ( & mut self , address : usize , data : & mut [ u8 ] ) -> Result < ( ) , Error > {
362
+ let bomb = DropBomb :: new ( ) ;
363
+
364
+ self . start_read ( address, data) ?;
323
365
self . wait_ready ( ) . await ;
324
366
325
367
bomb. defuse ( ) ;
326
368
327
369
Ok ( ( ) )
328
370
}
371
+
372
+ pub async fn write ( & mut self , address : usize , data : & [ u8 ] ) -> Result < ( ) , Error > {
373
+ let bomb = DropBomb :: new ( ) ;
374
+
375
+ //info!("WRITE {} bytes at {}", data.len(), address);
376
+ self . start_write ( address, data) ?;
377
+ //info!("STARTED");
378
+ self . wait_ready ( ) . await ;
379
+ //info!("WRITE DONE");
380
+
381
+ bomb. defuse ( ) ;
382
+
383
+ Ok ( ( ) )
384
+ }
385
+
386
+ pub async fn erase ( & mut self , address : usize ) -> Result < ( ) , Error > {
387
+ let bomb = DropBomb :: new ( ) ;
388
+
389
+ self . start_erase ( address) ?;
390
+ self . wait_ready ( ) . await ;
391
+
392
+ bomb. defuse ( ) ;
393
+
394
+ Ok ( ( ) )
395
+ }
396
+
397
+ pub fn blocking_read ( & mut self , address : usize , data : & mut [ u8 ] ) -> Result < ( ) , Error > {
398
+ self . start_read ( address, data) ?;
399
+ self . blocking_wait_ready ( ) ;
400
+ Ok ( ( ) )
401
+ }
402
+
403
+ pub fn blocking_write ( & mut self , address : usize , data : & [ u8 ] ) -> Result < ( ) , Error > {
404
+ self . start_write ( address, data) ?;
405
+ self . blocking_wait_ready ( ) ;
406
+ Ok ( ( ) )
407
+ }
408
+
409
+ pub fn blocking_erase ( & mut self , address : usize ) -> Result < ( ) , Error > {
410
+ self . start_erase ( address) ?;
411
+ self . blocking_wait_ready ( ) ;
412
+ Ok ( ( ) )
413
+ }
329
414
}
330
415
331
- impl < ' d , T : Instance > Drop for Qspi < ' d , T > {
416
+ impl < ' d , T : Instance , const FLASH_SIZE : usize > Drop for Qspi < ' d , T , FLASH_SIZE > {
332
417
fn drop ( & mut self ) {
333
418
let r = T :: regs ( ) ;
334
419
@@ -358,6 +443,8 @@ impl<'d, T: Instance> Drop for Qspi<'d, T> {
358
443
359
444
r. enable . write ( |w| w. enable ( ) . disabled ( ) ) ;
360
445
446
+ self . irq . disable ( ) ;
447
+
361
448
// Note: we do NOT deconfigure CSN here. If DPM is in use and we disconnect CSN,
362
449
// leaving it floating, the flash chip might read it as zero which would cause it to
363
450
// spuriously exit DPM.
@@ -371,6 +458,90 @@ impl<'d, T: Instance> Drop for Qspi<'d, T> {
371
458
}
372
459
}
373
460
461
+ use embedded_storage:: nor_flash:: {
462
+ ErrorType , NorFlash , NorFlashError , NorFlashErrorKind , ReadNorFlash ,
463
+ } ;
464
+
465
+ impl < ' d , T : Instance , const FLASH_SIZE : usize > ErrorType for Qspi < ' d , T , FLASH_SIZE > {
466
+ type Error = Error ;
467
+ }
468
+
469
+ impl NorFlashError for Error {
470
+ fn kind ( & self ) -> NorFlashErrorKind {
471
+ NorFlashErrorKind :: Other
472
+ }
473
+ }
474
+
475
+ impl < ' d , T : Instance , const FLASH_SIZE : usize > ReadNorFlash for Qspi < ' d , T , FLASH_SIZE > {
476
+ const READ_SIZE : usize = 4 ;
477
+
478
+ fn read ( & mut self , offset : u32 , bytes : & mut [ u8 ] ) -> Result < ( ) , Self :: Error > {
479
+ self . blocking_read ( offset as usize , bytes) ?;
480
+ Ok ( ( ) )
481
+ }
482
+
483
+ fn capacity ( & self ) -> usize {
484
+ FLASH_SIZE
485
+ }
486
+ }
487
+
488
+ impl < ' d , T : Instance , const FLASH_SIZE : usize > NorFlash for Qspi < ' d , T , FLASH_SIZE > {
489
+ const WRITE_SIZE : usize = 4 ;
490
+ const ERASE_SIZE : usize = 4096 ;
491
+
492
+ fn erase ( & mut self , from : u32 , to : u32 ) -> Result < ( ) , Self :: Error > {
493
+ for address in ( from as usize ..to as usize ) . step_by ( <Self as NorFlash >:: ERASE_SIZE ) {
494
+ self . blocking_erase ( address) ?;
495
+ }
496
+ Ok ( ( ) )
497
+ }
498
+
499
+ fn write ( & mut self , offset : u32 , bytes : & [ u8 ] ) -> Result < ( ) , Self :: Error > {
500
+ self . blocking_write ( offset as usize , bytes) ?;
501
+ Ok ( ( ) )
502
+ }
503
+ }
504
+
505
+ cfg_if:: cfg_if! {
506
+ if #[ cfg( feature = "nightly" ) ]
507
+ {
508
+ use embedded_storage_async:: nor_flash:: { AsyncNorFlash , AsyncReadNorFlash } ;
509
+ use core:: future:: Future ;
510
+
511
+ impl <' d, T : Instance , const FLASH_SIZE : usize > AsyncNorFlash for Qspi <' d, T , FLASH_SIZE > {
512
+ const WRITE_SIZE : usize = <Self as NorFlash >:: WRITE_SIZE ;
513
+ const ERASE_SIZE : usize = <Self as NorFlash >:: ERASE_SIZE ;
514
+
515
+ type WriteFuture <' a> = impl Future <Output = Result <( ) , Self :: Error >> + ' a where Self : ' a;
516
+ fn write<' a>( & ' a mut self , offset: u32 , data: & ' a [ u8 ] ) -> Self :: WriteFuture <' a> {
517
+ async move { self . write( offset as usize , data) . await }
518
+ }
519
+
520
+ type EraseFuture <' a> = impl Future <Output = Result <( ) , Self :: Error >> + ' a where Self : ' a;
521
+ fn erase<' a>( & ' a mut self , from: u32 , to: u32 ) -> Self :: EraseFuture <' a> {
522
+ async move {
523
+ for address in ( from as usize ..to as usize ) . step_by( <Self as AsyncNorFlash >:: ERASE_SIZE ) {
524
+ self . erase( address) . await ?
525
+ }
526
+ Ok ( ( ) )
527
+ }
528
+ }
529
+ }
530
+
531
+ impl <' d, T : Instance , const FLASH_SIZE : usize > AsyncReadNorFlash for Qspi <' d, T , FLASH_SIZE > {
532
+ const READ_SIZE : usize = 4 ;
533
+ type ReadFuture <' a> = impl Future <Output = Result <( ) , Self :: Error >> + ' a where Self : ' a;
534
+ fn read<' a>( & ' a mut self , address: u32 , data: & ' a mut [ u8 ] ) -> Self :: ReadFuture <' a> {
535
+ async move { self . read( address as usize , data) . await }
536
+ }
537
+
538
+ fn capacity( & self ) -> usize {
539
+ FLASH_SIZE
540
+ }
541
+ }
542
+ }
543
+ }
544
+
374
545
pub ( crate ) mod sealed {
375
546
use embassy:: waitqueue:: AtomicWaker ;
376
547
0 commit comments