mirror of
https://github.com/pellepl/spiffs.git
synced 2025-08-06 14:50:17 +08:00
added more documentation, error result for prohibited r|w, MIN MAX define
This commit is contained in:
14
README
14
README
@ -12,7 +12,7 @@ Love to hear feedback though!
|
||||
|
||||
* INTRODUCTION
|
||||
|
||||
Spiffs is a file system intended for SPI flash devices on embedded targets.
|
||||
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
|
||||
@ -22,7 +22,8 @@ Spiffs is designed with following characteristics in mind:
|
||||
- Zeroes can only be pulled to ones by erase
|
||||
- Wear leveling
|
||||
|
||||
** Features
|
||||
|
||||
* FEATURES
|
||||
|
||||
What spiffs does:
|
||||
- Posix-like api: open, close, read, write, seek, stat, etc
|
||||
@ -32,6 +33,7 @@ What spiffs does:
|
||||
SPI flash device
|
||||
- Implements static wear leveling
|
||||
- Built in file system consistency checks
|
||||
- Specifically designed for low ram usage
|
||||
|
||||
What spiffs does not:
|
||||
- Presently, spiffs does not support directories. It produces a flat
|
||||
@ -40,9 +42,15 @@ What spiffs does not:
|
||||
- It is not a realtime stack. One write operation might take much longer than
|
||||
another.
|
||||
- Poor scalability. Spiffs is intended for small memory devices - the normal
|
||||
sizes for SPI flashes. Going beyond ~128MB is probably a bad idea.
|
||||
sizes for SPI flashes. Going beyond ~128MB is probably a bad idea. This is
|
||||
a side effect of the design goal to use as little ram as possible.
|
||||
- Presently, it does not detect or handle bad blocks.
|
||||
|
||||
|
||||
* MORE INFO
|
||||
|
||||
For integration, see the docs/INTEGRATION file.
|
||||
|
||||
For use and design, see the docs/TECH_SPEC file.
|
||||
|
||||
For testing and contributions, see the docs/IMPLEMENTING file.
|
||||
|
@ -14,7 +14,7 @@ First and foremost, one must decide how to divide up the SPI flash for spiffs.
|
||||
Having the datasheet for the actual SPI flash in hand will help. Spiffs can be
|
||||
defined to use all or only parts of the SPI flash.
|
||||
|
||||
If following seems arcane, read the "DESIGN" chapter first.
|
||||
If following seems arcane, read the "HOW TO CONFIG" chapter first.
|
||||
|
||||
- Decide the logical size of blocks. This must be a multiple of the biggest
|
||||
physical SPI flash block size. To go safe, use the physical block size -
|
||||
@ -85,16 +85,26 @@ The config struct must be initialized prior to mounting. One must always
|
||||
define the SPI flash access functions:
|
||||
|
||||
spiffs_config.hal_read_f - pointing to the function reading the SPI flash
|
||||
|
||||
spiffs_config.hal_write_f - pointing to the function writing the SPI flash
|
||||
|
||||
spiffs_config.hal_erase_f - pointing to the function erasing the SPI flash
|
||||
|
||||
|
||||
Depending on the build config - if SPIFFS_SINGLETON is undefined - following
|
||||
parameters must be defined:
|
||||
|
||||
spiffs_config.phys_size - the physical number of bytes accounted for
|
||||
spiffs on the SPI flash
|
||||
|
||||
spiffs_config.phys_addr - the physical starting address on the SPI flash
|
||||
|
||||
TODO
|
||||
spiffs_config.phys_erase_block - the physical size of the largest block/sector
|
||||
on the SPI flash found within the spiffs
|
||||
usage address space
|
||||
|
||||
spiffs_config.log_block_size -
|
||||
|
||||
spiffs_config.log_page_size -
|
||||
|
||||
** Build config
|
||||
|
||||
@ -107,6 +117,21 @@ be typedeffed.
|
||||
spiffs_config.h: you also need to define a spiffs_config.h header. Example of
|
||||
this is found in the default/ directory.
|
||||
|
||||
** RAM
|
||||
|
||||
Spiffs needs ram. It needs a working buffer being double the size of the
|
||||
logical page size. It also needs at least one file descriptor. If cache is
|
||||
enabled (highly recommended), it will also need a bunch of cache pages.
|
||||
|
||||
Say you have a logical page size of 256 bytes. You want to be able to have four
|
||||
files open simultaneously, and you can give spiffs four cache pages. This sums
|
||||
up to:
|
||||
|
||||
256*2 (work buffer) + 32*4 (file descriptors) + (256+32)*4 cache pages
|
||||
i.e. 1792 bytes.
|
||||
|
||||
This is apart from call stack usage.
|
||||
|
||||
|
||||
* QUICK AND DIRTY INTEGRATION EXAMPLE
|
||||
|
||||
@ -129,7 +154,7 @@ typedefs:
|
||||
typedef unsigned short u16_t;
|
||||
typedef signed char s8_t;
|
||||
typedef unsigned char u8_t;
|
||||
|
||||
|
||||
Now it should build. Over to the mounting business. Assume you already
|
||||
implemented the read, write and erase functions to your SPI flash:
|
||||
|
||||
@ -231,3 +256,7 @@ And, crossing fingers hard, you'll get the output:
|
||||
|
||||
--> Hello world <--
|
||||
|
||||
|
||||
* HOW TO CONFIG
|
||||
|
||||
TODO
|
230
docs/TECH_SPEC
230
docs/TECH_SPEC
@ -2,29 +2,235 @@
|
||||
|
||||
TODO
|
||||
|
||||
* DESIGN
|
||||
|
||||
** SPI flash devices
|
||||
* SPIFFS DESIGN
|
||||
|
||||
Below is a small description of how SPI flashes work internally.
|
||||
Spiffs is inspired by YAFFS. However, YAFFS is designed for NAND flashes, and
|
||||
for bigger targets with much more ram. Nevertheless, many wise thoughts have
|
||||
been borrowed from YAFFS when writing spiffs. Kudos!
|
||||
|
||||
The main complication writing spiffs was that it cannot be assumed the target
|
||||
has a heap. Spiffs must go along only with the work ram buffer given to it.
|
||||
This forces extra implementation on many areas of spiffs.
|
||||
|
||||
|
||||
** SPI flash devices using NOR technology
|
||||
|
||||
Below is a small description of how SPI flashes work internally. This is to
|
||||
give an understanding of the design choices made in spiffs.
|
||||
|
||||
SPI flash devices are physically divided in blocks. On some SPI flash devices,
|
||||
blocks are further divided into sectors. Datasheets sometimes name blocks as
|
||||
sectors and vice versa.
|
||||
|
||||
Common memory capacaties for SPI flashes are 512kB up to 8 MB of data, with
|
||||
blocks of 64K. Sectors normally are 4K, if supported. The entire memory is
|
||||
linear and can be written in random access, but erasing can only be done block-
|
||||
or sectorwise; or by mass erase.
|
||||
Common memory capacaties for SPI flashes are 512kB up to 8MB of data, where
|
||||
blocks may be 64kB. Sectors can be e.g. 4kB, if supported. Many SPI flashes
|
||||
have uniform block sizes, whereas others have non-uniform - the latter meaning
|
||||
that e.g. the first 16 blocks are 4kB big, and the rest are 64kB.
|
||||
|
||||
The entire memory is linear and can be read and written in random access.
|
||||
Erasing can only be done block- or sectorwise; or by mass erase.
|
||||
|
||||
SPI flashes can normally be erased from 100.000 up to 1.000.000 cycles before
|
||||
they fail erasing.
|
||||
they fail.
|
||||
|
||||
A clean SPI flash from factory have all bits in entire memory set to one. A
|
||||
mass erase will reset the device to this state. Block or sector erasing will
|
||||
put the area given by the sector or block to ones. Writing to a SPI flash
|
||||
pulls ones to zeroes. Writing 0xFF to an address is simply a no-op. This way
|
||||
of "nand-writing" is used considerably in spiffs.
|
||||
put the all bits in the area given by the sector or block to ones. Writing to a
|
||||
NOR flash pulls ones to zeroes. Writing 0xFF to an address is simply a no-op.
|
||||
|
||||
** TODO
|
||||
Writing 0b10101010 to a flash address holding 0b00001111 will yield 0b00001010.
|
||||
|
||||
This way of "write by nand" is used considerably in spiffs.
|
||||
|
||||
Common characteristics of NOR flashes are quick reads, but slow writes.
|
||||
|
||||
|
||||
** Spiffs logical structure
|
||||
|
||||
Some terminology before proceeding. Physical blocks/sectors means sizes stated
|
||||
in the datasheet. Logical blocks and pages is something the integrator choose.
|
||||
|
||||
|
||||
** Blocks and pages
|
||||
|
||||
Spiffs is allocated to a part or all of the memory of the SPI flash device.
|
||||
This area is divided into logical blocks, which in turn are divided into
|
||||
logical pages. The boundary of a logical block must coincide with one or more
|
||||
physical blocks. The sizes for logical blocks and logical pages always remain
|
||||
the same, they are uniform.
|
||||
|
||||
Example: non-uniform flash mapped to spiffs with 128kB logical blocks
|
||||
|
||||
PHYSICAL FLASH BLOCKS SPIFFS LOGICAL BLOCKS: 128kB
|
||||
|
||||
+-----------------------+ - - - +-----------------------+
|
||||
| Block 1 : 16kB | | Block 1 : 128kB |
|
||||
+-----------------------+ | |
|
||||
| Block 2 : 16kB | | |
|
||||
+-----------------------+ | |
|
||||
| Block 3 : 16kB | | |
|
||||
+-----------------------+ | |
|
||||
| Block 4 : 16kB | | |
|
||||
+-----------------------+ | |
|
||||
| Block 5 : 64kB | | |
|
||||
+-----------------------+ - - - +-----------------------+
|
||||
| Block 6 : 64kB | | Block 2 : 128kB |
|
||||
+-----------------------+ | |
|
||||
| Block 7 : 64kB | | |
|
||||
+-----------------------+ - - - +-----------------------+
|
||||
| Block 8 : 64kB | | Block 3 : 128kB |
|
||||
+-----------------------+ | |
|
||||
| Block 9 : 64kB | | |
|
||||
+-----------------------+ - - - +-----------------------+
|
||||
| ... | | ... |
|
||||
|
||||
A logical block is divided further into a number of logical pages. A page
|
||||
defines the smallest data holding element known to spiffs. Hence, if a file
|
||||
is created being one byte big, it will occupy one page for index and one page
|
||||
for data - it will occupy 2 x size of a logical page on flash.
|
||||
So it seems it is good to select a small page size.
|
||||
|
||||
Each page has a metadata header being normally 5 to 9 bytes. This said, a very
|
||||
small page size will make metadata occupy a lot of the memory on the flash. A
|
||||
page size of 64 bytes will waste 8-14% on metadata, while 256 bytes 2-4%.
|
||||
So it seems it is good to select a big page size.
|
||||
|
||||
Also, spiffs uses a ram buffer being two times the page size. This ram buffer
|
||||
is used for loading and manipulating pages, but it is also used for algorithms
|
||||
to find free file ids, scanning the file system, etc. Having too small a page
|
||||
size means less work buffer for spiffs, ending up in more reads operations and
|
||||
eventually gives a slower file system.
|
||||
|
||||
Choosing the page size for the system involves many factors:
|
||||
- How big is the logical block size
|
||||
- What is the normal size of most files
|
||||
- How much ram can be spent
|
||||
- How much data (vs metadata) must be crammed into the file system
|
||||
- How fast must spiffs be
|
||||
- Other things impossible to find out
|
||||
|
||||
So, chosing the Optimal Page Size (tm) seems tricky, to say the least. Don't
|
||||
fret - there is no optimal page size. This varies from how the target will use
|
||||
spiffs. Use the golden rule:
|
||||
|
||||
~~~ Logical Page Size = Logical Block Size / 256 ~~~
|
||||
|
||||
This is a good starting point. The final page size can then be derived through
|
||||
heuristical experimenting for us non-analytical minds.
|
||||
|
||||
|
||||
** Objects, indices and look-ups
|
||||
|
||||
A file, or an object as called in spiffs, is identified by an object id.
|
||||
Another YAFFS rip-off. This object id is a part of the page header. So, all
|
||||
pages know to which object/file they belong - not counting the free pages.
|
||||
|
||||
An object is made up of two types of pages: object index pages and data pages.
|
||||
Data pages contain the data written by user. Index pages contain metadata about
|
||||
the object, more specifically what data pages are part of the object.
|
||||
|
||||
The page header also includes something called a span index. Let's say a file
|
||||
is written covering three data pages. The first data page will then have span
|
||||
index 0, the second span index 1, and the last data page will have span index
|
||||
2. Simple as that.
|
||||
|
||||
Finally, each page header contain flags, telling if the page is used,
|
||||
deleted, finalized, holds index or data, and more.
|
||||
|
||||
Object indices also have span indices, where an object index with span index 0
|
||||
is referred to as the object index header. This page does not only contain
|
||||
references to data pages, but also extra info such as object name, object size
|
||||
in bytes, flags for file or directory, etc.
|
||||
|
||||
If one were to create a file covering three data pages, named e.g.
|
||||
"spandex-joke.txt", given object id 12, it could look like this:
|
||||
|
||||
PAGE 0 <things to be unveiled soon>
|
||||
|
||||
PAGE 1 page header: [obj_id:12 span_ix:0 flags:USED|DATA]
|
||||
<first data page of joke>
|
||||
|
||||
PAGE 2 page header: [obj_id:12 span_ix:1 flags:USED|DATA]
|
||||
<second data page of joke>
|
||||
|
||||
PAGE 3 page header: [obj_id:545 span_ix:13 flags:USED|DATA]
|
||||
<some data belonging to object 545, probably not very amusing>
|
||||
|
||||
PAGE 4 page header: [obj_id:12 span_ix:2 flags:USED|DATA]
|
||||
<third data page of joke>
|
||||
|
||||
PAGE 5 page header: [obj_id:12 span_ix:0 flags:USED|INDEX]
|
||||
obj ix header: [name:spandex-joke.txt size:600 bytes flags:FILE]
|
||||
obj ix: [1 2 4]
|
||||
|
||||
Looking in detail at page 5, the object index header page, the object index
|
||||
array refers to each data page in order, as mentioned before. The index of the
|
||||
object index array correlates with the data page span index.
|
||||
|
||||
entry ix: 0 1 2
|
||||
obj ix: [1 2 4]
|
||||
| | |
|
||||
PAGE 1, DATA, SPAN_IX 0 --------/ | |
|
||||
PAGE 2, DATA, SPAN_IX 1 --------/ |
|
||||
PAGE 4, DATA, SPAN_IX 2 --------/
|
||||
|
||||
Things to be unveiled in page 0 - well.. Spiffs is designed for systems low on
|
||||
ram. We cannot keep a dynamic list on the whereabouts of each object index
|
||||
header so we can find a file fast. There might not even be a heap! But, we do
|
||||
not want to scan all page headers on the flash to find the object index header.
|
||||
|
||||
The first page(s) of each block contains the so called object look-up. These
|
||||
are not normal pages, they do not have a header. Instead, they are arrays
|
||||
pointing out what object-id the rest of all pages in the block belongs to.
|
||||
|
||||
By this look-up, only the first page(s) in each block must to scanned to find
|
||||
the actual page which contains the object index header of the desired object.
|
||||
|
||||
The object lookup is redundant metadata. The assumption is that it presents
|
||||
less overhead reading a full page of data to memory from each block and search
|
||||
that, instead of reading a small amount of data from each page (i.e. the page
|
||||
header) in all blocks. Each read operation from SPI flash normally contains
|
||||
extra data as the read command itself and the flash address. Also, depending on
|
||||
the underlying implementation, other criterions may need to be passed for each
|
||||
read transaction, like mutexes and such.
|
||||
|
||||
The veiled example unveiled would look like this, with some extra pages:
|
||||
|
||||
PAGE 0 [ 12 12 545 12 12 34 34 4 0 0 0 0 ...]
|
||||
PAGE 1 page header: [obj_id:12 span_ix:0 flags:USED|DATA] ...
|
||||
PAGE 2 page header: [obj_id:12 span_ix:1 flags:USED|DATA] ...
|
||||
PAGE 3 page header: [obj_id:545 span_ix:13 flags:USED|DATA] ...
|
||||
PAGE 4 page header: [obj_id:12 span_ix:2 flags:USED|DATA] ...
|
||||
PAGE 5 page header: [obj_id:12 span_ix:0 flags:USED|INDEX] ...
|
||||
PAGE 6 page header: [obj_id:34 span_ix:0 flags:USED|DATA] ...
|
||||
PAGE 7 page header: [obj_id:34 span_ix:1 flags:USED|DATA] ...
|
||||
PAGE 8 page header: [obj_id:4 span_ix:1 flags:USED|INDEX] ...
|
||||
PAGE 9 page header: [obj_id:23 span_ix:0 flags:DELETED|INDEX] ...
|
||||
PAGE 10 page header: [obj_id:23 span_ix:0 flags:DELETED|DATA] ...
|
||||
PAGE 11 page header: [obj_id:23 span_ix:1 flags:DELETED|DATA] ...
|
||||
PAGE 12 page header: [obj_id:23 span_ix:2 flags:DELETED|DATA] ...
|
||||
...
|
||||
|
||||
Ok, so why are page 9 to 12 marked as 0 when they belong to object id 23? These
|
||||
pages are deleted, so this is marked both in page header flags and in the look
|
||||
up. This is an example where spiffs uses NOR flashes "nand-way" of writing.
|
||||
|
||||
As a matter of fact, there are two object id's which are special:
|
||||
|
||||
obj id 0 (all bits zeroes) - indicates a deleted page in object look up
|
||||
obj id 0xff.. (all bits ones) - indicates a free page in object look up
|
||||
|
||||
Actually, the object id's have another quirk: if the most significant bit is
|
||||
set, this indicates an object index page. If the most significant bit is zero,
|
||||
this indicates a data page. So to be fully correct, page 0 in above example
|
||||
would look like this:
|
||||
|
||||
PAGE 0 [ 12 12 545 12 *12 34 34 *4 0 0 0 0 ...]
|
||||
|
||||
where the asterisk means the msb is set.
|
||||
|
||||
This is another way to speed up the searches when looking for object indices.
|
||||
By looking on the object id's msb in the object lookup, it is also possible
|
||||
whether the page is an object index page or a data page.
|
||||
|
||||
|
@ -8,13 +8,15 @@
|
||||
#ifndef SPIFFS_CONFIG_H_
|
||||
#define SPIFFS_CONFIG_H_
|
||||
|
||||
// following includes are for the linux test build of spiffs
|
||||
// this may/should/must be removed/altered/replaced in your target
|
||||
// ----------- 8< ------------
|
||||
// Following includes are for the linux test build of spiffs
|
||||
// These may/should/must be removed/altered/replaced in your target
|
||||
#include "params_test.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
// ----------- >8 ------------
|
||||
|
||||
// compile time switches
|
||||
|
||||
@ -48,6 +50,8 @@
|
||||
// Garbage collecting examines all pages in a block which and sums up
|
||||
// to a block score. Deleted pages normally gives positive score and
|
||||
// used pages normally gives a negative score (as these must be moved).
|
||||
// To have a fair wear-leveling, the erase age is also included in score,
|
||||
// whose factor normally is the most positive.
|
||||
// The larger the score, the more likely it is that the block will
|
||||
// picked for garbage collection.
|
||||
|
||||
@ -65,6 +69,44 @@
|
||||
// size of buffer on stack used when copying data
|
||||
#define SPIFFS_COPY_BUFFER_STACK (64)
|
||||
|
||||
// SPIFFS_LOCK and SPIFFS_UNLOCK protects spiffs from reentrancy on api level
|
||||
// These must be defined on a multithreaded system
|
||||
|
||||
// define this to entering a mutex if you're running on a multithreaded system
|
||||
#define SPIFFS_LOCK(fs)
|
||||
// define this to exiting a mutex if you're running on a multithreaded system
|
||||
#define SPIFFS_UNLOCK(fs)
|
||||
|
||||
|
||||
// Enable if only one spiffs instance with constant configuration will exist
|
||||
// on the target, this will reduce calculations, flash and memory accesses.
|
||||
#define SPIFFS_SINGLETON 0
|
||||
|
||||
#if SPIFFS_SINGLETON
|
||||
// instead of giving parameters in config struct, singleton build must
|
||||
// give parameters in defines below
|
||||
#define SPIFFS_CFG_PHYS_SZ(ignore) (1024*1024*2)
|
||||
#define SPIFFS_CFG_PHYS_ERASE_SZ(ignore) (65536)
|
||||
#define SPIFFS_CFG_PHYS_ADDR(ignore) (0)
|
||||
#define SPIFFS_CFG_LOG_PAGE_SZ(ignore) (256)
|
||||
#define SPIFFS_CFG_LOG_BLOCK_SZ(ignore) (65536)
|
||||
#endif
|
||||
|
||||
// Set SPFIFS_TEST_VISUALISATION to non-zero to enable SPIFFS_vis function
|
||||
// in the api. This function will visualize all filesystem using given printf
|
||||
// function.
|
||||
#define SPIFFS_TEST_VISUALISATION 1
|
||||
#if SPIFFS_TEST_VISUALISATION
|
||||
#define spiffs_printf(...) printf(__VA_ARGS__)
|
||||
// spiffs_printf argument for a free page
|
||||
#define SPIFFS_TEST_VIS_FREE_STR "_"
|
||||
// spiffs_printf argument for a deleted page
|
||||
#define SPIFFS_TEST_VIS_DELE_STR "/"
|
||||
// spiffs_printf argument for an index page for given object id
|
||||
#define SPIFFS_TEST_VIS_INDX_STR(id) "i"
|
||||
// spiffs_printf argument for a data page for given object id
|
||||
#define SPIFFS_TEST_VIS_DATA_STR(id) "d"
|
||||
#endif
|
||||
|
||||
// types and constants
|
||||
|
||||
@ -86,27 +128,4 @@ typedef u16_t spiffs_span_ix;
|
||||
// object type
|
||||
typedef u8_t spiffs_obj_type;
|
||||
|
||||
// enable if only one spiffs instance with constant configuration will exist
|
||||
// on the target, this will reduce calculations, flash and memory accesses
|
||||
//#define SPIFFS_SINGLETON
|
||||
|
||||
#ifdef SPIFFS_SINGLETON
|
||||
// instead of giving parameters in config struct, singleton build must
|
||||
// give parameters in defines below
|
||||
#define SPIFFS_CFG_PHYS_SZ(ignore) (1024*1024*1)
|
||||
#define SPIFFS_CFG_PHYS_ERASE_SZ(ignore) (65536)
|
||||
#define SPIFFS_CFG_PHYS_ADDR(ignore) (0)
|
||||
#define SPIFFS_CFG_LOG_PAGE_SZ(ignore) (256)
|
||||
#define SPIFFS_CFG_LOG_BLOCK_SZ(ignore) (65536)
|
||||
#endif
|
||||
|
||||
#define SPIFFS_TEST_VISUALISATION 1
|
||||
#if SPIFFS_TEST_VISUALISATION
|
||||
#define spiffs_printf(...) printf(__VA_ARGS__)
|
||||
#define SPIFFS_TEST_VIS_FREE_STR "_"
|
||||
#define SPIFFS_TEST_VIS_DELE_STR "/"
|
||||
#define SPIFFS_TEST_VIS_INDX_STR(id) "i"
|
||||
#define SPIFFS_TEST_VIS_DATA_STR(id) "d"
|
||||
#endif
|
||||
|
||||
#endif /* SPIFFS_CONFIG_H_ */
|
||||
|
25
src/spiffs.h
25
src/spiffs.h
@ -34,6 +34,8 @@
|
||||
#define SPIFFS_ERR_INDEX_FREE -10018
|
||||
#define SPIFFS_ERR_INDEX_LU -10019
|
||||
#define SPIFFS_ERR_INDEX_INVALID -10020
|
||||
#define SPIFFS_ERR_NOT_WRITABLE -10021
|
||||
#define SPIFFS_ERR_NOT_READABLE -10022
|
||||
|
||||
#define SPIFFS_ERR_INTERNAL -10050
|
||||
|
||||
@ -122,7 +124,7 @@ typedef struct {
|
||||
spiffs_write hal_write_f;
|
||||
// physical erase function
|
||||
spiffs_erase hal_erase_f;
|
||||
#ifndef SPIFFS_SINGLETON
|
||||
#if SPIFFS_SINGLETON == 0
|
||||
// physical size of the spi flash
|
||||
u32_t phys_size;
|
||||
// physical offset in spi flash used for spiffs,
|
||||
@ -345,8 +347,29 @@ void SPIFFS_close(spiffs *fs, spiffs_file fh);
|
||||
*/
|
||||
s32_t SPIFFS_errno(spiffs *fs);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @param fs the file system struct
|
||||
* @param name the name of the directory
|
||||
* @param d pointer the directory stream to be populated
|
||||
*/
|
||||
spiffs_DIR *SPIFFS_opendir(spiffs *fs, const char *name, spiffs_DIR *d);
|
||||
|
||||
/**
|
||||
* Closes a directory stream
|
||||
* @param d the directory stream to close
|
||||
*/
|
||||
s32_t SPIFFS_closedir(spiffs_DIR *d);
|
||||
|
||||
/**
|
||||
* Reads a directory into given spifs_dirent struct.
|
||||
* @param d pointer to the directory stream
|
||||
* @param e the dirent struct to be populated
|
||||
* @returns null if error or end of stream, else given dirent is returned
|
||||
*/
|
||||
struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e);
|
||||
|
||||
/**
|
||||
|
@ -175,6 +175,11 @@ s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
|
||||
res = spiffs_fd_get(fs, fh, &fd);
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
|
||||
if ((fd->mode & SPIFFS_RDONLY) == 0) {
|
||||
res = SPIFFS_ERR_NOT_READABLE;
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
}
|
||||
|
||||
#if SPIFFS_CACHE_WR
|
||||
spiffs_fflush_cache(fs, fh);
|
||||
#endif
|
||||
@ -235,6 +240,11 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
|
||||
res = spiffs_fd_get(fs, fh, &fd);
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
|
||||
if ((fd->mode & SPIFFS_WRONLY) == 0) {
|
||||
res = SPIFFS_ERR_NOT_WRITABLE;
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
}
|
||||
|
||||
offset = fd->fdoffset;
|
||||
|
||||
#if SPIFFS_CACHE_WR
|
||||
@ -423,6 +433,11 @@ s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh) {
|
||||
res = spiffs_fd_get(fs, fh, &fd);
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
|
||||
if ((fd->mode & SPIFFS_WRONLY) == 0) {
|
||||
res = SPIFFS_ERR_NOT_WRITABLE;
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
}
|
||||
|
||||
#if SPIFFS_CACHE_WR
|
||||
spiffs_cache_fd_release(fs, fd->cache_page);
|
||||
#endif
|
||||
|
@ -131,7 +131,7 @@
|
||||
#define SPIFFS_OBJ_ID_DELETED ((spiffs_obj_id)0)
|
||||
#define SPIFFS_OBJ_ID_FREE ((spiffs_obj_id)-1)
|
||||
|
||||
#ifndef SPIFFS_SINGLETON
|
||||
#if SPIFFS_SINGLETON == 0
|
||||
#define SPIFFS_CFG_LOG_PAGE_SZ(fs) \
|
||||
((fs)->cfg.log_page_size)
|
||||
#define SPIFFS_CFG_LOG_BLOCK_SZ(fs) \
|
||||
@ -426,6 +426,14 @@ typedef s32_t (*spiffs_visitor_f)(spiffs *fs, spiffs_obj_id id, spiffs_block_ix
|
||||
#define _spiffs_wr(fs, op, fh, addr, len, src) \
|
||||
spiffs_phys_wr((fs), (addr), (len), (src))
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
// ---------------
|
||||
|
||||
s32_t spiffs_phys_rd(
|
||||
|
@ -18,9 +18,6 @@
|
||||
|
||||
#define ASSERT(c, m) real_assert((c),(m), __FILE__, __LINE__);
|
||||
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
void real_assert(int c, const char *n, const char *file, int l);
|
||||
|
||||
typedef signed int s32_t;
|
||||
|
Reference in New Issue
Block a user