From 00110a8863d45a12afac2694a08010d6ec1cdbd6 Mon Sep 17 00:00:00 2001 From: CTCaer Date: Thu, 20 Jan 2022 12:48:41 +0200 Subject: [PATCH] bdk: move sd ops into bdk --- bdk/storage/sd.c | 250 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 bdk/storage/sd.c diff --git a/bdk/storage/sd.c b/bdk/storage/sd.c new file mode 100644 index 0000000..9f45fe9 --- /dev/null +++ b/bdk/storage/sd.c @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018-2022 CTCaer + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +static bool sd_mounted = false; +static bool sd_init_done = false; +static u16 sd_errors[3] = { 0 }; // Init and Read/Write errors. +static u32 sd_mode = SD_UHS_SDR104; + +sdmmc_t sd_sdmmc; +sdmmc_storage_t sd_storage; +FATFS sd_fs; + +void sd_error_count_increment(u8 type) +{ + switch (type) + { + case SD_ERROR_INIT_FAIL: + sd_errors[0]++; + break; + case SD_ERROR_RW_FAIL: + sd_errors[1]++; + break; + case SD_ERROR_RW_RETRY: + sd_errors[2]++; + break; + } +} + +u16 *sd_get_error_count() +{ + return sd_errors; +} + +bool sd_get_card_removed() +{ + if (sd_init_done && !sdmmc_get_sd_inserted()) + return true; + + return false; +} + +bool sd_get_card_initialized() +{ + return sd_init_done; +} + +bool sd_get_card_mounted() +{ + return sd_mounted; +} + +u32 sd_get_mode() +{ + 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 + { + sd_errors[SD_ERROR_INIT_FAIL]++; + + 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; + + int res = 0; + + if (!sd_init_done) + res = !sd_initialize(false); + + if (res) + { + gfx_con.mute = false; + 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 + { + sd_init_done = true; + res = f_mount(&sd_fs, "0:", 1); // Volume 0 is SD. + if (res == FR_OK) + { + sd_mounted = true; + return true; + } + else + { + gfx_con.mute = false; + EPRINTFARGS("Failed to mount SD card (FatFS Error %d).\nMake sure that a FAT partition exists..", res); + } + } + + return false; +} + +static void _sd_deinit(bool deinit) +{ + if (deinit && sd_mode == SD_INIT_FAIL) + sd_mode = SD_UHS_SDR104; + + if (sd_init_done && sd_mounted) + { + f_mount(NULL, "0:", 1); // Volume 0 is SD. + sd_mounted = false; + } + if (sd_init_done && deinit) + { + sdmmc_storage_end(&sd_storage); + sd_init_done = false; + } +} + +void sd_unmount() { _sd_deinit(false); } +void sd_end() { _sd_deinit(true); } + +bool sd_is_gpt() +{ + return sd_fs.part_type; +} + +void *sd_file_read(const char *path, u32 *fsize) +{ + FIL fp; + if (f_open(&fp, path, FA_READ) != FR_OK) + return NULL; + + u32 size = f_size(&fp); + if (fsize) + *fsize = size; + + void *buf = malloc(size); + + if (f_read(&fp, buf, size, NULL) != FR_OK) + { + free(buf); + f_close(&fp); + + return NULL; + } + + f_close(&fp); + + return buf; +} + +int sd_save_to_file(void *buf, u32 size, const char *filename) +{ + FIL fp; + u32 res = 0; + res = f_open(&fp, filename, FA_CREATE_ALWAYS | FA_WRITE); + if (res) + { + EPRINTFARGS("Error (%d) creating file\n%s.\n", res, filename); + return res; + } + + f_write(&fp, buf, size, NULL); + f_close(&fp); + + return 0; +}