diff --git a/bootloader/storage/nx_sd.c b/bootloader/storage/nx_sd.c index 7b9935a..459e30d 100644 --- a/bootloader/storage/nx_sd.c +++ b/bootloader/storage/nx_sd.c @@ -23,24 +23,96 @@ #include "../mem/heap.h" static bool sd_mounted = false; +static u32 sd_mode = SD_UHS_SDR82; + +u32 sd_mode_get() +{ + return sd_mode; +} + +int sd_init_retry(bool power_cycle) +{ + u32 bus_width = SDMMC_BUS_WIDTH_4; + u32 type = SDHCI_TIMING_UHS_SDR82; + + // Power cycle SD card. + if (power_cycle) + { + sd_mode--; + sdmmc_storage_end(&sd_storage); + } + + // Get init parameters. + switch (sd_mode) + { + case SD_INIT_FAIL: // Reset to max. + return 0; + case SD_1BIT_HS25: + bus_width = SDMMC_BUS_WIDTH_1; + type = SDHCI_TIMING_SD_HS25; + break; + case SD_4BIT_HS25: + type = SDHCI_TIMING_SD_HS25; + break; + case SD_UHS_SDR82: + type = SDHCI_TIMING_UHS_SDR82; + break; + default: + sd_mode = SD_UHS_SDR82; + } + + return sdmmc_storage_init_sd(&sd_storage, &sd_sdmmc, bus_width, type); +} + +bool sd_initialize(bool power_cycle) +{ + if (power_cycle) + sdmmc_storage_end(&sd_storage); + + int res = !sd_init_retry(false); + + while (true) + { + if (!res) + return true; + else if (!sdmmc_get_sd_inserted()) // SD Card is not inserted. + { + sd_mode = SD_UHS_SDR82; + break; + } + else if (sd_mode == SD_INIT_FAIL) + break; + else + res = !sd_init_retry(true); + } + + sdmmc_storage_end(&sd_storage); + + return false; +} bool sd_mount() { if (sd_mounted) return true; - if (!sdmmc_storage_init_sd(&sd_storage, &sd_sdmmc, SDMMC_BUS_WIDTH_4, SDHCI_TIMING_UHS_SDR82)) + int res = !sd_initialize(false); + + if (res) { gfx_con.mute = false; - EPRINTF("Failed to init SD card.\nMake sure that it is inserted.\nOr that SD reader is properly seated!"); + EPRINTF("Failed to init SD card."); + if (!sdmmc_get_sd_inserted()) + EPRINTF("Make sure that it is inserted."); + else + EPRINTF("SD Card Reader is not properly seated!"); } else { - int res = 0; res = f_mount(&sd_fs, "", 1); if (res == FR_OK) { - sd_mounted = 1; + sd_mounted = true; return true; } else @@ -55,6 +127,7 @@ bool sd_mount() void sd_unmount() { + sd_mode = SD_UHS_SDR82; if (sd_mounted) { f_mount(NULL, "", 1); diff --git a/bootloader/storage/nx_sd.h b/bootloader/storage/nx_sd.h index 0c7826e..4c86db0 100644 --- a/bootloader/storage/nx_sd.h +++ b/bootloader/storage/nx_sd.h @@ -22,10 +22,21 @@ #include "sdmmc_driver.h" #include "../libs/fatfs/ff.h" +enum +{ + SD_INIT_FAIL = 0, + SD_1BIT_HS25 = 1, + SD_4BIT_HS25 = 2, + SD_UHS_SDR82 = 3, +}; + sdmmc_t sd_sdmmc; sdmmc_storage_t sd_storage; FATFS sd_fs; +u32 sd_mode_get(); +int sd_init_retry(bool power_cycle); +bool sd_initialize(bool power_cycle); bool sd_mount(); void sd_unmount(); void *sd_file_read(const char *path, u32 *fsize); diff --git a/bootloader/storage/sdmmc.c b/bootloader/storage/sdmmc.c index fc941c8..902d0ca 100644 --- a/bootloader/storage/sdmmc.c +++ b/bootloader/storage/sdmmc.c @@ -18,6 +18,7 @@ #include #include "sdmmc.h" #include "mmc.h" +#include "nx_sd.h" #include "sd.h" #include "../../common/memory_map.h" #include "../gfx/gfx.h" @@ -172,25 +173,42 @@ int sdmmc_storage_end(sdmmc_storage_t *storage) static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf, u32 is_write) { u8 *bbuf = (u8 *)buf; - + bool first_reinit = false; while (num_sectors) { u32 blkcnt = 0; - //Retry 9 times on error. - u32 retries = 10; + // Retry 5 times if failed. + u32 retries = 5; do { +reinit_try: if (_sdmmc_storage_readwrite_ex(storage, &blkcnt, sector, MIN(num_sectors, 0xFFFF), bbuf, is_write)) goto out; else retries--; - msleep(100); + msleep(50); } while (retries); + // Disk IO failure! Reinit SD Card to a lower speed. + if (storage->sdmmc->id == SDMMC_1) + { + int res; + if (!first_reinit) + res = sd_initialize(true); + else + res = sd_init_retry(true); + + retries = 3; + first_reinit = true; + + if (res) + goto reinit_try; + } + return 0; -out:; +out: DPRINTF("readwrite: %08X\n", blkcnt); sector += blkcnt; num_sectors -= blkcnt; diff --git a/nyx/nyx_gui/storage/nx_sd.c b/nyx/nyx_gui/storage/nx_sd.c index 7251beb..c025e6b 100644 --- a/nyx/nyx_gui/storage/nx_sd.c +++ b/nyx/nyx_gui/storage/nx_sd.c @@ -33,6 +33,78 @@ bool sd_get_card_removed() return false; } +u32 sd_mode_get() +{ + return sd_mode; +} + +int sd_init_retry(bool power_cycle) +{ + u32 bus_width = SDMMC_BUS_WIDTH_4; + u32 type = SDHCI_TIMING_UHS_SDR104; + + // Power cycle SD card. + if (power_cycle) + { + sd_mode--; + sdmmc_storage_end(&sd_storage); + } + + // Get init parameters. + switch (sd_mode) + { + case SD_INIT_FAIL: // Reset to max. + return 0; + case SD_1BIT_HS25: + bus_width = SDMMC_BUS_WIDTH_1; + type = SDHCI_TIMING_SD_HS25; + break; + case SD_4BIT_HS25: + type = SDHCI_TIMING_SD_HS25; + break; + case SD_UHS_SDR82: + type = SDHCI_TIMING_UHS_SDR82; + break; + case SD_UHS_SDR104: + type = SDHCI_TIMING_UHS_SDR104; + break; + default: + sd_mode = SD_UHS_SDR104; + } + + return sdmmc_storage_init_sd(&sd_storage, &sd_sdmmc, bus_width, type); +} + +bool sd_initialize(bool power_cycle) +{ + if (power_cycle) + sdmmc_storage_end(&sd_storage); + + int res = !sd_init_retry(false); + + while (true) + { + if (!res) + return true; + else if (!sdmmc_get_sd_inserted()) // SD Card is not inserted. + { + sd_mode = SD_UHS_SDR104; + break; + } + else + { + if (sd_mode == SD_INIT_FAIL) + break; + else + res = !sd_init_retry(true); + } + } + + sdmmc_storage_end(&sd_storage); + + return false; +} + bool sd_mount() { if (sd_mounted) @@ -41,19 +113,20 @@ bool sd_mount() int res = 0; if (!sd_init_done) - { - res = !sdmmc_storage_init_sd(&sd_storage, &sd_sdmmc, SDMMC_BUS_WIDTH_4, SDHCI_TIMING_UHS_SDR82); - if (!res) - sd_init_done = true; - } + res = !sd_initialize(false); if (res) { - EPRINTF("Failed to init SD card.\nMake sure that it is inserted.\nOr that SD reader is properly seated!"); + EPRINTF("Failed to init SD card."); + if (!sdmmc_get_sd_inserted()) + EPRINTF("Make sure that it is inserted."); + else + EPRINTF("SD Card Reader is not properly seated!"); } else { - int res = f_mount(&sd_fs, "", 1); + sd_init_done = true; + res = f_mount(&sd_fs, "", 1); if (res == FR_OK) { sd_mounted = true; @@ -70,6 +143,9 @@ bool sd_mount() void sd_unmount(bool deinit) { + if (sd_mode == SD_INIT_FAIL) + sd_mode = SD_UHS_SDR104; + if (sd_init_done && sd_mounted) { f_mount(NULL, "", 1); diff --git a/nyx/nyx_gui/storage/nx_sd.h b/nyx/nyx_gui/storage/nx_sd.h index f9054ed..4698c7f 100644 --- a/nyx/nyx_gui/storage/nx_sd.h +++ b/nyx/nyx_gui/storage/nx_sd.h @@ -22,11 +22,23 @@ #include "sdmmc_driver.h" #include "../libs/fatfs/ff.h" +enum +{ + SD_INIT_FAIL = 0, + SD_1BIT_HS25 = 1, + SD_4BIT_HS25 = 2, + SD_UHS_SDR82 = 3, + SD_UHS_SDR104 = 4 +}; + sdmmc_t sd_sdmmc; sdmmc_storage_t sd_storage; FATFS sd_fs; bool sd_get_card_removed(); +u32 sd_get_mode(); +int sd_init_retry(bool power_cycle); +bool sd_initialize(bool power_cycle); bool sd_mount(); void sd_unmount(bool deinit); void *sd_file_read(const char *path, u32 *fsize); diff --git a/nyx/nyx_gui/storage/sdmmc.c b/nyx/nyx_gui/storage/sdmmc.c index 5ce0900..d60129e 100644 --- a/nyx/nyx_gui/storage/sdmmc.c +++ b/nyx/nyx_gui/storage/sdmmc.c @@ -18,6 +18,7 @@ #include #include "sdmmc.h" #include "mmc.h" +#include "nx_sd.h" #include "sd.h" #include "../../../common/memory_map.h" #include "../gfx/gfx.h" @@ -172,25 +173,43 @@ int sdmmc_storage_end(sdmmc_storage_t *storage) static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf, u32 is_write) { u8 *bbuf = (u8 *)buf; - + bool first_reinit = false; while (num_sectors) { u32 blkcnt = 0; - //Retry 9 times on error. - u32 retries = 10; + // Retry 5 times if failed. + u32 retries = 5; do { +reinit_try: if (_sdmmc_storage_readwrite_ex(storage, &blkcnt, sector, MIN(num_sectors, 0xFFFF), bbuf, is_write)) goto out; else retries--; - msleep(100); + msleep(50); } while (retries); + // Disk IO failure! Reinit SD Card to a lower speed. + if (storage->sdmmc->id == SDMMC_1) + { + int res; + + if (!first_reinit) + res = sd_initialize(true); + else + res = sd_init_retry(true); + + retries = 3; + first_reinit = true; + + if (res) + goto reinit_try; + } + return 0; -out:; +out: DPRINTF("readwrite: %08X\n", blkcnt); sector += blkcnt; num_sectors -= blkcnt;