4.3. spiffs — SPI Flash File System

The source code of this module is based on https://github.com/pellepl/spiffs.

4.3.1. About

Spiffs is a file system intended for SPI NOR flash devices on embedded targets.

Spiffs is designed with following characteristics in mind:

  • Small (embedded) targets, sparse RAM without heap.
  • Only big areas of data (blocks) can be erased.
  • An erase will reset all bits in block to ones.
  • Writing pulls one to zeroes.
  • Zeroes can only be pulled to ones by erase.
  • Wear leveling.

Source code: src/filesystems/spiffs.h, src/filesystems/spiffs.c

Test code: tst/filesystems/spiffs/main.c


Defines

SPIFFS_OK
SPIFFS_ERR_NOT_MOUNTED
SPIFFS_ERR_FULL
SPIFFS_ERR_NOT_FOUND
SPIFFS_ERR_END_OF_OBJECT
SPIFFS_ERR_DELETED
SPIFFS_ERR_NOT_FINALIZED
SPIFFS_ERR_NOT_INDEX
SPIFFS_ERR_OUT_OF_FILE_DESCS
SPIFFS_ERR_FILE_CLOSED
SPIFFS_ERR_FILE_DELETED
SPIFFS_ERR_BAD_DESCRIPTOR
SPIFFS_ERR_IS_INDEX
SPIFFS_ERR_IS_FREE
SPIFFS_ERR_INDEX_SPAN_MISMATCH
SPIFFS_ERR_DATA_SPAN_MISMATCH
SPIFFS_ERR_INDEX_REF_FREE
SPIFFS_ERR_INDEX_REF_LU
SPIFFS_ERR_INDEX_REF_INVALID
SPIFFS_ERR_INDEX_FREE
SPIFFS_ERR_INDEX_LU
SPIFFS_ERR_INDEX_INVALID
SPIFFS_ERR_NOT_WRITABLE
SPIFFS_ERR_NOT_READABLE
SPIFFS_ERR_CONFLICTING_NAME
SPIFFS_ERR_NOT_CONFIGURED
SPIFFS_ERR_NOT_A_FS
SPIFFS_ERR_MOUNTED
SPIFFS_ERR_ERASE_FAIL
SPIFFS_ERR_MAGIC_NOT_POSSIBLE
SPIFFS_ERR_NO_DELETED_BLOCKS
SPIFFS_ERR_FILE_EXISTS
SPIFFS_ERR_NOT_A_FILE
SPIFFS_ERR_RO_NOT_IMPL
SPIFFS_ERR_RO_ABORTED_OPERATION
SPIFFS_ERR_PROBE_TOO_FEW_BLOCKS
SPIFFS_ERR_PROBE_NOT_A_FS
SPIFFS_ERR_NAME_TOO_LONG
SPIFFS_ERR_INTERNAL
SPIFFS_ERR_TEST
SPIFFS_DBG(...)
SPIFFS_GC_DBG(...)
SPIFFS_CACHE_DBG(...)
SPIFFS_CHECK_DBG(...)
SPIFFS_APPEND

Any write to the filehandle is appended to end of the file.

SPIFFS_O_APPEND
SPIFFS_TRUNC

If the opened file exists, it will be truncated to zero length before opened.

SPIFFS_O_TRUNC
SPIFFS_CREAT

If the opened file does not exist, it will be created before opened.

SPIFFS_O_CREAT
SPIFFS_RDONLY

The opened file may only be read.

SPIFFS_O_RDONLY
SPIFFS_WRONLY

The opened file may only be written.

SPIFFS_O_WRONLY
SPIFFS_RDWR

The opened file may be both read and written.

SPIFFS_O_RDWR
SPIFFS_DIRECT

Any writes to the filehandle will never be cached but flushed directly.

SPIFFS_O_DIRECT
SPIFFS_EXCL

If SPIFFS_O_CREAT and SPIFFS_O_EXCL are set, SPIFFS_open() shall fail if the file exists.

SPIFFS_O_EXCL
SPIFFS_SEEK_SET
SPIFFS_SEEK_CUR
SPIFFS_SEEK_END
SPIFFS_TYPE_FILE
SPIFFS_TYPE_DIR
SPIFFS_LOCK(fs)
SPIFFS_UNLOCK(fs)

Typedefs

typedef int16_t spiffs_file_t

