/** * @file storage_sd.c * @brief Narrow SD-card storage wrapper built directly on FatFs. */ #include "storage_sd.h" #include "fatfs.h" #include "board_io.h" static uint8_t g_storage_mounted = 0u; static uint16_t g_storage_mount_depth = 0u; bool storage_sd_is_available(void) { return board_io_is_sd_card_present(); } FRESULT storage_sd_begin(void) { FRESULT result; if (!storage_sd_is_available()) { return FR_NOT_READY; } if (g_storage_mount_depth > 0u) { ++g_storage_mount_depth; return FR_OK; } result = f_mount(&SDFatFS, SDPath, 1u); if (result == FR_OK) { g_storage_mounted = 1u; g_storage_mount_depth = 1u; } return result; } FRESULT storage_sd_end(void) { FRESULT result; if (g_storage_mount_depth == 0u) { return FR_OK; } --g_storage_mount_depth; if (g_storage_mount_depth > 0u) { return FR_OK; } result = f_mount(NULL, SDPath, 1u); if (result == FR_OK) { g_storage_mounted = 0u; } else { g_storage_mount_depth = 1u; } return result; } FRESULT storage_sd_open_file(FIL *file, const char *path, BYTE mode) { FRESULT result; if ((file == NULL) || (path == NULL)) { return FR_INVALID_PARAMETER; } result = storage_sd_begin(); if (result != FR_OK) { return result; } result = f_open(file, path, mode); if (result != FR_OK) { (void)storage_sd_end(); } return result; } FRESULT storage_sd_close_file(FIL *file) { FRESULT close_result = FR_OK; FRESULT end_result; if (file != NULL) { close_result = f_close(file); } end_result = storage_sd_end(); if (close_result != FR_OK) { return close_result; } return end_result; } FRESULT storage_sd_read_bytes(const char *path, FSIZE_t offset, void *data, UINT size, UINT *bytes_read) { FIL file; UINT local_bytes_read = 0u; FRESULT result = storage_sd_open_file(&file, path, FA_READ); if (result != FR_OK) { return result; } result = f_lseek(&file, offset); if (result == FR_OK) { result = f_read(&file, data, size, &local_bytes_read); } (void)storage_sd_close_file(&file); if (bytes_read != NULL) { *bytes_read = local_bytes_read; } return result; } FRESULT storage_sd_stat(const char *path, FILINFO *out_info) { FRESULT result; if (path == NULL) { return FR_INVALID_PARAMETER; } result = storage_sd_begin(); if (result != FR_OK) { return result; } result = f_stat(path, out_info); (void)storage_sd_end(); return result; } bool storage_sd_file_exists(const char *path) { FILINFO info; return storage_sd_stat(path, &info) == FR_OK; } FRESULT storage_sd_make_directory(const char *path) { FRESULT result; if (path == NULL) { return FR_INVALID_PARAMETER; } result = storage_sd_begin(); if (result != FR_OK) { return result; } result = f_mkdir(path); if (result == FR_EXIST) { result = FR_OK; } (void)storage_sd_end(); return result; } FRESULT storage_sd_remove_file(const char *path) { FRESULT result; if (path == NULL) { return FR_INVALID_PARAMETER; } result = storage_sd_begin(); if (result != FR_OK) { return result; } result = f_unlink(path); if ((result == FR_NO_FILE) || (result == FR_NO_PATH)) { result = FR_OK; } (void)storage_sd_end(); return result; }