@@ -385,21 +385,21 @@ impl Sdmmc {
385
385
386
386
self . cmd ( common_cmd:: all_send_cid ( ) ) ?;
387
387
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 ( ) ,
392
392
] ) ;
393
393
394
394
self . cmd ( sd_cmd:: send_relative_address ( ) ) ?;
395
395
card. rca = RCA :: from ( self . sdmmc . resp1 . read ( ) . bits ( ) . to_le ( ) ) ;
396
396
397
397
self . cmd ( common_cmd:: send_csd ( card. rca . address ( ) ) ) ?;
398
398
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 ( ) ,
403
403
] ) ;
404
404
405
405
self . select_card ( card. rca . address ( ) ) ?;
@@ -838,3 +838,159 @@ impl embedded_sdmmc::BlockDevice for SdmmcBlockDevice<Sdmmc> {
838
838
) )
839
839
}
840
840
}
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