@@ -151,6 +151,8 @@ pub enum Error {
151
151
BadClock ,
152
152
/// Signaling switch failed.
153
153
SignalingSwitchFailed ,
154
+ /// Underrun error
155
+ Underrun ,
154
156
/// ST bit error.
155
157
#[ cfg( sdmmc_v1) ]
156
158
StBitErr ,
@@ -1025,6 +1027,9 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1025
1027
if status. dtimeout ( ) {
1026
1028
return Poll :: Ready ( Err ( Error :: Timeout ) ) ;
1027
1029
}
1030
+ if status. txunderr ( ) {
1031
+ return Poll :: Ready ( Err ( Error :: Underrun ) ) ;
1032
+ }
1028
1033
#[ cfg( sdmmc_v1) ]
1029
1034
if status. stbiterr ( ) {
1030
1035
return Poll :: Ready ( Err ( Error :: StBitErr ) ) ;
@@ -1080,6 +1085,73 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1080
1085
res
1081
1086
}
1082
1087
1088
+ /// Read multiple data blocks.
1089
+ #[ inline]
1090
+ pub async fn read_blocks ( & mut self , block_idx : u32 , blocks : & mut [ DataBlock ] ) -> Result < ( ) , Error > {
1091
+ let card_capacity = self . card ( ) ?. get_capacity ( ) ;
1092
+
1093
+ // NOTE(unsafe) reinterpret buffer as &mut [u32]
1094
+ let buffer = unsafe {
1095
+ let ptr = blocks. as_mut_ptr ( ) as * mut u32 ;
1096
+ let len = blocks. len ( ) * 128 ;
1097
+ core:: slice:: from_raw_parts_mut ( ptr, len)
1098
+ } ;
1099
+
1100
+ // Always read 1 block of 512 bytes
1101
+ // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
1102
+ let address = match card_capacity {
1103
+ CardCapacity :: StandardCapacity => block_idx * 512 ,
1104
+ _ => block_idx,
1105
+ } ;
1106
+ Self :: cmd ( common_cmd:: set_block_length ( 512 ) , false ) ?; // CMD16
1107
+
1108
+ let regs = T :: regs ( ) ;
1109
+ let on_drop = OnDrop :: new ( || Self :: on_drop ( ) ) ;
1110
+
1111
+ let transfer = Self :: prepare_datapath_read (
1112
+ & self . config ,
1113
+ #[ cfg( sdmmc_v1) ]
1114
+ & mut self . dma ,
1115
+ buffer,
1116
+ 512 * blocks. len ( ) as u32 ,
1117
+ 9 ,
1118
+ ) ;
1119
+ InterruptHandler :: < T > :: data_interrupts ( true ) ;
1120
+
1121
+ Self :: cmd ( common_cmd:: read_multiple_blocks ( address) , true ) ?;
1122
+
1123
+ let res = poll_fn ( |cx| {
1124
+ T :: state ( ) . register ( cx. waker ( ) ) ;
1125
+ let status = regs. star ( ) . read ( ) ;
1126
+
1127
+ if status. dcrcfail ( ) {
1128
+ return Poll :: Ready ( Err ( Error :: Crc ) ) ;
1129
+ }
1130
+ if status. dtimeout ( ) {
1131
+ return Poll :: Ready ( Err ( Error :: Timeout ) ) ;
1132
+ }
1133
+ #[ cfg( sdmmc_v1) ]
1134
+ if status. stbiterr ( ) {
1135
+ return Poll :: Ready ( Err ( Error :: StBitErr ) ) ;
1136
+ }
1137
+ if status. dataend ( ) {
1138
+ return Poll :: Ready ( Ok ( ( ) ) ) ;
1139
+ }
1140
+ Poll :: Pending
1141
+ } )
1142
+ . await ;
1143
+
1144
+ Self :: cmd ( common_cmd:: stop_transmission ( ) , false ) ?; // CMD12
1145
+ Self :: clear_interrupt_flags ( ) ;
1146
+
1147
+ if res. is_ok ( ) {
1148
+ on_drop. defuse ( ) ;
1149
+ Self :: stop_datapath ( ) ;
1150
+ drop ( transfer) ;
1151
+ }
1152
+ res
1153
+ }
1154
+
1083
1155
/// Write a data block.
1084
1156
pub async fn write_block ( & mut self , block_idx : u32 , buffer : & DataBlock ) -> Result < ( ) , Error > {
1085
1157
let card = self . card . as_mut ( ) . ok_or ( Error :: NoCard ) ?;
@@ -1088,7 +1160,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1088
1160
let buffer = unsafe { & * ( ( & buffer. 0 ) as * const [ u8 ; 512 ] as * const [ u32 ; 128 ] ) } ;
1089
1161
1090
1162
// Always read 1 block of 512 bytes
1091
- // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
1163
+ // cards are byte addressed hence the blockaddress is in multiples of 512 bytes
1092
1164
let address = match card. get_capacity ( ) {
1093
1165
CardCapacity :: StandardCapacity => block_idx * 512 ,
1094
1166
_ => block_idx,
@@ -1136,6 +1208,94 @@ impl<'d, T: Instance> Sdmmc<'d, T> {
1136
1208
}
1137
1209
}
1138
1210
1211
+ /// Write multiple data blocks.
1212
+ pub async fn write_blocks ( & mut self , block_idx : u32 , blocks : & [ DataBlock ] ) -> Result < ( ) , Error > {
1213
+ let card = self . card . as_mut ( ) . ok_or ( Error :: NoCard ) ?;
1214
+
1215
+ // NOTE(unsafe) reinterpret buffer as &[u32]
1216
+ let buffer = unsafe {
1217
+ let ptr = blocks. as_ptr ( ) as * const u32 ;
1218
+ let len = blocks. len ( ) * 128 ;
1219
+ core:: slice:: from_raw_parts ( ptr, len)
1220
+ } ;
1221
+
1222
+ // Always read 1 block of 512 bytes
1223
+ // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
1224
+ let address = match card. get_capacity ( ) {
1225
+ CardCapacity :: StandardCapacity => block_idx * 512 ,
1226
+ _ => block_idx,
1227
+ } ;
1228
+
1229
+ Self :: cmd ( common_cmd:: set_block_length ( 512 ) , false ) ?; // CMD16
1230
+
1231
+ let block_count = blocks. len ( ) ;
1232
+
1233
+ let regs = T :: regs ( ) ;
1234
+ let on_drop = OnDrop :: new ( || Self :: on_drop ( ) ) ;
1235
+
1236
+ #[ cfg( sdmmc_v1) ]
1237
+ Self :: cmd ( common_cmd:: write_multiple_blocks ( address) , true ) ?; // CMD25
1238
+
1239
+ // Setup write command
1240
+ let transfer = self . prepare_datapath_write ( buffer, 512 * block_count as u32 , 9 ) ;
1241
+ InterruptHandler :: < T > :: data_interrupts ( true ) ;
1242
+
1243
+ #[ cfg( sdmmc_v2) ]
1244
+ Self :: cmd ( common_cmd:: write_multiple_blocks ( address) , true ) ?; // CMD25
1245
+
1246
+ let res = poll_fn ( |cx| {
1247
+ T :: state ( ) . register ( cx. waker ( ) ) ;
1248
+
1249
+ let status = regs. star ( ) . read ( ) ;
1250
+
1251
+ if status. dcrcfail ( ) {
1252
+ return Poll :: Ready ( Err ( Error :: Crc ) ) ;
1253
+ }
1254
+ if status. dtimeout ( ) {
1255
+ return Poll :: Ready ( Err ( Error :: Timeout ) ) ;
1256
+ }
1257
+ if status. txunderr ( ) {
1258
+ return Poll :: Ready ( Err ( Error :: Underrun ) ) ;
1259
+ }
1260
+ #[ cfg( sdmmc_v1) ]
1261
+ if status. stbiterr ( ) {
1262
+ return Poll :: Ready ( Err ( Error :: StBitErr ) ) ;
1263
+ }
1264
+ if status. dataend ( ) {
1265
+ return Poll :: Ready ( Ok ( ( ) ) ) ;
1266
+ }
1267
+
1268
+ Poll :: Pending
1269
+ } )
1270
+ . await ;
1271
+
1272
+ Self :: cmd ( common_cmd:: stop_transmission ( ) , false ) ?; // CMD12
1273
+ Self :: clear_interrupt_flags ( ) ;
1274
+
1275
+ match res {
1276
+ Ok ( _) => {
1277
+ on_drop. defuse ( ) ;
1278
+ Self :: stop_datapath ( ) ;
1279
+ drop ( transfer) ;
1280
+
1281
+ // TODO: Make this configurable
1282
+ let mut timeout: u32 = 0x00FF_FFFF ;
1283
+
1284
+ // Try to read card status (ACMD13)
1285
+ while timeout > 0 {
1286
+ match self . read_sd_status ( ) . await {
1287
+ Ok ( _) => return Ok ( ( ) ) ,
1288
+ Err ( Error :: Timeout ) => ( ) , // Try again
1289
+ Err ( e) => return Err ( e) ,
1290
+ }
1291
+ timeout -= 1 ;
1292
+ }
1293
+ Err ( Error :: SoftwareTimeout )
1294
+ }
1295
+ Err ( e) => Err ( e) ,
1296
+ }
1297
+ }
1298
+
1139
1299
/// Get a reference to the initialized card
1140
1300
///
1141
1301
/// # Errors
@@ -1699,33 +1859,35 @@ impl<'d, T: Instance> block_device_driver::BlockDevice<512> for Sdmmc<'d, T> {
1699
1859
1700
1860
async fn read (
1701
1861
& mut self ,
1702
- mut block_address : u32 ,
1862
+ block_address : u32 ,
1703
1863
buf : & mut [ aligned:: Aligned < Self :: Align , [ u8 ; 512 ] > ] ,
1704
1864
) -> Result < ( ) , Self :: Error > {
1705
- // FIXME/TODO because of missing read_blocks multiple we have to do this one block at a time
1706
- for block in buf. iter_mut ( ) {
1707
- // safety aligned by block device
1708
- let block = unsafe { & mut * ( block as * mut _ as * mut crate :: sdmmc:: DataBlock ) } ;
1865
+ // TODO: I think block_address needs to be adjusted by the partition start offset
1866
+ if buf. len ( ) == 1 {
1867
+ let block = unsafe { & mut * ( & mut buf[ 0 ] as * mut _ as * mut crate :: sdmmc:: DataBlock ) } ;
1709
1868
self . read_block ( block_address, block) . await ?;
1710
- block_address += 1 ;
1869
+ } else {
1870
+ let blocks: & mut [ DataBlock ] =
1871
+ unsafe { core:: slice:: from_raw_parts_mut ( buf. as_mut_ptr ( ) as * mut DataBlock , buf. len ( ) ) } ;
1872
+ self . read_blocks ( block_address, blocks) . await ?;
1711
1873
}
1712
-
1713
1874
Ok ( ( ) )
1714
1875
}
1715
1876
1716
1877
async fn write (
1717
1878
& mut self ,
1718
- mut block_address : u32 ,
1879
+ block_address : u32 ,
1719
1880
buf : & [ aligned:: Aligned < Self :: Align , [ u8 ; 512 ] > ] ,
1720
1881
) -> Result < ( ) , Self :: Error > {
1721
- // FIXME/TODO because of missing read_blocks multiple we have to do this one block at a time
1722
- for block in buf. iter ( ) {
1723
- // safety aligned by block device
1724
- let block = unsafe { & * ( block as * const _ as * const crate :: sdmmc:: DataBlock ) } ;
1882
+ // TODO: I think block_address needs to be adjusted by the partition start offset
1883
+ if buf. len ( ) == 1 {
1884
+ let block = unsafe { & * ( & buf[ 0 ] as * const _ as * const crate :: sdmmc:: DataBlock ) } ;
1725
1885
self . write_block ( block_address, block) . await ?;
1726
- block_address += 1 ;
1886
+ } else {
1887
+ let blocks: & [ DataBlock ] =
1888
+ unsafe { core:: slice:: from_raw_parts ( buf. as_ptr ( ) as * const DataBlock , buf. len ( ) ) } ;
1889
+ self . write_blocks ( block_address, blocks) . await ?;
1727
1890
}
1728
-
1729
1891
Ok ( ( ) )
1730
1892
}
1731
1893
0 commit comments