From 2e604d157e91fa29ef33e1836a83fb41bb89eb10 Mon Sep 17 00:00:00 2001 From: sdomi Date: Tue, 21 Oct 2025 18:24:43 +0200 Subject: [PATCH 1/6] Improve sdmmc rcvr_datablock busy loop, for a slight perf increase --- ui/lib/sdmmc/sdmmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/lib/sdmmc/sdmmc.c b/ui/lib/sdmmc/sdmmc.c index 7d02d66..8379cb0 100644 --- a/ui/lib/sdmmc/sdmmc.c +++ b/ui/lib/sdmmc/sdmmc.c @@ -176,11 +176,11 @@ static int rcvr_datablock( /* 1:OK, 0:Failed */ { uint8_t d[2]; - for (int tmr = 1000; tmr; tmr--) + for (int tmr = 10000; tmr; tmr--) { /* Wait for data packet in timeout of 100ms */ rcvr_mmc(d, 1); if (d[0] != 0xFF) break; - sleep_us(100); + sleep_us(10); } if (d[0] != 0xFE) return 0; /* If not valid data token, return with error */ From 7511c38672b22d9efb02a5b1dfd62b2f7a514914 Mon Sep 17 00:00:00 2001 From: sdomi Date: Tue, 21 Oct 2025 19:47:10 +0200 Subject: [PATCH 2/6] Remove dead functions from the MMC driver MMC_sync was especially dangerous, as some cards don't like being selected and immediately deselected w/o any transmitted data. ref: https://dmitry.gr/?r=05.Projects&proj=36.%208pinLinux#_TOC_e23710bba70063c2e153d50ddbe4a51c --- ui/lib/sdmmc/sdmmc.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/ui/lib/sdmmc/sdmmc.c b/ui/lib/sdmmc/sdmmc.c index 8379cb0..c331697 100644 --- a/ui/lib/sdmmc/sdmmc.c +++ b/ui/lib/sdmmc/sdmmc.c @@ -429,21 +429,6 @@ bool MMC_disk_write(const uint8_t *buff, /* Pointer to the data to be written */ /* Miscellaneous Functions */ /*-----------------------------------------------------------------------*/ -bool MMC_sync(void) -{ - bool res; - - if (!MMC_disk_ready()) return false; - - res = select(); - - deselect(); - - return res; -} - -uint32_t MMC_get_block_size(void) { return 128; } - int32_t MMC_get_sector_count(void) { uint8_t n, csd[16]; From ad8fa9d3cbd8a77fb3c5812d173ced9a6c3c8edb Mon Sep 17 00:00:00 2001 From: sdomi Date: Tue, 21 Oct 2025 19:51:07 +0200 Subject: [PATCH 3/6] Correct the initial SPI clock speed from 300 to 400KHz As per Part 1 of the SD Spec, the initial clock can be anything from 100 to 400KHz. Setting it to 400KHz may slightly improve the bootup time, and there are no downsides. --- ui/lib/sdmmc/sdmmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/lib/sdmmc/sdmmc.c b/ui/lib/sdmmc/sdmmc.c index c331697..2194417 100644 --- a/ui/lib/sdmmc/sdmmc.c +++ b/ui/lib/sdmmc/sdmmc.c @@ -48,7 +48,7 @@ #define SD_SPI_SCK 18 #define SD_SPI_MOSI 19 -#define SD_SPI_BAUDRATE_INIT (300 * 1000) +#define SD_SPI_BAUDRATE_INIT (400 * 1000) #define SD_SPI_BAUDRATE (20 * 1000 * 1000) #define CS_H() gpio_put(SD_SPI_CS, 1) /* Set MMC CS "high" */ @@ -286,7 +286,7 @@ bool MMC_disk_initialize(void) sleep_us(10000); /* 10ms */ - // Enable SPI at 300khz and connect to GPIOs + // Enable SPI at 400khz and connect to GPIOs spi_init(SD_SPICH, SD_SPI_BAUDRATE_INIT); gpio_set_function(SD_SPI_MISO, GPIO_FUNC_SPI); gpio_set_function(SD_SPI_MOSI, GPIO_FUNC_SPI); From 6591a73a3de9de7fab0c40d394a5920f2b2dc9c5 Mon Sep 17 00:00:00 2001 From: sdomi Date: Tue, 21 Oct 2025 19:57:36 +0200 Subject: [PATCH 4/6] Decrease the sleep time in rcvr functions for a slight perf gain --- ui/lib/sdmmc/sdmmc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ui/lib/sdmmc/sdmmc.c b/ui/lib/sdmmc/sdmmc.c index 2194417..ce25f0a 100644 --- a/ui/lib/sdmmc/sdmmc.c +++ b/ui/lib/sdmmc/sdmmc.c @@ -127,11 +127,11 @@ static int wait_ready(void) /* 1:OK, 0:Timeout */ uint8_t d; unsigned int tmr; - for (tmr = 5000; tmr; tmr--) + for (tmr = 50000; tmr; tmr--) { /* Wait for ready in timeout of 500ms */ rcvr_mmc(&d, 1); if (d == 0xFF) break; - sleep_us(100); + sleep_us(10); } return tmr ? 1 : 0; @@ -307,10 +307,10 @@ bool MMC_disk_initialize(void) rcvr_mmc(buf, 4); /* Get trailing return value of R7 resp */ if (buf[2] == 0x01 && buf[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */ - for (tmr = 1000; tmr; tmr--) + for (tmr = 10000; tmr; tmr--) { /* Wait for leaving idle state (ACMD41 with HCS bit) */ if (send_cmd(ACMD41, 1UL << 30) == 0) break; - sleep_us(1000); + sleep_us(10); } if (tmr && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */ @@ -331,10 +331,10 @@ bool MMC_disk_initialize(void) ty = CT_MMC3; cmd = CMD1; /* MMCv3 */ } - for (tmr = 1000; tmr; tmr--) + for (tmr = 10000; tmr; tmr--) { /* Wait for leaving idle state */ if (send_cmd(cmd, 0) == 0) break; - sleep_us(1000); + sleep_us(10); } if (!tmr || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */ ty = 0; From aa5643eb59fa0178edbdd0d407366152614c46f4 Mon Sep 17 00:00:00 2001 From: sdomi Date: Tue, 21 Oct 2025 19:59:34 +0200 Subject: [PATCH 5/6] Fix the MMC init function to actually do 80 clocks (instead of 10) --- ui/lib/sdmmc/sdmmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/lib/sdmmc/sdmmc.c b/ui/lib/sdmmc/sdmmc.c index ce25f0a..ad34f37 100644 --- a/ui/lib/sdmmc/sdmmc.c +++ b/ui/lib/sdmmc/sdmmc.c @@ -296,8 +296,8 @@ bool MMC_disk_initialize(void) CS_H(); gpio_set_dir(SD_SPI_CS, GPIO_OUT); - for (n = 10; n; n--) - rcvr_mmc(buf, 1); /* Apply 80 dummy clocks and the card gets ready to receive command */ + for (n = 20; n; n--) + rcvr_mmc(buf, 4); /* Apply 80 dummy clocks and the card gets ready to receive command */ ty = 0; if (send_cmd(CMD0, 0) == 1) From 8f092727f1d54187d1ea47be3e8b96265f8f8a44 Mon Sep 17 00:00:00 2001 From: sdomi Date: Tue, 21 Oct 2025 19:59:49 +0200 Subject: [PATCH 6/6] Rework MMC code to use CMD23 instead of manual control where possible --- ui/lib/sdmmc/sdmmc.c | 61 +++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/ui/lib/sdmmc/sdmmc.c b/ui/lib/sdmmc/sdmmc.c index ad34f37..7addea7 100644 --- a/ui/lib/sdmmc/sdmmc.c +++ b/ui/lib/sdmmc/sdmmc.c @@ -194,29 +194,39 @@ static int rcvr_datablock( /* 1:OK, 0:Failed */ /* Send a data packet to the card */ /*-----------------------------------------------------------------------*/ -static int xmit_datablock( /* 1:OK, 0:Failed */ - const uint8_t *buff, /* 512 byte data block to be transmitted */ - uint8_t token /* Data/Stop token */ +static int _xmit_datablock( /* 1:OK, 0:Failed */ + const uint8_t *buff, /* data block to be transmitted */ + uint8_t token, /* Data/Stop token */ + unsigned int len, /* length of the data block */ + bool wait /* Skip waitingg*/ ) { - uint8_t d[2]; + uint8_t d[3]; - if (!wait_ready()) return 0; + if (wait) + if(!wait_ready()) return 0; d[0] = token; xmit_mmc(d, 1); /* Xmit a token */ if (token != 0xFD) { /* Is it data token? */ - xmit_mmc(buff, 512); /* Xmit the 512 byte data block to MMC */ - rcvr_mmc(d, 2); /* Xmit dummy CRC (0xFF,0xFF) */ - rcvr_mmc(d, 1); /* Receive data response */ - if ((d[0] & 0x1F) != 0x05) /* If not accepted, return with error */ + xmit_mmc(buff, len); /* Xmit the 512 byte data block to MMC */ + rcvr_mmc(d, 3); /* Xmit dummy CRC (0xFF,0xFF); Receive data response */ + if ((d[2] & 0x1F) != 0x05) /* If not accepted, return with error */ return 0; } return 1; } +static int xmit_datablock( /* Wrapper function */ + const uint8_t *buff, + uint8_t token +) +{ + return _xmit_datablock(buff, token, 512, true); +} + /*-----------------------------------------------------------------------*/ /* Send a command packet to the card */ /*-----------------------------------------------------------------------*/ @@ -370,16 +380,21 @@ bool MMC_disk_read(uint8_t *buff, /* Pointer to the data buffer to store rea if (!(CardType & CT_BLOCK)) sect *= 512; /* Convert LBA to byte address if needed */ - cmd = count > 1 ? CMD18 : CMD17; /* READ_MULTIPLE_BLOCK : READ_SINGLE_BLOCK */ - if (send_cmd(cmd, sect) == 0) + if (count > 1) { - do - { - if (!rcvr_datablock(buff, 512)) break; - buff += 512; - } while (--count); - if (cmd == CMD18) send_cmd(CMD12, 0); /* STOP_TRANSMISSION */ + cmd = CMD18; + send_cmd(CMD23, count); } + else + { + cmd = CMD17; + } + + if (send_cmd(cmd, sect) == 0) { + rcvr_datablock(buff, count * 512); + count = 0; + } + deselect(); return (count == 0); @@ -409,15 +424,13 @@ bool MMC_disk_write(const uint8_t *buff, /* Pointer to the data to be written */ else { /* Multiple block write */ if (CardType & CT_SDC) send_cmd(ACMD23, count); + send_cmd(CMD23, count); if (send_cmd(CMD25, sect) == 0) { /* WRITE_MULTIPLE_BLOCK */ - do - { - if (!xmit_datablock(buff, 0xFC)) break; - buff += 512; - } while (--count); - if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */ - count = 1; + _xmit_datablock(buff, 0xFC, count * 512, false); + count = 0; + // if (!_xmit_datablock(0, 0xFD, 512, false)) /* STOP_TRAN token */ + // count = 1; } } deselect();