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