@@ -52,6 +52,7 @@ static uint8_t last_cmd;
52
52
static bool is_acmd = false;
53
53
static bool is_idle = true;
54
54
static bool is_initialized = false;
55
+ static bool ongoing_multiblock_read = false;
55
56
56
57
static const uint8_t * response = NULL ;
57
58
static int response_length = 0 ;
@@ -188,6 +189,29 @@ set_response_r7(void)
188
189
response_length = sizeof (r7 );
189
190
}
190
191
192
+ // Return length of reply
193
+ static int loadBlock (uint8_t * dest )
194
+ {
195
+ int response_length = 0 ;
196
+
197
+ dest [0 ] = 0xFE ; // Data token for CMD17/18
198
+ #ifdef VERBOSE
199
+ printf ("*** SD Reading LBA %d\n" , lba );
200
+ #endif
201
+ if ((Sint64 )lba * 512 >= x16size (sdcard_file )) {
202
+ dest [0 ] = 0x08 ; // Error token: out of range
203
+ response_length = 1 ;
204
+ } else {
205
+ x16seek (sdcard_file , (Sint64 )lba * 512 , XSEEK_SET );
206
+ int bytes_read = x16read (sdcard_file , & dest [1 ], 1 , 512 );
207
+ if (bytes_read != 512 ) {
208
+ printf ("Warning: short read!\n" );
209
+ }
210
+ response_length = 1 + 512 + 2 ;
211
+ }
212
+ return response_length ;
213
+ }
214
+
191
215
uint8_t
192
216
sdcard_handle (uint8_t inbyte )
193
217
{
@@ -203,7 +227,21 @@ sdcard_handle(uint8_t inbyte)
203
227
if (response ) {
204
228
outbyte = response [response_counter ++ ];
205
229
if (response_counter == response_length ) {
206
- response = NULL ;
230
+ if (ongoing_multiblock_read ) {
231
+ static uint8_t read_multiblock_next_response [1 + 512 + 2 ];
232
+ // Prepare next multiblock reply
233
+ lba ++ ;
234
+ response_length = loadBlock (& read_multiblock_next_response [0 ]);
235
+ // Stop multiblock read if error
236
+ if (response_length == 1 ) {
237
+ ongoing_multiblock_read = false;
238
+ }
239
+ response = read_multiblock_next_response ;
240
+ response_counter = 0 ;
241
+ } else {
242
+ response = NULL ;
243
+ ongoing_multiblock_read = false;
244
+ }
207
245
}
208
246
}
209
247
@@ -259,6 +297,13 @@ sdcard_handle(uint8_t inbyte)
259
297
break ;
260
298
}
261
299
300
+ case CMD12 : {
301
+ // STOP_TRANSMISSION: Abort ongoing multiple block read
302
+ ongoing_multiblock_read = false;
303
+ set_response_r1 ();
304
+ break ;
305
+ }
306
+
262
307
case CMD13 : {
263
308
// SEND_STATUS: Asks the selected card to send its status register
264
309
set_response_r2 ();
@@ -269,28 +314,22 @@ sdcard_handle(uint8_t inbyte)
269
314
set_response_r1 ();
270
315
break ;
271
316
}
317
+ case CMD18 : {
318
+ // READ_MULTIPLE_BLOCK
319
+ ongoing_multiblock_read = true;
320
+ // Fallthrough
321
+ }
272
322
case CMD17 : {
273
323
// READ_SINGLE_BLOCK
274
- uint32_t lba = (rxbuf [1 ] << 24 ) | (rxbuf [2 ] << 16 ) | (rxbuf [3 ] << 8 ) | rxbuf [4 ];
324
+ lba = (rxbuf [1 ] << 24 ) | (rxbuf [2 ] << 16 ) | (rxbuf [3 ] << 8 ) | rxbuf [4 ];
275
325
static uint8_t read_block_response [2 + 512 + 2 ];
276
- read_block_response [0 ] = 0 ;
277
- read_block_response [1 ] = 0xFE ;
278
- #ifdef VERBOSE
279
- printf ("*** SD Reading LBA %d\n" , lba );
280
- #endif
281
- if ((Sint64 )lba * 512 >= x16size (sdcard_file )) {
282
- read_block_response [1 ] = 0x08 ; // out of range
283
- response_length = 2 ;
284
- } else {
285
- x16seek (sdcard_file , (Sint64 )lba * 512 , XSEEK_SET );
286
- int bytes_read = x16read (sdcard_file , & read_block_response [2 ], 1 , 512 );
287
- if (bytes_read != 512 ) {
288
- printf ("Warning: short read!\n" );
289
- }
290
-
291
- response = read_block_response ;
292
- response_length = 2 + 512 + 2 ;
326
+ read_block_response [0 ] = 0 ; // R1 response to command
327
+ response_length = 1 + loadBlock (& read_block_response [1 ]);
328
+ // Stop multiblock read if error
329
+ if (response_length == 2 ) {
330
+ ongoing_multiblock_read = false;
293
331
}
332
+ response = read_block_response ;
294
333
break ;
295
334
}
296
335
0 commit comments