1
- use core:: { fmt, ops:: ControlFlow } ;
1
+ #![ cfg( feature = "sdmmc" ) ]
2
+
3
+ use core:: {
4
+ fmt,
5
+ ops:: { ControlFlow , Deref , DerefMut } ,
6
+ } ;
2
7
3
8
use fugit:: HertzU32 as Hertz ;
4
9
use sdio_host:: {
@@ -12,7 +17,6 @@ use crate::{
12
17
pac:: { sdmmc1, SDMMC1 } ,
13
18
rcc:: { Clocks , Enable , Reset , APB2 } ,
14
19
} ;
15
-
16
20
pub trait PinClk { }
17
21
pub trait PinCmd { }
18
22
pub trait PinD0 { }
@@ -147,12 +151,8 @@ pub enum Error {
147
151
WrongResponseSize ,
148
152
}
149
153
150
- macro_rules! try_datapath {
151
- ( $sta: ident) => {
152
- if $sta. rxoverr( ) . bit( ) {
153
- return Err ( Error :: RxOverFlow ) ;
154
- }
155
-
154
+ macro_rules! datapath_err {
155
+ ( $sta: expr) => {
156
156
if $sta. dcrcfail( ) . bit( ) {
157
157
return Err ( Error :: DataCrcFail ) ;
158
158
}
@@ -163,6 +163,26 @@ macro_rules! try_datapath {
163
163
} ;
164
164
}
165
165
166
+ macro_rules! datapath_rx_err {
167
+ ( $sta: expr) => {
168
+ if $sta. rxoverr( ) . bit( ) {
169
+ return Err ( Error :: RxOverFlow ) ;
170
+ }
171
+
172
+ datapath_err!( $sta)
173
+ } ;
174
+ }
175
+
176
+ macro_rules! datapath_tx_err {
177
+ ( $sta: expr) => {
178
+ if $sta. rxoverr( ) . bit( ) {
179
+ return Err ( Error :: RxOverFlow ) ;
180
+ }
181
+
182
+ datapath_err!( $sta)
183
+ } ;
184
+ }
185
+
166
186
fn clear_all_interrupts ( icr : & sdmmc1:: ICR ) {
167
187
icr. modify ( |_, w| {
168
188
w. ccrcfailc ( )
@@ -385,7 +405,21 @@ impl Sdmmc {
385
405
Ok ( ( ) )
386
406
}
387
407
388
- pub fn read_block ( & mut self , addr : u32 , buf : & mut [ u8 ; 512 ] ) -> Result < ( ) , Error > {
408
+ #[ inline]
409
+ pub fn read_block < B : DerefMut < Target = [ u8 ; 512 ] > > (
410
+ & mut self ,
411
+ addr : u32 ,
412
+ block : B ,
413
+ ) -> Result < ( ) , Error > {
414
+ self . read_blocks ( addr, & mut [ block] )
415
+ }
416
+
417
+ #[ inline]
418
+ pub fn read_blocks < B : DerefMut < Target = [ u8 ; 512 ] > > (
419
+ & mut self ,
420
+ addr : u32 ,
421
+ blocks : & mut [ B ] ,
422
+ ) -> Result < ( ) , Error > {
389
423
let card = self . card ( ) ?;
390
424
391
425
let addr = match card. capacity ( ) {
@@ -395,17 +429,28 @@ impl Sdmmc {
395
429
396
430
self . cmd ( common_cmd:: set_block_length ( 512 ) ) ?;
397
431
398
- self . start_datapath_transfer ( 512 , 9 , Dir :: CardToHost ) ;
399
- self . cmd ( common_cmd:: read_single_block ( addr) ) ?;
432
+ let bytes = blocks. len ( ) * 512 ;
433
+ self . start_datapath_transfer ( bytes as u32 , 9 , Dir :: CardToHost ) ;
434
+
435
+ match blocks. len ( ) {
436
+ 0 => return Ok ( ( ) ) ,
437
+ 1 => self . cmd ( common_cmd:: read_single_block ( addr) ) ?,
438
+ _ => self . cmd ( common_cmd:: read_multiple_blocks ( addr) ) ?,
439
+ }
400
440
401
441
let mut i = 0 ;
402
442
loop {
403
443
match self . read_fifo_hf ( |bits| {
404
- buf[ i..( i + 4 ) ] . copy_from_slice ( & bits. to_be_bytes ( ) ) ;
444
+ let start = i % 512 ;
445
+ blocks[ i / 512 ] [ start..( start + 4 ) ] . copy_from_slice ( & bits. to_be_bytes ( ) ) ;
405
446
i += 4 ;
406
447
} ) ? {
407
448
ControlFlow :: Break ( ( ) ) => {
408
- if i == buf. len ( ) {
449
+ if blocks. len ( ) > 1 {
450
+ self . cmd ( common_cmd:: stop_transmission ( ) ) ?;
451
+ }
452
+
453
+ if i == bytes {
409
454
return Ok ( ( ) ) ;
410
455
} else {
411
456
return Err ( Error :: WrongResponseSize ) ;
@@ -416,60 +461,89 @@ impl Sdmmc {
416
461
}
417
462
}
418
463
419
- #[ inline]
420
- pub fn read_blocks ( & mut self , addr : u32 , buf : & mut [ u8 ] ) -> Result < ( ) , Error > {
421
- let card = self . card ( ) ?;
464
+ pub fn write_block < B : Deref < Target = [ u8 ; 512 ] > > (
465
+ & mut self ,
466
+ addr : u32 ,
467
+ block : B ,
468
+ ) -> Result < ( ) , Error > {
469
+ self . write_blocks ( addr, & [ block] )
470
+ }
422
471
423
- assert ! (
424
- buf. len( ) % 512 == 0 ,
425
- "Buffer length must be a multiple of 512."
426
- ) ;
472
+ fn write_blocks < B : Deref < Target = [ u8 ; 512 ] > > (
473
+ & mut self ,
474
+ addr : u32 ,
475
+ blocks : & [ B ] ,
476
+ ) -> Result < ( ) , Error > {
477
+ let card = self . card ( ) ?;
427
478
428
479
let addr = match card. capacity ( ) {
429
480
CardCapacity :: StandardCapacity => addr * 512 ,
430
481
_ => addr,
431
482
} ;
432
483
484
+ let bytes = blocks. len ( ) * 512 ;
433
485
self . cmd ( common_cmd:: set_block_length ( 512 ) ) ?;
486
+ self . start_datapath_transfer ( bytes as u32 , 9 , Dir :: HostToCard ) ;
434
487
435
- self . start_datapath_transfer ( buf. len ( ) as u32 , 9 , Dir :: CardToHost ) ;
436
- self . cmd ( common_cmd:: read_multiple_blocks ( addr) ) ?;
488
+ match blocks. len ( ) {
489
+ 0 => return Ok ( ( ) ) ,
490
+ 1 => self . cmd ( common_cmd:: write_single_block ( addr) ) ?,
491
+ _ => self . cmd ( common_cmd:: write_multiple_blocks ( addr) ) ?,
492
+ }
437
493
438
494
let mut i = 0 ;
439
495
loop {
440
- match self . read_fifo_hf ( |bits| {
441
- buf[ i..( i + 4 ) ] . copy_from_slice ( & bits. to_be_bytes ( ) ) ;
442
- i += 4 ;
443
- } ) ? {
444
- ControlFlow :: Break ( ( ) ) => {
445
- self . cmd ( common_cmd:: stop_transmission ( ) ) ?;
496
+ let sta = self . sdmmc . sta . read ( ) ;
446
497
447
- if i == buf. len ( ) {
448
- return Ok ( ( ) ) ;
449
- } else {
450
- return Err ( Error :: WrongResponseSize ) ;
498
+ datapath_tx_err ! ( sta) ;
499
+
500
+ if i == bytes {
501
+ // If we sent all data, wait for transfer to end.
502
+ if sta. dbckend ( ) . bit ( ) {
503
+ if blocks. len ( ) > 1 {
504
+ self . cmd ( common_cmd:: stop_transmission ( ) ) ?;
505
+ }
506
+
507
+ break ;
508
+ }
509
+ } else {
510
+ // If the FIFO is half-empty, send some data.
511
+ if sta. txfifohe ( ) . bit ( ) {
512
+ for _ in 0 ..8 {
513
+ let block = & blocks[ i / 512 ] ;
514
+ let start = i % 512 ;
515
+
516
+ let bits = u32:: from_be_bytes ( [
517
+ block[ start] ,
518
+ block[ start + 1 ] ,
519
+ block[ start + 2 ] ,
520
+ block[ start + 3 ] ,
521
+ ] ) ;
522
+ self . sdmmc . fifo . write ( |w| unsafe { w. bits ( bits. to_be ( ) ) } ) ;
523
+ i += 4 ;
451
524
}
452
525
}
453
- ControlFlow :: Continue ( ( ) ) => continue ,
454
526
}
455
527
}
456
- }
457
528
458
- pub fn write_block ( & mut self , addr : u32 , block : & [ u8 ; 512 ] ) -> Result < ( ) , Error > {
459
- self . card ( ) ?;
529
+ let timeout: u32 = 0xffff_ffff ;
530
+ for _ in 0 ..timeout {
531
+ if self . card_ready ( ) ? {
532
+ return Ok ( ( ) ) ;
533
+ }
534
+ }
460
535
461
- todo ! ( )
536
+ Err ( Error :: SoftwareTimeout )
462
537
}
463
538
464
539
/// Read eight 32-bit values from a half-full FIFO.
465
540
#[ inline]
466
541
fn read_fifo_hf ( & mut self , mut f : impl FnMut ( u32 ) -> ( ) ) -> Result < ControlFlow < ( ) , ( ) > , Error > {
467
- // TODO: Better timeout value.
468
542
let timeout: u32 = 0xffff_ffff ;
469
543
for _ in 0 ..timeout {
470
544
let sta = self . sdmmc . sta . read ( ) ;
471
545
472
- try_datapath ! ( sta) ;
546
+ datapath_rx_err ! ( sta) ;
473
547
474
548
if sta. dbckend ( ) . bit ( ) {
475
549
return Ok ( ControlFlow :: Break ( ( ) ) ) ;
@@ -556,26 +630,31 @@ impl Sdmmc {
556
630
557
631
let mut scr = [ 0 ; 2 ] ;
558
632
559
- ' outer: for n in scr. iter_mut ( ) . rev ( ) {
560
- loop {
561
- let sta = self . sdmmc . sta . read ( ) ;
633
+ let mut i = scr. len ( ) ;
562
634
563
- try_datapath ! ( sta) ;
635
+ let timeout: u32 = 0xffff_ffff ;
636
+ for _ in 0 ..timeout {
637
+ let sta = self . sdmmc . sta . read ( ) ;
564
638
565
- if sta. dataend ( ) . bit ( ) {
566
- break ' outer;
567
- }
639
+ datapath_rx_err ! ( sta) ;
568
640
641
+ if i == 0 {
642
+ if sta. dbckend ( ) . bit ( ) {
643
+ return Ok ( SCR :: from ( scr) ) ;
644
+ }
645
+ } else {
569
646
if sta. rxdavl ( ) . bit_is_set ( ) {
647
+ i -= 1 ;
648
+
570
649
let bits = u32:: from_be ( self . sdmmc . fifo . read ( ) . bits ( ) ) ;
571
- * n = bits. to_le ( ) ;
650
+ scr [ i ] = bits. to_le ( ) ;
572
651
573
- continue ' outer ;
652
+ continue ;
574
653
}
575
654
}
576
655
}
577
656
578
- return Ok ( SCR :: from ( scr ) ) ;
657
+ return Err ( Error :: SoftwareTimeout ) ;
579
658
}
580
659
581
660
pub fn power_card ( & mut self , on : bool ) {
@@ -719,6 +798,7 @@ pub struct SdmmcBlockDevice<SDMMC> {
719
798
sdmmc : core:: cell:: RefCell < SDMMC > ,
720
799
}
721
800
801
+ #[ cfg( feature = "embedded-sdmmc" ) ]
722
802
impl embedded_sdmmc:: BlockDevice for SdmmcBlockDevice < Sdmmc > {
723
803
type Error = Error ;
724
804
@@ -728,15 +808,8 @@ impl embedded_sdmmc::BlockDevice for SdmmcBlockDevice<Sdmmc> {
728
808
start_block_idx : embedded_sdmmc:: BlockIdx ,
729
809
_reason : & str ,
730
810
) -> Result < ( ) , Self :: Error > {
731
- let start = start_block_idx. 0 ;
732
811
let mut sdmmc = self . sdmmc . borrow_mut ( ) ;
733
- for block_idx in start..( start + blocks. len ( ) as u32 ) {
734
- sdmmc. read_block (
735
- block_idx,
736
- & mut blocks[ ( block_idx - start) as usize ] . contents ,
737
- ) ?;
738
- }
739
- Ok ( ( ) )
812
+ sdmmc. read_blocks ( start_block_idx. 0 , blocks)
740
813
}
741
814
742
815
fn write (
@@ -746,10 +819,7 @@ impl embedded_sdmmc::BlockDevice for SdmmcBlockDevice<Sdmmc> {
746
819
) -> Result < ( ) , Self :: Error > {
747
820
let start = start_block_idx. 0 ;
748
821
let mut sdmmc = self . sdmmc . borrow_mut ( ) ;
749
- for block_idx in start..( start + blocks. len ( ) as u32 ) {
750
- sdmmc. write_block ( block_idx, & blocks[ ( block_idx - start) as usize ] . contents ) ?;
751
- }
752
- Ok ( ( ) )
822
+ sdmmc. write_blocks ( start_block_idx. 0 , blocks)
753
823
}
754
824
755
825
fn num_blocks ( & self ) -> Result < embedded_sdmmc:: BlockCount , Self :: Error > {
0 commit comments