@@ -11,7 +11,8 @@ use core::cell::RefCell;
11
11
12
12
const DEFAULT_DELAY_COUNT : u32 = 32_000 ;
13
13
14
- /// Represents an SD Card interface built from an SPI peripheral and a Chip
14
+ /// Represents an inactive SD Card interface.
15
+ /// Built from an SPI peripheral and a Chip
15
16
/// Select pin. We need Chip Select to be separate so we can clock out some
16
17
/// bytes without Chip Select asserted (which puts the card into SPI mode).
17
18
pub struct SdMmcSpi < SPI , CS >
26
27
state : State ,
27
28
}
28
29
30
+ /// An initialized block device used to access the SD card.
31
+ /// Uses SPI mode.
32
+ pub struct BlockSpi < ' a , SPI , CS > ( & ' a mut SdMmcSpi < SPI , CS > )
33
+ where
34
+ SPI : embedded_hal:: blocking:: spi:: Transfer < u8 > ,
35
+ CS : embedded_hal:: digital:: v2:: OutputPin ,
36
+ <SPI as embedded_hal:: blocking:: spi:: Transfer < u8 > >:: Error : core:: fmt:: Debug ;
37
+
29
38
/// The possible errors `SdMmcSpi` can generate.
30
39
#[ derive( Debug , Copy , Clone ) ]
31
40
pub enum Error {
@@ -134,12 +143,6 @@ where
134
143
}
135
144
}
136
145
137
- /// Get a temporary borrow on the underlying SPI device. Useful if you
138
- /// need to re-clock the SPI after performing `init()`.
139
- pub fn spi ( & mut self ) -> core:: cell:: RefMut < SPI > {
140
- self . spi . borrow_mut ( )
141
- }
142
-
143
146
fn cs_high ( & self ) -> Result < ( ) , Error > {
144
147
self . cs
145
148
. borrow_mut ( )
@@ -151,19 +154,13 @@ where
151
154
self . cs . borrow_mut ( ) . set_low ( ) . map_err ( |_| Error :: GpioError )
152
155
}
153
156
154
- /// This routine must be performed with an SPI clock speed of around 100 - 400 kHz.
155
- /// Afterwards you may increase the SPI clock speed.
156
- pub fn init ( & mut self ) -> Result < ( ) , Error > {
157
- self . init_with_opts ( Default :: default ( ) )
158
- }
159
-
160
- /// De-init the card so it can't be used
161
- pub fn deinit ( & mut self ) {
162
- self . state = State :: NoInit ;
157
+ /// Initializes the card into a known state
158
+ pub fn acquire ( & mut self ) -> Result < BlockSpi < SPI , CS > , Error > {
159
+ self . acquire_with_opts ( Default :: default ( ) )
163
160
}
164
161
165
162
/// Initializes the card into a known state
166
- pub fn init_with_opts ( & mut self , options : AcquireOpts ) -> Result < ( ) , Error > {
163
+ pub fn acquire_with_opts ( & mut self , options : AcquireOpts ) -> Result < BlockSpi < SPI , CS > , Error > {
167
164
let f = |s : & mut Self | {
168
165
// Assume it hasn't worked
169
166
s. state = State :: Error ;
@@ -248,48 +245,9 @@ where
248
245
let result = f ( self ) ;
249
246
self . cs_high ( ) ?;
250
247
let _ = self . receive ( ) ;
251
- result
252
- }
253
-
254
- /// Return the usable size of this SD card in bytes.
255
- pub fn card_size_bytes ( & self ) -> Result < u64 , Error > {
256
- self . check_state ( ) ?;
257
- self . with_chip_select ( |s| {
258
- let csd = s. read_csd ( ) ?;
259
- match csd {
260
- Csd :: V1 ( ref contents) => Ok ( contents. card_capacity_bytes ( ) ) ,
261
- Csd :: V2 ( ref contents) => Ok ( contents. card_capacity_bytes ( ) ) ,
262
- }
263
- } )
264
- }
265
-
266
- /// Erase some blocks on the card.
267
- pub fn erase ( & mut self , _first_block : BlockIdx , _last_block : BlockIdx ) -> Result < ( ) , Error > {
268
- self . check_state ( ) ?;
269
- unimplemented ! ( ) ;
248
+ result. map ( move |( ) | BlockSpi ( self ) )
270
249
}
271
250
272
- /// Can this card erase single blocks?
273
- pub fn erase_single_block_enabled ( & self ) -> Result < bool , Error > {
274
- self . check_state ( ) ?;
275
- self . with_chip_select ( |s| {
276
- let csd = s. read_csd ( ) ?;
277
- match csd {
278
- Csd :: V1 ( ref contents) => Ok ( contents. erase_single_block_enabled ( ) ) ,
279
- Csd :: V2 ( ref contents) => Ok ( contents. erase_single_block_enabled ( ) ) ,
280
- }
281
- } )
282
- }
283
-
284
- /// Return an error if we're not in `State::Idle`. It probably means
285
- /// they haven't called `begin()`.
286
- fn check_state ( & self ) -> Result < ( ) , Error > {
287
- if self . state != State :: Idle {
288
- Err ( Error :: BadState )
289
- } else {
290
- Ok ( ( ) )
291
- }
292
- }
293
251
294
252
/// Perform a function that might error with the chipselect low.
295
253
/// Always releases the chipselect, even if the function errors.
@@ -315,77 +273,6 @@ where
315
273
result
316
274
}
317
275
318
- /// Read the 'card specific data' block.
319
- fn read_csd ( & self ) -> Result < Csd , Error > {
320
- match self . card_type {
321
- CardType :: SD1 => {
322
- let mut csd = CsdV1 :: new ( ) ;
323
- if self . card_command ( CMD9 , 0 ) ? != 0 {
324
- return Err ( Error :: RegisterReadError ) ;
325
- }
326
- self . read_data ( & mut csd. data ) ?;
327
- Ok ( Csd :: V1 ( csd) )
328
- }
329
- CardType :: SD2 | CardType :: SDHC => {
330
- let mut csd = CsdV2 :: new ( ) ;
331
- if self . card_command ( CMD9 , 0 ) ? != 0 {
332
- return Err ( Error :: RegisterReadError ) ;
333
- }
334
- self . read_data ( & mut csd. data ) ?;
335
- Ok ( Csd :: V2 ( csd) )
336
- }
337
- }
338
- }
339
-
340
- /// Read an arbitrary number of bytes from the card. Always fills the
341
- /// given buffer, so make sure it's the right size.
342
- fn read_data ( & self , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
343
- // Get first non-FF byte.
344
- let mut delay = Delay :: new ( ) ;
345
- let status = loop {
346
- let s = self . receive ( ) ?;
347
- if s != 0xFF {
348
- break s;
349
- }
350
- delay. delay ( Error :: TimeoutReadBuffer ) ?;
351
- } ;
352
- if status != DATA_START_BLOCK {
353
- return Err ( Error :: ReadError ) ;
354
- }
355
-
356
- for b in buffer. iter_mut ( ) {
357
- * b = self . receive ( ) ?;
358
- }
359
-
360
- let mut crc = u16:: from ( self . receive ( ) ?) ;
361
- crc <<= 8 ;
362
- crc |= u16:: from ( self . receive ( ) ?) ;
363
-
364
- let calc_crc = crc16 ( buffer) ;
365
- if crc != calc_crc {
366
- return Err ( Error :: CrcError ( crc, calc_crc) ) ;
367
- }
368
-
369
- Ok ( ( ) )
370
- }
371
-
372
- /// Write an arbitrary number of bytes to the card.
373
- fn write_data ( & self , token : u8 , buffer : & [ u8 ] ) -> Result < ( ) , Error > {
374
- let calc_crc = crc16 ( buffer) ;
375
- self . send ( token) ?;
376
- for & b in buffer. iter ( ) {
377
- self . send ( b) ?;
378
- }
379
- self . send ( ( calc_crc >> 8 ) as u8 ) ?;
380
- self . send ( calc_crc as u8 ) ?;
381
- let status = self . receive ( ) ?;
382
- if ( status & DATA_RES_MASK ) != DATA_RES_ACCEPTED {
383
- Err ( Error :: WriteError )
384
- } else {
385
- Ok ( ( ) )
386
- }
387
- }
388
-
389
276
/// Perform an application-specific command.
390
277
fn card_acmd ( & self , command : u8 , arg : u32 ) -> Result < u8 , Error > {
391
278
self . card_command ( CMD55 , 0 ) ?;
@@ -458,7 +345,124 @@ where
458
345
}
459
346
}
460
347
461
- impl < SPI , CS > BlockDevice for SdMmcSpi < SPI , CS >
348
+ impl < SPI , CS > BlockSpi < ' _ , SPI , CS >
349
+ where
350
+ SPI : embedded_hal:: blocking:: spi:: Transfer < u8 > ,
351
+ CS : embedded_hal:: digital:: v2:: OutputPin ,
352
+ <SPI as embedded_hal:: blocking:: spi:: Transfer < u8 > >:: Error : core:: fmt:: Debug ,
353
+ {
354
+ /// Get a temporary borrow on the underlying SPI device. Useful if you
355
+ /// need to re-clock the SPI.
356
+ pub fn spi ( & mut self ) -> core:: cell:: RefMut < SPI > {
357
+ self . 0 . spi . borrow_mut ( )
358
+ }
359
+
360
+ /// Mark the card as unused.
361
+ // If there is any need to flush data, it should be implemented here.
362
+ fn deinit ( & mut self ) {
363
+ self . 0 . state = State :: NoInit ;
364
+ }
365
+
366
+ /// Return the usable size of this SD card in bytes.
367
+ pub fn card_size_bytes ( & self ) -> Result < u64 , Error > {
368
+ self . 0 . with_chip_select ( |_s| {
369
+ let csd = self . read_csd ( ) ?;
370
+ match csd {
371
+ Csd :: V1 ( ref contents) => Ok ( contents. card_capacity_bytes ( ) ) ,
372
+ Csd :: V2 ( ref contents) => Ok ( contents. card_capacity_bytes ( ) ) ,
373
+ }
374
+ } )
375
+ }
376
+
377
+ /// Erase some blocks on the card.
378
+ pub fn erase ( & mut self , _first_block : BlockIdx , _last_block : BlockIdx ) -> Result < ( ) , Error > {
379
+ unimplemented ! ( ) ;
380
+ }
381
+
382
+ /// Can this card erase single blocks?
383
+ pub fn erase_single_block_enabled ( & self ) -> Result < bool , Error > {
384
+ self . 0 . with_chip_select ( |_s| {
385
+ let csd = self . read_csd ( ) ?;
386
+ match csd {
387
+ Csd :: V1 ( ref contents) => Ok ( contents. erase_single_block_enabled ( ) ) ,
388
+ Csd :: V2 ( ref contents) => Ok ( contents. erase_single_block_enabled ( ) ) ,
389
+ }
390
+ } )
391
+ }
392
+
393
+ /// Read the 'card specific data' block.
394
+ fn read_csd ( & self ) -> Result < Csd , Error > {
395
+ match self . 0 . card_type {
396
+ CardType :: SD1 => {
397
+ let mut csd = CsdV1 :: new ( ) ;
398
+ if self . 0 . card_command ( CMD9 , 0 ) ? != 0 {
399
+ return Err ( Error :: RegisterReadError ) ;
400
+ }
401
+ self . read_data ( & mut csd. data ) ?;
402
+ Ok ( Csd :: V1 ( csd) )
403
+ }
404
+ CardType :: SD2 | CardType :: SDHC => {
405
+ let mut csd = CsdV2 :: new ( ) ;
406
+ if self . 0 . card_command ( CMD9 , 0 ) ? != 0 {
407
+ return Err ( Error :: RegisterReadError ) ;
408
+ }
409
+ self . read_data ( & mut csd. data ) ?;
410
+ Ok ( Csd :: V2 ( csd) )
411
+ }
412
+ }
413
+ }
414
+
415
+ /// Read an arbitrary number of bytes from the card. Always fills the
416
+ /// given buffer, so make sure it's the right size.
417
+ fn read_data ( & self , buffer : & mut [ u8 ] ) -> Result < ( ) , Error > {
418
+ // Get first non-FF byte.
419
+ let mut delay = Delay :: new ( ) ;
420
+ let status = loop {
421
+ let s = self . 0 . receive ( ) ?;
422
+ if s != 0xFF {
423
+ break s;
424
+ }
425
+ delay. delay ( Error :: TimeoutReadBuffer ) ?;
426
+ } ;
427
+ if status != DATA_START_BLOCK {
428
+ return Err ( Error :: ReadError ) ;
429
+ }
430
+
431
+ for b in buffer. iter_mut ( ) {
432
+ * b = self . 0 . receive ( ) ?;
433
+ }
434
+
435
+ let mut crc = u16:: from ( self . 0 . receive ( ) ?) ;
436
+ crc <<= 8 ;
437
+ crc |= u16:: from ( self . 0 . receive ( ) ?) ;
438
+
439
+ let calc_crc = crc16 ( buffer) ;
440
+ if crc != calc_crc {
441
+ return Err ( Error :: CrcError ( crc, calc_crc) ) ;
442
+ }
443
+
444
+ Ok ( ( ) )
445
+ }
446
+
447
+ /// Write an arbitrary number of bytes to the card.
448
+ fn write_data ( & self , token : u8 , buffer : & [ u8 ] ) -> Result < ( ) , Error > {
449
+ let calc_crc = crc16 ( buffer) ;
450
+ self . 0 . send ( token) ?;
451
+ for & b in buffer. iter ( ) {
452
+ self . 0 . send ( b) ?;
453
+ }
454
+ self . 0 . send ( ( calc_crc >> 8 ) as u8 ) ?;
455
+ self . 0 . send ( calc_crc as u8 ) ?;
456
+ let status = self . 0 . receive ( ) ?;
457
+ if ( status & DATA_RES_MASK ) != DATA_RES_ACCEPTED {
458
+ Err ( Error :: WriteError )
459
+ } else {
460
+ Ok ( ( ) )
461
+ }
462
+ }
463
+ }
464
+
465
+ impl < SPI , CS > BlockDevice for BlockSpi < ' _ , SPI , CS >
462
466
where
463
467
SPI : embedded_hal:: blocking:: spi:: Transfer < u8 > ,
464
468
<SPI as embedded_hal:: blocking:: spi:: Transfer < u8 > >:: Error : core:: fmt:: Debug ,
@@ -473,21 +477,20 @@ where
473
477
start_block_idx : BlockIdx ,
474
478
_reason : & str ,
475
479
) -> Result < ( ) , Self :: Error > {
476
- self . check_state ( ) ?;
477
- let start_idx = match self . card_type {
480
+ let start_idx = match self . 0 . card_type {
478
481
CardType :: SD1 | CardType :: SD2 => start_block_idx. 0 * 512 ,
479
482
CardType :: SDHC => start_block_idx. 0 ,
480
483
} ;
481
- self . with_chip_select ( |s| {
484
+ self . 0 . with_chip_select ( |s| {
482
485
if blocks. len ( ) == 1 {
483
486
// Start a single-block read
484
487
s. card_command ( CMD17 , start_idx) ?;
485
- s . read_data ( & mut blocks[ 0 ] . contents ) ?;
488
+ self . read_data ( & mut blocks[ 0 ] . contents ) ?;
486
489
} else {
487
490
// Start a multi-block read
488
491
s. card_command ( CMD18 , start_idx) ?;
489
492
for block in blocks. iter_mut ( ) {
490
- s . read_data ( & mut block. contents ) ?;
493
+ self . read_data ( & mut block. contents ) ?;
491
494
}
492
495
// Stop the read
493
496
s. card_command ( CMD12 , 0 ) ?;
@@ -498,16 +501,15 @@ where
498
501
499
502
/// Write one or more blocks, starting at the given block index.
500
503
fn write ( & self , blocks : & [ Block ] , start_block_idx : BlockIdx ) -> Result < ( ) , Self :: Error > {
501
- self . check_state ( ) ?;
502
- let start_idx = match self . card_type {
504
+ let start_idx = match self . 0 . card_type {
503
505
CardType :: SD1 | CardType :: SD2 => start_block_idx. 0 * 512 ,
504
506
CardType :: SDHC => start_block_idx. 0 ,
505
507
} ;
506
- self . with_chip_select_mut ( |s| {
508
+ self . 0 . with_chip_select_mut ( |s| {
507
509
if blocks. len ( ) == 1 {
508
510
// Start a single-block write
509
511
s. card_command ( CMD24 , start_idx) ?;
510
- s . write_data ( DATA_START_BLOCK , & blocks[ 0 ] . contents ) ?;
512
+ self . write_data ( DATA_START_BLOCK , & blocks[ 0 ] . contents ) ?;
511
513
s. wait_not_busy ( ) ?;
512
514
if s. card_command ( CMD13 , 0 ) ? != 0x00 {
513
515
return Err ( Error :: WriteError ) ;
@@ -520,7 +522,7 @@ where
520
522
s. card_command ( CMD25 , start_idx) ?;
521
523
for block in blocks. iter ( ) {
522
524
s. wait_not_busy ( ) ?;
523
- s . write_data ( WRITE_MULTIPLE_TOKEN , & block. contents ) ?;
525
+ self . write_data ( WRITE_MULTIPLE_TOKEN , & block. contents ) ?;
524
526
}
525
527
// Stop the write
526
528
s. wait_not_busy ( ) ?;
@@ -538,6 +540,17 @@ where
538
540
}
539
541
}
540
542
543
+ impl < SPI , CS > Drop for BlockSpi < ' _ , SPI , CS >
544
+ where
545
+ SPI : embedded_hal:: blocking:: spi:: Transfer < u8 > ,
546
+ <SPI as embedded_hal:: blocking:: spi:: Transfer < u8 > >:: Error : core:: fmt:: Debug ,
547
+ CS : embedded_hal:: digital:: v2:: OutputPin ,
548
+ {
549
+ fn drop ( & mut self ) {
550
+ self . deinit ( )
551
+ }
552
+ }
553
+
541
554
// ****************************************************************************
542
555
//
543
556
// End Of File
0 commit comments