#include "esp_common.h" #include #include #define NUM_SYS_FD 3 static spiffs fs; static u8_t *spiffs_work_buf; static u8_t *spiffs_fd_buf; static u8_t *spiffs_cache_buf; #define FLASH_UNIT_SIZE 4 static s32_t esp_spiffs_readwrite(u32_t addr, u32_t size, u8_t *p, int write) { /* * With proper configurarion spiffs never reads or writes more than * LOG_PAGE_SIZE */ if (size > fs.cfg.log_page_size) { printf("Invalid size provided to read/write (%d)\n\r", (int) size); return SPIFFS_ERR_NOT_CONFIGURED; } char tmp_buf[fs.cfg.log_page_size + FLASH_UNIT_SIZE * 2]; u32_t aligned_addr = addr & (-FLASH_UNIT_SIZE); u32_t aligned_size = ((size + (FLASH_UNIT_SIZE - 1)) & -FLASH_UNIT_SIZE) + FLASH_UNIT_SIZE; int res = spi_flash_read(aligned_addr, (u32_t *) tmp_buf, aligned_size); if (res != 0) { printf("spi_flash_read failed: %d (%d, %d)\n\r", res, (int) aligned_addr, (int) aligned_size); return res; } if (!write) { memcpy(p, tmp_buf + (addr - aligned_addr), size); return SPIFFS_OK; } memcpy(tmp_buf + (addr - aligned_addr), p, size); res = spi_flash_write(aligned_addr, (u32_t *) tmp_buf, aligned_size); if (res != 0) { // printf("spi_flash_write failed: %d (%d, %d)\n\r", res, // (int) aligned_addr, (int) aligned_size); return res; } return SPIFFS_OK; } static s32_t esp_spiffs_read(u32_t addr, u32_t size, u8_t *dst) { return esp_spiffs_readwrite(addr, size, dst, 0); } static s32_t esp_spiffs_write(u32_t addr, u32_t size, u8_t *src) { return esp_spiffs_readwrite(addr, size, src, 1); } static s32_t esp_spiffs_erase(u32_t addr, u32_t size) { /* * With proper configurarion spiffs always * provides here sector address & sector size */ if (size != fs.cfg.phys_erase_block || addr % fs.cfg.phys_erase_block != 0) { printf("Invalid size provided to esp_spiffs_erase (%d, %d)\n\r", (int) addr, (int) size); return SPIFFS_ERR_NOT_CONFIGURED; } return spi_flash_erase_sector(addr / fs.cfg.phys_erase_block); } s32_t esp_spiffs_init(struct esp_spiffs_config *config) { if (SPIFFS_mounted(&fs)) { return -1; } spiffs_config cfg; s32_t ret; cfg.phys_size = config->phys_size; cfg.phys_addr = config->phys_addr; cfg.phys_erase_block = config->phys_erase_block; cfg.log_block_size = config->log_block_size; cfg.log_page_size = config->log_page_size; cfg.hal_read_f = esp_spiffs_read; cfg.hal_write_f = esp_spiffs_write; cfg.hal_erase_f = esp_spiffs_erase; if (spiffs_work_buf != NULL) { free(spiffs_work_buf); spiffs_work_buf = NULL; } spiffs_work_buf = malloc(config->log_page_size * 2); if (spiffs_work_buf == NULL) { return -1; } if (spiffs_fd_buf != NULL) { free(spiffs_fd_buf); spiffs_fd_buf = NULL; } spiffs_fd_buf = malloc(config->fd_buf_size); if (spiffs_fd_buf == NULL) { free(spiffs_work_buf); return -1; } if (spiffs_cache_buf != NULL) { free(spiffs_cache_buf); spiffs_cache_buf = NULL; } spiffs_cache_buf = malloc(config->cache_buf_size); if (spiffs_cache_buf == NULL) { free(spiffs_work_buf); free(spiffs_fd_buf); return -1; } ret = SPIFFS_mount(&fs, &cfg, spiffs_work_buf, spiffs_fd_buf, config->fd_buf_size, spiffs_cache_buf, config->cache_buf_size, 0); if (ret == -1) { free(spiffs_work_buf); free(spiffs_fd_buf); free(spiffs_cache_buf); } return ret; } void esp_spiffs_deinit(u8_t format) { if (SPIFFS_mounted(&fs)) { SPIFFS_unmount(&fs); free(spiffs_work_buf); free(spiffs_fd_buf); free(spiffs_cache_buf); if (format) { SPIFFS_format(&fs); } } } int _open_r(struct _reent *r, const char *filename, int flags, int mode) { spiffs_mode sm = 0; int res; int rw = (flags & 3); if (rw == O_RDONLY || rw == O_RDWR) { sm |= SPIFFS_RDONLY; } if (rw == O_WRONLY || rw == O_RDWR) { sm |= SPIFFS_WRONLY; } if (flags & O_CREAT) { sm |= SPIFFS_CREAT; } if (flags & O_TRUNC) { sm |= SPIFFS_TRUNC; } if (flags & O_APPEND) { sm |= SPIFFS_APPEND; } /* Supported in newer versions of SPIFFS. */ /* if (flags && O_EXCL) sm |= SPIFFS_EXCL; */ /* if (flags && O_DIRECT) sm |= SPIFFS_DIRECT; */ res = SPIFFS_open(&fs, (char *) filename, sm, 0); if (res >= 0) { res += NUM_SYS_FD; } return res; } _ssize_t _read_r(struct _reent *r, int fd, void *buf, size_t len) { ssize_t res; if (fd < NUM_SYS_FD) { res = -1; } else { res = SPIFFS_read(&fs, fd - NUM_SYS_FD, buf, len); } return res; } _ssize_t _write_r(struct _reent *r, int fd, void *buf, size_t len) { if (fd < NUM_SYS_FD) { return -1; } int res = SPIFFS_write(&fs, fd - NUM_SYS_FD, (char *) buf, len); return res; } _off_t _lseek_r(struct _reent *r, int fd, _off_t where, int whence) { ssize_t res; if (fd < NUM_SYS_FD) { res = -1; } else { res = SPIFFS_lseek(&fs, fd - NUM_SYS_FD, where, whence); } return res; } int _close_r(struct _reent *r, int fd) { if (fd < NUM_SYS_FD) { return -1; } SPIFFS_close(&fs, fd - NUM_SYS_FD); return 0; } int _rename_r(struct _reent *r, const char *from, const char *to) { int res = SPIFFS_rename(&fs, (char *) from, (char *) to); return res; } int _unlink_r(struct _reent *r, const char *filename) { int res = SPIFFS_remove(&fs, (char *) filename); return res; } int _fstat_r(struct _reent *r, int fd, struct stat *s) { int res; spiffs_stat ss; memset(s, 0, sizeof(*s)); if (fd < NUM_SYS_FD) { s->st_ino = fd; s->st_rdev = fd; s->st_mode = S_IFCHR | 0666; return 0; } res = SPIFFS_fstat(&fs, fd - NUM_SYS_FD, &ss); if (res < 0) { return res; } s->st_ino = ss.obj_id; s->st_mode = 0666; s->st_nlink = 1; s->st_size = ss.size; return 0; }