text/plain
•
4.43 KB
•
165 lines
#include "storage.h"
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include "esp_vfs_fat.h"
#include "sdmmc_cmd.h"
#include "driver/sdspi_host.h"
#include "driver/spi_common.h"
#define MOUNT_POINT "/sdcard"
// SD card SPI pins
#define SD_PIN_CS 9
#define SD_PIN_CLK 10
#define SD_PIN_MOSI 11
#define SD_PIN_MISO 12
static const char *TAG = "storage";
static bool mounted = false;
static sdmmc_card_t *card = NULL;
bool storage_init(void) {
esp_err_t ret;
// SPI bus configuration
spi_bus_config_t bus_cfg = {
.mosi_io_num = SD_PIN_MOSI,
.miso_io_num = SD_PIN_MISO,
.sclk_io_num = SD_PIN_CLK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 4096,
};
// Initialize SPI bus (SPI3_HOST to avoid conflict with display on SPI2)
ret = spi_bus_initialize(SPI3_HOST, &bus_cfg, SDSPI_DEFAULT_DMA);
if (ret != ESP_OK) {
printf("%s: Failed to initialize SPI bus: %s\n", TAG, esp_err_to_name(ret));
return false;
}
// SD card mount configuration
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
.format_if_mount_failed = false,
.max_files = 5,
.allocation_unit_size = 16 * 1024,
};
// SD SPI device configuration
sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
slot_config.gpio_cs = SD_PIN_CS;
slot_config.host_id = SPI3_HOST;
// SD host configuration
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
host.slot = SPI3_HOST;
// Mount filesystem
ret = esp_vfs_fat_sdspi_mount(MOUNT_POINT, &host, &slot_config, &mount_config, &card);
if (ret != ESP_OK) {
if (ret == ESP_FAIL) {
printf("%s: Failed to mount filesystem\n", TAG);
} else {
printf("%s: Failed to initialize SD card: %s\n", TAG, esp_err_to_name(ret));
}
spi_bus_free(SPI3_HOST);
return false;
}
// Card has been initialized, print its properties
sdmmc_card_print_info(stdout, card);
mounted = true;
printf("%s: SD card mounted at %s\n", TAG, MOUNT_POINT);
return true;
}
bool storage_is_mounted(void) {
return mounted;
}
int storage_list_dir(const char *path, storage_entry_t *entries, int max) {
if (!mounted || !entries || max <= 0) {
return -1;
}
char full_path[STORAGE_MAX_PATH];
if (path == NULL || path[0] == '\0' || strcmp(path, "/") == 0) {
snprintf(full_path, sizeof(full_path), "%s", MOUNT_POINT);
} else {
snprintf(full_path, sizeof(full_path), "%s/%s", MOUNT_POINT, path);
}
DIR *dir = opendir(full_path);
if (!dir) {
printf("%s: Failed to open directory %s\n", TAG, full_path);
return -1;
}
int count = 0;
struct dirent *ent;
while ((ent = readdir(dir)) != NULL && count < max) {
// Skip . and ..
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {
continue;
}
strncpy(entries[count].name, ent->d_name, STORAGE_MAX_NAME - 1);
entries[count].name[STORAGE_MAX_NAME - 1] = '\0';
// Get file info
char file_path[STORAGE_MAX_PATH*2];
snprintf(file_path, sizeof(file_path), "%s/%s", full_path, ent->d_name);
struct stat st;
if (stat(file_path, &st) == 0) {
entries[count].type = S_ISDIR(st.st_mode) ? STORAGE_TYPE_DIR : STORAGE_TYPE_FILE;
entries[count].size = (size_t)st.st_size;
} else {
entries[count].type = STORAGE_TYPE_FILE;
entries[count].size = 0;
}
count++;
}
closedir(dir);
return count;
}
storage_file_t storage_open(const char *path, const char *mode) {
if (!mounted || !path || !mode) {
return NULL;
}
char full_path[STORAGE_MAX_PATH];
snprintf(full_path, sizeof(full_path), "%s/%s", MOUNT_POINT, path);
FILE *f = fopen(full_path, mode);
if (!f) {
printf("%s: Failed to open %s\n", TAG, full_path);
}
return (storage_file_t)f;
}
size_t storage_read(storage_file_t file, void *buf, size_t size) {
if (!file || !buf) {
return 0;
}
return fread(buf, 1, size, (FILE *)file);
}
size_t storage_write(storage_file_t file, const void *buf, size_t size) {
if (!file || !buf) {
return 0;
}
return fwrite(buf, 1, size, (FILE *)file);
}
int storage_close(storage_file_t file) {
if (!file) {
return -1;
}
return fclose((FILE *)file);
}