Skip to content

Commit 6e2babc

Browse files
committed
Add support for SD card command READ_MULTIPLE_BLOCK
1 parent 1e07a40 commit 6e2babc

File tree

1 file changed

+58
-19
lines changed

1 file changed

+58
-19
lines changed

src/sdcard.c

Lines changed: 58 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ static uint8_t last_cmd;
5252
static bool is_acmd = false;
5353
static bool is_idle = true;
5454
static bool is_initialized = false;
55+
static bool ongoing_multiblock_read = false;
5556

5657
static const uint8_t *response = NULL;
5758
static int response_length = 0;
@@ -188,6 +189,29 @@ set_response_r7(void)
188189
response_length = sizeof(r7);
189190
}
190191

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+
191215
uint8_t
192216
sdcard_handle(uint8_t inbyte)
193217
{
@@ -203,7 +227,21 @@ sdcard_handle(uint8_t inbyte)
203227
if (response) {
204228
outbyte = response[response_counter++];
205229
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+
}
207245
}
208246
}
209247

@@ -259,6 +297,13 @@ sdcard_handle(uint8_t inbyte)
259297
break;
260298
}
261299

300+
case CMD12: {
301+
// STOP_TRANSMISSION: Abort ongoing multiple block read
302+
ongoing_multiblock_read = false;
303+
set_response_r1();
304+
break;
305+
}
306+
262307
case CMD13: {
263308
// SEND_STATUS: Asks the selected card to send its status register
264309
set_response_r2();
@@ -269,28 +314,22 @@ sdcard_handle(uint8_t inbyte)
269314
set_response_r1();
270315
break;
271316
}
317+
case CMD18: {
318+
// READ_MULTIPLE_BLOCK
319+
ongoing_multiblock_read = true;
320+
// Fallthrough
321+
}
272322
case CMD17: {
273323
// 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];
275325
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;
293331
}
332+
response = read_block_response;
294333
break;
295334
}
296335

0 commit comments

Comments
 (0)