From 2523670f8b1c11850e45e26f65b68c2d7fecf639 Mon Sep 17 00:00:00 2001 From: Ben Wynn Date: Sat, 15 Nov 2025 12:12:09 -0500 Subject: [PATCH] sdcard: Adding tests for csd parsing. Signed-off-by: Ben Wynn --- micropython/drivers/storage/sdcard/sdcard.py | 21 ++++++---- micropython/drivers/storage/sdcard/sdtest.py | 44 ++++++++++++++++++++ 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/micropython/drivers/storage/sdcard/sdcard.py b/micropython/drivers/storage/sdcard/sdcard.py index 3df4788a2..01a249b24 100644 --- a/micropython/drivers/storage/sdcard/sdcard.py +++ b/micropython/drivers/storage/sdcard/sdcard.py @@ -92,10 +92,23 @@ def init_card(self, baudrate): # get the number of sectors # CMD9: response R2 (R1 byte + 16-byte block read) + csd = self.get_csd() + self.parse_csd(csd) + + # CMD16: set block length to 512 bytes + if self.cmd(16, 512, 0) != 0: + raise OSError("can't set 512 block size") + + # set to high data rate now that it's initialised + self.init_spi(baudrate) + + def get_csd(self): if self.cmd(9, 0, 0, 0, False) != 0: raise OSError("no response from SD card") csd = bytearray(16) self.readinto(csd) + + def parse_csd(self, csd): if csd[0] & 0xC0 == 0x40: # CSD version 2.0 self.sectors = ((csd[7] << 16 | csd[8] << 8 | csd[9]) + 1) * 1024 elif csd[0] & 0xC0 == 0x00: # CSD version 1.0 (old, <=2GB) @@ -106,14 +119,6 @@ def init_card(self, baudrate): self.sectors = capacity // 512 else: raise OSError("SD card CSD format not supported") - # print('sectors', self.sectors) - - # CMD16: set block length to 512 bytes - if self.cmd(16, 512, 0) != 0: - raise OSError("can't set 512 block size") - - # set to high data rate now that it's initialised - self.init_spi(baudrate) def init_card_v1(self): for i in range(_CMD_TIMEOUT): diff --git a/micropython/drivers/storage/sdcard/sdtest.py b/micropython/drivers/storage/sdcard/sdtest.py index ce700e2a8..50d6b2c41 100644 --- a/micropython/drivers/storage/sdcard/sdtest.py +++ b/micropython/drivers/storage/sdcard/sdtest.py @@ -6,6 +6,7 @@ def sdtest(): + """this test requires specific hardware, so is not run by CI""" spi = machine.SPI(1) spi.init() # Ensure right baudrate sd = sdcard.SDCard(spi, machine.Pin.board.X21) # Compatible with PCB @@ -61,3 +62,46 @@ def sdtest(): success = False print() print("Tests", "passed" if success else "failed") + + +class MockSDCard(sdcard.SDCard): + """instantiates a sdcard object without talking to hardware""" + + def __init__(self, spi, cs, baudrate=100_000): + super().__init__(spi, cs, baudrate=baudrate) + + def init_card(self, baudrate): + """yeah, this is where we're just going to skip the whole hardware initalization thing""" + self.baudrate = baudrate + + +def test_parse_csd(mockSD): + """test the parse_csd function""" + csd_tests = [ + { + "name": "64g card", + "sectors": 122191872, + "csd": bytearray(b"@\x0e\x002[Y\x00\x01\xd2\x1f\x7f\x80\n@\x00S"), + }, + { + "name": "128g card", + "sectors": 244277248, + "csd": bytearray(b"@\x0e\x002[Y\x00\x03\xa3\xd7\x7f\x80\n@\x00A"), + }, + ] + + for test in csd_tests: + mockSD.parse_csd(test["csd"]) + sectors = mockSD.ioctl(4, None) + assert sectors == test["sectors"], "Failed to parse csd for test {}, {} != {}".format( + test["name"], sectors, test["sectors"] + ) + + +def run_tests(): + mockSD = MockSDCard(None, None) + test_parse_csd(mockSD) + print("OK") + + +run_tests()