sd: Fix SDSC card support
All checks were successful
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m18s
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Successful in 9s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 4s
Run unit tests on host / Run-Unit-Tests (push) Successful in 7s
Run pytests / Check-Pytest (push) Successful in 10s

- Old SDSC cards could have a native blocksize != 512 bytes, but they
  should support the SET_BLOCKLEN command to set the blocksize to 512.
  Use that so we can just assume 512 everywhere else.

- SDSC cards used byte addresses, not sector numbers, for the argument
  of READ_BLOCK and WRITE_BLOCK. Check the card type and multiply the
  sector number with 512 if necessary.

Tested with a noname chinese 128 MiB-ish card.

Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
This commit is contained in:
2025-09-07 15:50:27 +02:00
parent e33fefc552
commit d39157ba0a
2 changed files with 41 additions and 3 deletions

View File

@@ -74,6 +74,7 @@ static bool sd_send_op_cond(void)
#ifdef SD_DEBUG
printf("sd_init: card does not understand ACMD41, try CMD1...\n");
#endif
use_acmd = false;
continue;
} else if (buf != 0x01) {
printf("sd_init: send_op_cond failed\n");
@@ -174,6 +175,7 @@ static bool sd_read_csd(struct sd_context *sd_context)
}
}
sd_context->blocks = blocks;
sd_context->blocksize = blocksize;
#ifdef SD_DEBUG
printf("CSD version %u.0, blocksize %u, blocks %u, capacity %llu MiB\n", version, blocksize, blocks,
((uint64_t)blocksize * blocks) / (1024 * 1024));
@@ -225,6 +227,26 @@ bool sd_init(struct sd_context *sd_context, int mosi, int miso, int sck, int ss,
return false;
}
if (sd_context->blocksize != SD_SECTOR_SIZE) {
if (sd_context->blocksize != 1024 && sd_context->blocksize != 2048) {
printf("sd_init: Unsupported block size %u\n", sd_context->blocksize);
return false;
}
// Attempt SET_BLOCKLEN command
uint8_t resp[1];
if (!sd_cmd(16, SD_SECTOR_SIZE, 1, resp)) {
printf("sd_init: SET_BLOCKLEN failed\n");
return false;
}
// Successfully set blocksize to SD_SECTOR_SIZE, adjust context
sd_context->blocks *= sd_context->blocksize / SD_SECTOR_SIZE;
#ifdef SD_DEBUG
printf("Adjusted blocksize from %u to 512, card now has %u blocks\n", sd_context->blocksize,
sd_context->blocks);
#endif
sd_context->blocksize = SD_SECTOR_SIZE;
}
#ifdef SD_DEBUG
sd_dump_cid();
#endif
@@ -246,14 +268,24 @@ bool sd_readblock(struct sd_context *sd_context, size_t sector_num, uint8_t buff
if (!sd_context->initialized || sector_num >= sd_context->blocks)
return false;
return sd_cmd_read(17, sector_num, SD_SECTOR_SIZE, buffer);
uint32_t addr = sector_num;
if (!sd_context->sdhc_sdxc) {
// SDSC cards used byte addressing
addr *= SD_SECTOR_SIZE;
}
return sd_cmd_read(17, addr, SD_SECTOR_SIZE, buffer);
}
bool sd_readblock_start(struct sd_context *sd_context, size_t sector_num, uint8_t buffer[static SD_SECTOR_SIZE])
{
if (!sd_context->initialized || sector_num >= sd_context->blocks)
return false;
return sd_cmd_read_start(17, sector_num, SD_SECTOR_SIZE, buffer);
uint32_t addr = sector_num;
if (!sd_context->sdhc_sdxc) {
// SDSC cards used byte addressing
addr *= SD_SECTOR_SIZE;
}
return sd_cmd_read_start(17, addr, SD_SECTOR_SIZE, buffer);
}
bool sd_readblock_complete(struct sd_context *sd_context)
@@ -271,5 +303,10 @@ bool sd_writeblock(struct sd_context *sd_context, size_t sector_num, uint8_t buf
if (!sd_context->initialized || sector_num >= sd_context->blocks)
return false;
return sd_cmd_write(24, sector_num, SD_SECTOR_SIZE, buffer);
uint32_t addr = sector_num;
if (!sd_context->sdhc_sdxc) {
// SDSC cards used byte addressing
addr *= SD_SECTOR_SIZE;
}
return sd_cmd_write(24, addr, SD_SECTOR_SIZE, buffer);
}

View File

@@ -8,6 +8,7 @@
struct sd_context {
size_t blocks;
size_t blocksize;
bool initialized;
bool old_card;
bool sdhc_sdxc;