mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-27 21:16:50 +03:00
parent
d7078ed9b5
commit
6a7551e1f0
@ -1,306 +0,0 @@
|
||||
* QUICK AND DIRTY INTEGRATION EXAMPLE
|
||||
|
||||
So, assume you're running a Cortex-M3 board with a 2 MB SPI flash on it. The
|
||||
SPI flash has 64kB blocks. Your project is built using gnumake, and now you
|
||||
want to try things out.
|
||||
|
||||
First, you simply copy the files in src/ to your own source folder. Exclude
|
||||
all files in test folder. Then you point out these files in your make script
|
||||
for compilation.
|
||||
|
||||
Also copy the spiffs_config.h over from the src/default/ folder.
|
||||
|
||||
Try building. This fails, nagging about inclusions and u32_t and whatnot. Open
|
||||
the spiffs_config.h and delete the bad inclusions. Also, add following
|
||||
typedefs:
|
||||
|
||||
typedef signed int s32_t;
|
||||
typedef unsigned int u32_t;
|
||||
typedef signed short s16_t;
|
||||
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:
|
||||
|
||||
void my_spi_read(int addr, int size, char *buf)
|
||||
void my_spi_write(int addr, int size, char *buf)
|
||||
void my_spi_erase(int addr, int size)
|
||||
|
||||
In your main.c or similar, include the spiffs.h and do that spiffs struct:
|
||||
|
||||
#include <spiffs.h>
|
||||
|
||||
static spiffs fs;
|
||||
|
||||
Also, toss up some of the needed buffers:
|
||||
|
||||
#define LOG_PAGE_SIZE 256
|
||||
|
||||
static u8_t spiffs_work_buf[LOG_PAGE_SIZE*2];
|
||||
static u8_t spiffs_fds[32*4];
|
||||
static u8_t spiffs_cache_buf[(LOG_PAGE_SIZE+32)*4];
|
||||
|
||||
Now, write the my_spiffs_mount function:
|
||||
|
||||
void my_spiffs_mount() {
|
||||
spiffs_config cfg;
|
||||
cfg.phys_size = 2*1024*1024; // use all spi flash
|
||||
cfg.phys_addr = 0; // start spiffs at start of spi flash
|
||||
cfg.phys_erase_block = 65536; // according to datasheet
|
||||
cfg.log_block_size = 65536; // let us not complicate things
|
||||
cfg.log_page_size = LOG_PAGE_SIZE; // as we said
|
||||
|
||||
cfg.hal_read_f = my_spi_read;
|
||||
cfg.hal_write_f = my_spi_write;
|
||||
cfg.hal_erase_f = my_spi_erase;
|
||||
|
||||
int res = SPIFFS_mount(&fs,
|
||||
&cfg,
|
||||
spiffs_work_buf,
|
||||
spiffs_fds,
|
||||
sizeof(spiffs_fds),
|
||||
spiffs_cache_buf,
|
||||
sizeof(spiffs_cache_buf),
|
||||
0);
|
||||
printf("mount res: %i\n", res);
|
||||
}
|
||||
|
||||
Now, build warns about the my_spi_read, write and erase functions. Wrong
|
||||
signatures, so go wrap them:
|
||||
|
||||
static s32_t my_spiffs_read(u32_t addr, u32_t size, u8_t *dst) {
|
||||
my_spi_read(addr, size, dst);
|
||||
return SPIFFS_OK;
|
||||
}
|
||||
|
||||
static s32_t my_spiffs_write(u32_t addr, u32_t size, u8_t *src) {
|
||||
my_spi_write(addr, size, dst);
|
||||
return SPIFFS_OK;
|
||||
}
|
||||
|
||||
static s32_t my_spiffs_erase(u32_t addr, u32_t size) {
|
||||
my_spi_erase(addr, size);
|
||||
return SPIFFS_OK;
|
||||
}
|
||||
|
||||
Redirect the config in my_spiffs_mount to the wrappers instead:
|
||||
|
||||
cfg.hal_read_f = my_spiffs_read;
|
||||
cfg.hal_write_f = my_spiffs_write;
|
||||
cfg.hal_erase_f = my_spiffs_erase;
|
||||
|
||||
Ok, now you should be able to build and run. However, you get this output:
|
||||
|
||||
mount res: -1
|
||||
|
||||
but you wanted
|
||||
|
||||
mount res: 0
|
||||
|
||||
This is probably due to you having experimented with your SPI flash, so it
|
||||
contains rubbish from spiffs's point of view. Do a mass erase and run again.
|
||||
|
||||
If all is ok now, you're good to go. Try creating a file and read it back:
|
||||
|
||||
static void test_spiffs() {
|
||||
char buf[12];
|
||||
|
||||
// Surely, I've mounted spiffs before entering here
|
||||
|
||||
spiffs_file fd = SPIFFS_open(&fs, "my_file", SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_RDWR, 0);
|
||||
if (SPIFFS_write(&fs, fd, (u8_t *)"Hello world", 12) < 0) printf("errno %i\n", SPIFFS_errno(&fs));
|
||||
SPIFFS_close(&fs, fd);
|
||||
|
||||
fd = SPIFFS_open(&fs, "my_file", SPIFFS_RDWR, 0);
|
||||
if (SPIFFS_read(&fs, fd, (u8_t *)buf, 12) < 0) printf("errno %i\n", SPIFFS_errno(&fs));
|
||||
SPIFFS_close(&fs, fd);
|
||||
|
||||
printf("--> %s <--\n", buf);
|
||||
}
|
||||
|
||||
Compile, run, cross fingers hard, and you'll get the output:
|
||||
|
||||
--> Hello world <--
|
||||
|
||||
Got errors? Check spiffs.h for error definitions to get a clue what went voodoo.
|
||||
|
||||
|
||||
* THINGS TO CHECK
|
||||
|
||||
When you alter the spiffs_config values, make sure you also check the typedefs
|
||||
in spiffs_config.h:
|
||||
|
||||
- spiffs_block_ix
|
||||
- spiffs_page_ix
|
||||
- spiffs_obj_id
|
||||
- spiffs_span_ix
|
||||
|
||||
The sizes of these typedefs must not underflow, else spiffs might end up in
|
||||
eternal loops. Each typedef is commented what check for.
|
||||
|
||||
Also, if you alter the code or just want to verify your configuration, you can
|
||||
run
|
||||
|
||||
> make test
|
||||
|
||||
in the spiffs folder. This will run all testcases using the configuration in
|
||||
default/spiffs_config.h and test/params_test.h. The tests are written for linux
|
||||
but should run under cygwin also.
|
||||
|
||||
|
||||
* INTEGRATING SPIFFS
|
||||
|
||||
In order to integrate spiffs to your embedded target, you will basically need:
|
||||
- A SPI flash device which your processor can communicate with
|
||||
- An implementation for reading, writing and erasing the flash
|
||||
- Memory (flash or ram) for the code
|
||||
- Memory (ram) for the stack
|
||||
|
||||
Other stuff may be needed, threaded systems might need mutexes and so on.
|
||||
|
||||
** Logical structure
|
||||
|
||||
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 "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 -
|
||||
which in many cases is 65536 bytes.
|
||||
- Decide the logical size of pages. This must be a 2nd logarithm part of the
|
||||
logical block size. To go safe, use 256 bytes to start with.
|
||||
- Decide how much of the SPI flash memory to be used for spiffs. This must be
|
||||
on logical block boundary. If unsafe, use 1 megabyte to start with.
|
||||
- Decide where on the SPI flash memory the spiffs area should start. This must
|
||||
be on physical block/sector boundary. If unsafe, use address 0.
|
||||
|
||||
** SPI flash API
|
||||
|
||||
The target must provide three functions to spiffs:
|
||||
|
||||
- s32_t (*spiffs_read)(u32_t addr, u32_t size, u8_t *dst)
|
||||
- s32_t (*spiffs_write)(u32_t addr, u32_t size, u8_t *src)
|
||||
- s32_t (*spiffs_erase)(u32_t addr, u32_t size)
|
||||
|
||||
These functions define the only communication between the SPI flash and the
|
||||
spiffs stack.
|
||||
|
||||
On success these must return 0 (or SPIFFS_OK). Anything else will be considered
|
||||
an error.
|
||||
|
||||
The size for read and write requests will never exceed the logical page size,
|
||||
but it may be less.
|
||||
|
||||
The address and size on erase requests will always be on physical block size
|
||||
boundaries.
|
||||
|
||||
** Mount specification
|
||||
|
||||
In spiffs.h, there is a SPIFFS_mount function defined, used to mount spiffs on
|
||||
the SPI flash.
|
||||
|
||||
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,
|
||||
spiffs_check_callback check_cb_f)
|
||||
|
||||
- fs Points to a spiffs struct. This may be totally uninitialized.
|
||||
- config Points to a spiffs_config struct. This struct must be
|
||||
initialized when mounting. See below.
|
||||
- work A ram memory buffer being double the size of the logical page
|
||||
size. This buffer is used excessively by the spiffs stack. If
|
||||
logical page size is 256, this buffer must be 512 bytes.
|
||||
- fd_space A ram memory buffer used for file descriptors.
|
||||
- fd_space_size The size of the file descriptor buffer. A file descriptor
|
||||
normally is around 32 bytes depending on the build config -
|
||||
the bigger the buffer, the more file descriptors are
|
||||
available.
|
||||
- cache A ram memory buffer used for cache. Ignored if cache is
|
||||
disabled in build config.
|
||||
- cache_size The size of the cache buffer. Ignored if cache is disabled in
|
||||
build config. One cache page will be slightly larger than the
|
||||
logical page size. The more ram, the more cache pages, the
|
||||
quicker the system.
|
||||
- check_cb_f Callback function for monitoring spiffs consistency checks and
|
||||
mending operations. May be null.
|
||||
|
||||
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 set to zero - 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
|
||||
|
||||
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 - the logical size of a spiffs block
|
||||
|
||||
spiffs_config.log_page_size - the logical size of a spiffs page
|
||||
|
||||
If SPIFFS_SINGLETON is set to one, above parameters must be set ny defines in
|
||||
the config header file, spiffs_config.h.
|
||||
|
||||
|
||||
** Build config
|
||||
|
||||
makefile: The files needed to be compiled to your target resides in files.mk to
|
||||
be included in your makefile, either by cut and paste or by inclusion.
|
||||
|
||||
Types: spiffs uses the types u8_t, s8_t, u16_t, s16_t, u32_t, s32_t; these must
|
||||
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
|
||||
roughly sums up to:
|
||||
|
||||
256*2 (work buffer) +
|
||||
32*4 (file descriptors) +
|
||||
(256+32)*4 (cache pages) + 40 (cache metadata)
|
||||
|
||||
i.e. 1832 bytes.
|
||||
|
||||
This is apart from call stack usage.
|
||||
|
||||
To get the exact amount of bytes needed on your specific target, enable
|
||||
SPIFFS_BUFFER_HELP in spiffs_config.h, rebuild and call:
|
||||
|
||||
SPIFFS_buffer_bytes_for_filedescs
|
||||
SPIFFS_buffer_bytes_for_cache
|
||||
|
||||
Having these figures you can disable SPIFFS_BUFFER_HELP again to save flash.
|
||||
|
||||
|
||||
* HOW TO CONFIG
|
||||
|
||||
TODO
|
0
cores/esp8266/spiffs/LICENSE
Executable file → Normal file
0
cores/esp8266/spiffs/LICENSE
Executable file → Normal file
@ -1,110 +0,0 @@
|
||||
SPIFFS (SPI Flash File System)
|
||||
V0.3.2
|
||||
|
||||
Copyright (c) 2013-2015 Peter Andersson (pelleplutt1976<at>gmail.com)
|
||||
|
||||
For legal stuff, see LICENCE in this directory. Basically, you may do whatever
|
||||
you want with the source. Use, modify, sell, print it out, roll it and smoke it
|
||||
- as long as I won't be held responsible.
|
||||
|
||||
Love to hear feedback though!
|
||||
|
||||
|
||||
* INTRODUCTION
|
||||
|
||||
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
|
||||
|
||||
|
||||
* FEATURES
|
||||
|
||||
What spiffs does:
|
||||
- Specifically designed for low ram usage
|
||||
- Uses statically sized ram buffers, independent of number of files
|
||||
- Posix-like api: open, close, read, write, seek, stat, etc
|
||||
- It can be run on any NOR flash, not only SPI flash - theoretically also on
|
||||
embedded flash of an microprocessor
|
||||
- Multiple spiffs configurations can be run on same target - and even on same
|
||||
SPI flash device
|
||||
- Implements static wear leveling
|
||||
- Built in file system consistency checks
|
||||
|
||||
What spiffs does not:
|
||||
- Presently, spiffs does not support directories. It produces a flat
|
||||
structure. Creating a file with path "tmp/myfile.txt" will create a file
|
||||
called "tmp/myfile.txt" instead of a "myfile.txt" under directory "tmp".
|
||||
- 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. 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.
|
||||
|
||||
* HISTORY
|
||||
|
||||
0.3.2
|
||||
Limit cache size if too much cache is given (thanks pgeiem)
|
||||
New feature - Controlled erase. #23
|
||||
SPIFFS_rename leaks file descriptors #28 (thanks benpicco)
|
||||
moved dbg print defines in test framework to params_test.h
|
||||
lseek should return the resulting offset (thanks hefloryd)
|
||||
fixed type on dbg ifdefs
|
||||
silence warning about signed/unsigned comparison when spiffs_obj_id is 32 bit (thanks benpicco)
|
||||
Possible error in test_spiffs.c #21 (thanks yihcdaso-yeskela)
|
||||
Cache might writethrough too often #16
|
||||
even moar testrunner updates
|
||||
Test framework update and some added tests
|
||||
Some thoughts for next gen
|
||||
Test sigsevs when having too many sectors #13 (thanks alonewolfx2)
|
||||
GC might be suboptimal #11
|
||||
Fix eternal readdir when objheader at last block, last entry
|
||||
|
||||
New API functions:
|
||||
SPIFFS_gc_quick - call a nonintrusive gc
|
||||
SPIFFS_gc - call a full-scale intrusive gc
|
||||
|
||||
0.3.1
|
||||
Removed two return warnings, was too triggerhappy on release
|
||||
|
||||
0.3.0
|
||||
Added existing namecheck when creating files
|
||||
Lots of static analysis bugs #6
|
||||
Added rename func
|
||||
Fix SPIFFS_read length when reading beyond file size
|
||||
Added reading beyond file length testcase
|
||||
Made build a bit more configurable
|
||||
Changed name in spiffs from "errno" to "err_code" due to conflicts compiling
|
||||
in mingw
|
||||
Improved GC checks, fixed an append bug, more robust truncate for very special
|
||||
case
|
||||
GC checks preempts GC, truncate even less picky
|
||||
Struct alignment needed for some targets, define in spiffs config #10
|
||||
Spiffs filesystem magic, definable in config
|
||||
|
||||
New config defines:
|
||||
SPIFFS_USE_MAGIC - enable or disable magic check upon mount
|
||||
SPIFFS_ALIGNED_OBJECT_INDEX_TABLES - alignment for certain targets
|
||||
New API functions:
|
||||
SPIFFS_rename - rename files
|
||||
SPIFFS_clearerr - clears last errno
|
||||
SPIFFS_info - returns info on used and total bytes in fs
|
||||
SPIFFS_format - formats the filesystem
|
||||
SPIFFS_mounted - checks if filesystem is mounted
|
||||
|
||||
|
146
cores/esp8266/spiffs/README.md
Normal file
146
cores/esp8266/spiffs/README.md
Normal file
@ -0,0 +1,146 @@
|
||||
# SPIFFS (SPI Flash File System)
|
||||
**V0.3.4**
|
||||
|
||||
Copyright (c) 2013-2016 Peter Andersson (pelleplutt1976 at gmail.com)
|
||||
|
||||
For legal stuff, see [LICENSE](https://github.com/pellepl/spiffs/blob/master/LICENSE). Basically, you may do whatever you want with the source. Use, modify, sell, print it out, roll it and smoke it - as long as I won't be held responsible.
|
||||
|
||||
Love to hear feedback though!
|
||||
|
||||
|
||||
## INTRODUCTION
|
||||
|
||||
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
|
||||
|
||||
|
||||
## FEATURES
|
||||
|
||||
What spiffs does:
|
||||
- Specifically designed for low ram usage
|
||||
- Uses statically sized ram buffers, independent of number of files
|
||||
- Posix-like api: open, close, read, write, seek, stat, etc
|
||||
- It can be run on any NOR flash, not only SPI flash - theoretically also on embedded flash of an microprocessor
|
||||
- Multiple spiffs configurations can be run on same target - and even on same SPI flash device
|
||||
- Implements static wear leveling
|
||||
- Built in file system consistency checks
|
||||
|
||||
What spiffs does not:
|
||||
- Presently, spiffs does not support directories. It produces a flat structure. Creating a file with path *tmp/myfile.txt* will create a file called *tmp/myfile.txt* instead of a *myfile.txt* under directory *tmp*.
|
||||
- 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. 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
|
||||
|
||||
See the [wiki](https://github.com/pellepl/spiffs/wiki) for configuring, integrating and using spiffs.
|
||||
|
||||
For design, see [docs/TECH_SPEC](https://github.com/pellepl/spiffs/blob/master/docs/TECH_SPEC).
|
||||
|
||||
For a generic spi flash driver, see [this](https://github.com/pellepl/spiflash_driver).
|
||||
|
||||
## HISTORY
|
||||
|
||||
### 0.3.4
|
||||
- Added user callback file func.
|
||||
- Fixed a stat bug with obj id.
|
||||
- SPIFFS_probe_fs added
|
||||
- Add possibility to compile a read-only version of spiffs
|
||||
- Make magic dependent on fs length, if needed (see #59 & #66) (thanks @hreintke)
|
||||
- Exposed SPIFFS_open_by_page_function
|
||||
- Zero-size file cannot be seek #57 (thanks @lishen2)
|
||||
- Add tell and eof functions #54 (thanks @raburton)
|
||||
- Make api string params const #53 (thanks @raburton)
|
||||
- Preserve user_data during mount() #51 (thanks @rojer)
|
||||
|
||||
New API functions:
|
||||
- `SPIFFS_set_file_callback_func` - register a callback informing about file events
|
||||
- `SPIFFS_probe_fs` - probe a spi flash trying to figure out size of fs
|
||||
- `SPIFFS_open_by_page` - open a file by page index
|
||||
- `SPIFFS_eof` - checks if end of file is reached
|
||||
- `SPIFFS_tell` - returns current file offset
|
||||
|
||||
New config defines:
|
||||
- `SPIFFS_READ_ONLY`
|
||||
- `SPIFFS_USE_MAGIC_LENGTH`
|
||||
|
||||
### 0.3.3
|
||||
**Might not be compatible with 0.3.2 structures. See issue #40**
|
||||
- Possibility to add integer offset to file handles
|
||||
- Truncate function presumes too few free pages #49
|
||||
- Bug in truncate function #48 (thanks @PawelDefee)
|
||||
- Update spiffs_gc.c - remove unnecessary parameter (thanks @PawelDefee)
|
||||
- Update INTEGRATION docs (thanks @PawelDefee)
|
||||
- Fix pointer truncation in 64-bit platforms (thanks @igrr)
|
||||
- Zero-sized files cannot be read #44 (thanks @rojer)
|
||||
- (More) correct calculation of max_id in obj_lu_find #42 #41 (thanks @lishen2)
|
||||
- Check correct error code in obj_lu_find_free #41 (thanks @lishen2)
|
||||
- Moar comments for SPIFFS_lseek (thanks @igrr)
|
||||
- Fixed padding in spiffs_page_object_ix #40 (thanks @jmattsson @lishen2)
|
||||
- Fixed gc_quick test (thanks @jmattsson)
|
||||
- Add SPIFFS_EXCL flag #36
|
||||
- SPIFFS_close may fail silently if cache is enabled #37
|
||||
- User data in callbacks #34
|
||||
- Ignoring SINGLETON build in cache setup (thanks Luca)
|
||||
- Compilation error fixed #32 (thanks @chotasanjiv)
|
||||
- Align cand_scores (thanks @hefloryd)
|
||||
- Fix build warnings when SPIFFS_CACHE is 0 (thanks @ajaybhargav)
|
||||
|
||||
New config defines:
|
||||
- `SPIFFS_FILEHDL_OFFSET`
|
||||
|
||||
### 0.3.2
|
||||
- Limit cache size if too much cache is given (thanks pgeiem)
|
||||
- New feature - Controlled erase. #23
|
||||
- SPIFFS_rename leaks file descriptors #28 (thanks benpicco)
|
||||
- moved dbg print defines in test framework to params_test.h
|
||||
- lseek should return the resulting offset (thanks hefloryd)
|
||||
- fixed type on dbg ifdefs
|
||||
- silence warning about signed/unsigned comparison when spiffs_obj_id is 32 bit (thanks benpicco)
|
||||
- Possible error in test_spiffs.c #21 (thanks yihcdaso-yeskela)
|
||||
- Cache might writethrough too often #16
|
||||
- even moar testrunner updates
|
||||
- Test framework update and some added tests
|
||||
- Some thoughts for next gen
|
||||
- Test sigsevs when having too many sectors #13 (thanks alonewolfx2)
|
||||
- GC might be suboptimal #11
|
||||
- Fix eternal readdir when objheader at last block, last entry
|
||||
|
||||
New API functions:
|
||||
- `SPIFFS_gc_quick` - call a nonintrusive gc
|
||||
- `SPIFFS_gc` - call a full-scale intrusive gc
|
||||
|
||||
### 0.3.1
|
||||
- Removed two return warnings, was too triggerhappy on release
|
||||
|
||||
### 0.3.0
|
||||
- Added existing namecheck when creating files
|
||||
- Lots of static analysis bugs #6
|
||||
- Added rename func
|
||||
- Fix SPIFFS_read length when reading beyond file size
|
||||
- Added reading beyond file length testcase
|
||||
- Made build a bit more configurable
|
||||
- Changed name in spiffs from "errno" to "err_code" due to conflicts compiling in mingw
|
||||
- Improved GC checks, fixed an append bug, more robust truncate for very special case
|
||||
- GC checks preempts GC, truncate even less picky
|
||||
- Struct alignment needed for some targets, define in spiffs config #10
|
||||
- Spiffs filesystem magic, definable in config
|
||||
|
||||
New config defines:
|
||||
- `SPIFFS_USE_MAGIC` - enable or disable magic check upon mount
|
||||
- `SPIFFS_ALIGNED_OBJECT_INDEX_TABLES` - alignment for certain targets
|
||||
|
||||
New API functions:
|
||||
- `SPIFFS_rename` - rename files
|
||||
- `SPIFFS_clearerr` - clears last errno
|
||||
- `SPIFFS_info` - returns info on used and total bytes in fs
|
||||
- `SPIFFS_format` - formats the filesystem
|
||||
- `SPIFFS_mounted` - checks if filesystem is mounted
|
@ -49,6 +49,11 @@ extern "C" {
|
||||
|
||||
#define SPIFFS_ERR_FILE_EXISTS -10030
|
||||
|
||||
#define SPIFFS_ERR_NOT_A_FILE -10031
|
||||
#define SPIFFS_ERR_RO_NOT_IMPL -10032
|
||||
#define SPIFFS_ERR_RO_ABORTED_OPERATION -10033
|
||||
#define SPIFFS_ERR_PROBE_TOO_FEW_BLOCKS -10034
|
||||
#define SPIFFS_ERR_PROBE_NOT_A_FS -10035
|
||||
#define SPIFFS_ERR_INTERNAL -10050
|
||||
|
||||
#define SPIFFS_ERR_TEST -10100
|
||||
@ -63,9 +68,10 @@ typedef u16_t spiffs_mode;
|
||||
// object type
|
||||
typedef u8_t spiffs_obj_type;
|
||||
|
||||
#if SPIFFS_HAL_CALLBACK_EXTRA
|
||||
struct spiffs_t;
|
||||
|
||||
#if SPIFFS_HAL_CALLBACK_EXTRA
|
||||
|
||||
/* spi read call function type */
|
||||
typedef s32_t (*spiffs_read)(struct spiffs_t *fs, u32_t addr, u32_t size, u8_t *dst);
|
||||
/* spi write call function type */
|
||||
@ -110,6 +116,19 @@ typedef void (*spiffs_check_callback)(spiffs_check_type type, spiffs_check_repor
|
||||
u32_t arg1, u32_t arg2);
|
||||
#endif // SPIFFS_HAL_CALLBACK_EXTRA
|
||||
|
||||
/* file system listener callback operation */
|
||||
typedef enum {
|
||||
/* the file has been created */
|
||||
SPIFFS_CB_CREATED = 0,
|
||||
/* the file has been updated or moved to another page */
|
||||
SPIFFS_CB_UPDATED,
|
||||
/* the file has been deleted */
|
||||
SPIFFS_CB_DELETED,
|
||||
} spiffs_fileop_type;
|
||||
|
||||
/* file system listener callback function */
|
||||
typedef void (*spiffs_file_callback)(struct spiffs_t *fs, spiffs_fileop_type op, spiffs_obj_id obj_id, spiffs_page_ix pix);
|
||||
|
||||
#ifndef SPIFFS_DBG
|
||||
#define SPIFFS_DBG(...) \
|
||||
print(__VA_ARGS__)
|
||||
@ -247,7 +266,8 @@ typedef struct spiffs_t {
|
||||
|
||||
// check callback function
|
||||
spiffs_check_callback check_cb_f;
|
||||
|
||||
// file callback function
|
||||
spiffs_file_callback file_cb_f;
|
||||
// mounted flag
|
||||
u8_t mounted;
|
||||
// user data
|
||||
@ -261,6 +281,7 @@ typedef struct {
|
||||
spiffs_obj_id obj_id;
|
||||
u32_t size;
|
||||
spiffs_obj_type type;
|
||||
spiffs_page_ix pix;
|
||||
u8_t name[SPIFFS_OBJ_NAME_LEN];
|
||||
} spiffs_stat;
|
||||
|
||||
@ -280,6 +301,40 @@ typedef struct {
|
||||
|
||||
// functions
|
||||
|
||||
#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0
|
||||
/**
|
||||
* Special function. This takes a spiffs config struct and returns the number
|
||||
* of blocks this file system was formatted with. This function relies on
|
||||
* that following info is set correctly in given config struct:
|
||||
*
|
||||
* phys_addr, log_page_size, and log_block_size.
|
||||
*
|
||||
* Also, hal_read_f must be set in the config struct.
|
||||
*
|
||||
* One must be sure of the correct page size and that the physical address is
|
||||
* correct in the probed file system when calling this function. It is not
|
||||
* checked if the phys_addr actually points to the start of the file system,
|
||||
* so one might get a false positive if entering a phys_addr somewhere in the
|
||||
* middle of the file system at block boundary. In addition, it is not checked
|
||||
* if the page size is actually correct. If it is not, weird file system sizes
|
||||
* will be returned.
|
||||
*
|
||||
* If this function detects a file system it returns the assumed file system
|
||||
* size, which can be used to set the phys_size.
|
||||
*
|
||||
* Otherwise, it returns an error indicating why it is not regarded as a file
|
||||
* system.
|
||||
*
|
||||
* Note: this function is not protected with SPIFFS_LOCK and SPIFFS_UNLOCK
|
||||
* macros. It returns the error code directly, instead of as read by
|
||||
* SPIFFS_errno.
|
||||
*
|
||||
* @param config essential parts of the physical and logical
|
||||
* configuration of the file system.
|
||||
*/
|
||||
s32_t SPIFFS_probe_fs(spiffs_config *config);
|
||||
#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -326,14 +381,13 @@ s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode);
|
||||
*/
|
||||
spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs_mode 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.
|
||||
* @param fs the file system struct
|
||||
* @param path the dir entry to the file
|
||||
* @param e the dir entry to the file
|
||||
* @param 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.
|
||||
@ -342,6 +396,22 @@ spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs
|
||||
*/
|
||||
spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_flags flags, spiffs_mode 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.
|
||||
* @param fs the file system struct
|
||||
* @param page_ix the page index
|
||||
* @param 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.
|
||||
* @param mode ignored, for posix compliance
|
||||
*/
|
||||
spiffs_file SPIFFS_open_by_page(spiffs *fs, spiffs_page_ix page_ix, spiffs_flags flags, spiffs_mode mode);
|
||||
|
||||
/**
|
||||
* Reads from given filehandle.
|
||||
* @param fs the file system struct
|
||||
@ -562,6 +632,22 @@ s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh);
|
||||
*/
|
||||
s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param fs the file system struct
|
||||
* @param cb_func the callback on file operations
|
||||
*/
|
||||
s32_t SPIFFS_set_file_callback_func(spiffs *fs, spiffs_file_callback cb_func);
|
||||
|
||||
#if SPIFFS_TEST_VISUALISATION
|
||||
/**
|
||||
* Prints out a visualization of the filesystem.
|
||||
|
@ -19,9 +19,11 @@
|
||||
* Author: petera
|
||||
*/
|
||||
|
||||
|
||||
#include "spiffs.h"
|
||||
#include "spiffs_nucleus.h"
|
||||
|
||||
#if !SPIFFS_READ_ONLY
|
||||
|
||||
#if SPIFFS_HAL_CALLBACK_EXTRA
|
||||
#define CHECK_CB(_fs, _type, _rep, _arg1, _arg2) \
|
||||
@ -106,6 +108,7 @@ static s32_t spiffs_rewrite_index(spiffs *fs, spiffs_obj_id obj_id, spiffs_span_
|
||||
} else {
|
||||
// calc entry in index
|
||||
entry = SPIFFS_OBJ_IX_ENTRY(fs, data_spix);
|
||||
|
||||
}
|
||||
// load index
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
@ -989,3 +992,4 @@ s32_t spiffs_object_index_consistency_check(spiffs *fs) {
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif // !SPIFFS_READ_ONLY
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include "spiffs.h"
|
||||
#include "spiffs_nucleus.h"
|
||||
|
||||
#if !SPIFFS_READ_ONLY
|
||||
|
||||
// Erases a logical block and updates the erase counter.
|
||||
// If cache is enabled, all pages that might be cached in this block
|
||||
// is dropped.
|
||||
@ -571,3 +573,4 @@ s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif // !SPIFFS_READ_ONLY
|
||||
|
@ -36,6 +36,10 @@ u8_t SPIFFS_mounted(spiffs *fs) {
|
||||
}
|
||||
|
||||
s32_t SPIFFS_format(spiffs *fs) {
|
||||
#if SPIFFS_READ_ONLY
|
||||
(void)fs;
|
||||
return SPIFFS_ERR_RO_NOT_IMPL;
|
||||
#else
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
if (SPIFFS_CHECK_MOUNT(fs)) {
|
||||
fs->err_code = SPIFFS_ERR_MOUNTED;
|
||||
@ -59,8 +63,18 @@ s32_t SPIFFS_format(spiffs *fs) {
|
||||
SPIFFS_UNLOCK(fs);
|
||||
|
||||
return 0;
|
||||
#endif // SPIFFS_READ_ONLY
|
||||
}
|
||||
|
||||
#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0
|
||||
|
||||
s32_t SPIFFS_probe_fs(spiffs_config *config) {
|
||||
s32_t res = spiffs_probe(config);
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==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,
|
||||
@ -167,6 +181,10 @@ void SPIFFS_clearerr(spiffs *fs) {
|
||||
}
|
||||
|
||||
s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode) {
|
||||
#if SPIFFS_READ_ONLY
|
||||
(void)fs; (void)path; (void)mode;
|
||||
return SPIFFS_ERR_RO_NOT_IMPL;
|
||||
#else
|
||||
(void)mode;
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
@ -180,6 +198,7 @@ s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode) {
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
SPIFFS_UNLOCK(fs);
|
||||
return 0;
|
||||
#endif // SPIFFS_READ_ONLY
|
||||
}
|
||||
|
||||
spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs_mode mode) {
|
||||
@ -191,6 +210,11 @@ spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs
|
||||
spiffs_fd *fd;
|
||||
spiffs_page_ix pix;
|
||||
|
||||
#if SPIFFS_READ_ONLY
|
||||
// not valid flags in read only mode
|
||||
flags &= ~SPIFFS_WRONLY | SPIFFS_CREAT | SPIFFS_TRUNC;
|
||||
#endif // SPIFFS_READ_ONLY
|
||||
|
||||
s32_t res = spiffs_fd_find_new(fs, &fd);
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
|
||||
@ -211,6 +235,7 @@ spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs
|
||||
}
|
||||
|
||||
if ((flags & SPIFFS_CREAT) && res == SPIFFS_ERR_NOT_FOUND) {
|
||||
#if !SPIFFS_READ_ONLY
|
||||
spiffs_obj_id obj_id;
|
||||
// no need to enter conflicting name here, already looked for it above
|
||||
res = spiffs_obj_lu_find_free_obj_id(fs, &obj_id, 0);
|
||||
@ -224,6 +249,7 @@ spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs
|
||||
}
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
flags &= ~SPIFFS_TRUNC;
|
||||
#endif // !SPIFFS_READ_ONLY
|
||||
} else {
|
||||
if (res < SPIFFS_OK) {
|
||||
spiffs_fd_return(fs, fd->file_nbr);
|
||||
@ -235,6 +261,7 @@ spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs
|
||||
spiffs_fd_return(fs, fd->file_nbr);
|
||||
}
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
#if !SPIFFS_READ_ONLY
|
||||
if (flags & SPIFFS_TRUNC) {
|
||||
res = spiffs_object_truncate(fd, 0, 0);
|
||||
if (res < SPIFFS_OK) {
|
||||
@ -242,6 +269,7 @@ spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs
|
||||
}
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
}
|
||||
#endif // !SPIFFS_READ_ONLY
|
||||
|
||||
fd->fdoffset = 0;
|
||||
|
||||
@ -265,6 +293,7 @@ spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_fl
|
||||
spiffs_fd_return(fs, fd->file_nbr);
|
||||
}
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
#if !SPIFFS_READ_ONLY
|
||||
if (flags & SPIFFS_TRUNC) {
|
||||
res = spiffs_object_truncate(fd, 0, 0);
|
||||
if (res < SPIFFS_OK) {
|
||||
@ -272,6 +301,53 @@ spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_fl
|
||||
}
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
}
|
||||
#endif // !SPIFFS_READ_ONLY
|
||||
|
||||
fd->fdoffset = 0;
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
|
||||
return SPIFFS_FH_OFFS(fs, fd->file_nbr);
|
||||
}
|
||||
|
||||
spiffs_file SPIFFS_open_by_page(spiffs *fs, spiffs_page_ix page_ix, spiffs_flags flags, spiffs_mode mode) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
spiffs_fd *fd;
|
||||
|
||||
s32_t res = spiffs_fd_find_new(fs, &fd);
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
|
||||
if (SPIFFS_IS_LOOKUP_PAGE(fs, page_ix)) {
|
||||
res = SPIFFS_ERR_NOT_A_FILE;
|
||||
spiffs_fd_return(fs, fd->file_nbr);
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
}
|
||||
|
||||
res = spiffs_object_open_by_page(fs, page_ix, fd, flags, mode);
|
||||
if (res == SPIFFS_ERR_IS_FREE ||
|
||||
res == SPIFFS_ERR_DELETED ||
|
||||
res == SPIFFS_ERR_NOT_FINALIZED ||
|
||||
res == SPIFFS_ERR_NOT_INDEX ||
|
||||
res == SPIFFS_ERR_INDEX_SPAN_MISMATCH) {
|
||||
res = SPIFFS_ERR_NOT_A_FILE;
|
||||
}
|
||||
if (res < SPIFFS_OK) {
|
||||
spiffs_fd_return(fs, fd->file_nbr);
|
||||
}
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
|
||||
#if !SPIFFS_READ_ONLY
|
||||
if (flags & SPIFFS_TRUNC) {
|
||||
res = spiffs_object_truncate(fd, 0, 0);
|
||||
if (res < SPIFFS_OK) {
|
||||
spiffs_fd_return(fs, fd->file_nbr);
|
||||
}
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
}
|
||||
#endif // !SPIFFS_READ_ONLY
|
||||
|
||||
fd->fdoffset = 0;
|
||||
|
||||
@ -334,6 +410,7 @@ s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
|
||||
return len;
|
||||
}
|
||||
|
||||
#if !SPIFFS_READ_ONLY
|
||||
static s32_t spiffs_hydro_write(spiffs *fs, spiffs_fd *fd, void *buf, u32_t offset, s32_t len) {
|
||||
(void)fs;
|
||||
s32_t res = SPIFFS_OK;
|
||||
@ -355,8 +432,13 @@ static s32_t spiffs_hydro_write(spiffs *fs, spiffs_fd *fd, void *buf, u32_t offs
|
||||
return len;
|
||||
|
||||
}
|
||||
#endif // !SPIFFS_READ_ONLY
|
||||
|
||||
s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
|
||||
#if SPIFFS_READ_ONLY
|
||||
(void)fs; (void)fh; (void)buf; (void)len;
|
||||
return SPIFFS_ERR_RO_NOT_IMPL;
|
||||
#else
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
@ -374,6 +456,10 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
}
|
||||
|
||||
if ((fd->flags & SPIFFS_APPEND)) {
|
||||
fd->fdoffset = fd->size == SPIFFS_UNDEFINED_LEN ? 0 : fd->size;
|
||||
}
|
||||
|
||||
offset = fd->fdoffset;
|
||||
|
||||
#if SPIFFS_CACHE_WR
|
||||
@ -474,6 +560,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
|
||||
SPIFFS_UNLOCK(fs);
|
||||
|
||||
return res;
|
||||
#endif // SPIFFS_READ_ONLY
|
||||
}
|
||||
|
||||
s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
|
||||
@ -500,7 +587,7 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (offs > (s32_t)fd->size) {
|
||||
if ((offs > (s32_t)fd->size) && (SPIFFS_UNDEFINED_LEN != fd->size)) {
|
||||
res = SPIFFS_ERR_END_OF_OBJECT;
|
||||
}
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
@ -523,6 +610,10 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
|
||||
}
|
||||
|
||||
s32_t SPIFFS_remove(spiffs *fs, const char *path) {
|
||||
#if SPIFFS_READ_ONLY
|
||||
(void)fs; (void)path;
|
||||
return SPIFFS_ERR_RO_NOT_IMPL;
|
||||
#else
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
@ -554,9 +645,14 @@ s32_t SPIFFS_remove(spiffs *fs, const char *path) {
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
return 0;
|
||||
#endif // SPIFFS_READ_ONLY
|
||||
}
|
||||
|
||||
s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh) {
|
||||
#if SPIFFS_READ_ONLY
|
||||
(void)fs; (void)fh;
|
||||
return SPIFFS_ERR_RO_NOT_IMPL;
|
||||
#else
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
@ -583,6 +679,7 @@ s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh) {
|
||||
SPIFFS_UNLOCK(fs);
|
||||
|
||||
return 0;
|
||||
#endif // SPIFFS_READ_ONLY
|
||||
}
|
||||
|
||||
static s32_t spiffs_stat_pix(spiffs *fs, spiffs_page_ix pix, spiffs_file fh, spiffs_stat *s) {
|
||||
@ -599,9 +696,10 @@ static s32_t spiffs_stat_pix(spiffs *fs, spiffs_page_ix pix, spiffs_file fh, spi
|
||||
obj_id_addr, sizeof(spiffs_obj_id), (u8_t *)&obj_id);
|
||||
SPIFFS_API_CHECK_RES(fs, res);
|
||||
|
||||
s->obj_id = obj_id;
|
||||
s->obj_id = obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
|
||||
s->type = objix_hdr.type;
|
||||
s->size = objix_hdr.size == SPIFFS_UNDEFINED_LEN ? 0 : objix_hdr.size;
|
||||
s->pix = pix;
|
||||
strncpy((char *)s->name, (char *)objix_hdr.name, SPIFFS_OBJ_NAME_LEN);
|
||||
|
||||
return res;
|
||||
@ -655,7 +753,7 @@ static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh) {
|
||||
(void)fs;
|
||||
(void)fh;
|
||||
s32_t res = SPIFFS_OK;
|
||||
#if SPIFFS_CACHE_WR
|
||||
#if !SPIFFS_READ_ONLY && SPIFFS_CACHE_WR
|
||||
|
||||
spiffs_fd *fd;
|
||||
res = spiffs_fd_get(fs, fh, &fd);
|
||||
@ -689,7 +787,7 @@ 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
|
||||
#if !SPIFFS_READ_ONLY && SPIFFS_CACHE_WR
|
||||
SPIFFS_LOCK(fs);
|
||||
fh = SPIFFS_FH_UNOFFS(fs, fh);
|
||||
res = spiffs_fflush_cache(fs, fh);
|
||||
@ -721,6 +819,10 @@ s32_t SPIFFS_close(spiffs *fs, spiffs_file fh) {
|
||||
}
|
||||
|
||||
s32_t SPIFFS_rename(spiffs *fs, const char *old, const char *new) {
|
||||
#if SPIFFS_READ_ONLY
|
||||
(void)fs; (void)old; (void)new;
|
||||
return SPIFFS_ERR_RO_NOT_IMPL;
|
||||
#else
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
@ -758,6 +860,7 @@ s32_t SPIFFS_rename(spiffs *fs, const char *old, const char *new) {
|
||||
SPIFFS_UNLOCK(fs);
|
||||
|
||||
return res;
|
||||
#endif // SPIFFS_READ_ONLY
|
||||
}
|
||||
|
||||
spiffs_DIR *SPIFFS_opendir(spiffs *fs, const char *name, spiffs_DIR *d) {
|
||||
@ -854,6 +957,10 @@ s32_t SPIFFS_closedir(spiffs_DIR *d) {
|
||||
}
|
||||
|
||||
s32_t SPIFFS_check(spiffs *fs) {
|
||||
#if SPIFFS_READ_ONLY
|
||||
(void)fs;
|
||||
return SPIFFS_ERR_RO_NOT_IMPL;
|
||||
#else
|
||||
s32_t res;
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
@ -869,6 +976,7 @@ s32_t SPIFFS_check(spiffs *fs) {
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
return res;
|
||||
#endif // SPIFFS_READ_ONLY
|
||||
}
|
||||
|
||||
s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used) {
|
||||
@ -896,6 +1004,10 @@ s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used) {
|
||||
}
|
||||
|
||||
s32_t SPIFFS_gc_quick(spiffs *fs, u16_t max_free_pages) {
|
||||
#if SPIFFS_READ_ONLY
|
||||
(void)fs; (void)max_free_pages;
|
||||
return SPIFFS_ERR_RO_NOT_IMPL;
|
||||
#else
|
||||
s32_t res;
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
@ -906,10 +1018,15 @@ s32_t SPIFFS_gc_quick(spiffs *fs, u16_t max_free_pages) {
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
SPIFFS_UNLOCK(fs);
|
||||
return 0;
|
||||
#endif // SPIFFS_READ_ONLY
|
||||
}
|
||||
|
||||
|
||||
s32_t SPIFFS_gc(spiffs *fs, u32_t size) {
|
||||
#if SPIFFS_READ_ONLY
|
||||
(void)fs; (void)size;
|
||||
return SPIFFS_ERR_RO_NOT_IMPL;
|
||||
#else
|
||||
s32_t res;
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
@ -920,6 +1037,7 @@ s32_t SPIFFS_gc(spiffs *fs, u32_t size) {
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
SPIFFS_UNLOCK(fs);
|
||||
return 0;
|
||||
#endif // SPIFFS_READ_ONLY
|
||||
}
|
||||
|
||||
s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh) {
|
||||
@ -939,7 +1057,7 @@ s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh) {
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
#endif
|
||||
|
||||
res = (fd->fdoffset == fd->size);
|
||||
res = (fd->fdoffset >= (fd->size == SPIFFS_UNDEFINED_LEN ? 0 : fd->size));
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
return res;
|
||||
@ -968,6 +1086,12 @@ s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh) {
|
||||
return res;
|
||||
}
|
||||
|
||||
s32_t SPIFFS_set_file_callback_func(spiffs *fs, spiffs_file_callback cb_func) {
|
||||
SPIFFS_LOCK(fs);
|
||||
fs->file_cb_f = cb_func;
|
||||
SPIFFS_UNLOCK(fs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if SPIFFS_TEST_VISUALISATION
|
||||
s32_t SPIFFS_vis(spiffs *fs) {
|
||||
|
@ -29,6 +29,7 @@ static s32_t spiffs_page_data_check(spiffs *fs, spiffs_fd *fd, spiffs_page_ix pi
|
||||
return res;
|
||||
}
|
||||
|
||||
#if !SPIFFS_READ_ONLY
|
||||
static s32_t spiffs_page_index_check(spiffs *fs, spiffs_fd *fd, spiffs_page_ix pix, spiffs_span_ix spix) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
if (pix == (spiffs_page_ix)-1) {
|
||||
@ -56,6 +57,7 @@ static s32_t spiffs_page_index_check(spiffs *fs, spiffs_fd *fd, spiffs_page_ix p
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
#endif // !SPIFFS_READ_ONLY
|
||||
|
||||
#if !SPIFFS_CACHE
|
||||
|
||||
@ -77,6 +79,7 @@ s32_t spiffs_phys_wr(
|
||||
|
||||
#endif
|
||||
|
||||
#if !SPIFFS_READ_ONLY
|
||||
s32_t spiffs_phys_cpy(
|
||||
spiffs *fs,
|
||||
spiffs_file fh,
|
||||
@ -98,6 +101,7 @@ s32_t spiffs_phys_cpy(
|
||||
}
|
||||
return SPIFFS_OK;
|
||||
}
|
||||
#endif // !SPIFFS_READ_ONLY
|
||||
|
||||
// Find object lookup entry containing given id with visitor.
|
||||
// Iterate over object lookup pages in each block until a given object id entry is found.
|
||||
@ -218,6 +222,7 @@ s32_t spiffs_obj_lu_find_entry_visitor(
|
||||
return SPIFFS_VIS_END;
|
||||
}
|
||||
|
||||
#if !SPIFFS_READ_ONLY
|
||||
s32_t spiffs_erase_block(
|
||||
spiffs *fs,
|
||||
spiffs_block_ix bix) {
|
||||
@ -243,7 +248,7 @@ s32_t spiffs_erase_block(
|
||||
|
||||
#if SPIFFS_USE_MAGIC
|
||||
// finally, write magic
|
||||
spiffs_obj_id magic = SPIFFS_MAGIC(fs);
|
||||
spiffs_obj_id magic = SPIFFS_MAGIC(fs, bix);
|
||||
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);
|
||||
@ -257,6 +262,59 @@ s32_t spiffs_erase_block(
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif // !SPIFFS_READ_ONLY
|
||||
|
||||
#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0
|
||||
s32_t spiffs_probe(
|
||||
spiffs_config *cfg) {
|
||||
s32_t res;
|
||||
u32_t paddr;
|
||||
spiffs dummy_fs; // create a dummy fs struct just to be able to use macros
|
||||
memcpy(&dummy_fs.cfg, cfg, sizeof(spiffs_config));
|
||||
dummy_fs.block_count = 0;
|
||||
|
||||
// Read three magics, as one block may be in an aborted erase state.
|
||||
// At least two of these must contain magic and be in decreasing order.
|
||||
spiffs_obj_id magic[3];
|
||||
spiffs_obj_id bix_count[3];
|
||||
|
||||
spiffs_block_ix bix;
|
||||
for (bix = 0; bix < 3; bix++) {
|
||||
paddr = SPIFFS_MAGIC_PADDR(&dummy_fs, bix);
|
||||
#if SPIFFS_HAL_CALLBACK_EXTRA
|
||||
// not any proper fs to report here, so callback with null
|
||||
// (cross fingers that no-one gets angry)
|
||||
res = cfg->hal_read_f((void *)0, paddr, sizeof(spiffs_obj_id), (u8_t *)&magic[bix]);
|
||||
#else
|
||||
res = cfg->hal_read_f(paddr, sizeof(spiffs_obj_id), (u8_t *)&magic[bix]);
|
||||
#endif
|
||||
bix_count[bix] = magic[bix] ^ SPIFFS_MAGIC(&dummy_fs, 0);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
|
||||
// check that we have sane number of blocks
|
||||
if (bix_count[0] < 3) return SPIFFS_ERR_PROBE_TOO_FEW_BLOCKS;
|
||||
// check that the order is correct, take aborted erases in calculation
|
||||
// first block aborted erase
|
||||
if (magic[0] == (spiffs_obj_id)(-1) && bix_count[1] - bix_count[2] == 1) {
|
||||
return (bix_count[1]+1) * cfg->log_block_size;
|
||||
}
|
||||
// second block aborted erase
|
||||
if (magic[1] == (spiffs_obj_id)(-1) && bix_count[0] - bix_count[2] == 2) {
|
||||
return bix_count[0] * cfg->log_block_size;
|
||||
}
|
||||
// third block aborted erase
|
||||
if (magic[2] == (spiffs_obj_id)(-1) && bix_count[0] - bix_count[1] == 1) {
|
||||
return bix_count[0] * cfg->log_block_size;
|
||||
}
|
||||
// no block has aborted erase
|
||||
if (bix_count[0] - bix_count[1] == 1 && bix_count[1] - bix_count[2] == 1) {
|
||||
return bix_count[0] * cfg->log_block_size;
|
||||
}
|
||||
|
||||
return SPIFFS_ERR_PROBE_NOT_A_FS;
|
||||
}
|
||||
#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0
|
||||
|
||||
|
||||
static s32_t spiffs_obj_lu_scan_v(
|
||||
@ -311,7 +369,7 @@ s32_t spiffs_obj_lu_scan(
|
||||
sizeof(spiffs_obj_id), (u8_t *)&magic);
|
||||
|
||||
SPIFFS_CHECK_RES(res);
|
||||
if (magic != SPIFFS_MAGIC(fs)) {
|
||||
if (magic != SPIFFS_MAGIC(fs, bix)) {
|
||||
if (unerased_bix == (spiffs_block_ix)-1) {
|
||||
// allow one unerased block as it might be powered down during an erase
|
||||
unerased_bix = bix;
|
||||
@ -349,8 +407,12 @@ s32_t spiffs_obj_lu_scan(
|
||||
#if SPIFFS_USE_MAGIC
|
||||
if (unerased_bix != (spiffs_block_ix)-1) {
|
||||
// found one unerased block, remedy
|
||||
SPIFFS_DBG("mount: erase block %d\n", bix);
|
||||
SPIFFS_DBG("mount: erase block %i\n", bix);
|
||||
#if SPIFFS_READ_ONLY
|
||||
res = SPIFFS_ERR_RO_ABORTED_OPERATION;
|
||||
#else
|
||||
res = spiffs_erase_block(fs, unerased_bix);
|
||||
#endif // SPIFFS_READ_ONLY
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
#endif
|
||||
@ -381,6 +443,7 @@ s32_t spiffs_obj_lu_scan(
|
||||
return res;
|
||||
}
|
||||
|
||||
#if !SPIFFS_READ_ONLY
|
||||
// Find free object lookup entry
|
||||
// Iterate over object lookup pages in each block until a free object id entry is found
|
||||
s32_t spiffs_obj_lu_find_free(
|
||||
@ -415,6 +478,7 @@ s32_t spiffs_obj_lu_find_free(
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif // !SPIFFS_READ_ONLY
|
||||
|
||||
// Find object lookup entry containing given id
|
||||
// Iterate over object lookup pages in each block until a given object id entry is found
|
||||
@ -536,6 +600,7 @@ s32_t spiffs_obj_lu_find_id_and_span_by_phdr(
|
||||
return res;
|
||||
}
|
||||
|
||||
#if !SPIFFS_READ_ONLY
|
||||
// Allocates a free defined page with given obj_id
|
||||
// Occupies object lookup entry and page
|
||||
// data may be NULL; where only page header is stored, len and page_offs is ignored
|
||||
@ -593,7 +658,9 @@ s32_t spiffs_page_allocate_data(
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif // !SPIFFS_READ_ONLY
|
||||
|
||||
#if !SPIFFS_READ_ONLY
|
||||
// Moves a page from src to a free page and finalizes it. Updates page index. Page data is given in param page.
|
||||
// If page data is null, provided header is used for metainfo and page data is physically copied.
|
||||
s32_t spiffs_page_move(
|
||||
@ -656,7 +723,9 @@ s32_t spiffs_page_move(
|
||||
res = spiffs_page_delete(fs, src_pix);
|
||||
return res;
|
||||
}
|
||||
#endif // !SPIFFS_READ_ONLY
|
||||
|
||||
#if !SPIFFS_READ_ONLY
|
||||
// Deletes a page and removes it from object lookup.
|
||||
s32_t spiffs_page_delete(
|
||||
spiffs *fs,
|
||||
@ -685,7 +754,9 @@ s32_t spiffs_page_delete(
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif // !SPIFFS_READ_ONLY
|
||||
|
||||
#if !SPIFFS_READ_ONLY
|
||||
// Create an object index header page with empty index and undefined length
|
||||
s32_t spiffs_object_create(
|
||||
spiffs *fs,
|
||||
@ -706,7 +777,7 @@ s32_t spiffs_object_create(
|
||||
// find free entry
|
||||
res = spiffs_obj_lu_find_free(fs, fs->free_cursor_block_ix, fs->free_cursor_obj_lu_entry, &bix, &entry);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
SPIFFS_DBG("create: found free page @ %04x bix:%d entry:%d\n", SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry), bix, entry);
|
||||
SPIFFS_DBG("create: found free page @ %04x bix:%i entry:%i\n", SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry), bix, entry);
|
||||
|
||||
// occupy page in object lookup
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT,
|
||||
@ -737,7 +808,9 @@ s32_t spiffs_object_create(
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif // !SPIFFS_READ_ONLY
|
||||
|
||||
#if !SPIFFS_READ_ONLY
|
||||
// update object index header with any combination of name/size/index
|
||||
// new_objix_hdr_data may be null, if so the object index header page is loaded
|
||||
// name may be null, if so name is not changed
|
||||
@ -792,18 +865,19 @@ s32_t spiffs_object_update_index_hdr(
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif // !SPIFFS_READ_ONLY
|
||||
|
||||
void spiffs_cb_object_event(
|
||||
spiffs *fs,
|
||||
spiffs_fd *fd,
|
||||
int ev,
|
||||
spiffs_obj_id obj_id,
|
||||
spiffs_obj_id obj_id_raw,
|
||||
spiffs_span_ix spix,
|
||||
spiffs_page_ix new_pix,
|
||||
u32_t new_size) {
|
||||
(void)fd;
|
||||
// update index caches in all file descriptors
|
||||
obj_id &= ~SPIFFS_OBJ_ID_IX_FLAG;
|
||||
spiffs_obj_id obj_id = obj_id_raw & ~SPIFFS_OBJ_ID_IX_FLAG;
|
||||
u32_t i;
|
||||
spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
|
||||
for (i = 0; i < fs->fd_count; i++) {
|
||||
@ -811,7 +885,7 @@ void spiffs_cb_object_event(
|
||||
if (cur_fd->file_nbr == 0 || (cur_fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG) != obj_id) continue;
|
||||
if (spix == 0) {
|
||||
if (ev == SPIFFS_EV_IX_NEW || ev == SPIFFS_EV_IX_UPD) {
|
||||
SPIFFS_DBG(" callback: setting fd %d:%04x objix_hdr_pix to %04x, size:%d\n", cur_fd->file_nbr, cur_fd->obj_id, new_pix, new_size);
|
||||
SPIFFS_DBG(" callback: setting fd %i:%04x objix_hdr_pix to %04x, size:%i\n", cur_fd->file_nbr, cur_fd->obj_id, new_pix, new_size);
|
||||
cur_fd->objix_hdr_pix = new_pix;
|
||||
if (new_size != 0) {
|
||||
cur_fd->size = new_size;
|
||||
@ -823,13 +897,29 @@ void spiffs_cb_object_event(
|
||||
}
|
||||
if (cur_fd->cursor_objix_spix == spix) {
|
||||
if (ev == SPIFFS_EV_IX_NEW || ev == SPIFFS_EV_IX_UPD) {
|
||||
SPIFFS_DBG(" callback: setting fd %d:%04x span:%04x objix_pix to %04x\n", cur_fd->file_nbr, cur_fd->obj_id, spix, new_pix);
|
||||
SPIFFS_DBG(" callback: setting fd %i:%04x span:%04x objix_pix to %04x\n", cur_fd->file_nbr, cur_fd->obj_id, spix, new_pix);
|
||||
cur_fd->cursor_objix_pix = new_pix;
|
||||
} else {
|
||||
cur_fd->cursor_objix_pix = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// callback to user if object index header
|
||||
if (fs->file_cb_f && spix == 0 && (obj_id_raw & SPIFFS_OBJ_ID_IX_FLAG)) {
|
||||
spiffs_fileop_type op;
|
||||
if (ev == SPIFFS_EV_IX_NEW) {
|
||||
op = SPIFFS_CB_CREATED;
|
||||
} else if (ev == SPIFFS_EV_IX_UPD) {
|
||||
op = SPIFFS_CB_UPDATED;
|
||||
} else if (ev == SPIFFS_EV_IX_DEL) {
|
||||
op = SPIFFS_CB_DELETED;
|
||||
} else {
|
||||
SPIFFS_DBG(" callback: WARNING unknown callback event %02x\n", ev);
|
||||
return; // bail out
|
||||
}
|
||||
fs->file_cb_f(fs, op, obj_id, new_pix);
|
||||
}
|
||||
}
|
||||
|
||||
// Open object by id
|
||||
@ -883,11 +973,12 @@ s32_t spiffs_object_open_by_page(
|
||||
|
||||
SPIFFS_VALIDATE_OBJIX(oix_hdr.p_hdr, fd->obj_id, 0);
|
||||
|
||||
SPIFFS_DBG("open: fd %d is obj id %04x\n", fd->file_nbr, fd->obj_id);
|
||||
SPIFFS_DBG("open: fd %i is obj id %04x\n", fd->file_nbr, fd->obj_id);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#if !SPIFFS_READ_ONLY
|
||||
// Append to object
|
||||
// keep current object index (header) page in fs->work buffer
|
||||
s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
@ -895,7 +986,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
u32_t written = 0;
|
||||
|
||||
SPIFFS_DBG("append: %d bytes @ offs %d of size %d\n", len, offset, fd->size);
|
||||
SPIFFS_DBG("append: %i bytes @ offs %i of size %i\n", len, offset, fd->size);
|
||||
|
||||
if (offset > fd->size) {
|
||||
SPIFFS_DBG("append: offset reversed to size\n");
|
||||
@ -904,7 +995,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
|
||||
res = spiffs_gc_check(fs, len + SPIFFS_DATA_PAGE_SIZE(fs)); // add an extra page of data worth for meta
|
||||
if (res != SPIFFS_OK) {
|
||||
SPIFFS_DBG("append: gc check fail %d\n", res);
|
||||
SPIFFS_DBG("append: gc check fail %i\n", res);
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
@ -932,7 +1023,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
// within this clause we return directly if something fails, object index mess-up
|
||||
if (written > 0) {
|
||||
// store previous object index page, unless first pass
|
||||
SPIFFS_DBG("append: %04x store objix %04x:%04x, written %d\n", fd->obj_id,
|
||||
SPIFFS_DBG("append: %04x store objix %04x:%04x, written %i\n", fd->obj_id,
|
||||
cur_objix_pix, prev_objix_spix, written);
|
||||
if (prev_objix_spix == 0) {
|
||||
// this is an update to object index header page
|
||||
@ -949,7 +1040,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
|
||||
fd->objix_hdr_pix, fs->work, 0, offset+written, &new_objix_hdr_page);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
SPIFFS_DBG("append: %04x store new objix_hdr, %04x:%04x, written %d\n", fd->obj_id,
|
||||
SPIFFS_DBG("append: %04x store new objix_hdr, %04x:%04x, written %i\n", fd->obj_id,
|
||||
new_objix_hdr_page, 0, written);
|
||||
}
|
||||
} else {
|
||||
@ -965,7 +1056,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
|
||||
fd->objix_hdr_pix, 0, 0, offset+written, &new_objix_hdr_page);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
SPIFFS_DBG("append: %04x store new size I %d in objix_hdr, %04x:%04x, written %d\n", fd->obj_id,
|
||||
SPIFFS_DBG("append: %04x store new size I %i in objix_hdr, %04x:%04x, written %i\n", fd->obj_id,
|
||||
offset+written, new_objix_hdr_page, 0, written);
|
||||
}
|
||||
fd->size = offset+written;
|
||||
@ -994,7 +1085,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
// quick "load" of new object index page
|
||||
memset(fs->work, 0xff, SPIFFS_CFG_LOG_PAGE_SZ(fs));
|
||||
memcpy(fs->work, &p_hdr, sizeof(spiffs_page_header));
|
||||
SPIFFS_DBG("append: %04x create objix page, %04x:%04x, written %d\n", fd->obj_id
|
||||
SPIFFS_DBG("append: %04x create objix page, %04x:%04x, written %i\n", fd->obj_id
|
||||
, cur_objix_pix, cur_objix_spix, written);
|
||||
} else {
|
||||
// on first pass, we load existing object index page
|
||||
@ -1006,7 +1097,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
res = spiffs_obj_lu_find_id_and_span(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, 0, &pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
SPIFFS_DBG("append: %04x found object index at page %04x [fd size %d]\n", fd->obj_id, pix, fd->size);
|
||||
SPIFFS_DBG("append: %04x found object index at page %04x [fd size %i]\n", fd->obj_id, pix, fd->size);
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
|
||||
fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
@ -1030,7 +1121,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
p_hdr.flags = 0xff & ~(SPIFFS_PH_FLAG_FINAL); // finalize immediately
|
||||
res = spiffs_page_allocate_data(fs, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
|
||||
&p_hdr, &data[written], to_write, page_offs, 1, &data_page);
|
||||
SPIFFS_DBG("append: %04x store new data page, %04x:%04x offset:%d, len %d, written %d\n", fd->obj_id,
|
||||
SPIFFS_DBG("append: %04x store new data page, %04x:%04x offset:%i, len %i, written %i\n", fd->obj_id,
|
||||
data_page, data_spix, page_offs, to_write, written);
|
||||
} else {
|
||||
// append to existing page, fill out free data in existing page
|
||||
@ -1047,7 +1138,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
|
||||
fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, data_page) + sizeof(spiffs_page_header) + page_offs, to_write, &data[written]);
|
||||
SPIFFS_DBG("append: %04x store to existing data page, %04x:%04x offset:%d, len %d, written %d\n", fd->obj_id
|
||||
SPIFFS_DBG("append: %04x store to existing data page, %04x:%04x offset:%i, len %i, written %i\n", fd->obj_id
|
||||
, data_page, data_spix, page_offs, to_write, written);
|
||||
}
|
||||
|
||||
@ -1083,7 +1174,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
if (cur_objix_spix != 0) {
|
||||
// wrote beyond object index header page
|
||||
// write last modified object index page, unless object header index page
|
||||
SPIFFS_DBG("append: %04x store objix page, %04x:%04x, written %d\n", fd->obj_id,
|
||||
SPIFFS_DBG("append: %04x store objix page, %04x:%04x, written %i\n", fd->obj_id,
|
||||
cur_objix_pix, cur_objix_spix, written);
|
||||
|
||||
res2 = spiffs_page_index_check(fs, fd, cur_objix_pix, cur_objix_spix);
|
||||
@ -1097,7 +1188,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
// update size in object header index page
|
||||
res2 = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
|
||||
fd->objix_hdr_pix, 0, 0, offset+written, &new_objix_hdr_page);
|
||||
SPIFFS_DBG("append: %04x store new size II %d in objix_hdr, %04x:%04x, written %d, res %d\n", fd->obj_id
|
||||
SPIFFS_DBG("append: %04x store new size II %i in objix_hdr, %04x:%04x, written %i, res %i\n", fd->obj_id
|
||||
, offset+written, new_objix_hdr_page, 0, written, res2);
|
||||
SPIFFS_CHECK_RES(res2);
|
||||
} else {
|
||||
@ -1105,7 +1196,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
if (offset == 0) {
|
||||
// wrote to empty object - simply update size and write whole page
|
||||
objix_hdr->size = offset+written;
|
||||
SPIFFS_DBG("append: %04x store fresh objix_hdr page, %04x:%04x, written %d\n", fd->obj_id
|
||||
SPIFFS_DBG("append: %04x store fresh objix_hdr page, %04x:%04x, written %i\n", fd->obj_id
|
||||
, cur_objix_pix, cur_objix_spix, written);
|
||||
|
||||
res2 = spiffs_page_index_check(fs, fd, cur_objix_pix, cur_objix_spix);
|
||||
@ -1120,15 +1211,17 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
// modifying object index header page, update size and make new copy
|
||||
res2 = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
|
||||
fd->objix_hdr_pix, fs->work, 0, offset+written, &new_objix_hdr_page);
|
||||
SPIFFS_DBG("append: %04x store modified objix_hdr page, %04x:%04x, written %d\n", fd->obj_id
|
||||
SPIFFS_DBG("append: %04x store modified objix_hdr page, %04x:%04x, written %i\n", fd->obj_id
|
||||
, new_objix_hdr_page, 0, written);
|
||||
SPIFFS_CHECK_RES(res2);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
} // spiffs_object_append
|
||||
#endif // !SPIFFS_READ_ONLY
|
||||
|
||||
#if !SPIFFS_READ_ONLY
|
||||
// Modify object
|
||||
// keep current object index (header) page in fs->work buffer
|
||||
s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
@ -1168,7 +1261,7 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
// store previous object index header page
|
||||
res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
|
||||
fd->objix_hdr_pix, fs->work, 0, 0, &new_objix_hdr_pix);
|
||||
SPIFFS_DBG("modify: store modified objix_hdr page, %04x:%04x, written %d\n", new_objix_hdr_pix, 0, written);
|
||||
SPIFFS_DBG("modify: store modified objix_hdr page, %04x:%04x, written %i\n", new_objix_hdr_pix, 0, written);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
} else {
|
||||
// store new version of previous object index page
|
||||
@ -1178,7 +1271,7 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
res = spiffs_page_move(fs, fd->file_nbr, (u8_t*)objix, fd->obj_id, 0, cur_objix_pix, &new_objix_pix);
|
||||
SPIFFS_DBG("modify: store previous modified objix page, %04x:%04x, written %d\n", new_objix_pix, objix->p_hdr.span_ix, written);
|
||||
SPIFFS_DBG("modify: store previous modified objix page, %04x:%04x, written %i\n", new_objix_pix, objix->p_hdr.span_ix, written);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, fd->obj_id, objix->p_hdr.span_ix, new_objix_pix, 0);
|
||||
}
|
||||
@ -1233,7 +1326,7 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
// a full page, allocate and write a new page of data
|
||||
res = spiffs_page_allocate_data(fs, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
|
||||
&p_hdr, &data[written], to_write, page_offs, 1, &data_pix);
|
||||
SPIFFS_DBG("modify: store new data page, %04x:%04x offset:%d, len %d, written %d\n", data_pix, data_spix, page_offs, to_write, written);
|
||||
SPIFFS_DBG("modify: store new data page, %04x:%04x offset:%i, len %i, written %i\n", data_pix, data_spix, page_offs, to_write, written);
|
||||
} else {
|
||||
// write to existing page, allocate new and copy unmodified data
|
||||
|
||||
@ -1274,7 +1367,7 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
(u8_t *)&p_hdr.flags);
|
||||
if (res != SPIFFS_OK) break;
|
||||
|
||||
SPIFFS_DBG("modify: store to existing data page, src:%04x, dst:%04x:%04x offset:%d, len %d, written %d\n", orig_data_pix, data_pix, data_spix, page_offs, to_write, written);
|
||||
SPIFFS_DBG("modify: store to existing data page, src:%04x, dst:%04x:%04x offset:%i, len %i, written %i\n", orig_data_pix, data_pix, data_spix, page_offs, to_write, written);
|
||||
}
|
||||
|
||||
// delete original data page
|
||||
@ -1313,7 +1406,7 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
SPIFFS_CHECK_RES(res2);
|
||||
|
||||
res2 = spiffs_page_move(fs, fd->file_nbr, (u8_t*)objix, fd->obj_id, 0, cur_objix_pix, &new_objix_pix);
|
||||
SPIFFS_DBG("modify: store modified objix page, %04x:%04x, written %d\n", new_objix_pix, cur_objix_spix, written);
|
||||
SPIFFS_DBG("modify: store modified objix page, %04x:%04x, written %i\n", new_objix_pix, cur_objix_spix, written);
|
||||
fd->cursor_objix_pix = new_objix_pix;
|
||||
fd->cursor_objix_spix = cur_objix_spix;
|
||||
SPIFFS_CHECK_RES(res2);
|
||||
@ -1323,12 +1416,13 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
// wrote within object index header page
|
||||
res2 = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
|
||||
fd->objix_hdr_pix, fs->work, 0, 0, &new_objix_hdr_pix);
|
||||
SPIFFS_DBG("modify: store modified objix_hdr page, %04x:%04x, written %d\n", new_objix_hdr_pix, 0, written);
|
||||
SPIFFS_DBG("modify: store modified objix_hdr page, %04x:%04x, written %i\n", new_objix_hdr_pix, 0, written);
|
||||
SPIFFS_CHECK_RES(res2);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
} // spiffs_object_modify
|
||||
#endif // !SPIFFS_READ_ONLY
|
||||
|
||||
static s32_t spiffs_object_find_object_index_header_by_name_v(
|
||||
spiffs *fs,
|
||||
@ -1394,6 +1488,7 @@ s32_t spiffs_object_find_object_index_header_by_name(
|
||||
return res;
|
||||
}
|
||||
|
||||
#if !SPIFFS_READ_ONLY
|
||||
// Truncates object to new size. If new size is null, object may be removed totally
|
||||
s32_t spiffs_object_truncate(
|
||||
spiffs_fd *fd,
|
||||
@ -1402,6 +1497,11 @@ s32_t spiffs_object_truncate(
|
||||
s32_t res = SPIFFS_OK;
|
||||
spiffs *fs = fd->fs;
|
||||
|
||||
if ((fd->size == SPIFFS_UNDEFINED_LEN || fd->size == 0) && !remove) {
|
||||
// no op
|
||||
return res;
|
||||
}
|
||||
|
||||
// need 2 pages if not removing: object index page + possibly chopped data page
|
||||
res = spiffs_gc_check(fs, remove ? 0 : SPIFFS_DATA_PAGE_SIZE(fs) * 2);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
@ -1444,7 +1544,7 @@ s32_t spiffs_object_truncate(
|
||||
spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_DEL, fd->obj_id, objix->p_hdr.span_ix, objix_pix, 0);
|
||||
if (prev_objix_spix > 0) {
|
||||
// update object index header page
|
||||
SPIFFS_DBG("truncate: update objix hdr page %04x:%04x to size %d\n", fd->objix_hdr_pix, prev_objix_spix, cur_size);
|
||||
SPIFFS_DBG("truncate: update objix hdr page %04x:%04x to size %i\n", fd->objix_hdr_pix, prev_objix_spix, cur_size);
|
||||
res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
|
||||
fd->objix_hdr_pix, 0, 0, cur_size, &new_objix_hdr_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
@ -1487,14 +1587,14 @@ s32_t spiffs_object_truncate(
|
||||
// delete full data page
|
||||
res = spiffs_page_data_check(fs, fd, data_pix, data_spix);
|
||||
if (res != SPIFFS_ERR_DELETED && res != SPIFFS_OK && res != SPIFFS_ERR_INDEX_REF_FREE) {
|
||||
SPIFFS_DBG("truncate: err validating data pix %d\n", res);
|
||||
SPIFFS_DBG("truncate: err validating data pix %i\n", res);
|
||||
break;
|
||||
}
|
||||
|
||||
if (res == SPIFFS_OK) {
|
||||
res = spiffs_page_delete(fs, data_pix);
|
||||
if (res != SPIFFS_OK) {
|
||||
SPIFFS_DBG("truncate: err deleting data pix %d\n", res);
|
||||
SPIFFS_DBG("truncate: err deleting data pix %i\n", res);
|
||||
break;
|
||||
}
|
||||
} else if (res == SPIFFS_ERR_DELETED || res == SPIFFS_ERR_INDEX_REF_FREE) {
|
||||
@ -1509,13 +1609,13 @@ s32_t spiffs_object_truncate(
|
||||
}
|
||||
fd->size = cur_size;
|
||||
fd->offset = cur_size;
|
||||
SPIFFS_DBG("truncate: delete data page %04x for data spix:%04x, cur_size:%d\n", data_pix, data_spix, cur_size);
|
||||
SPIFFS_DBG("truncate: delete data page %04x for data spix:%04x, cur_size:%i\n", data_pix, data_spix, cur_size);
|
||||
} else {
|
||||
// delete last page, partially
|
||||
spiffs_page_header p_hdr;
|
||||
spiffs_page_ix new_data_pix;
|
||||
u32_t bytes_to_remove = SPIFFS_DATA_PAGE_SIZE(fs) - (new_size % SPIFFS_DATA_PAGE_SIZE(fs));
|
||||
SPIFFS_DBG("truncate: delete %d bytes from data page %04x for data spix:%04x, cur_size:%d\n", bytes_to_remove, data_pix, data_spix, cur_size);
|
||||
SPIFFS_DBG("truncate: delete %i bytes from data page %04x for data spix:%04x, cur_size:%i\n", bytes_to_remove, data_pix, data_spix, cur_size);
|
||||
|
||||
res = spiffs_page_data_check(fs, fd, data_pix, data_spix);
|
||||
if (res != SPIFFS_OK) break;
|
||||
@ -1614,7 +1714,8 @@ s32_t spiffs_object_truncate(
|
||||
fd->size = cur_size;
|
||||
|
||||
return res;
|
||||
}
|
||||
} // spiffs_object_truncate
|
||||
#endif // !SPIFFS_READ_ONLY
|
||||
|
||||
s32_t spiffs_object_read(
|
||||
spiffs_fd *fd,
|
||||
@ -1670,7 +1771,7 @@ s32_t spiffs_object_read(
|
||||
len_to_read = MIN(len_to_read, SPIFFS_DATA_PAGE_SIZE(fs) - (cur_offset % SPIFFS_DATA_PAGE_SIZE(fs)));
|
||||
// remaining data in file
|
||||
len_to_read = MIN(len_to_read, fd->size);
|
||||
SPIFFS_DBG("read: offset:%d rd:%d data spix:%04x is data_pix:%04x addr:%08x\n", cur_offset, len_to_read, data_spix, data_pix,
|
||||
SPIFFS_DBG("read: offset:%i rd:%i data spix:%04x is data_pix:%04x addr:%08x\n", cur_offset, len_to_read, data_spix, data_pix,
|
||||
SPIFFS_PAGE_TO_PADDR(fs, data_pix) + sizeof(spiffs_page_header) + (cur_offset % SPIFFS_DATA_PAGE_SIZE(fs)));
|
||||
if (len_to_read <= 0) {
|
||||
res = SPIFFS_ERR_END_OF_OBJECT;
|
||||
@ -1694,6 +1795,7 @@ s32_t spiffs_object_read(
|
||||
return res;
|
||||
}
|
||||
|
||||
#if !SPIFFS_READ_ONLY
|
||||
typedef struct {
|
||||
spiffs_obj_id min_obj_id;
|
||||
spiffs_obj_id max_obj_id;
|
||||
@ -1756,7 +1858,7 @@ static s32_t spiffs_obj_lu_find_free_obj_id_compact_v(spiffs *fs, spiffs_obj_id
|
||||
if (id >= state->min_obj_id && id <= state->max_obj_id) {
|
||||
u8_t *map = (u8_t *)fs->work;
|
||||
int ix = (id - state->min_obj_id) / state->compaction;
|
||||
//SPIFFS_DBG("free_obj_id: add ix %d for id %04x min:%04x max%04x comp:%d\n", ix, id, state->min_obj_id, state->max_obj_id, state->compaction);
|
||||
//SPIFFS_DBG("free_obj_id: add ix %i for id %04x min:%04x max%04x comp:%i\n", ix, id, state->min_obj_id, state->max_obj_id, state->compaction);
|
||||
map[ix]++;
|
||||
}
|
||||
}
|
||||
@ -1829,7 +1931,7 @@ s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id, const u8
|
||||
return SPIFFS_ERR_FULL;
|
||||
}
|
||||
|
||||
SPIFFS_DBG("free_obj_id: COMP select index:%d min_count:%d min:%04x max:%04x compact:%d\n", min_i, min_count, state.min_obj_id, state.max_obj_id, state.compaction);
|
||||
SPIFFS_DBG("free_obj_id: COMP select index:%i min_count:%i min:%04x max:%04x compact:%i\n", min_i, min_count, state.min_obj_id, state.max_obj_id, state.compaction);
|
||||
|
||||
if (min_count == 0) {
|
||||
// no id in this range, skip compacting and use directly
|
||||
@ -1849,7 +1951,7 @@ s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id, const u8
|
||||
// in a work memory of log_page_size bytes, we may fit in log_page_size ids
|
||||
// todo what if compaction is > 255 - then we cannot fit it in a byte
|
||||
state.compaction = (state.max_obj_id-state.min_obj_id) / ((SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(u8_t)));
|
||||
SPIFFS_DBG("free_obj_id: COMP min:%04x max:%04x compact:%d\n", state.min_obj_id, state.max_obj_id, state.compaction);
|
||||
SPIFFS_DBG("free_obj_id: COMP min:%04x max:%04x compact:%i\n", state.min_obj_id, state.max_obj_id, state.compaction);
|
||||
|
||||
memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs));
|
||||
res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_obj_lu_find_free_obj_id_compact_v, &state, 0, 0, 0);
|
||||
@ -1861,6 +1963,7 @@ s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id, const u8
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif // !SPIFFS_READ_ONLY
|
||||
|
||||
s32_t spiffs_fd_find_new(spiffs *fs, spiffs_fd **fd) {
|
||||
u32_t i;
|
||||
|
@ -131,7 +131,15 @@
|
||||
#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)))
|
||||
#if SPIFFS_USE_MAGIC
|
||||
#if !SPIFFS_USE_MAGIC_LENGTH
|
||||
#define SPIFFS_MAGIC(fs, bix) \
|
||||
((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs)))
|
||||
#else // SPIFFS_USE_MAGIC_LENGTH
|
||||
#define SPIFFS_MAGIC(fs, bix) \
|
||||
((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs) ^ ((fs)->block_count - (bix))))
|
||||
#endif // SPIFFS_USE_MAGIC_LENGTH
|
||||
#endif // SPIFFS_USE_MAGIC
|
||||
|
||||
#define SPIFFS_CONFIG_MAGIC (0x20090315)
|
||||
|
||||
@ -530,6 +538,11 @@ s32_t spiffs_erase_block(
|
||||
spiffs *fs,
|
||||
spiffs_block_ix bix);
|
||||
|
||||
#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
|
||||
s32_t spiffs_probe(
|
||||
spiffs_config *cfg);
|
||||
#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
|
||||
|
||||
// ---------------
|
||||
|
||||
s32_t spiffs_obj_lu_scan(
|
||||
|
Loading…
x
Reference in New Issue
Block a user