Spiffs file descriptor index type. must be signed.

typedef uint16_t spiffs_flags_t

Spiffs file descriptor flags.

typedef uint16_t spiffs_mode_t

Spiffs file mode.

typedef uint8_t spiffs_obj_type_t

Object type.

typedef int32_t (*spiffs_read_cb_t)(uint32_t addr, uint32_t size, uint8_t *dst_p)

Spi read call function type.

typedef int32_t (*spiffs_write_cb_t)(uint32_t addr, uint32_t size, uint8_t *src_p)

Spi write call function type.

typedef int32_t (*spiffs_erase_cb_t)(uint32_t addr, uint32_t size)

Spi erase call function type.

typedef void (*spiffs_check_callback_t)(enum spiffs_check_type_t type, enum spiffs_check_report_t report, uint32_t arg1, uint32_t arg2)

File system check callback function.

typedef void (*spiffs_file_callback_t)(struct spiffs_t *fs_p, enum spiffs_fileop_type_t op, spiffs_obj_id_t obj_id, spiffs_page_ix_t pix)

File system listener callback function.

typedef spiffs_block_ix_t spiffs_block_ix
typedef spiffs_page_ix_t spiffs_page_ix
typedef spiffs_obj_id_t spiffs_obj_id
typedef spiffs_span_ix_t spiffs_span_ix
typedef struct spiffs_t spiffs
typedef spiffs_file_t spiffs_file
typedef spiffs_flags_t spiffs_flags
typedef spiffs_obj_type_t spiffs_obj_type
typedef spiffs_mode_t spiffs_mode
typedef enum spiffs_fileop_type_t spiffs_fileop_type
typedef struct spiffs_config_t spiffs_config
typedef spiffs_check_callback_t spiffs_check_callback
typedef struct spiffs_dirent_t spiffs_dirent
typedef struct spiffs_dir_t spiffs_DIR
typedef spiffs_file_callback_t spiffs_file_callback

Enums

enum spiffs_check_type_t

File system check callback report operation.

Values:

SPIFFS_CHECK_LOOKUP = 0
SPIFFS_CHECK_INDEX
SPIFFS_CHECK_PAGE
enum spiffs_check_report_t

File system check callback report type.

Values:

SPIFFS_CHECK_PROGRESS = 0
SPIFFS_CHECK_ERROR
SPIFFS_CHECK_FIX_INDEX
SPIFFS_CHECK_FIX_LOOKUP
SPIFFS_CHECK_DELETE_ORPHANED_INDEX
SPIFFS_CHECK_DELETE_PAGE
SPIFFS_CHECK_DELETE_BAD_FILE
enum spiffs_fileop_type_t

File system listener callback operation.

Values:

SPIFFS_CB_CREATED = 0

The file has been created.

SPIFFS_CB_UPDATED

The file has been updated or moved to another page.

SPIFFS_CB_DELETED

The file has been deleted.

Functions

int32_t spiffs_mount(struct spiffs_t *self_p, struct spiffs_config_t *config_p, uint8_t *work_p, uint8_t *fd_space_p, uint32_t fd_space_size, void *cache_p, uint32_t cache_size, spiffs_check_callback_t check_cb)

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.

Return
zero(0) or negative error code.
Parameters
  • self_p: The file system struct.
  • config_p: The physical and logical configuration of the file system.
  • work_p: A memory work buffer comprising 2*config->log_page_size bytes used throughout all file system operations
  • fd_space_p: Memory for file descriptors.
  • fd_space_size: Memory size of file descriptors.
  • cache_p: Memory for cache, may be NULL.
  • cache_size: Memory size of cache.
  • check_cb: Callback function for reporting during consistency checks.

void spiffs_unmount(struct spiffs_t *self_p)

Unmounts the file system. All file handles will be flushed of any cached writes and closed.

Return
void.
Parameters
  • self_p: The file system struct.

int32_t spiffs_creat(struct spiffs_t *self_p, const char *path_p, spiffs_mode_t mode)

Creates a new file.

Return
zero(0) or negative error code.
Parameters
  • self_p: The file system struct.
  • path_p: The path of the new file.
  • mode: Ignored, for posix compliance.

spiffs_file_t spiffs_open(struct spiffs_t *self_p, const char *path_p, spiffs_flags_t flags, spiffs_mode_t mode)

Opens/creates a file.

