1- use core:: { fmt, ops:: ControlFlow } ;
1+ #![ cfg( feature = "sdmmc" ) ]
2+
3+ use core:: {
4+ fmt,
5+ ops:: { ControlFlow , Deref , DerefMut } ,
6+ } ;
27
38use fugit:: HertzU32 as Hertz ;
49use sdio_host:: {
@@ -12,7 +17,6 @@ use crate::{
1217 pac:: { sdmmc1, SDMMC1 } ,
1318 rcc:: { Clocks , Enable , Reset , APB2 } ,
1419} ;
15-
1620pub trait PinClk { }
1721pub trait PinCmd { }
1822pub trait PinD0 { }
@@ -147,12 +151,8 @@ pub enum Error {
147151 WrongResponseSize ,
148152}
149153
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) => {
156156 if $sta. dcrcfail( ) . bit( ) {
157157 return Err ( Error :: DataCrcFail ) ;
158158 }
@@ -163,6 +163,26 @@ macro_rules! try_datapath {
163163 } ;
164164}
165165
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+
166186fn clear_all_interrupts ( icr : & sdmmc1:: ICR ) {
167187 icr. modify ( |_, w| {
168188 w. ccrcfailc ( )
@@ -385,7 +405,21 @@ impl Sdmmc {
385405 Ok ( ( ) )
386406 }
387407
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 > {
389423 let card = self . card ( ) ?;
390424
391425 let addr = match card. capacity ( ) {
@@ -395,17 +429,28 @@ impl Sdmmc {
395429
396430 self . cmd ( common_cmd:: set_block_length ( 512 ) ) ?;
397431
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+ }
400440
401441 let mut i = 0 ;
402442 loop {
403443 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 ( ) ) ;
405446 i += 4 ;
406447 } ) ? {
407448 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 {
409454 return Ok ( ( ) ) ;
410455 } else {
411456 return Err ( Error :: WrongResponseSize ) ;
@@ -416,60 +461,89 @@ impl Sdmmc {
416461 }
417462 }
418463
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+ }
422471
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 ( ) ?;
427478
428479 let addr = match card. capacity ( ) {
429480 CardCapacity :: StandardCapacity => addr * 512 ,
430481 _ => addr,
431482 } ;
432483
484+ let bytes = blocks. len ( ) * 512 ;
433485 self . cmd ( common_cmd:: set_block_length ( 512 ) ) ?;
486+ self . start_datapath_transfer ( bytes as u32 , 9 , Dir :: HostToCard ) ;
434487
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+ }
437493
438494 let mut i = 0 ;
439495 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 ( ) ;
446497
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 ;
451524 }
452525 }
453- ControlFlow :: Continue ( ( ) ) => continue ,
454526 }
455527 }
456- }
457528
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+ }
460535
461- todo ! ( )
536+ Err ( Error :: SoftwareTimeout )
462537 }
463538
464539 /// Read eight 32-bit values from a half-full FIFO.
465540 #[ inline]
466541 fn read_fifo_hf ( & mut self , mut f : impl FnMut ( u32 ) -> ( ) ) -> Result < ControlFlow < ( ) , ( ) > , Error > {
467- // TODO: Better timeout value.
468542 let timeout: u32 = 0xffff_ffff ;
469543 for _ in 0 ..timeout {
470544 let sta = self . sdmmc . sta . read ( ) ;
471545
472- try_datapath ! ( sta) ;
546+ datapath_rx_err ! ( sta) ;
473547
474548 if sta. dbckend ( ) . bit ( ) {
475549 return Ok ( ControlFlow :: Break ( ( ) ) ) ;
@@ -556,26 +630,31 @@ impl Sdmmc {
556630
557631 let mut scr = [ 0 ; 2 ] ;
558632
559- ' outer: for n in scr. iter_mut ( ) . rev ( ) {
560- loop {
561- let sta = self . sdmmc . sta . read ( ) ;
633+ let mut i = scr. len ( ) ;
562634
563- try_datapath ! ( sta) ;
635+ let timeout: u32 = 0xffff_ffff ;
636+ for _ in 0 ..timeout {
637+ let sta = self . sdmmc . sta . read ( ) ;
564638
565- if sta. dataend ( ) . bit ( ) {
566- break ' outer;
567- }
639+ datapath_rx_err ! ( sta) ;
568640
641+ if i == 0 {
642+ if sta. dbckend ( ) . bit ( ) {
643+ return Ok ( SCR :: from ( scr) ) ;
644+ }
645+ } else {
569646 if sta. rxdavl ( ) . bit_is_set ( ) {
647+ i -= 1 ;
648+
570649 let bits = u32:: from_be ( self . sdmmc . fifo . read ( ) . bits ( ) ) ;
571- * n = bits. to_le ( ) ;
650+ scr [ i ] = bits. to_le ( ) ;
572651
573- continue ' outer ;
652+ continue ;
574653 }
575654 }
576655 }
577656
578- return Ok ( SCR :: from ( scr ) ) ;
657+ return Err ( Error :: SoftwareTimeout ) ;
579658 }
580659
581660 pub fn power_card ( & mut self , on : bool ) {
@@ -719,6 +798,7 @@ pub struct SdmmcBlockDevice<SDMMC> {
719798 sdmmc : core:: cell:: RefCell < SDMMC > ,
720799}
721800
801+ #[ cfg( feature = "embedded-sdmmc" ) ]
722802impl embedded_sdmmc:: BlockDevice for SdmmcBlockDevice < Sdmmc > {
723803 type Error = Error ;
724804
@@ -728,15 +808,8 @@ impl embedded_sdmmc::BlockDevice for SdmmcBlockDevice<Sdmmc> {
728808 start_block_idx : embedded_sdmmc:: BlockIdx ,
729809 _reason : & str ,
730810 ) -> Result < ( ) , Self :: Error > {
731- let start = start_block_idx. 0 ;
732811 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)
740813 }
741814
742815 fn write (
@@ -746,10 +819,7 @@ impl embedded_sdmmc::BlockDevice for SdmmcBlockDevice<Sdmmc> {
746819 ) -> Result < ( ) , Self :: Error > {
747820 let start = start_block_idx. 0 ;
748821 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)
753823 }
754824
755825 fn num_blocks ( & self ) -> Result < embedded_sdmmc:: BlockCount , Self :: Error > {
0 commit comments