Merge pull request #558 from DiUS/spiffs-0.3.2
Updated SPIFFS to 0.3.2.
This commit is contained in:
commit
849407b275
|
@ -110,7 +110,7 @@ static int file_seek (lua_State *L)
|
|||
int op = luaL_checkoption(L, 1, "cur", modenames);
|
||||
long offset = luaL_optlong(L, 2, 0);
|
||||
op = fs_seek(file_fd, offset, mode[op]);
|
||||
if (op)
|
||||
if (op < 0)
|
||||
lua_pushnil(L); /* error */
|
||||
else
|
||||
lua_pushinteger(L, fs_tell(file_fd));
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "c_stdio.h"
|
||||
#include "spiffs_config.h"
|
||||
|
||||
#define SPIFFS_OK 0
|
||||
|
@ -41,6 +40,14 @@ extern "C" {
|
|||
#define SPIFFS_ERR_NOT_WRITABLE -10021
|
||||
#define SPIFFS_ERR_NOT_READABLE -10022
|
||||
#define SPIFFS_ERR_CONFLICTING_NAME -10023
|
||||
#define SPIFFS_ERR_NOT_CONFIGURED -10024
|
||||
|
||||
#define SPIFFS_ERR_NOT_A_FS -10025
|
||||
#define SPIFFS_ERR_MOUNTED -10026
|
||||
#define SPIFFS_ERR_ERASE_FAIL -10027
|
||||
#define SPIFFS_ERR_MAGIC_NOT_POSSIBLE -10028
|
||||
|
||||
#define SPIFFS_ERR_NO_DELETED_BLOCKS -10029
|
||||
|
||||
#define SPIFFS_ERR_INTERNAL -10050
|
||||
|
||||
|
@ -215,6 +222,11 @@ typedef struct {
|
|||
|
||||
// check callback function
|
||||
spiffs_check_callback check_cb_f;
|
||||
|
||||
// mounted flag
|
||||
u8_t mounted;
|
||||
// config magic
|
||||
u32_t config_magic;
|
||||
} spiffs;
|
||||
|
||||
/* spiffs file status struct */
|
||||
|
@ -242,7 +254,10 @@ typedef struct {
|
|||
// functions
|
||||
|
||||
/**
|
||||
* Initializes the file system dynamic parameters and mounts the filesystem
|
||||
* Initializes the file system dynamic parameters and mounts the filesystem.
|
||||
* If SPIFFS_USE_MAGIC is enabled the mounting may fail with SPIFFS_ERR_NOT_A_FS
|
||||
* if the flash does not contain a recognizable file system.
|
||||
* In this case, SPIFFS_format must be called prior to remounting.
|
||||
* @param fs the file system struct
|
||||
* @param config the physical and logical configuration of the file system
|
||||
* @param work a memory work buffer comprising 2*config->log_page_size
|
||||
|
@ -308,7 +323,7 @@ spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_fl
|
|||
* @param len how much to read
|
||||
* @returns number of bytes read, or -1 if error
|
||||
*/
|
||||
s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, u32_t len);
|
||||
s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len);
|
||||
|
||||
/**
|
||||
* Writes to given filehandle.
|
||||
|
@ -318,7 +333,7 @@ s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, u32_t len);
|
|||
* @param len how much to write
|
||||
* @returns number of bytes written, or -1 if error
|
||||
*/
|
||||
s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, u32_t len);
|
||||
s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len);
|
||||
|
||||
/**
|
||||
* Moves the read/write file offset
|
||||
|
@ -426,6 +441,12 @@ struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e);
|
|||
*/
|
||||
s32_t SPIFFS_check(spiffs *fs);
|
||||
|
||||
/**
|
||||
* Searches for a block with only deleted entries. If found, it is erased.
|
||||
* @param fs the file system struct
|
||||
*/
|
||||
s32_t SPIFFS_erase_deleted_block(spiffs *fs);
|
||||
|
||||
|
||||
/**
|
||||
* Returns number of total bytes available and number of used bytes.
|
||||
|
@ -442,13 +463,69 @@ s32_t SPIFFS_check(spiffs *fs);
|
|||
s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used);
|
||||
|
||||
/**
|
||||
* Check if EOF reached.
|
||||
* Formats the entire file system. All data will be lost.
|
||||
* The filesystem must not be mounted when calling this.
|
||||
*
|
||||
* NB: formatting is awkward. Due to backwards compatibility, SPIFFS_mount
|
||||
* MUST be called prior to formatting in order to configure the filesystem.
|
||||
* If SPIFFS_mount succeeds, SPIFFS_unmount must be called before calling
|
||||
* SPIFFS_format.
|
||||
* If SPIFFS_mount fails, SPIFFS_format can be called directly without calling
|
||||
* SPIFFS_unmount first.
|
||||
*
|
||||
* @param fs the file system struct
|
||||
* @param fh the filehandle of the file to check
|
||||
*/
|
||||
s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh);
|
||||
s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh);
|
||||
s32_t SPIFFS_size(spiffs *fs, spiffs_file fh);
|
||||
s32_t SPIFFS_format(spiffs *fs);
|
||||
|
||||
/**
|
||||
* Returns nonzero if spiffs is mounted, or zero if unmounted.
|
||||
* @param fs the file system struct
|
||||
*/
|
||||
u8_t SPIFFS_mounted(spiffs *fs);
|
||||
|
||||
/**
|
||||
* Tries to find a block where most or all pages are deleted, and erase that
|
||||
* block if found. Does not care for wear levelling. Will not move pages
|
||||
* around.
|
||||
* If parameter max_free_pages are set to 0, only blocks with only deleted
|
||||
* pages will be selected.
|
||||
*
|
||||
* NB: the garbage collector is automatically called when spiffs needs free
|
||||
* pages. The reason for this function is to give possibility to do background
|
||||
* tidying when user knows the system is idle.
|
||||
*
|
||||
* Use with care.
|
||||
*
|
||||
* Setting max_free_pages to anything larger than zero will eventually wear
|
||||
* flash more as a block containing free pages can be erased.
|
||||
*
|
||||
* Will set err_no to SPIFFS_OK if a block was found and erased,
|
||||
* SPIFFS_ERR_NO_DELETED_BLOCK if no matching block was found,
|
||||
* or other error.
|
||||
*
|
||||
* @param fs the file system struct
|
||||
* @param max_free_pages maximum number allowed free pages in block
|
||||
*/
|
||||
s32_t SPIFFS_gc_quick(spiffs *fs, u16_t max_free_pages);
|
||||
|
||||
/**
|
||||
* Will try to make room for given amount of bytes in the filesystem by moving
|
||||
* pages and erasing blocks.
|
||||
* If it is physically impossible, err_no will be set to SPIFFS_ERR_FULL. If
|
||||
* there already is this amount (or more) of free space, SPIFFS_gc will
|
||||
* silently return. It is recommended to call SPIFFS_info before invoking
|
||||
* this method in order to determine what amount of bytes to give.
|
||||
*
|
||||
* NB: the garbage collector is automatically called when spiffs needs free
|
||||
* pages. The reason for this function is to give possibility to do background
|
||||
* tidying when user knows the system is idle.
|
||||
*
|
||||
* Use with care.
|
||||
*
|
||||
* @param fs the file system struct
|
||||
* @param size amount of bytes that should be freed
|
||||
*/
|
||||
s32_t SPIFFS_gc(spiffs *fs, u32_t size);
|
||||
|
||||
#if SPIFFS_TEST_VISUALISATION
|
||||
/**
|
||||
|
@ -495,6 +572,10 @@ int myspiffs_check( void );
|
|||
int myspiffs_rename( const char *old, const char *newname );
|
||||
size_t myspiffs_size( int fd );
|
||||
|
||||
s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh);
|
||||
s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh);
|
||||
s32_t SPIFFS_size(spiffs *fs, spiffs_file fh);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -195,7 +195,7 @@ s32_t spiffs_phys_wr(
|
|||
cache->last_access++;
|
||||
cp->last_access = cache->last_access;
|
||||
|
||||
if (cp->flags && SPIFFS_CACHE_FLAG_WRTHRU) {
|
||||
if (cp->flags & SPIFFS_CACHE_FLAG_WRTHRU) {
|
||||
// page is being updated, no write-cache, just pass thru
|
||||
return fs->cfg.hal_write_f(addr, len, src);
|
||||
} else {
|
||||
|
|
|
@ -119,6 +119,14 @@ typedef uint8_t u8_t;
|
|||
#define SPIFFS_COPY_BUFFER_STACK (64)
|
||||
#endif
|
||||
|
||||
// Enable this to have an identifiable spiffs filesystem. This will look for
|
||||
// a magic in all sectors to determine if this is a valid spiffs system or
|
||||
// not on mount point. If not, SPIFFS_format must be called prior to mounting
|
||||
// again.
|
||||
#ifndef SPIFFS_USE_MAGIC
|
||||
#define SPIFFS_USE_MAGIC (0)
|
||||
#endif
|
||||
|
||||
// SPIFFS_LOCK and SPIFFS_UNLOCK protects spiffs from reentrancy on api level
|
||||
// These should be defined on a multithreaded system
|
||||
|
||||
|
|
|
@ -8,31 +8,11 @@ static s32_t spiffs_gc_erase_block(
|
|||
spiffs *fs,
|
||||
spiffs_block_ix bix) {
|
||||
s32_t res;
|
||||
u32_t addr = SPIFFS_BLOCK_TO_PADDR(fs, bix);
|
||||
s32_t size = SPIFFS_CFG_LOG_BLOCK_SZ(fs);
|
||||
|
||||
SPIFFS_GC_DBG("gc: erase block %i\n", bix);
|
||||
|
||||
// here we ignore res, just try erasing the block
|
||||
while (size > 0) {
|
||||
SPIFFS_GC_DBG("gc: erase %08x:%08x\n", addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
|
||||
(void)fs->cfg.hal_erase_f(addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
|
||||
addr += SPIFFS_CFG_PHYS_ERASE_SZ(fs);
|
||||
size -= SPIFFS_CFG_PHYS_ERASE_SZ(fs);
|
||||
}
|
||||
fs->free_blocks++;
|
||||
|
||||
// register erase count for this block
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_C_WRTHRU | SPIFFS_OP_T_OBJ_LU2, 0,
|
||||
SPIFFS_ERASE_COUNT_PADDR(fs, bix),
|
||||
sizeof(spiffs_obj_id), (u8_t *)&fs->max_erase_count);
|
||||
res = spiffs_erase_block(fs, bix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
fs->max_erase_count++;
|
||||
if (fs->max_erase_count == SPIFFS_OBJ_ID_IX_FLAG) {
|
||||
fs->max_erase_count = 0;
|
||||
}
|
||||
|
||||
#if SPIFFS_CACHE
|
||||
{
|
||||
u32_t i;
|
||||
|
@ -48,7 +28,7 @@ static s32_t spiffs_gc_erase_block(
|
|||
// the block is erased. Compared to the non-quick gc, the quick one ensures
|
||||
// that no updates are needed on existing objects on pages that are erased.
|
||||
s32_t spiffs_gc_quick(
|
||||
spiffs *fs) {
|
||||
spiffs *fs, u16_t max_free_pages) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
u32_t blocks = fs->block_count;
|
||||
spiffs_block_ix cur_block = 0;
|
||||
|
@ -67,6 +47,7 @@ s32_t spiffs_gc_quick(
|
|||
// check each block
|
||||
while (res == SPIFFS_OK && blocks--) {
|
||||
u16_t deleted_pages_in_block = 0;
|
||||
u16_t free_pages_in_block = 0;
|
||||
|
||||
int obj_lookup_page = 0;
|
||||
// check each object lookup page
|
||||
|
@ -83,9 +64,12 @@ s32_t spiffs_gc_quick(
|
|||
deleted_pages_in_block++;
|
||||
} else if (obj_id == SPIFFS_OBJ_ID_FREE) {
|
||||
// kill scan, go for next block
|
||||
free_pages_in_block++;
|
||||
if (free_pages_in_block > max_free_pages) {
|
||||
obj_lookup_page = SPIFFS_OBJ_LOOKUP_PAGES(fs);
|
||||
res = 1; // kill object lu loop
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// kill scan, go for next block
|
||||
obj_lookup_page = SPIFFS_OBJ_LOOKUP_PAGES(fs);
|
||||
|
@ -98,7 +82,9 @@ s32_t spiffs_gc_quick(
|
|||
} // per object lookup page
|
||||
if (res == 1) res = SPIFFS_OK;
|
||||
|
||||
if (res == SPIFFS_OK && deleted_pages_in_block == SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
|
||||
if (res == SPIFFS_OK &&
|
||||
deleted_pages_in_block + free_pages_in_block == SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs) &&
|
||||
free_pages_in_block <= max_free_pages) {
|
||||
// found a fully deleted block
|
||||
fs->stats_p_deleted -= deleted_pages_in_block;
|
||||
res = spiffs_gc_erase_block(fs, cur_block);
|
||||
|
@ -110,10 +96,13 @@ s32_t spiffs_gc_quick(
|
|||
cur_block_addr += SPIFFS_CFG_LOG_BLOCK_SZ(fs);
|
||||
} // per block
|
||||
|
||||
if (res == SPIFFS_OK) {
|
||||
res = SPIFFS_ERR_NO_DELETED_BLOCKS;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// Checks if garbaga collecting is necessary. If so a candidate block is found,
|
||||
// Checks if garbage collecting is necessary. If so a candidate block is found,
|
||||
// cleansed and erased
|
||||
s32_t spiffs_gc_check(
|
||||
spiffs *fs,
|
||||
|
@ -130,12 +119,15 @@ s32_t spiffs_gc_check(
|
|||
}
|
||||
|
||||
u32_t needed_pages = (len + SPIFFS_DATA_PAGE_SIZE(fs) - 1) / SPIFFS_DATA_PAGE_SIZE(fs);
|
||||
if (fs->free_blocks <= 2 && (s32_t)needed_pages > free_pages) {
|
||||
// if (fs->free_blocks <= 2 && (s32_t)needed_pages > free_pages) {
|
||||
// SPIFFS_GC_DBG("gc: full freeblk:%i needed:%i free:%i dele:%i\n", fs->free_blocks, needed_pages, free_pages, fs->stats_p_deleted);
|
||||
// return SPIFFS_ERR_FULL;
|
||||
// }
|
||||
if ((s32_t)needed_pages > (s32_t)(free_pages + fs->stats_p_deleted)) {
|
||||
SPIFFS_GC_DBG("gc_check: full freeblk:%i needed:%i free:%i dele:%i\n", fs->free_blocks, needed_pages, free_pages, fs->stats_p_deleted);
|
||||
return SPIFFS_ERR_FULL;
|
||||
}
|
||||
|
||||
//printf("gcing started %i dirty, blocks %i free, want %i bytes\n", fs->stats_p_allocated + fs->stats_p_deleted, fs->free_blocks, len);
|
||||
|
||||
do {
|
||||
SPIFFS_GC_DBG("\ngc_check #%i: run gc free_blocks:%i pfree:%i pallo:%i pdele:%i [%i] len:%i of %i\n",
|
||||
tries,
|
||||
|
@ -145,11 +137,13 @@ s32_t spiffs_gc_check(
|
|||
spiffs_block_ix *cands;
|
||||
int count;
|
||||
spiffs_block_ix cand;
|
||||
res = spiffs_gc_find_candidate(fs, &cands, &count);
|
||||
s32_t prev_free_pages = free_pages;
|
||||
// if the fs is crammed, ignore block age when selecting candidate - kind of a bad state
|
||||
res = spiffs_gc_find_candidate(fs, &cands, &count, free_pages <= 0);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
if (count == 0) {
|
||||
SPIFFS_GC_DBG("gc_check: no candidates, return\n");
|
||||
return res;
|
||||
return (s32_t)needed_pages < free_pages ? SPIFFS_OK : SPIFFS_ERR_FULL;
|
||||
}
|
||||
#if SPIFFS_GC_STATS
|
||||
fs->stats_gc_runs++;
|
||||
|
@ -176,6 +170,12 @@ s32_t spiffs_gc_check(
|
|||
(SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * (fs->block_count - 2)
|
||||
- fs->stats_p_allocated - fs->stats_p_deleted;
|
||||
|
||||
if (prev_free_pages <= 0 && prev_free_pages == free_pages) {
|
||||
// abort early to reduce wear, at least tried once
|
||||
SPIFFS_GC_DBG("gc_check: early abort, no result on gc when fs crammed\n");
|
||||
break;
|
||||
}
|
||||
|
||||
} while (++tries < SPIFFS_GC_MAX_RUNS && (fs->free_blocks <= 2 ||
|
||||
(s32_t)len > free_pages*(s32_t)SPIFFS_DATA_PAGE_SIZE(fs)));
|
||||
|
||||
|
@ -234,7 +234,8 @@ s32_t spiffs_gc_erase_page_stats(
|
|||
s32_t spiffs_gc_find_candidate(
|
||||
spiffs *fs,
|
||||
spiffs_block_ix **block_candidates,
|
||||
int *candidate_count) {
|
||||
int *candidate_count,
|
||||
char fs_crammed) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
u32_t blocks = fs->block_count;
|
||||
spiffs_block_ix cur_block = 0;
|
||||
|
@ -307,7 +308,7 @@ s32_t spiffs_gc_find_candidate(
|
|||
s32_t score =
|
||||
deleted_pages_in_block * SPIFFS_GC_HEUR_W_DELET +
|
||||
used_pages_in_block * SPIFFS_GC_HEUR_W_USED +
|
||||
erase_age * SPIFFS_GC_HEUR_W_ERASE_AGE;
|
||||
erase_age * (fs_crammed ? 0 : SPIFFS_GC_HEUR_W_ERASE_AGE);
|
||||
int cand_ix = 0;
|
||||
SPIFFS_GC_DBG("gc_check: bix:%i del:%i use:%i score:%i\n", cur_block, deleted_pages_in_block, used_pages_in_block, score);
|
||||
while (cand_ix < max_candidates) {
|
||||
|
|
|
@ -21,6 +21,36 @@ u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages) {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
u8_t SPIFFS_mounted(spiffs *fs) {
|
||||
return SPIFFS_CHECK_MOUNT(fs);
|
||||
}
|
||||
|
||||
s32_t SPIFFS_format(spiffs *fs) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
if (SPIFFS_CHECK_MOUNT(fs)) {
|
||||
fs->err_code = SPIFFS_ERR_MOUNTED;
|
||||
return -1;
|
||||
}
|
||||
|
||||
s32_t res;
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
spiffs_block_ix bix = 0;
|
||||
while (bix < fs->block_count) {
|
||||
fs->max_erase_count = 0;
|
||||
res = spiffs_erase_block(fs, bix);
|
||||
if (res != SPIFFS_OK) {
|
||||
res = SPIFFS_ERR_ERASE_FAIL;
|
||||
}
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
bix++;
|
||||
}
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
|
||||
u8_t *fd_space, u32_t fd_space_size,
|
||||
void *cache, u32_t cache_size,
|
||||
|
@ -34,10 +64,10 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
|
|||
c_memset(fd_space, 0, fd_space_size);
|
||||
// align fd_space pointer to pointer size byte boundary, below is safe
|
||||
u8_t ptr_size = sizeof(void*);
|
||||
// #pragma GCC diagnostic push
|
||||
// #pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
|
||||
u8_t addr_lsb = (u8_t)(((u32_t)fd_space) & (ptr_size-1));
|
||||
// #pragma GCC diagnostic pop
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
|
||||
u8_t addr_lsb = ((u8_t)fd_space) & (ptr_size-1);
|
||||
#pragma GCC diagnostic pop
|
||||
if (addr_lsb) {
|
||||
fd_space += (ptr_size-addr_lsb);
|
||||
fd_space_size -= (ptr_size-addr_lsb);
|
||||
|
@ -46,10 +76,10 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
|
|||
fs->fd_count = (fd_space_size/sizeof(spiffs_fd));
|
||||
|
||||
// align cache pointer to 4 byte boundary, below is safe
|
||||
// #pragma GCC diagnostic push
|
||||
// #pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
|
||||
addr_lsb = (u8_t)(((u32_t)cache) & (ptr_size-1));
|
||||
// #pragma GCC diagnostic pop
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
|
||||
addr_lsb = ((u8_t)cache) & (ptr_size-1);
|
||||
#pragma GCC diagnostic pop
|
||||
if (addr_lsb) {
|
||||
u8_t *cache_8 = (u8_t *)cache;
|
||||
cache_8 += (ptr_size-addr_lsb);
|
||||
|
@ -61,11 +91,20 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
|
|||
}
|
||||
#if SPIFFS_CACHE
|
||||
fs->cache = cache;
|
||||
fs->cache_size = cache_size;
|
||||
fs->cache_size = (cache_size > (config->log_page_size*32)) ? config->log_page_size*32 : cache_size;
|
||||
spiffs_cache_init(fs);
|
||||
#endif
|
||||
|
||||
s32_t res = spiffs_obj_lu_scan(fs);
|
||||
s32_t res;
|
||||
|
||||
#if SPIFFS_USE_MAGIC
|
||||
res = SPIFFS_CHECK_MAGIC_POSSIBLE(fs) ? SPIFFS_OK : SPIFFS_ERR_MAGIC_NOT_POSSIBLE;
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
#endif
|
||||
|
||||
fs->config_magic = SPIFFS_CONFIG_MAGIC;
|
||||
|
||||
res = spiffs_obj_lu_scan(fs);
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
|
||||
SPIFFS_DBG("page index byte len: %i\n", SPIFFS_CFG_LOG_PAGE_SZ(fs));
|
||||
|
@ -79,13 +118,15 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
|
|||
|
||||
fs->check_cb_f = check_cb_f;
|
||||
|
||||
fs->mounted = 1;
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SPIFFS_unmount(spiffs *fs) {
|
||||
if (!SPIFFS_CHECK_MOUNT(fs)) return;
|
||||
if (!SPIFFS_CHECK_CFG(fs) || !SPIFFS_CHECK_MOUNT(fs)) return;
|
||||
SPIFFS_LOCK(fs);
|
||||
u32_t i;
|
||||
spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
|
||||
|
@ -98,7 +139,8 @@ void SPIFFS_unmount(spiffs *fs) {
|
|||
spiffs_fd_return(fs, cur_fd->file_nbr);
|
||||
}
|
||||
}
|
||||
fs->block_count = 0;
|
||||
fs->mounted = 0;
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
}
|
||||
|
||||
|
@ -112,6 +154,7 @@ void SPIFFS_clearerr(spiffs *fs) {
|
|||
|
||||
s32_t SPIFFS_creat(spiffs *fs, char *path, spiffs_mode mode) {
|
||||
(void)mode;
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
spiffs_obj_id obj_id;
|
||||
|
@ -127,6 +170,7 @@ s32_t SPIFFS_creat(spiffs *fs, char *path, spiffs_mode mode) {
|
|||
|
||||
spiffs_file SPIFFS_open(spiffs *fs, char *path, spiffs_flags flags, spiffs_mode mode) {
|
||||
(void)mode;
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -185,6 +229,7 @@ spiffs_file SPIFFS_open(spiffs *fs, char *path, spiffs_flags flags, spiffs_mode
|
|||
}
|
||||
|
||||
spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_flags flags, spiffs_mode mode) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -213,7 +258,8 @@ spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_fl
|
|||
return fd->file_nbr;
|
||||
}
|
||||
|
||||
s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, u32_t len) {
|
||||
s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -281,7 +327,8 @@ static s32_t spiffs_hydro_write(spiffs *fs, spiffs_fd *fd, void *buf, u32_t offs
|
|||
|
||||
}
|
||||
|
||||
s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, u32_t len) {
|
||||
s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -400,6 +447,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, u32_t len) {
|
|||
}
|
||||
|
||||
s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -440,10 +488,11 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
|
|||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
|
||||
return 0;
|
||||
return offs;
|
||||
}
|
||||
|
||||
s32_t SPIFFS_remove(spiffs *fs, char *path) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -477,6 +526,7 @@ s32_t SPIFFS_remove(spiffs *fs, char *path) {
|
|||
}
|
||||
|
||||
s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -525,6 +575,7 @@ static s32_t spiffs_stat_pix(spiffs *fs, spiffs_page_ix pix, spiffs_file fh, spi
|
|||
}
|
||||
|
||||
s32_t SPIFFS_stat(spiffs *fs, char *path, spiffs_stat *s) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -542,6 +593,7 @@ s32_t SPIFFS_stat(spiffs *fs, char *path, spiffs_stat *s) {
|
|||
}
|
||||
|
||||
s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -595,6 +647,7 @@ static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh) {
|
|||
}
|
||||
|
||||
s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
s32_t res = SPIFFS_OK;
|
||||
#if SPIFFS_CACHE_WR
|
||||
|
@ -608,6 +661,11 @@ s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) {
|
|||
}
|
||||
|
||||
void SPIFFS_close(spiffs *fs, spiffs_file fh) {
|
||||
if (!SPIFFS_CHECK_CFG((fs))) {
|
||||
(fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SPIFFS_CHECK_MOUNT(fs)) {
|
||||
fs->err_code = SPIFFS_ERR_NOT_MOUNTED;
|
||||
return;
|
||||
|
@ -623,6 +681,7 @@ void SPIFFS_close(spiffs *fs, spiffs_file fh) {
|
|||
}
|
||||
|
||||
s32_t SPIFFS_rename(spiffs *fs, char *old, char *new) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -652,9 +711,8 @@ s32_t SPIFFS_rename(spiffs *fs, char *old, char *new) {
|
|||
res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, fd->objix_hdr_pix, 0, (u8_t*)new,
|
||||
0, &pix_dummy);
|
||||
|
||||
if (res != SPIFFS_OK) {
|
||||
spiffs_fd_return(fs, fd->file_nbr);
|
||||
}
|
||||
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
|
@ -664,10 +722,17 @@ s32_t SPIFFS_rename(spiffs *fs, char *old, char *new) {
|
|||
|
||||
spiffs_DIR *SPIFFS_opendir(spiffs *fs, char *name, spiffs_DIR *d) {
|
||||
(void)name;
|
||||
|
||||
if (!SPIFFS_CHECK_CFG((fs))) {
|
||||
(fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!SPIFFS_CHECK_MOUNT(fs)) {
|
||||
fs->err_code = SPIFFS_ERR_NOT_MOUNTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
d->fs = fs;
|
||||
d->block = 0;
|
||||
d->entry = 0;
|
||||
|
@ -743,12 +808,14 @@ struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e) {
|
|||
}
|
||||
|
||||
s32_t SPIFFS_closedir(spiffs_DIR *d) {
|
||||
SPIFFS_API_CHECK_CFG(d->fs);
|
||||
SPIFFS_API_CHECK_MOUNT(d->fs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32_t SPIFFS_check(spiffs *fs) {
|
||||
s32_t res;
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -766,6 +833,7 @@ s32_t SPIFFS_check(spiffs *fs) {
|
|||
|
||||
s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -787,25 +855,6 @@ s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used) {
|
|||
return res;
|
||||
}
|
||||
|
||||
s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh) {
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
spiffs_fd *fd;
|
||||
s32_t res;
|
||||
res = spiffs_fd_get(fs, fh, &fd);
|
||||
SPIFFS_API_CHECK_RES(fs, res);
|
||||
|
||||
#if SPIFFS_CACHE_WR
|
||||
spiffs_fflush_cache(fs, fh);
|
||||
#endif
|
||||
|
||||
res = (fd->fdoffset == fd->size);
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
return res;
|
||||
}
|
||||
|
||||
s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh) {
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
@ -825,6 +874,25 @@ s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh) {
|
|||
return res;
|
||||
}
|
||||
|
||||
s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh) {
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
spiffs_fd *fd;
|
||||
s32_t res;
|
||||
res = spiffs_fd_get(fs, fh, &fd);
|
||||
SPIFFS_API_CHECK_RES(fs, res);
|
||||
|
||||
#if SPIFFS_CACHE_WR
|
||||
spiffs_fflush_cache(fs, fh);
|
||||
#endif
|
||||
|
||||
res = (fd->fdoffset == fd->size);
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
return res;
|
||||
}
|
||||
|
||||
s32_t SPIFFS_size(spiffs *fs, spiffs_file fh) {
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
@ -844,9 +912,38 @@ s32_t SPIFFS_size(spiffs *fs, spiffs_file fh) {
|
|||
return res;
|
||||
}
|
||||
|
||||
s32_t SPIFFS_gc_quick(spiffs *fs, u16_t max_free_pages) {
|
||||
s32_t res;
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
res = spiffs_gc_quick(fs, max_free_pages);
|
||||
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
SPIFFS_UNLOCK(fs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
s32_t SPIFFS_gc(spiffs *fs, u32_t size) {
|
||||
s32_t res;
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
res = spiffs_gc_check(fs, size);
|
||||
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
SPIFFS_UNLOCK(fs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if SPIFFS_TEST_VISUALISATION
|
||||
s32_t SPIFFS_vis(spiffs *fs) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
|
|
@ -142,11 +142,15 @@ s32_t spiffs_obj_lu_find_entry_visitor(
|
|||
cur_block++;
|
||||
cur_block_addr = cur_block * SPIFFS_CFG_LOG_BLOCK_SZ(fs);
|
||||
if (cur_block >= fs->block_count) {
|
||||
if (flags & SPIFFS_VIS_NO_WRAP) {
|
||||
return SPIFFS_VIS_END;
|
||||
} else {
|
||||
// block wrap
|
||||
cur_block = 0;
|
||||
cur_block_addr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check each block
|
||||
while (res == SPIFFS_OK && entry_count > 0) {
|
||||
|
@ -213,6 +217,45 @@ s32_t spiffs_obj_lu_find_entry_visitor(
|
|||
return SPIFFS_VIS_END;
|
||||
}
|
||||
|
||||
s32_t spiffs_erase_block(
|
||||
spiffs *fs,
|
||||
spiffs_block_ix bix) {
|
||||
s32_t res;
|
||||
u32_t addr = SPIFFS_BLOCK_TO_PADDR(fs, bix);
|
||||
s32_t size = SPIFFS_CFG_LOG_BLOCK_SZ(fs);
|
||||
|
||||
// here we ignore res, just try erasing the block
|
||||
while (size > 0) {
|
||||
SPIFFS_DBG("erase %08x:%08x\n", addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
|
||||
(void)fs->cfg.hal_erase_f(addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
|
||||
addr += SPIFFS_CFG_PHYS_ERASE_SZ(fs);
|
||||
size -= SPIFFS_CFG_PHYS_ERASE_SZ(fs);
|
||||
}
|
||||
fs->free_blocks++;
|
||||
|
||||
// register erase count for this block
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_C_WRTHRU | SPIFFS_OP_T_OBJ_LU2, 0,
|
||||
SPIFFS_ERASE_COUNT_PADDR(fs, bix),
|
||||
sizeof(spiffs_obj_id), (u8_t *)&fs->max_erase_count);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
#if SPIFFS_USE_MAGIC
|
||||
// finally, write magic
|
||||
spiffs_obj_id magic = SPIFFS_MAGIC(fs);
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_C_WRTHRU | SPIFFS_OP_T_OBJ_LU2, 0,
|
||||
SPIFFS_MAGIC_PADDR(fs, bix),
|
||||
sizeof(spiffs_obj_id), (u8_t *)&magic);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
#endif
|
||||
|
||||
fs->max_erase_count++;
|
||||
if (fs->max_erase_count == SPIFFS_OBJ_ID_IX_FLAG) {
|
||||
fs->max_erase_count = 0;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static s32_t spiffs_obj_lu_scan_v(
|
||||
spiffs *fs,
|
||||
|
@ -238,40 +281,44 @@ static s32_t spiffs_obj_lu_scan_v(
|
|||
return SPIFFS_VIS_COUNTINUE;
|
||||
}
|
||||
|
||||
|
||||
// Scans thru all obj lu and counts free, deleted and used pages
|
||||
// Find the maximum block erase count
|
||||
// Checks magic if enabled
|
||||
s32_t spiffs_obj_lu_scan(
|
||||
spiffs *fs) {
|
||||
s32_t res;
|
||||
spiffs_block_ix bix;
|
||||
int entry;
|
||||
#if SPIFFS_USE_MAGIC
|
||||
spiffs_block_ix unerased_bix = (spiffs_block_ix)-1;
|
||||
#endif
|
||||
|
||||
fs->free_blocks = 0;
|
||||
fs->stats_p_allocated = 0;
|
||||
fs->stats_p_deleted = 0;
|
||||
|
||||
res = spiffs_obj_lu_find_entry_visitor(fs,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
spiffs_obj_lu_scan_v,
|
||||
0,
|
||||
0,
|
||||
&bix,
|
||||
&entry);
|
||||
|
||||
if (res == SPIFFS_VIS_END) {
|
||||
res = SPIFFS_OK;
|
||||
}
|
||||
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
// find out erase count
|
||||
// if enabled, check magic
|
||||
bix = 0;
|
||||
spiffs_obj_id erase_count_final;
|
||||
spiffs_obj_id erase_count_min = SPIFFS_OBJ_ID_FREE;
|
||||
spiffs_obj_id erase_count_max = 0;
|
||||
while (bix < fs->block_count) {
|
||||
#if SPIFFS_USE_MAGIC
|
||||
spiffs_obj_id magic;
|
||||
res = _spiffs_rd(fs,
|
||||
SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_MAGIC_PADDR(fs, bix) ,
|
||||
sizeof(spiffs_obj_id), (u8_t *)&magic);
|
||||
|
||||
SPIFFS_CHECK_RES(res);
|
||||
if (magic != SPIFFS_MAGIC(fs)) {
|
||||
if (unerased_bix == (spiffs_block_ix)-1) {
|
||||
// allow one unerased block as it might be powered down during an erase
|
||||
unerased_bix = bix;
|
||||
} else {
|
||||
// more than one unerased block, bail out
|
||||
SPIFFS_CHECK_RES(SPIFFS_ERR_NOT_A_FS);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
spiffs_obj_id erase_count;
|
||||
res = _spiffs_rd(fs,
|
||||
SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
|
@ -297,6 +344,38 @@ s32_t spiffs_obj_lu_scan(
|
|||
|
||||
fs->max_erase_count = erase_count_final;
|
||||
|
||||
#if SPIFFS_USE_MAGIC
|
||||
if (unerased_bix != (spiffs_block_ix)-1) {
|
||||
// found one unerased block, remedy
|
||||
SPIFFS_DBG("mount: erase block %i\n", bix);
|
||||
res = spiffs_erase_block(fs, unerased_bix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
#endif
|
||||
|
||||
// count blocks
|
||||
|
||||
fs->free_blocks = 0;
|
||||
fs->stats_p_allocated = 0;
|
||||
fs->stats_p_deleted = 0;
|
||||
|
||||
res = spiffs_obj_lu_find_entry_visitor(fs,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
spiffs_obj_lu_scan_v,
|
||||
0,
|
||||
0,
|
||||
&bix,
|
||||
&entry);
|
||||
|
||||
if (res == SPIFFS_VIS_END) {
|
||||
res = SPIFFS_OK;
|
||||
}
|
||||
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -310,7 +389,10 @@ s32_t spiffs_obj_lu_find_free(
|
|||
int *lu_entry) {
|
||||
s32_t res;
|
||||
if (!fs->cleaning && fs->free_blocks < 2) {
|
||||
res = spiffs_gc_quick(fs);
|
||||
res = spiffs_gc_quick(fs, 0);
|
||||
if (res == SPIFFS_ERR_NO_DELETED_BLOCKS) {
|
||||
res = SPIFFS_OK;
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
if (fs->free_blocks < 2) {
|
||||
return SPIFFS_ERR_FULL;
|
||||
|
|
|
@ -124,13 +124,17 @@
|
|||
#define SPIFFS_EV_IX_NEW 1
|
||||
#define SPIFFS_EV_IX_DEL 2
|
||||
|
||||
#define SPIFFS_OBJ_ID_IX_FLAG (1<<(8*sizeof(spiffs_obj_id)-1))
|
||||
#define SPIFFS_OBJ_ID_IX_FLAG ((spiffs_obj_id)(1<<(8*sizeof(spiffs_obj_id)-1)))
|
||||
|
||||
#define SPIFFS_UNDEFINED_LEN (u32_t)(-1)
|
||||
|
||||
#define SPIFFS_OBJ_ID_DELETED ((spiffs_obj_id)0)
|
||||
#define SPIFFS_OBJ_ID_FREE ((spiffs_obj_id)-1)
|
||||
|
||||
#define SPIFFS_MAGIC(fs) ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs)))
|
||||
|
||||
#define SPIFFS_CONFIG_MAGIC (0x20090315)
|
||||
|
||||
#if SPIFFS_SINGLETON == 0
|
||||
#define SPIFFS_CFG_LOG_PAGE_SZ(fs) \
|
||||
((fs)->cfg.log_page_size)
|
||||
|
@ -189,9 +193,18 @@
|
|||
// returns data size in a data page
|
||||
#define SPIFFS_DATA_PAGE_SIZE(fs) \
|
||||
( SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header) )
|
||||
// returns physical address for block's erase count
|
||||
// returns physical address for block's erase count,
|
||||
// always in the physical last entry of the last object lookup page
|
||||
#define SPIFFS_ERASE_COUNT_PADDR(fs, bix) \
|
||||
( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id) )
|
||||
// returns physical address for block's magic,
|
||||
// always in the physical second last entry of the last object lookup page
|
||||
#define SPIFFS_MAGIC_PADDR(fs, bix) \
|
||||
( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id)*2 )
|
||||
// checks if there is any room for magic in the object luts
|
||||
#define SPIFFS_CHECK_MAGIC_POSSIBLE(fs) \
|
||||
( (SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) % (SPIFFS_CFG_LOG_PAGE_SZ(fs)/sizeof(spiffs_obj_id))) * sizeof(spiffs_obj_id) \
|
||||
<= (SPIFFS_CFG_LOG_PAGE_SZ(fs)-sizeof(spiffs_obj_id)*2) )
|
||||
|
||||
// define helpers object
|
||||
|
||||
|
@ -238,7 +251,10 @@
|
|||
|
||||
|
||||
#define SPIFFS_CHECK_MOUNT(fs) \
|
||||
((fs)->block_count > 0)
|
||||
((fs)->mounted != 0)
|
||||
|
||||
#define SPIFFS_CHECK_CFG(fs) \
|
||||
((fs)->config_magic == SPIFFS_CONFIG_MAGIC)
|
||||
|
||||
#define SPIFFS_CHECK_RES(res) \
|
||||
do { \
|
||||
|
@ -251,6 +267,12 @@
|
|||
return -1; \
|
||||
}
|
||||
|
||||
#define SPIFFS_API_CHECK_CFG(fs) \
|
||||
if (!SPIFFS_CHECK_CFG((fs))) { \
|
||||
(fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED; \
|
||||
return -1; \
|
||||
}
|
||||
|
||||
#define SPIFFS_API_CHECK_RES(fs, res) \
|
||||
if ((res) < SPIFFS_OK) { \
|
||||
(fs)->err_code = (res); \
|
||||
|
@ -381,6 +403,8 @@ typedef struct {
|
|||
// object structs
|
||||
|
||||
// page header, part of each page except object lookup pages
|
||||
// NB: this is always aligned when the data page is an object index,
|
||||
// as in this case struct spiffs_page_object_ix is used
|
||||
typedef struct __attribute(( packed )) {
|
||||
// object id
|
||||
spiffs_obj_id obj_id;
|
||||
|
@ -391,11 +415,10 @@ typedef struct __attribute(( packed )) {
|
|||
} spiffs_page_header;
|
||||
|
||||
// object index header page header
|
||||
typedef struct __attribute(( packed )) {
|
||||
typedef struct __attribute(( packed, aligned(4) ))
|
||||
{
|
||||
// common page header
|
||||
spiffs_page_header p_hdr;
|
||||
// alignment
|
||||
u8_t _align[4 - ((sizeof(spiffs_page_header)+sizeof(spiffs_obj_type)+SPIFFS_OBJ_NAME_LEN)&3)==0 ? 4 : ((sizeof(spiffs_page_header)+sizeof(spiffs_obj_type)+SPIFFS_OBJ_NAME_LEN)&3)];
|
||||
// size of object
|
||||
u32_t size;
|
||||
// type of object
|
||||
|
@ -405,9 +428,8 @@ typedef struct __attribute(( packed )) {
|
|||
} spiffs_page_object_ix_header;
|
||||
|
||||
// object index page header
|
||||
typedef struct __attribute(( packed )) {
|
||||
typedef struct __attribute(( packed, aligned(4) )) {
|
||||
spiffs_page_header p_hdr;
|
||||
u8_t _align[4 - (sizeof(spiffs_page_header)&3)==0 ? 4 : (sizeof(spiffs_page_header)&3)];
|
||||
} spiffs_page_object_ix;
|
||||
|
||||
// callback func for object lookup visitor
|
||||
|
@ -478,6 +500,10 @@ s32_t spiffs_obj_lu_find_entry_visitor(
|
|||
spiffs_block_ix *block_ix,
|
||||
int *lu_entry);
|
||||
|
||||
s32_t spiffs_erase_block(
|
||||
spiffs *fs,
|
||||
spiffs_block_ix bix);
|
||||
|
||||
// ---------------
|
||||
|
||||
s32_t spiffs_obj_lu_scan(
|
||||
|
@ -625,14 +651,15 @@ s32_t spiffs_gc_erase_page_stats(
|
|||
s32_t spiffs_gc_find_candidate(
|
||||
spiffs *fs,
|
||||
spiffs_block_ix **block_candidate,
|
||||
int *candidate_count);
|
||||
int *candidate_count,
|
||||
char fs_crammed);
|
||||
|
||||
s32_t spiffs_gc_clean(
|
||||
spiffs *fs,
|
||||
spiffs_block_ix bix);
|
||||
|
||||
s32_t spiffs_gc_quick(
|
||||
spiffs *fs);
|
||||
spiffs *fs, u16_t max_free_pages);
|
||||
|
||||
// ---------------
|
||||
|
||||
|
|
Loading…
Reference in New Issue