Parameters
  • self_p: The file system struct.
  • path_p: The path of the new file.
  • flags: The flags for the open command, can be combinations of SPIFFS_O_APPEND, SPIFFS_O_TRUNC, SPIFFS_O_CREAT, SPIFFS_O_RDONLY, SPIFFS_O_WRONLY, SPIFFS_O_RDWR, SPIFFS_O_DIRECT, SPIFFS_O_EXCL.
  • mode: Ignored, for posix compliance.

spiffs_file_t spiffs_open_by_dirent(struct spiffs_t *self_p, struct spiffs_dirent_t *ent_p, spiffs_flags_t flags, spiffs_mode_t mode)

Opens a file by given dir entry.

Optimization purposes, when traversing a file system with SPIFFS_readdir a normal SPIFFS_open would need to traverse the filesystem again to find the file, whilst SPIFFS_open_by_dirent already knows where the file resides.

Parameters
  • self_p: The file system struct.
  • e_p: The dir entry to the file.
  • flags: The flags for the open command, can be combinations of SPIFFS_APPEND, SPIFFS_TRUNC, SPIFFS_CREAT, SPIFFS_RD_ONLY, SPIFFS_WR_ONLY, SPIFFS_RDWR, SPIFFS_DIRECT. SPIFFS_CREAT will have no effect in this case.
  • mode: Ignored, for posix compliance.

spiffs_file_t spiffs_open_by_page(struct spiffs_t *self_p, spiffs_page_ix_t page_ix, spiffs_flags_t flags, spiffs_mode_t mode)

Opens a file by given page index.

Optimization purposes, opens a file by directly pointing to the page index in the spi flash. If the page index does not point to a file header SPIFFS_ERR_NOT_A_FILE is returned.

Parameters
  • self_p: The file system struct.
  • page_ix: The page index.
  • flags: The flags for the open command, can be combinations of SPIFFS_APPEND, SPIFFS_TRUNC, SPIFFS_CREAT, SPIFFS_RD_ONLY, SPIFFS_WR_ONLY, SPIFFS_RDWR, SPIFFS_DIRECT. SPIFFS_CREAT will have no effect in this case.
  • mode: Ignored, for posix compliance.

int32_t spiffs_read(struct spiffs_t *self_p, spiffs_file_t fh, void *buf_p, int32_t len)

Reads from given filehandle.

Return
Number of bytes read or negative error code.
Parameters
  • self_p: The file system struct.
  • fh: The filehandle.
  • buf_p: Where to put read data.
  • len: How much to read.

int32_t spiffs_write(struct spiffs_t *self_p, spiffs_file_t fh, void *buf_p, int32_t len)

Writes to given filehandle.

Return
Number of bytes written, or negative error code.
Parameters
  • self_p: The file system struct.
  • fh: The filehandle.
  • buf_p: The data to write.
  • len: How much to write.

int32_t spiffs_lseek(struct spiffs_t *self_p, spiffs_file_t fh, int32_t offs, int whence)

Moves the read/write file offset. Resulting offset is returned or negative if error.

lseek(fs, fd, 0, SPIFFS_SEEK_CUR) will thus return current offset.

If SPIFFS_SEEK_CUR, the file offset shall be set to its current location plus offset.

Parameters
  • self_p: The file system struct.
  • fh: The filehandle.
  • offs: How much/where to move the offset.
  • whence: If SPIFFS_SEEK_SET, the file offset shall be set to offset bytes.

If SPIFFS_SEEK_END, the file offset shall be set to the size of the file plus offse, which should be negative.

Return
zero(0) or negative error code.

int32_t spiffs_remove(struct spiffs_t *self_p, const char *path_p)

Removes a file by path.

Return
zero(0) or negative error code.
Parameters
  • self_p: The file system struct.
  • path_p: The path of the file to remove.

int32_t spiffs_fremove(struct spiffs_t *self_p, spiffs_file_t fh)

Removes a file by filehandle.

Return
zero(0) or negative error code.
Parameters
  • self_p: The file system struct.
  • fh: The filehandle of the file to remove.

int32_t spiffs_stat(struct spiffs_t *self_p, const char *path_p, struct spiffs_stat_t *stat_p)

Gets file status by path.

Return
zero(0) or negative error code.
Parameters
  • self_p: The file system struct.
  • path_p: The path of the file to stat.
  • stat_p: The stat struct to populate.

