@@ -385,21 +385,21 @@ impl Sdmmc {
385385
386386 self . cmd ( common_cmd:: all_send_cid ( ) ) ?;
387387 card. cid = CID :: from ( [
388- self . sdmmc . resp4 . read ( ) . bits ( ) . to_le ( ) ,
389- self . sdmmc . resp3 . read ( ) . bits ( ) . to_le ( ) ,
390- self . sdmmc . resp2 . read ( ) . bits ( ) . to_le ( ) ,
391- self . sdmmc . resp1 . read ( ) . bits ( ) . to_le ( ) ,
388+ self . sdmmc . resp4 . read ( ) . bits ( ) . to_le ( ) ,
389+ self . sdmmc . resp3 . read ( ) . bits ( ) . to_le ( ) ,
390+ self . sdmmc . resp2 . read ( ) . bits ( ) . to_le ( ) ,
391+ self . sdmmc . resp1 . read ( ) . bits ( ) . to_le ( ) ,
392392 ] ) ;
393393
394394 self . cmd ( sd_cmd:: send_relative_address ( ) ) ?;
395395 card. rca = RCA :: from ( self . sdmmc . resp1 . read ( ) . bits ( ) . to_le ( ) ) ;
396396
397397 self . cmd ( common_cmd:: send_csd ( card. rca . address ( ) ) ) ?;
398398 card. csd = CSD :: from ( [
399- self . sdmmc . resp4 . read ( ) . bits ( ) . to_le ( ) ,
400- self . sdmmc . resp3 . read ( ) . bits ( ) . to_le ( ) ,
401- self . sdmmc . resp2 . read ( ) . bits ( ) . to_le ( ) ,
402- self . sdmmc . resp1 . read ( ) . bits ( ) . to_le ( ) ,
399+ self . sdmmc . resp4 . read ( ) . bits ( ) . to_le ( ) ,
400+ self . sdmmc . resp3 . read ( ) . bits ( ) . to_le ( ) ,
401+ self . sdmmc . resp2 . read ( ) . bits ( ) . to_le ( ) ,
402+ self . sdmmc . resp1 . read ( ) . bits ( ) . to_le ( ) ,
403403 ] ) ;
404404
405405 self . select_card ( card. rca . address ( ) ) ?;
@@ -838,3 +838,159 @@ impl embedded_sdmmc::BlockDevice for SdmmcBlockDevice<Sdmmc> {
838838 ) )
839839 }
840840}
841+
842+ #[ cfg( feature = "fatfs" ) ]
843+ use fatfs:: { IntoStorage , IoBase , IoError , Read , Seek , SeekFrom , Write } ;
844+
845+ impl IoError for Error {
846+ fn is_interrupted ( & self ) -> bool {
847+ false
848+ }
849+
850+ fn new_unexpected_eof_error ( ) -> Self {
851+ unimplemented ! ( )
852+ }
853+
854+ fn new_write_zero_error ( ) -> Self {
855+ unimplemented ! ( )
856+ }
857+ }
858+
859+ #[ derive( Debug ) ]
860+ pub struct FatFsCursor < SDMMC > {
861+ sdmmc : SDMMC ,
862+ pos : u64 ,
863+ partition_info : Option < ( u32 , u32 ) > ,
864+ }
865+
866+ impl FatFsCursor < Sdmmc > {
867+ pub fn new ( sdmmc : Sdmmc ) -> Self {
868+ Self {
869+ sdmmc,
870+ pos : 0 ,
871+ partition_info : None ,
872+ }
873+ }
874+
875+ pub fn partition_info ( & mut self ) -> Result < ( u32 , u32 ) , Error > {
876+ if let Some ( partition_info) = self . partition_info {
877+ return Ok ( partition_info) ;
878+ }
879+
880+ let mut block = [ 0 ; 512 ] ;
881+ self . sdmmc . read_block ( 0 , & mut block) ?;
882+
883+ // TODO: Support other partitions.
884+ let partition1_info = & block[ 446 ..] [ ..16 ] ;
885+ let lba_start = u32:: from_le_bytes ( [
886+ partition1_info[ 8 ] ,
887+ partition1_info[ 9 ] ,
888+ partition1_info[ 10 ] ,
889+ partition1_info[ 11 ] ,
890+ ] ) ;
891+
892+ let num_blocks = u32:: from_le_bytes ( [
893+ partition1_info[ 12 ] ,
894+ partition1_info[ 13 ] ,
895+ partition1_info[ 14 ] ,
896+ partition1_info[ 15 ] ,
897+ ] ) ;
898+
899+ Ok ( * self . partition_info . get_or_insert ( ( lba_start, num_blocks) ) )
900+ }
901+ }
902+
903+ #[ cfg( feature = "fatfs" ) ]
904+ impl IntoStorage < FatFsCursor < Sdmmc > > for Sdmmc {
905+ fn into_storage ( self ) -> FatFsCursor < Sdmmc > {
906+ FatFsCursor :: new ( self )
907+ }
908+ }
909+
910+ #[ cfg( feature = "fatfs" ) ]
911+ impl < SDMMC > IoBase for FatFsCursor < SDMMC > {
912+ type Error = fatfs:: Error < Error > ;
913+ }
914+
915+ #[ cfg( feature = "fatfs" ) ]
916+ impl Seek for FatFsCursor < Sdmmc > {
917+ fn seek ( & mut self , pos : SeekFrom ) -> Result < u64 , Self :: Error > {
918+ let itm = unsafe { & mut * cortex_m:: peripheral:: ITM :: PTR } ;
919+ // cortex_m::itm::write_fmt(&mut itm.stim[0], format_args!("Seek from {} to {:?}\n", self.pos, pos));
920+
921+ // TODO: Use `checked_add_signed` when stable.
922+ let new_pos = match pos {
923+ SeekFrom :: Start ( offset) => offset as i128 ,
924+ SeekFrom :: End ( offset) => {
925+ let end = self . partition_info ( ) ?. 1 * 512 ;
926+ end as i128 + offset as i128
927+ }
928+ SeekFrom :: Current ( offset) => self . pos as i128 + offset as i128 ,
929+ } ;
930+
931+ if new_pos < 0 || new_pos > u64:: MAX as i128 {
932+ // Seek to negative or overflowing position.
933+ return Err ( Self :: Error :: InvalidInput ) ;
934+ }
935+ let new_pos = new_pos as u64 ;
936+
937+ self . pos = new_pos;
938+ Ok ( self . pos )
939+ }
940+ }
941+
942+ #[ cfg( feature = "fatfs" ) ]
943+ impl Read for FatFsCursor < Sdmmc > {
944+ #[ track_caller]
945+ fn read ( & mut self , buf : & mut [ u8 ] ) -> Result < usize , Self :: Error > {
946+ let ( start, end) = self . partition_info ( ) ?;
947+
948+ let end = end as u64 * 512 ;
949+ let pos = self . pos . min ( end) ;
950+
951+ let addr = start + ( pos / 512 ) as u32 ;
952+ let offset = ( pos % 512 ) as usize ;
953+ let len = buf. len ( ) . min ( 512 - offset) ;
954+
955+ let mut block = [ 0 ; 512 ] ;
956+ self . sdmmc . read_block ( addr, & mut block) ?;
957+ buf[ 0 ..len] . copy_from_slice ( & block[ offset..( offset + len) ] ) ;
958+ self . pos += len as u64 ;
959+
960+ Ok ( len)
961+ }
962+
963+ // TODO: Add `read_exact` implementation which supports reading multiple blocks.
964+ }
965+
966+ #[ cfg( feature = "fatfs" ) ]
967+ impl Write for FatFsCursor < Sdmmc > {
968+ fn write ( & mut self , buf : & [ u8 ] ) -> Result < usize , Self :: Error > {
969+ let ( start, end) = self . partition_info ( ) ?;
970+
971+ let end = end as u64 * 512 ;
972+ let pos = self . pos ;
973+
974+ if pos + buf. len ( ) as u64 >= end {
975+ return Err ( Self :: Error :: NotEnoughSpace ) ;
976+ }
977+
978+ let addr = start + ( pos / 512 ) as u32 ;
979+ let offset = ( pos % 512 ) as usize ;
980+ let len = buf. len ( ) . min ( 512 - offset) ;
981+
982+ let mut block = [ 0 ; 512 ] ;
983+ self . sdmmc . read_block ( addr, & mut block) ?;
984+ block[ offset..( offset + len) ] . copy_from_slice ( & buf[ 0 ..len] ) ;
985+ self . sdmmc . write_block ( addr, & block) ?;
986+ self . pos += len as u64 ;
987+
988+ Ok ( len)
989+ }
990+
991+ // TODO: Add `write_exact` implementation which supports writing multiple blocks.
992+
993+ fn flush ( & mut self ) -> Result < ( ) , Self :: Error > {
994+ Ok ( ( ) )
995+ }
996+ }
0 commit comments