int32_t spiffs_fstat(struct spiffs_t *self_p, spiffs_file_t fh, struct spiffs_stat_t *stat_p)

Gets file status by filehandle.

Return
zero(0) or negative error code.
Parameters
  • self_p: The file system struct.
  • fh: The filehandle of the file to stat.
  • stat_p: The stat struct to populate.

int32_t spiffs_fflush(struct spiffs_t *self_p, spiffs_file_t fh)

Flushes all pending write operations from cache for given file.

Return
zero(0) or negative error code.
Parameters
  • self_p: The file system struct.
  • fh: The filehandle of the file to flush.

int32_t spiffs_close(struct spiffs_t *self_p, spiffs_file_t fh)

Closes a filehandle. If there are pending write operations, these are finalized before closing.

Return
zero(0) or negative error code.
Parameters
  • self_p: The file system struct.
  • fh: The filehandle of the file to close.

int32_t spiffs_rename(struct spiffs_t *self_p, const char *old_path_p, const char *new_path_p)

Renames a file.

Return
zero(0) or negative error code.
Parameters
  • self_p: The file system struct.
  • old_path_p: Path of file to rename.
  • new_path_p: New path of file.

int32_t spiffs_errno(struct spiffs_t *self_p)

Returns last error of last file operation.

Return
zero(0) or negative error code.
Parameters
  • self_p: The file system struct.

void spiffs_clearerr(struct spiffs_t *self_p)

Clears last error.

Return
void.
Parameters
  • self_p: The file system struct.

struct spiffs_dir_t *spiffs_opendir(struct spiffs_t *self_p, const char *name_p, struct spiffs_dir_t *dir_p)

Opens a directory stream corresponding to the given name. The stream is positioned at the first entry in the directory. On hydrogen builds the name argument is ignored as hydrogen builds always correspond to a flat file structure - no directories.

Parameters
  • self_p: The file system struct.
  • name_p: The name of the directory.
  • dir_p: Pointer the directory stream to be populated.

int32_t spiffs_closedir(struct spiffs_dir_t *dir_p)

Closes a directory stream

Return
zero(0) or negative error code.
Parameters
  • dir_p: The directory stream to close.

struct spiffs_dirent_t *spiffs_readdir(struct spiffs_dir_t *dir_p, struct spiffs_dirent_t *ent_p)

Reads a directory into given spifs_dirent struct.

Return
NULL if error or end of stream, else given dirent is returned.
Parameters
  • dir_p: Pointer to the directory stream.
  • ent_p: The dirent struct to be populated.

int32_t spiffs_check(struct spiffs_t *self_p)

Runs a consistency check on given filesystem.

Return
zero(0) or negative error code.
Parameters
  • self_p: The file system struct.

int32_t spiffs_info(struct spiffs_t *self_p, uint32_t *total_p, uint32_t *used_p)

Returns number of total bytes available and number of used bytes. This is an estimation, and depends on if there a many files with little data or few files with much data.

NB: If used number of bytes exceeds total bytes, a SPIFFS_check should run. This indicates a power loss in midst of things. In worst case (repeated powerlosses in mending or gc) you might have to delete some files.

Return
zero(0) or negative error code.
Parameters
  • self_p: The file system struct.
  • total_p: Total number of bytes in filesystem.
  • used_p: Used number of bytes in filesystem.

int32_t spiffs_format(struct spiffs_t *self_p)

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.

Return
zero(0) or negative error code.
Parameters
  • self_p: The file system struct.

uint8_t spiffs_mounted(struct spiffs_t *self_p)

Returns nonzero if spiffs is mounted, or zero if unmounted.

Parameters
  • self_p: The file system struct.

int32_t spiffs_gc_quick(struct spiffs_t *self_p, uint16_t max_free_pages)

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.

Return
zero(0) or negative error code.
Parameters
  • self_p: The file system struct.
  • max_free_pages: maximum number allowed free pages in block.

int32_t spiffs_gc(struct spiffs_t *self_p, uint32_t size)

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.

Return
zero(0) or negative error code.
Parameters
  • self_p: The file system struct.
  • size: Amount of bytes that should be freed.

int32_t spiffs_eof(struct spiffs_t *self_p, spiffs_file_t fh)

Check if EOF reached.

Return
zero(0) or negative error code.
Parameters
  • self_p: The file system struct.
  • fh: The filehandle of the file to check.

int32_t spiffs_tell(struct spiffs_t *self_p, spiffs_file_t fh)

Get position in file.

Return
zero(0) or negative error code.
Parameters
  • self_p: The file system struct.
  • fh: The filehandle of the file to check.

int32_t spiffs_set_file_callback_func(struct spiffs_t *self_p, spiffs_file_callback_t cb_func)

Registers a callback function that keeps track on operations on file headers. Do note, that this callback is called from within internal spiffs mechanisms. Any operations on the actual file system being callbacked from in this callback will mess things up for sure - do not do this. This can be used to track where files are and move around during garbage collection, which in turn can be used to build location tables in ram. Used in conjuction with SPIFFS_open_by_page this may improve performance when opening a lot of files. Must be invoked after mount.

Return
zero(0) or negative error code.
Parameters
  • self_p: The file system struct.
  • cb_func: The callback on file operations.

struct spiffs_config_t
#include <spiffs.h>

Spiffs spi configuration struct.

Public Members

spiffs_read_cb_t spiffs_config_thal_read_f

Physical read function.

spiffs_write_cb_t spiffs_config_thal_write_f

Physical write function.

spiffs_erase_cb_t spiffs_config_thal_erase_f

Physical erase function.

uint32_t spiffs_config_tphys_size

Physical size of the spi flash.

uint32_t spiffs_config_tphys_addr

Physical offset in spi flash used for spiffs, must be on block boundary.

uint32_t spiffs_config_tphys_erase_block

Physical size when erasing a block.

uint32_t spiffs_config_tlog_block_size

Logical size of a block, must be on physical block size boundary and must never be less than a physical block.

uint32_t spiffs_config_tlog_page_size

Logical size of a page, must be at least log_block_size /

struct spiffs_t

Public Members

struct spiffs_config_t spiffs_tcfg

File system configuration.

uint32_t spiffs_tblock_count

Number of logical blocks.

spiffs_block_ix_t spiffs_tfree_cursor_block_ix

Cursor for free blocks, block index.

int spiffs_tfree_cursor_obj_lu_entry

Cursor for free blocks, entry index.

spiffs_block_ix_t spiffs_tcursor_block_ix

Cursor when searching, block index.

int spiffs_tcursor_obj_lu_entry

Cursor when searching, entry index.

uint8_t *spiffs_tlu_work

Primary work buffer, size of a logical page.

uint8_t *spiffs_twork

Secondary work buffer, size of a logical page.

uint8_t *spiffs_tfd_space

File descriptor memory area.

uint32_t spiffs_tfd_count

Available file descriptors.

int32_t spiffs_terr_code

Last error.

uint32_t spiffs_tfree_blocks

Current number of free blocks.

uint32_t spiffs_tstats_p_allocated

Current number of busy pages.

uint32_t spiffs_tstats_p_deleted

Current number of deleted pages.

uint8_t spiffs_tcleaning

Flag indicating that garbage collector is cleaning.

spiffs_obj_id_t spiffs_tmax_erase_count

Max erase count amongst all blocks.

spiffs_check_callback_t spiffs_tcheck_cb_f

Check callback function.

spiffs_file_callback_t spiffs_tfile_cb_f

File callback function.

uint8_t spiffs_tmounted

Mounted flag.

void *spiffs_tuser_data

User data.

uint32_t spiffs_tconfig_magic

Config magic.

struct spiffs_stat_t
#include <spiffs.h>

Spiffs file status struct.

Public Members

spiffs_obj_id_t spiffs_stat_tobj_id
uint32_t spiffs_stat_tsize
spiffs_obj_type_t spiffs_stat_ttype
spiffs_page_ix_t spiffs_stat_tpix
uint8_t spiffs_stat_tname[SPIFFS_OBJ_NAME_LEN]
struct spiffs_dirent_t

Public Members

spiffs_obj_id_t spiffs_dirent_tobj_id
uint8_t spiffs_dirent_tname[SPIFFS_OBJ_NAME_LEN]
spiffs_obj_type_t spiffs_dirent_ttype
uint32_t spiffs_dirent_tsize
spiffs_page_ix_t spiffs_dirent_tpix
struct spiffs_dir_t

Public Members

struct spiffs_t *spiffs_dir_tfs
spiffs_block_ix_t spiffs_dir_tblock
int spiffs_dir_tentry