Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
Nodemcu Firmware
Commits
be047ff7
Commit
be047ff7
authored
Aug 02, 2016
by
Marcel Stör
Browse files
Merge branch 'dev', 1.5.4.1 master drop
parents
b580bfe7
a8d984ae
Changes
116
Hide whitespace changes
Inline
Side-by-side
app/platform/flash_api.c
View file @
be047ff7
...
...
@@ -118,6 +118,18 @@ uint32_t flash_rom_get_size_byte(void)
// 32Mbit, 4MByte
flash_size
=
4
*
1024
*
1024
;
break
;
case
SIZE_32MBIT_16M_16M
:
// 32Mbit, 4MByte
flash_size
=
4
*
1024
*
1024
;
break
;
case
SIZE_64MBIT
:
// 64Mbit, 8MByte
flash_size
=
8
*
1024
*
1024
;
break
;
case
SIZE_128MBIT
:
// 128Mbit, 16MByte
flash_size
=
16
*
1024
*
1024
;
break
;
default:
// Unknown flash size, fall back mode.
flash_size
=
512
*
1024
;
...
...
@@ -184,18 +196,16 @@ bool flash_rom_set_size_byte(uint32_t size)
flash_size
=
SIZE_32MBIT
;
flash_rom_set_size_type
(
flash_size
);
break
;
/*
case
8
*
1024
*
1024
:
// 64Mbit, 8MByte
flash_size = SIZE_
1
6MBIT
_8M_8M
;
flash_size
=
SIZE_6
4
MBIT
;
flash_rom_set_size_type
(
flash_size
);
break
;
case
16
*
1024
*
1024
:
// 128Mbit, 16MByte
flash_size = SIZE_
32
MBIT
_8M_8M
;
flash_size
=
SIZE_
128
MBIT
;
flash_rom_set_size_type
(
flash_size
);
break
;
*/
default:
// Unknown flash size.
result
=
false
;
...
...
app/platform/flash_api.h
View file @
be047ff7
...
...
@@ -80,6 +80,9 @@ typedef struct
SIZE_32MBIT
=
4
,
SIZE_16MBIT_8M_8M
=
5
,
SIZE_32MBIT_8M_8M
=
6
,
SIZE_32MBIT_16M_16M
=
7
,
SIZE_64MBIT
=
8
,
SIZE_128MBIT
=
9
,
}
size
:
4
;
uint32_t
entry_point
;
uint32_t
memory_offset
;
...
...
app/platform/flash_fs.h
View file @
be047ff7
...
...
@@ -6,7 +6,7 @@
#if defined( BUILD_SPIFFS )
#include "spiffs.h"
#include "
my
spiffs.h"
#define FS_OPEN_OK 1
...
...
app/platform/platform.c
View file @
be047ff7
...
...
@@ -612,7 +612,7 @@ void platform_sigma_delta_set_prescale( uint8_t prescale )
sigma_delta_set_prescale_target
(
prescale
,
-
1
);
}
void
platform_sigma_delta_set_target
(
uint8_t
target
)
void
ICACHE_RAM_ATTR
platform_sigma_delta_set_target
(
uint8_t
target
)
{
sigma_delta_set_prescale_target
(
-
1
,
target
);
}
...
...
app/spiffs/LICENSE
View file @
be047ff7
The MIT License (MIT)
Copyright (c) 2013-201
5
Peter Andersson (pelleplutt1976<at>gmail.com)
Copyright (c) 2013-201
6
Peter Andersson (pelleplutt1976<at>gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
...
...
app/spiffs/Makefile
View file @
be047ff7
...
...
@@ -22,7 +22,7 @@ endif
# makefile at its root level - these are then overridden
# for a subtree within the makefile rooted therein
#
#
DEFINES +=
DEFINES
+=
-Dprintf
=
c_printf
#############################################################
# Recursion Magic - Don't touch this!!
...
...
app/spiffs/docs/INTEGRATION
deleted
100644 → 0
View file @
b580bfe7
* 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
\ No newline at end of file
app/spiffs/docs/TODO
View file @
be047ff7
* When mending lost pages, also see if they fit into length specified in object index header
\ No newline at end of file
* When mending lost pages, also see if they fit into length specified in object index header
SPIFFS2 thoughts
* Instead of exact object id:s in the object lookup tables, use a hash of span index and object id.
Eg. object id xor:ed with bit-reversed span index.
This should decrease number of actual pages that needs to be visited when looking thru the obj lut.
* Logical number of each block. When moving stuff in a garbage collected page, the free
page is assigned the same number as the garbage collected. Thus, object index pages do not have to
be rewritten.
* Steal one page, use as a bit parity page. When starting an fs modification operation, write one bit
as zero. When ending, write another bit as zero. On mount, if number of zeroes in page is uneven, a
check is automatically run.
\ No newline at end of file
app/spiffs/myspiffs.h
0 → 100644
View file @
be047ff7
#include "spiffs.h"
bool
myspiffs_mount
();
void
myspiffs_unmount
();
int
myspiffs_open
(
const
char
*
name
,
int
flags
);
int
myspiffs_close
(
int
fd
);
size_t
myspiffs_write
(
int
fd
,
const
void
*
ptr
,
size_t
len
);
size_t
myspiffs_read
(
int
fd
,
void
*
ptr
,
size_t
len
);
int
myspiffs_lseek
(
int
fd
,
int
off
,
int
whence
);
int
myspiffs_eof
(
int
fd
);
int
myspiffs_tell
(
int
fd
);
int
myspiffs_getc
(
int
fd
);
int
myspiffs_ungetc
(
int
c
,
int
fd
);
int
myspiffs_flush
(
int
fd
);
int
myspiffs_error
(
int
fd
);
void
myspiffs_clearerr
(
int
fd
);
int
myspiffs_check
(
void
);
int
myspiffs_rename
(
const
char
*
old
,
const
char
*
newname
);
size_t
myspiffs_size
(
int
fd
);
int
myspiffs_format
(
void
);
app/spiffs/nodemcu_spiffs.h
0 → 100644
View file @
be047ff7
#ifndef _NODEMCU_SPIFFS_H
#define _NODEMCU_SPIFFS_H
#ifndef NODEMCU_SPIFFS_NO_INCLUDE
#include "c_stdint.h"
#include "c_stddef.h"
#include "c_stdio.h"
#include "user_interface.h"
typedef
uint32_t
intptr_t
;
#endif
// Turn off stats
#define SPIFFS_CACHE_STATS 0
#define SPIFFS_GC_STATS 0
// Needs to align stuff
#define SPIFFS_ALIGNED_OBJECT_INDEX_TABLES 1
// Enable magic so we can find the file system (but not yet)
#define SPIFFS_USE_MAGIC 1
#define SPIFFS_USE_MAGIC_LENGTH 1
// Reduce the chance of returning disk full
#define SPIFFS_GC_MAX_RUNS 256
#endif
app/spiffs/spiffs.c
View file @
be047ff7
#include "c_stdio.h"
#include "platform.h"
#include "spiffs.h"
spiffs
fs
;
#define LOG_PAGE_SIZE 256
#define LOG_PAGE_SIZE 256
#define LOG_BLOCK_SIZE (INTERNAL_FLASH_SECTOR_SIZE * 2)
#define LOG_BLOCK_SIZE_SMALL_FS (INTERNAL_FLASH_SECTOR_SIZE)
#define MIN_BLOCKS_FS 4
static
u8_t
spiffs_work_buf
[
LOG_PAGE_SIZE
*
2
];
static
u8_t
spiffs_fds
[
32
*
4
];
...
...
@@ -44,25 +47,121 @@ The small 4KB sectors allow for greater flexibility in applications th
********************/
void
myspiffs_mount
()
{
spiffs_config
cfg
;
static
bool
myspiffs_set_location
(
spiffs_config
*
cfg
,
int
align
,
int
offset
,
int
block_size
)
{
#ifdef SPIFFS_FIXED_LOCATION
cfg
.
phys_addr
=
SPIFFS_FIXED_LOCATION
;
cfg
->
phys_addr
=
(
SPIFFS_FIXED_LOCATION
+
block_size
-
1
)
&
~
(
block_size
-
1
);
#else
cfg
->
phys_addr
=
(
u32_t
)
platform_flash_get_first_free_block_address
(
NULL
)
+
offset
;
cfg
->
phys_addr
=
(
cfg
->
phys_addr
+
align
-
1
)
&
~
(
align
-
1
);
#endif
#ifdef SPIFFS_SIZE_1M_BOUNDARY
cfg
->
phys_size
=
((
0x100000
-
(
SYS_PARAM_SEC_NUM
*
INTERNAL_FLASH_SECTOR_SIZE
)
-
(
(
u32_t
)
cfg
->
phys_addr
))
&
~
(
block_size
-
1
))
&
0xfffff
;
#else
cfg
->
phys_size
=
(
INTERNAL_FLASH_SIZE
-
(
(
u32_t
)
cfg
->
phys_addr
))
&
~
(
block_size
-
1
);
#endif
if
((
int
)
cfg
->
phys_size
<
0
)
{
return
FALSE
;
}
cfg
->
log_block_size
=
block_size
;
return
(
cfg
->
phys_size
/
block_size
)
>=
MIN_BLOCKS_FS
;
}
/*
* Returns TRUE if FS was found
* align must be a power of two
*/
static
bool
myspiffs_set_cfg
(
spiffs_config
*
cfg
,
int
align
,
int
offset
,
bool
force_create
)
{
cfg
->
phys_erase_block
=
INTERNAL_FLASH_SECTOR_SIZE
;
// according to datasheet
cfg
->
log_page_size
=
LOG_PAGE_SIZE
;
// as we said
cfg
->
hal_read_f
=
my_spiffs_read
;
cfg
->
hal_write_f
=
my_spiffs_write
;
cfg
->
hal_erase_f
=
my_spiffs_erase
;
if
(
!
myspiffs_set_location
(
cfg
,
align
,
offset
,
LOG_BLOCK_SIZE
))
{
if
(
!
myspiffs_set_location
(
cfg
,
align
,
offset
,
LOG_BLOCK_SIZE_SMALL_FS
))
{
return
FALSE
;
}
}
NODE_DBG
(
"fs.start:%x,max:%x
\n
"
,
cfg
->
phys_addr
,
cfg
->
phys_size
);
#ifdef SPIFFS_USE_MAGIC_LENGTH
if
(
force_create
)
{
return
TRUE
;
}
int
size
=
SPIFFS_probe_fs
(
cfg
);
if
(
size
>
0
&&
size
<
cfg
->
phys_size
)
{
NODE_DBG
(
"Overriding size:%x
\n
"
,
size
);
cfg
->
phys_size
=
size
;
}
if
(
size
>
0
)
{
return
TRUE
;
}
return
FALSE
;
#else
cfg
.
phys_addr
=
(
u32_t
)
platform_flash_get_first_free_block_address
(
NULL
);
return
TRUE
;
#endif
}
static
bool
myspiffs_find_cfg
(
spiffs_config
*
cfg
,
bool
force_create
)
{
int
i
;
if
(
!
force_create
)
{
#ifdef SPIFFS_FIXED_LOCATION
if
(
myspiffs_set_cfg
(
cfg
,
0
,
0
,
FALSE
))
{
return
TRUE
;
}
#else
if
(
INTERNAL_FLASH_SIZE
>=
700000
)
{
for
(
i
=
0
;
i
<
8
;
i
++
)
{
if
(
myspiffs_set_cfg
(
cfg
,
0x10000
,
0x10000
*
i
,
FALSE
))
{
return
TRUE
;
}
}
}
for
(
i
=
0
;
i
<
8
;
i
++
)
{
if
(
myspiffs_set_cfg
(
cfg
,
LOG_BLOCK_SIZE
,
LOG_BLOCK_SIZE
*
i
,
FALSE
))
{
return
TRUE
;
}
}
#endif
}
// No existing file system -- set up for a format
if
(
INTERNAL_FLASH_SIZE
>=
700000
)
{
myspiffs_set_cfg
(
cfg
,
0x10000
,
0x10000
,
TRUE
);
#ifndef SPIFFS_MAX_FILESYSTEM_SIZE
if
(
cfg
->
phys_size
<
400000
)
{
// Don't waste so much in alignment
myspiffs_set_cfg
(
cfg
,
LOG_BLOCK_SIZE
,
LOG_BLOCK_SIZE
*
4
,
TRUE
);
}
#endif
}
else
{
myspiffs_set_cfg
(
cfg
,
LOG_BLOCK_SIZE
,
0
,
TRUE
);
}
#ifdef SPIFFS_MAX_FILESYSTEM_SIZE
if
(
cfg
->
phys_size
>
SPIFFS_MAX_FILESYSTEM_SIZE
)
{
cfg
->
phys_size
=
(
SPIFFS_MAX_FILESYSTEM_SIZE
)
&
~
(
cfg
->
log_block_size
-
1
);
}
#endif
cfg
.
phys_addr
+=
0x3FFF
;
cfg
.
phys_addr
&=
0xFFFFC000
;
// align to 4 sector.
cfg
.
phys_size
=
INTERNAL_FLASH_SIZE
-
(
(
u32_t
)
cfg
.
phys_addr
);
cfg
.
phys_erase_block
=
INTERNAL_FLASH_SECTOR_SIZE
;
// according to datasheet
cfg
.
log_block_size
=
INTERNAL_FLASH_SECTOR_SIZE
;
// let us not complicate things
cfg
.
log_page_size
=
LOG_PAGE_SIZE
;
// as we said
NODE_DBG
(
"fs.start:%x,max:%x
\n
"
,
cfg
.
phys_addr
,
cfg
.
phys_size
);
cfg
.
hal_read_f
=
my_spiffs_read
;
cfg
.
hal_write_f
=
my_spiffs_write
;
cfg
.
hal_erase_f
=
my_spiffs_erase
;
return
FALSE
;
}
static
bool
myspiffs_mount_internal
(
bool
force_mount
)
{
spiffs_config
cfg
;
if
(
!
myspiffs_find_cfg
(
&
cfg
,
force_mount
)
&&
!
force_mount
)
{
return
FALSE
;
}
fs
.
err_code
=
0
;
int
res
=
SPIFFS_mount
(
&
fs
,
&
cfg
,
spiffs_work_buf
,
...
...
@@ -76,7 +175,12 @@ void myspiffs_mount() {
#endif
// myspiffs_check_callback);
0
);
NODE_DBG
(
"mount res: %i
\n
"
,
res
);
NODE_DBG
(
"mount res: %d, %d
\n
"
,
res
,
fs
.
err_code
);
return
res
==
SPIFFS_OK
;
}
bool
myspiffs_mount
()
{
return
myspiffs_mount_internal
(
FALSE
);
}
void
myspiffs_unmount
()
{
...
...
@@ -88,23 +192,16 @@ void myspiffs_unmount() {
int
myspiffs_format
(
void
)
{
SPIFFS_unmount
(
&
fs
);
u32_t
sect_first
,
sect_last
;
#ifdef SPIFFS_FIXED_LOCATION
sect_first
=
SPIFFS_FIXED_LOCATION
;
#else
sect_first
=
(
u32_t
)
platform_flash_get_first_free_block_address
(
NULL
);
#endif
sect_first
+=
0x3FFF
;
sect_first
&=
0xFFFFC000
;
// align to 4 sector.
sect_first
=
platform_flash_get_sector_of_address
(
sect_first
);
sect_last
=
INTERNAL_FLASH_SIZE
-
SYS_PARAM_SEC_NUM
;
sect_last
=
platform_flash_get_sector_of_address
(
sect_last
);
NODE_DBG
(
"sect_first: %x, sect_last: %x
\n
"
,
sect_first
,
sect_last
);
while
(
sect_first
<=
sect_last
)
if
(
platform_flash_erase_sector
(
sect_first
++
)
==
PLATFORM_ERR
)
return
0
;
myspiffs_mount
();
return
1
;
myspiffs_mount_internal
(
TRUE
);
SPIFFS_unmount
(
&
fs
);
NODE_DBG
(
"Formatting: size 0x%x, addr 0x%x
\n
"
,
fs
.
cfg
.
phys_size
,
fs
.
cfg
.
phys_addr
);
if
(
SPIFFS_format
(
&
fs
)
<
0
)
{
return
0
;
}
return
myspiffs_mount
();
}
int
myspiffs_check
(
void
)
...
...
@@ -120,8 +217,7 @@ int myspiffs_open(const char *name, int flags){
}
int
myspiffs_close
(
int
fd
){
SPIFFS_close
(
&
fs
,
(
spiffs_file
)
fd
);
return
0
;
return
SPIFFS_close
(
&
fs
,
(
spiffs_file
)
fd
);
}
size_t
myspiffs_write
(
int
fd
,
const
void
*
ptr
,
size_t
len
){
#if 0
...
...
@@ -184,7 +280,10 @@ int myspiffs_rename( const char *old, const char *newname ){
return
SPIFFS_rename
(
&
fs
,
(
char
*
)
old
,
(
char
*
)
newname
);
}
size_t
myspiffs_size
(
int
fd
){
return
SPIFFS_size
(
&
fs
,
(
spiffs_file
)
fd
);
int32_t
curpos
=
SPIFFS_tell
(
&
fs
,
(
spiffs_file
)
fd
);
int32_t
size
=
SPIFFS_lseek
(
&
fs
,
(
spiffs_file
)
fd
,
SPIFFS_SEEK_END
,
0
);
(
void
)
SPIFFS_lseek
(
&
fs
,
(
spiffs_file
)
fd
,
SPIFFS_SEEK_SET
,
curpos
);
return
size
;
}
#if 0
void test_spiffs() {
...
...
app/spiffs/spiffs.h
View file @
be047ff7
...
...
@@ -5,8 +5,6 @@
* Author: petera
*/
#ifndef SPIFFS_H_
#define SPIFFS_H_
#if defined(__cplusplus)
...
...
@@ -49,6 +47,15 @@ extern "C" {
#define SPIFFS_ERR_NO_DELETED_BLOCKS -10029
#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_NAME_TOO_LONG -10036
#define SPIFFS_ERR_INTERNAL -10050
#define SPIFFS_ERR_TEST -10100
...
...
@@ -63,12 +70,26 @@ typedef u16_t spiffs_mode;
// object type
typedef
u8_t
spiffs_obj_type
;
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 */
typedef
s32_t
(
*
spiffs_write
)(
struct
spiffs_t
*
fs
,
u32_t
addr
,
u32_t
size
,
u8_t
*
src
);
/* spi erase call function type */
typedef
s32_t
(
*
spiffs_erase
)(
struct
spiffs_t
*
fs
,
u32_t
addr
,
u32_t
size
);
#else // SPIFFS_HAL_CALLBACK_EXTRA
/* spi read call function type */
typedef
s32_t
(
*
spiffs_read
)(
u32_t
addr
,
u32_t
size
,
u8_t
*
dst
);
/* spi write call function type */
typedef
s32_t
(
*
spiffs_write
)(
u32_t
addr
,
u32_t
size
,
u8_t
*
src
);
/* spi erase call function type */
typedef
s32_t
(
*
spiffs_erase
)(
u32_t
addr
,
u32_t
size
);
#endif // SPIFFS_HAL_CALLBACK_EXTRA
/* file system check callback report operation */
typedef
enum
{
...
...
@@ -85,12 +106,30 @@ typedef enum {
SPIFFS_CHECK_FIX_LOOKUP
,
SPIFFS_CHECK_DELETE_ORPHANED_INDEX
,
SPIFFS_CHECK_DELETE_PAGE
,
SPIFFS_CHECK_DELETE_BAD_FILE
,
SPIFFS_CHECK_DELETE_BAD_FILE
}
spiffs_check_report
;
/* file system check callback function */
#if SPIFFS_HAL_CALLBACK_EXTRA
typedef
void
(
*
spiffs_check_callback
)(
struct
spiffs_t
*
fs
,
spiffs_check_type
type
,
spiffs_check_report
report
,
u32_t
arg1
,
u32_t
arg2
);
#else // SPIFFS_HAL_CALLBACK_EXTRA
typedef
void
(
*
spiffs_check_callback
)(
spiffs_check_type
type
,
spiffs_check_report
report
,
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(...) \
...
...
@@ -108,18 +147,28 @@ typedef void (*spiffs_check_callback)(spiffs_check_type type, spiffs_check_repor
/* Any write to the filehandle is appended to end of the file */
#define SPIFFS_APPEND (1<<0)
#define SPIFFS_O_APPEND SPIFFS_APPEND
/* If the opened file exists, it will be truncated to zero length before opened */
#define SPIFFS_TRUNC (1<<1)
#define SPIFFS_O_TRUNC SPIFFS_TRUNC
/* If the opened file does not exist, it will be created before opened */
#define SPIFFS_CREAT (1<<2)
#define SPIFFS_O_CREAT SPIFFS_CREAT
/* The opened file may only be read */
#define SPIFFS_RDONLY (1<<3)
/* The opened file may only be writted */
#define SPIFFS_O_RDONLY SPIFFS_RDONLY
/* The opened file may only be written */
#define SPIFFS_WRONLY (1<<4)
/* The opened file may be both read and writted */
#define SPIFFS_O_WRONLY SPIFFS_WRONLY
/* The opened file may be both read and written */
#define SPIFFS_RDWR (SPIFFS_RDONLY | SPIFFS_WRONLY)
/* Any writes to the filehandle will never be cached */
#define SPIFFS_O_RDWR SPIFFS_RDWR
/* Any writes to the filehandle will never be cached but flushed directly */
#define SPIFFS_DIRECT (1<<5)
#define SPIFFS_O_DIRECT SPIFFS_DIRECT
/* If SPIFFS_O_CREAT and SPIFFS_O_EXCL are set, SPIFFS_open() shall fail if the file exists */
#define SPIFFS_EXCL (1<<6)
#define SPIFFS_O_EXCL SPIFFS_EXCL
#define SPIFFS_SEEK_SET (0)
#define SPIFFS_SEEK_CUR (1)
...
...
@@ -164,10 +213,15 @@ typedef struct {
// logical size of a page, must be at least
// log_block_size / 8
u32_t
log_page_size
;
#endif
#if SPIFFS_FILEHDL_OFFSET
// an integer offset added to each file handle
u16_t
fh_ix_offset
;
#endif
}
spiffs_config
;
typedef
struct
{
typedef
struct
spiffs_t
{
// file system configuration
spiffs_config
cfg
;
// number of logical blocks
...
...
@@ -222,9 +276,12 @@ typedef struct {
// 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
void
*
user_data
;
// config magic
u32_t
config_magic
;
}
spiffs
;
...
...
@@ -234,6 +291,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
;
...
...
@@ -253,6 +311,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
...
...
@@ -286,19 +378,18 @@ void SPIFFS_unmount(spiffs *fs);
* @param path the path of the new file
* @param mode ignored, for posix compliance
*/
s32_t
SPIFFS_creat
(
spiffs
*
fs
,
char
*
path
,
spiffs_mode
mode
);
s32_t
SPIFFS_creat
(
spiffs
*
fs
,
const
char
*
path
,
spiffs_mode
mode
);
/**
* Opens/creates a file.
* @param fs the file system struct
* @param path the path of the new 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
* SPIFFS_
O_
APPEND, SPIFFS_
O_
TRUNC, SPIFFS_
O_
CREAT, SPIFFS_
O_
RDONLY,
* SPIFFS_
O_
WRONLY, SPIFFS_
O_
RDWR, SPIFFS_
O_
DIRECT
, SPIFFS_O_EXCL
* @param mode ignored, for posix compliance
*/
spiffs_file
SPIFFS_open
(
spiffs
*
fs
,
char
*
path
,
spiffs_flags
flags
,
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.
...
...
@@ -306,7 +397,7 @@ spiffs_file SPIFFS_open(spiffs *fs, char *path, spiffs_flags flags, spiffs_mode
* 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.
...
...
@@ -315,6 +406,22 @@ spiffs_file SPIFFS_open(spiffs *fs, char *path, spiffs_flags flags, spiffs_mode
*/
spiffs_file
SPIFFS_open_by_dirent
(
spiffs
*
fs
,
struct
spiffs_dirent
*
e
,
spiffs_flags
flags
,
spiffs_mode
mode
);
/**
* 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
...
...
@@ -336,13 +443,14 @@ s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len);
s32_t
SPIFFS_write
(
spiffs
*
fs
,
spiffs_file
fh
,
void
*
buf
,
s32_t
len
);
/**
* Moves the read/write file offset
* Moves the read/write file offset. Resulting offset is returned or negative if error.
* lseek(fs, fd, 0, SPIFFS_SEEK_CUR) will thus return current offset.
* @param fs the file system struct
* @param fh the filehandle
* @param offs how much/where to move the offset
* @param whence if SPIFFS_SEEK_SET, the file offset shall be set to offset bytes
* if SPIFFS_SEEK_CUR, the file offset shall be set to its current location plus offset
* if SPIFFS_SEEK_END, the file offset shall be set to the size of the file plus offse
t
* if SPIFFS_SEEK_END, the file offset shall be set to the size of the file plus offse
, which should be negative
*/
s32_t
SPIFFS_lseek
(
spiffs
*
fs
,
spiffs_file
fh
,
s32_t
offs
,
int
whence
);
...
...
@@ -351,7 +459,7 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence);
* @param fs the file system struct
* @param path the path of the file to remove
*/
s32_t
SPIFFS_remove
(
spiffs
*
fs
,
char
*
path
);
s32_t
SPIFFS_remove
(
spiffs
*
fs
,
const
char
*
path
);
/**
* Removes a file by filehandle
...
...
@@ -366,7 +474,7 @@ s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh);
* @param path the path of the file to stat
* @param s the stat struct to populate
*/
s32_t
SPIFFS_stat
(
spiffs
*
fs
,
char
*
path
,
spiffs_stat
*
s
);
s32_t
SPIFFS_stat
(
spiffs
*
fs
,
const
char
*
path
,
spiffs_stat
*
s
);
/**
* Gets file status by filehandle
...
...
@@ -388,7 +496,7 @@ s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh);
* @param fs the file system struct
* @param fh the filehandle of the file to close
*/
void
SPIFFS_close
(
spiffs
*
fs
,
spiffs_file
fh
);
s32_t
SPIFFS_close
(
spiffs
*
fs
,
spiffs_file
fh
);
/**
* Renames a file
...
...
@@ -396,7 +504,7 @@ void SPIFFS_close(spiffs *fs, spiffs_file fh);
* @param old path of file to rename
* @param newPath new path of file
*/
s32_t
SPIFFS_rename
(
spiffs
*
fs
,
char
*
old
,
char
*
newPath
);
s32_t
SPIFFS_rename
(
spiffs
*
fs
,
const
char
*
old
,
const
char
*
newPath
);
/**
* Returns last error of last file operation.
...
...
@@ -419,7 +527,7 @@ void SPIFFS_clearerr(spiffs *fs);
* @param name the name of the directory
* @param d pointer the directory stream to be populated
*/
spiffs_DIR
*
SPIFFS_opendir
(
spiffs
*
fs
,
char
*
name
,
spiffs_DIR
*
d
);
spiffs_DIR
*
SPIFFS_opendir
(
spiffs
*
fs
,
const
char
*
name
,
spiffs_DIR
*
d
);
/**
* Closes a directory stream
...
...
@@ -441,13 +549,6 @@ struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e);
*/
s32_t
SPIFFS_check
(
spiffs
*
fs
);
/**
* Searches for a block with only deleted entries. If found, it is erased.
* @param fs the file system struct
*/
s32_t
SPIFFS_erase_deleted_block
(
spiffs
*
fs
);
/**
* Returns number of total bytes available and number of used bytes.
* This is an estimation, and depends on if there a many files with little
...
...
@@ -527,6 +628,36 @@ s32_t SPIFFS_gc_quick(spiffs *fs, u16_t max_free_pages);
*/
s32_t
SPIFFS_gc
(
spiffs
*
fs
,
u32_t
size
);
/**
* Check if EOF reached.
* @param fs the file system struct
* @param fh the filehandle of the file to check
*/
s32_t
SPIFFS_eof
(
spiffs
*
fs
,
spiffs_file
fh
);
/**
* Get position in file.
* @param fs the file system struct
* @param fh the filehandle of the file to check
*/
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.
...
...
@@ -553,30 +684,6 @@ u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages);
#if SPIFFS_CACHE
#endif
void
myspiffs_mount
();
void
myspiffs_unmount
();
int
myspiffs_open
(
const
char
*
name
,
int
flags
);
int
myspiffs_close
(
int
fd
);
size_t
myspiffs_write
(
int
fd
,
const
void
*
ptr
,
size_t
len
);
size_t
myspiffs_read
(
int
fd
,
void
*
ptr
,
size_t
len
);
int
myspiffs_lseek
(
int
fd
,
int
off
,
int
whence
);
int
myspiffs_eof
(
int
fd
);
int
myspiffs_tell
(
int
fd
);
int
myspiffs_getc
(
int
fd
);
int
myspiffs_ungetc
(
int
c
,
int
fd
);
int
myspiffs_flush
(
int
fd
);
int
myspiffs_error
(
int
fd
);
void
myspiffs_clearerr
(
int
fd
);
int
myspiffs_check
(
void
);
int
myspiffs_rename
(
const
char
*
old
,
const
char
*
newname
);
size_t
myspiffs_size
(
int
fd
);
int
myspiffs_format
(
void
);
s32_t
SPIFFS_eof
(
spiffs
*
fs
,
spiffs_file
fh
);
s32_t
SPIFFS_tell
(
spiffs
*
fs
,
spiffs_file
fh
);
s32_t
SPIFFS_size
(
spiffs
*
fs
,
spiffs_file
fh
);
#if defined(__cplusplus)
}
#endif
...
...
app/spiffs/spiffs_cache.c
View file @
be047ff7
...
...
@@ -39,7 +39,7 @@ static s32_t spiffs_cache_page_free(spiffs *fs, int ix, u8_t write_back) {
(
cp
->
flags
&
SPIFFS_CACHE_FLAG_TYPE_WR
)
==
0
&&
(
cp
->
flags
&
SPIFFS_CACHE_FLAG_DIRTY
))
{
u8_t
*
mem
=
spiffs_get_cache_page
(
fs
,
cache
,
ix
);
res
=
fs
->
cfg
.
hal_write_f
(
SPIFFS_PAGE_TO_PADDR
(
fs
,
cp
->
pix
),
SPIFFS_CFG_LOG_PAGE_SZ
(
fs
),
mem
);
res
=
SPIFFS_HAL_WRITE
(
fs
,
SPIFFS_PAGE_TO_PADDR
(
fs
,
cp
->
pix
),
SPIFFS_CFG_LOG_PAGE_SZ
(
fs
),
mem
);
}
cp
->
flags
=
0
;
...
...
@@ -137,10 +137,7 @@ s32_t spiffs_phys_rd(
}
else
{
if
((
op
&
SPIFFS_OP_TYPE_MASK
)
==
SPIFFS_OP_T_OBJ_LU2
)
{
// for second layer lookup functions, we do not cache in order to prevent shredding
return
fs
->
cfg
.
hal_read_f
(
addr
,
len
,
dst
);
return
SPIFFS_HAL_READ
(
fs
,
addr
,
len
,
dst
);
}
#if SPIFFS_CACHE_STATS
fs
->
cache_misses
++
;
...
...
@@ -151,8 +148,7 @@ s32_t spiffs_phys_rd(
cp
->
flags
=
SPIFFS_CACHE_FLAG_WRTHRU
;
cp
->
pix
=
SPIFFS_PADDR_TO_PAGE
(
fs
,
addr
);
}
s32_t
res2
=
fs
->
cfg
.
hal_read_f
(
s32_t
res2
=
SPIFFS_HAL_READ
(
fs
,
addr
-
SPIFFS_PADDR_TO_PAGE_OFFSET
(
fs
,
addr
),
SPIFFS_CFG_LOG_PAGE_SZ
(
fs
),
spiffs_get_cache_page
(
fs
,
cache
,
cp
->
ix
));
...
...
@@ -161,7 +157,7 @@ s32_t spiffs_phys_rd(
}
}
u8_t
*
mem
=
spiffs_get_cache_page
(
fs
,
cache
,
cp
->
ix
);
c_
memcpy
(
dst
,
&
mem
[
SPIFFS_PADDR_TO_PAGE_OFFSET
(
fs
,
addr
)],
len
);
memcpy
(
dst
,
&
mem
[
SPIFFS_PADDR_TO_PAGE_OFFSET
(
fs
,
addr
)],
len
);
return
res
;
}
...
...
@@ -186,24 +182,24 @@ s32_t spiffs_phys_wr(
(
op
&
SPIFFS_OP_TYPE_MASK
)
!=
SPIFFS_OP_T_OBJ_LU
)
{
// page is being deleted, wipe from cache - unless it is a lookup page
spiffs_cache_page_free
(
fs
,
cp
->
ix
,
0
);
return
fs
->
cfg
.
hal_write_f
(
addr
,
len
,
src
);
return
SPIFFS_HAL_WRITE
(
fs
,
addr
,
len
,
src
);
}
u8_t
*
mem
=
spiffs_get_cache_page
(
fs
,
cache
,
cp
->
ix
);
c_
memcpy
(
&
mem
[
SPIFFS_PADDR_TO_PAGE_OFFSET
(
fs
,
addr
)],
src
,
len
);
memcpy
(
&
mem
[
SPIFFS_PADDR_TO_PAGE_OFFSET
(
fs
,
addr
)],
src
,
len
);
cache
->
last_access
++
;
cp
->
last_access
=
cache
->
last_access
;
if
(
cp
->
flags
&
SPIFFS_CACHE_FLAG_WRTHRU
)
{
// page is being updated, no write-cache, just pass thru
return
fs
->
cfg
.
hal_write_f
(
addr
,
len
,
src
);
return
SPIFFS_HAL_WRITE
(
fs
,
addr
,
len
,
src
);
}
else
{
return
SPIFFS_OK
;
}
}
else
{
// no cache page, no write cache - just write thru
return
fs
->
cfg
.
hal_write_f
(
addr
,
len
,
src
);
return
SPIFFS_HAL_WRITE
(
fs
,
addr
,
len
,
src
);
}
}
...
...
@@ -282,17 +278,17 @@ void spiffs_cache_init(spiffs *fs) {
}
spiffs_cache
cache
;
c_
memset
(
&
cache
,
0
,
sizeof
(
spiffs_cache
));
memset
(
&
cache
,
0
,
sizeof
(
spiffs_cache
));
cache
.
cpage_count
=
cache_entries
;
cache
.
cpages
=
(
u8_t
*
)((
u8_t
*
)
fs
->
cache
+
sizeof
(
spiffs_cache
));
cache
.
cpage_use_map
=
0xffffffff
;
cache
.
cpage_use_mask
=
cache_mask
;
c_
memcpy
(
fs
->
cache
,
&
cache
,
sizeof
(
spiffs_cache
));
memcpy
(
fs
->
cache
,
&
cache
,
sizeof
(
spiffs_cache
));
spiffs_cache
*
c
=
spiffs_get_cache
(
fs
);
c_
memset
(
c
->
cpages
,
0
,
c
->
cpage_count
*
SPIFFS_CACHE_PAGE_SIZE
(
fs
));
memset
(
c
->
cpages
,
0
,
c
->
cpage_count
*
SPIFFS_CACHE_PAGE_SIZE
(
fs
));
c
->
cpage_use_map
&=
~
(
c
->
cpage_use_mask
);
for
(
i
=
0
;
i
<
cache
.
cpage_count
;
i
++
)
{
...
...
app/spiffs/spiffs_check.c
View file @
be047ff7
...
...
@@ -19,9 +19,24 @@
* 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) \
do { \
if ((_fs)->check_cb_f) (_fs)->check_cb_f((_fs), (_type), (_rep), (_arg1), (_arg2)); \
} while (0)
#else
#define CHECK_CB(_fs, _type, _rep, _arg1, _arg2) \
do { \
if ((_fs)->check_cb_f) (_fs)->check_cb_f((_type), (_rep), (_arg1), (_arg2)); \
} while (0)
#endif
//---------------------------------------
// Look up consistency
...
...
@@ -93,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
,
...
...
@@ -194,9 +210,9 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
res
=
spiffs_page_delete
(
fs
,
new_pix
);
SPIFFS_CHECK_RES
(
res
);
res
=
spiffs_delete_obj_lazy
(
fs
,
p_hdr
->
obj_id
);
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_DELETE_BAD_FILE
,
p_hdr
->
obj_id
,
0
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_DELETE_BAD_FILE
,
p_hdr
->
obj_id
,
0
);
}
else
{
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_FIX_INDEX
,
p_hdr
->
obj_id
,
p_hdr
->
span_ix
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_FIX_INDEX
,
p_hdr
->
obj_id
,
p_hdr
->
span_ix
);
}
SPIFFS_CHECK_RES
(
res
);
}
...
...
@@ -216,7 +232,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
SPIFFS_CHECK_DBG
(
"LU: FIXUP: ix page with data not found elsewhere, rewriting %04x to new page %04x
\n
"
,
cur_pix
,
new_pix
);
SPIFFS_CHECK_RES
(
res
);
*
reload_lu
=
1
;
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_FIX_LOOKUP
,
p_hdr
->
obj_id
,
p_hdr
->
span_ix
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_FIX_LOOKUP
,
p_hdr
->
obj_id
,
p_hdr
->
span_ix
);
}
}
else
{
SPIFFS_CHECK_RES
(
res
);
...
...
@@ -254,7 +270,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
SPIFFS_CHECK_RES
(
res
);
res
=
spiffs_delete_obj_lazy
(
fs
,
p_hdr
->
obj_id
);
*
reload_lu
=
1
;
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_DELETE_BAD_FILE
,
p_hdr
->
obj_id
,
0
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_DELETE_BAD_FILE
,
p_hdr
->
obj_id
,
0
);
}
SPIFFS_CHECK_RES
(
res
);
}
...
...
@@ -306,7 +322,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
new_ph
.
obj_id
=
p_hdr
->
obj_id
|
SPIFFS_OBJ_ID_IX_FLAG
;
res
=
spiffs_rewrite_page
(
fs
,
cur_pix
,
&
new_ph
,
&
new_pix
);
SPIFFS_CHECK_DBG
(
"LU: FIXUP: rewrite page %04x as %04x to pix %04x
\n
"
,
cur_pix
,
new_ph
.
obj_id
,
new_pix
);
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_FIX_LOOKUP
,
p_hdr
->
obj_id
,
p_hdr
->
span_ix
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_FIX_LOOKUP
,
p_hdr
->
obj_id
,
p_hdr
->
span_ix
);
SPIFFS_CHECK_RES
(
res
);
*
reload_lu
=
1
;
}
else
if
((
objix_pix_ph
&&
data_pix_ph
&&
data_pix_lu
&&
objix_pix_lu
==
0
)
||
...
...
@@ -315,7 +331,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
// rewrite as obj_id_lu
new_ph
.
obj_id
=
lu_obj_id
|
SPIFFS_OBJ_ID_IX_FLAG
;
SPIFFS_CHECK_DBG
(
"LU: FIXUP: rewrite page %04x as %04x
\n
"
,
cur_pix
,
new_ph
.
obj_id
);
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_FIX_LOOKUP
,
p_hdr
->
obj_id
,
p_hdr
->
span_ix
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_FIX_LOOKUP
,
p_hdr
->
obj_id
,
p_hdr
->
span_ix
);
res
=
spiffs_rewrite_page
(
fs
,
cur_pix
,
&
new_ph
,
&
new_pix
);
SPIFFS_CHECK_RES
(
res
);
*
reload_lu
=
1
;
...
...
@@ -353,7 +369,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
// if only data page exists, make this page index
if
(
data_pix
&&
objix_pix_d
==
0
)
{
SPIFFS_CHECK_DBG
(
"LU: FIXUP: other data page exists, make this index
\n
"
);
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_FIX_INDEX
,
lu_obj_id
,
p_hdr
->
span_ix
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_FIX_INDEX
,
lu_obj_id
,
p_hdr
->
span_ix
);
spiffs_page_header
new_ph
;
spiffs_page_ix
new_pix
;
new_ph
.
flags
=
0xff
&
~
(
SPIFFS_PH_FLAG_USED
|
SPIFFS_PH_FLAG_FINAL
|
SPIFFS_PH_FLAG_INDEX
);
...
...
@@ -369,7 +385,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
// if only index exists, make data page
if
(
data_pix
==
0
&&
objix_pix_d
)
{
SPIFFS_CHECK_DBG
(
"LU: FIXUP: other index page exists, make this data
\n
"
);
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_FIX_LOOKUP
,
lu_obj_id
,
p_hdr
->
span_ix
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_FIX_LOOKUP
,
lu_obj_id
,
p_hdr
->
span_ix
);
spiffs_page_header
new_ph
;
spiffs_page_ix
new_pix
;
new_ph
.
flags
=
0xff
&
~
(
SPIFFS_PH_FLAG_USED
|
SPIFFS_PH_FLAG_FINAL
);
...
...
@@ -406,7 +422,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
// page referenced by object index but not final
// just finalize
SPIFFS_CHECK_DBG
(
"LU: FIXUP: unfinalized page is referred, finalizing
\n
"
);
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_FIX_LOOKUP
,
p_hdr
->
obj_id
,
p_hdr
->
span_ix
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_FIX_LOOKUP
,
p_hdr
->
obj_id
,
p_hdr
->
span_ix
);
u8_t
flags
=
0xff
&
~
SPIFFS_PH_FLAG_FINAL
;
res
=
_spiffs_wr
(
fs
,
SPIFFS_OP_T_OBJ_DA
|
SPIFFS_OP_C_UPDT
,
0
,
SPIFFS_PAGE_TO_PADDR
(
fs
,
cur_pix
)
+
offsetof
(
spiffs_page_header
,
flags
),
...
...
@@ -418,7 +434,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
if
(
delete_page
)
{
SPIFFS_CHECK_DBG
(
"LU: FIXUP: deleting page %04x
\n
"
,
cur_pix
);
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_DELETE_PAGE
,
cur_pix
,
0
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_DELETE_PAGE
,
cur_pix
,
0
);
res
=
spiffs_page_delete
(
fs
,
cur_pix
);
SPIFFS_CHECK_RES
(
res
);
}
...
...
@@ -427,14 +443,14 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
}
static
s32_t
spiffs_lookup_check_v
(
spiffs
*
fs
,
spiffs_obj_id
obj_id
,
spiffs_block_ix
cur_block
,
int
cur_entry
,
u32_t
user_data
,
void
*
user_p
)
{
(
void
)
user_
data
;
(
void
)
user_p
;
const
void
*
user_const_p
,
void
*
user_
var_
p
)
{
(
void
)
user_
const_p
;
(
void
)
user_
var_
p
;
s32_t
res
=
SPIFFS_OK
;
spiffs_page_header
p_hdr
;
spiffs_page_ix
cur_pix
=
SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX
(
fs
,
cur_block
,
cur_entry
);
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_PROGRESS
,
CHECK_CB
(
fs
,
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_PROGRESS
,
(
cur_block
*
256
)
/
fs
->
block_count
,
0
);
// load header
...
...
@@ -460,7 +476,7 @@ s32_t spiffs_lookup_consistency_check(spiffs *fs, u8_t check_all_objects) {
(
void
)
check_all_objects
;
s32_t
res
=
SPIFFS_OK
;
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_PROGRESS
,
0
,
0
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_PROGRESS
,
0
,
0
);
res
=
spiffs_obj_lu_find_entry_visitor
(
fs
,
0
,
0
,
0
,
0
,
spiffs_lookup_check_v
,
0
,
0
,
0
,
0
);
...
...
@@ -469,10 +485,10 @@ s32_t spiffs_lookup_consistency_check(spiffs *fs, u8_t check_all_objects) {
}
if
(
res
!=
SPIFFS_OK
)
{
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_ERROR
,
res
,
0
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_ERROR
,
res
,
0
);
}
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_PROGRESS
,
256
,
0
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_LOOKUP
,
SPIFFS_CHECK_PROGRESS
,
256
,
0
);
return
res
;
}
...
...
@@ -501,19 +517,22 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
while
(
pix_offset
<
SPIFFS_PAGES_PER_BLOCK
(
fs
)
*
fs
->
block_count
)
{
// set this flag to abort all checks and rescan the page range
u8_t
restart
=
0
;
c_
memset
(
fs
->
work
,
0
,
SPIFFS_CFG_LOG_PAGE_SZ
(
fs
));
memset
(
fs
->
work
,
0
,
SPIFFS_CFG_LOG_PAGE_SZ
(
fs
));
spiffs_block_ix
cur_block
=
0
;
// build consistency bitmap for id range traversing all blocks
while
(
!
restart
&&
cur_block
<
fs
->
block_count
)
{
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_PROGRESS
,
CHECK_CB
(
fs
,
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_PROGRESS
,
(
pix_offset
*
256
)
/
(
SPIFFS_PAGES_PER_BLOCK
(
fs
)
*
fs
->
block_count
)
+
((((
cur_block
*
pages_per_scan
*
256
)
/
(
SPIFFS_PAGES_PER_BLOCK
(
fs
)
*
fs
->
block_count
)))
/
fs
->
block_count
),
0
);
// traverse each page except for lookup pages
spiffs_page_ix
cur_pix
=
SPIFFS_OBJ_LOOKUP_PAGES
(
fs
)
+
SPIFFS_PAGES_PER_BLOCK
(
fs
)
*
cur_block
;
while
(
!
restart
&&
cur_pix
<
SPIFFS_PAGES_PER_BLOCK
(
fs
)
*
(
cur_block
+
1
))
{
//if ((cur_pix & 0xff) == 0)
// SPIFFS_CHECK_DBG("PA: processing pix %08x, block %08x of pix %08x, block %08x\n",
// cur_pix, cur_block, SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count, fs->block_count);
// read header
spiffs_page_header
p_hdr
;
res
=
_spiffs_rd
(
fs
,
SPIFFS_OP_T_OBJ_LU2
|
SPIFFS_OP_C_READ
,
...
...
@@ -598,11 +617,11 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
if
(
res
<=
_SPIFFS_ERR_CHECK_FIRST
&&
res
>
_SPIFFS_ERR_CHECK_LAST
)
{
// index bad also, cannot mend this file
SPIFFS_CHECK_DBG
(
"PA: FIXUP: index bad %i, cannot mend - delete object
\n
"
,
res
);
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_DELETE_BAD_FILE
,
objix_p_hdr
->
obj_id
,
0
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_DELETE_BAD_FILE
,
objix_p_hdr
->
obj_id
,
0
);
// delete file
res
=
spiffs_page_delete
(
fs
,
cur_pix
);
}
else
{
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_FIX_INDEX
,
objix_p_hdr
->
obj_id
,
objix_p_hdr
->
span_ix
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_FIX_INDEX
,
objix_p_hdr
->
obj_id
,
objix_p_hdr
->
span_ix
);
}
SPIFFS_CHECK_RES
(
res
);
restart
=
1
;
...
...
@@ -636,7 +655,7 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
if
(
data_pix
==
0
)
{
// not found, this index is badly borked
SPIFFS_CHECK_DBG
(
"PA: FIXUP: index bad, delete object id %04x
\n
"
,
p_hdr
.
obj_id
);
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_DELETE_BAD_FILE
,
p_hdr
.
obj_id
,
0
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_DELETE_BAD_FILE
,
p_hdr
.
obj_id
,
0
);
res
=
spiffs_delete_obj_lazy
(
fs
,
p_hdr
.
obj_id
);
SPIFFS_CHECK_RES
(
res
);
break
;
...
...
@@ -648,10 +667,10 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
if
(
res
<=
_SPIFFS_ERR_CHECK_FIRST
&&
res
>
_SPIFFS_ERR_CHECK_LAST
)
{
// index bad also, cannot mend this file
SPIFFS_CHECK_DBG
(
"PA: FIXUP: index bad %i, cannot mend!
\n
"
,
res
);
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_DELETE_BAD_FILE
,
p_hdr
.
obj_id
,
0
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_DELETE_BAD_FILE
,
p_hdr
.
obj_id
,
0
);
res
=
spiffs_delete_obj_lazy
(
fs
,
p_hdr
.
obj_id
);
}
else
{
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_FIX_INDEX
,
p_hdr
.
obj_id
,
p_hdr
.
span_ix
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_FIX_INDEX
,
p_hdr
.
obj_id
,
p_hdr
.
span_ix
);
}
SPIFFS_CHECK_RES
(
res
);
restart
=
1
;
...
...
@@ -669,7 +688,7 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
// the object which is referring to this page
SPIFFS_CHECK_DBG
(
"PA: FIXUP: removing object %04x and page %04x
\n
"
,
p_hdr
.
obj_id
,
cur_pix
);
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_DELETE_BAD_FILE
,
p_hdr
.
obj_id
,
0
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_DELETE_BAD_FILE
,
p_hdr
.
obj_id
,
0
);
res
=
spiffs_delete_obj_lazy
(
fs
,
p_hdr
.
obj_id
);
SPIFFS_CHECK_RES
(
res
);
// extra precaution, delete this page also
...
...
@@ -764,19 +783,19 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
if
(
res
<=
_SPIFFS_ERR_CHECK_FIRST
&&
res
>
_SPIFFS_ERR_CHECK_LAST
)
{
// index bad also, cannot mend this file
SPIFFS_CHECK_DBG
(
"PA: FIXUP: index bad %i, cannot mend!
\n
"
,
res
);
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_DELETE_BAD_FILE
,
p_hdr
.
obj_id
,
0
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_DELETE_BAD_FILE
,
p_hdr
.
obj_id
,
0
);
res
=
spiffs_page_delete
(
fs
,
cur_pix
);
SPIFFS_CHECK_RES
(
res
);
res
=
spiffs_delete_obj_lazy
(
fs
,
p_hdr
.
obj_id
);
}
else
{
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_FIX_INDEX
,
p_hdr
.
obj_id
,
p_hdr
.
span_ix
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_FIX_INDEX
,
p_hdr
.
obj_id
,
p_hdr
.
span_ix
);
}
SPIFFS_CHECK_RES
(
res
);
restart
=
1
;
continue
;
}
else
if
(
delete_page
)
{
SPIFFS_CHECK_DBG
(
"PA: FIXUP: deleting page %04x
\n
"
,
cur_pix
);
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_DELETE_PAGE
,
cur_pix
,
0
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_DELETE_PAGE
,
cur_pix
,
0
);
res
=
spiffs_page_delete
(
fs
,
cur_pix
);
}
SPIFFS_CHECK_RES
(
res
);
...
...
@@ -818,6 +837,8 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
}
}
}
SPIFFS_CHECK_DBG
(
"PA: processed %04x, restart %i
\n
"
,
pix_offset
,
restart
);
// next page range
if
(
!
restart
)
{
pix_offset
+=
pages_per_scan
;
...
...
@@ -828,12 +849,12 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
// Checks consistency amongst all pages and fixes irregularities
s32_t
spiffs_page_consistency_check
(
spiffs
*
fs
)
{
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_PROGRESS
,
0
,
0
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_PROGRESS
,
0
,
0
);
s32_t
res
=
spiffs_page_consistency_check_i
(
fs
);
if
(
res
!=
SPIFFS_OK
)
{
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_ERROR
,
res
,
0
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_ERROR
,
res
,
0
);
}
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_PROGRESS
,
256
,
0
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_PAGE
,
SPIFFS_CHECK_PROGRESS
,
256
,
0
);
return
res
;
}
...
...
@@ -855,14 +876,14 @@ static int spiffs_object_index_search(spiffs *fs, spiffs_obj_id obj_id) {
}
static
s32_t
spiffs_object_index_consistency_check_v
(
spiffs
*
fs
,
spiffs_obj_id
obj_id
,
spiffs_block_ix
cur_block
,
int
cur_entry
,
u32_t
user_data
,
void
*
user_p
)
{
(
void
)
user_
data
;
int
cur_entry
,
const
void
*
user_const_p
,
void
*
user_
var_
p
)
{
(
void
)
user_
const_p
;
s32_t
res_c
=
SPIFFS_VIS_COUNTINUE
;
s32_t
res
=
SPIFFS_OK
;
u32_t
*
log_ix
=
(
u32_t
*
)
user_p
;
u32_t
*
log_ix
=
(
u32_t
*
)
user_
var_
p
;
spiffs_obj_id
*
obj_table
=
(
spiffs_obj_id
*
)
fs
->
work
;
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_INDEX
,
SPIFFS_CHECK_PROGRESS
,
CHECK_CB
(
fs
,
SPIFFS_CHECK_INDEX
,
SPIFFS_CHECK_PROGRESS
,
(
cur_block
*
256
)
/
fs
->
block_count
,
0
);
if
(
obj_id
!=
SPIFFS_OBJ_ID_FREE
&&
obj_id
!=
SPIFFS_OBJ_ID_DELETED
&&
(
obj_id
&
SPIFFS_OBJ_ID_IX_FLAG
))
{
...
...
@@ -879,7 +900,7 @@ static s32_t spiffs_object_index_consistency_check_v(spiffs *fs, spiffs_obj_id o
(
SPIFFS_PH_FLAG_DELET
))
{
SPIFFS_CHECK_DBG
(
"IX: pix %04x, obj id:%04x spix:%04x header not fully deleted - deleting
\n
"
,
cur_pix
,
obj_id
,
p_hdr
.
span_ix
);
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_INDEX
,
SPIFFS_CHECK_DELETE_PAGE
,
cur_pix
,
obj_id
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_INDEX
,
SPIFFS_CHECK_DELETE_PAGE
,
cur_pix
,
obj_id
);
res
=
spiffs_page_delete
(
fs
,
cur_pix
);
SPIFFS_CHECK_RES
(
res
);
return
res_c
;
...
...
@@ -935,7 +956,7 @@ static s32_t spiffs_object_index_consistency_check_v(spiffs *fs, spiffs_obj_id o
if
(
delete
)
{
SPIFFS_CHECK_DBG
(
"IX: FIXUP: pix %04x, obj id:%04x spix:%04x is orphan index - deleting
\n
"
,
cur_pix
,
obj_id
,
p_hdr
.
span_ix
);
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_INDEX
,
SPIFFS_CHECK_DELETE_ORPHANED_INDEX
,
cur_pix
,
obj_id
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_INDEX
,
SPIFFS_CHECK_DELETE_ORPHANED_INDEX
,
cur_pix
,
obj_id
);
res
=
spiffs_page_delete
(
fs
,
cur_pix
);
SPIFFS_CHECK_RES
(
res
);
}
...
...
@@ -956,18 +977,19 @@ s32_t spiffs_object_index_consistency_check(spiffs *fs) {
// indicating whether they can be reached or not. Acting as a fifo if object ids cannot fit.
// In the temporary object index memory, SPIFFS_OBJ_ID_IX_FLAG bit is used to indicate
// a reachable/unreachable object id.
c_
memset
(
fs
->
work
,
0
,
SPIFFS_CFG_LOG_PAGE_SZ
(
fs
));
memset
(
fs
->
work
,
0
,
SPIFFS_CFG_LOG_PAGE_SZ
(
fs
));
u32_t
obj_id_log_ix
=
0
;
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_INDEX
,
SPIFFS_CHECK_PROGRESS
,
0
,
0
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_INDEX
,
SPIFFS_CHECK_PROGRESS
,
0
,
0
);
res
=
spiffs_obj_lu_find_entry_visitor
(
fs
,
0
,
0
,
0
,
0
,
spiffs_object_index_consistency_check_v
,
0
,
&
obj_id_log_ix
,
0
,
0
);
0
,
0
);
if
(
res
==
SPIFFS_VIS_END
)
{
res
=
SPIFFS_OK
;
}
if
(
res
!=
SPIFFS_OK
)
{
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_INDEX
,
SPIFFS_CHECK_ERROR
,
res
,
0
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_INDEX
,
SPIFFS_CHECK_ERROR
,
res
,
0
);
}
if
(
fs
->
check_cb_f
)
fs
->
check_cb_f
(
SPIFFS_CHECK_INDEX
,
SPIFFS_CHECK_PROGRESS
,
256
,
0
);
CHECK_CB
(
fs
,
SPIFFS_CHECK_INDEX
,
SPIFFS_CHECK_PROGRESS
,
256
,
0
);
return
res
;
}
#endif // !SPIFFS_READ_ONLY
app/spiffs/spiffs_config.h
View file @
be047ff7
...
...
@@ -8,30 +8,28 @@
#ifndef SPIFFS_CONFIG_H_
#define SPIFFS_CONFIG_H_
#include "user_config.h"
#include "c_stdio.h"
#include "c_stdint.h"
#include "c_string.h"
// For u32_t etc
#include "user_interface.h"
// ----------- 8< ------------
// Following includes are for the linux test build of spiffs
// These may/should/must be removed/altered/replaced in your target
#include "nodemcu_spiffs.h"
// ----------- >8 ------------
// compile time switches
// Set generic spiffs debug output call.
#ifndef SPIFFS_D
G
B
#ifndef SPIFFS_DB
G
#define SPIFFS_DBG(...) //printf(__VA_ARGS__)
#endif
// Set spiffs debug output call for garbage collecting.
#ifndef SPIFFS_GC_D
G
B
#ifndef SPIFFS_GC_DB
G
#define SPIFFS_GC_DBG(...) //printf(__VA_ARGS__)
#endif
// Set spiffs debug output call for caching.
#ifndef SPIFFS_CACHE_D
G
B
#ifndef SPIFFS_CACHE_DB
G
#define SPIFFS_CACHE_DBG(...) //printf(__VA_ARGS__)
#endif
// Set spiffs debug output call for system consistency checks.
#ifndef SPIFFS_CHECK_D
G
B
#ifndef SPIFFS_CHECK_DB
G
#define SPIFFS_CHECK_DBG(...) //printf(__VA_ARGS__)
#endif
...
...
@@ -55,10 +53,8 @@
// Enable/disable statistics on caching. Debug/test purpose only.
#ifndef SPIFFS_CACHE_STATS
#define SPIFFS_CACHE_STATS
0
#define SPIFFS_CACHE_STATS
1
#endif
#else
#define SPIFFS_CACHE_WR 0
#endif
// Always check header of each accessed page to ensure consistent state.
...
...
@@ -74,7 +70,7 @@
// Enable/disable statistics on gc. Debug/test purpose only.
#ifndef SPIFFS_GC_STATS
#define SPIFFS_GC_STATS
0
#define SPIFFS_GC_STATS
1
#endif
// Garbage collecting examines all pages in a block which and sums up
...
...
@@ -99,7 +95,9 @@
#define SPIFFS_GC_HEUR_W_ERASE_AGE (50)
#endif
// Object name maximum length.
// Object name maximum length. Note that this length include the
// zero-termination character, meaning maximum string of characters
// can at most be SPIFFS_OBJ_NAME_LEN - 1.
#ifndef SPIFFS_OBJ_NAME_LEN
#define SPIFFS_OBJ_NAME_LEN (32)
#endif
...
...
@@ -119,19 +117,29 @@
#define SPIFFS_USE_MAGIC (0)
#endif
#if SPIFFS_USE_MAGIC
// Only valid when SPIFFS_USE_MAGIC is enabled. If SPIFFS_USE_MAGIC_LENGTH is
// enabled, the magic will also be dependent on the length of the filesystem.
// For example, a filesystem configured and formatted for 4 megabytes will not
// be accepted for mounting with a configuration defining the filesystem as 2
// megabytes.
#ifndef SPIFFS_USE_MAGIC_LENGTH
#define SPIFFS_USE_MAGIC_LENGTH (0)
#endif
#endif
// SPIFFS_LOCK and SPIFFS_UNLOCK protects spiffs from reentrancy on api level
// These should be defined on a multithreaded system
// define this to enter
ing
a mutex if you're running on a multithreaded system
// define this to enter a mutex if you're running on a multithreaded system
#ifndef SPIFFS_LOCK
#define SPIFFS_LOCK(fs)
#endif
// define this to exit
ing
a mutex if you're running on a multithreaded system
// define this to exit a mutex if you're running on a multithreaded system
#ifndef SPIFFS_UNLOCK
#define SPIFFS_UNLOCK(fs)
#endif
// Enable if only one spiffs instance with constant configuration will exist
// on the target. This will reduce calculations, flash and memory accesses.
// Parts of configuration must be defined below instead of at time of mount.
...
...
@@ -159,7 +167,41 @@
#endif
#endif
// Set SPFIFS_TEST_VISUALISATION to non-zero to enable SPIFFS_vis function
// Enable this if your target needs aligned data for index tables
#ifndef SPIFFS_ALIGNED_OBJECT_INDEX_TABLES
#define SPIFFS_ALIGNED_OBJECT_INDEX_TABLES 0
#endif
// Enable this if you want the HAL callbacks to be called with the spiffs struct
#ifndef SPIFFS_HAL_CALLBACK_EXTRA
#define SPIFFS_HAL_CALLBACK_EXTRA 0
#endif
// Enable this if you want to add an integer offset to all file handles
// (spiffs_file). This is useful if running multiple instances of spiffs on
// same target, in order to recognise to what spiffs instance a file handle
// belongs.
// NB: This adds config field fh_ix_offset in the configuration struct when
// mounting, which must be defined.
#ifndef SPIFFS_FILEHDL_OFFSET
#define SPIFFS_FILEHDL_OFFSET 0
#endif
// Enable this to compile a read only version of spiffs.
// This will reduce binary size of spiffs. All code comprising modification
// of the file system will not be compiled. Some config will be ignored.
// HAL functions for erasing and writing to spi-flash may be null. Cache
// can be disabled for even further binary size reduction (and ram savings).
// Functions modifying the fs will return SPIFFS_ERR_RO_NOT_IMPL.
// If the file system cannot be mounted due to aborted erase operation and
// SPIFFS_USE_MAGIC is enabled, SPIFFS_ERR_RO_ABORTED_OPERATION will be
// returned.
// Might be useful for e.g. bootloaders and such.
#ifndef SPIFFS_READ_ONLY
#define SPIFFS_READ_ONLY 0
#endif
// Set SPIFFS_TEST_VISUALISATION to non-zero to enable SPIFFS_vis function
// in the api. This function will visualize all filesystem using given printf
// function.
#ifndef SPIFFS_TEST_VISUALISATION
...
...
@@ -167,7 +209,7 @@
#endif
#if SPIFFS_TEST_VISUALISATION
#ifndef spiffs_printf
#define spiffs_printf(...)
c_
printf(__VA_ARGS__)
#define spiffs_printf(...) printf(__VA_ARGS__)
#endif
// spiffs_printf argument for a free page
#ifndef SPIFFS_TEST_VIS_FREE_STR
...
...
app/spiffs/spiffs_gc.c
View file @
be047ff7
#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.
...
...
@@ -36,7 +38,7 @@ s32_t spiffs_gc_quick(
int
cur_entry
=
0
;
spiffs_obj_id
*
obj_lu_buf
=
(
spiffs_obj_id
*
)
fs
->
lu_work
;
SPIFFS_GC_DBG
(
"gc_quick: running
\n
"
,
cur_block
);
SPIFFS_GC_DBG
(
"gc_quick: running
\n
"
);
#if SPIFFS_GC_STATS
fs
->
stats_gc_runs
++
;
#endif
...
...
@@ -246,17 +248,15 @@ s32_t spiffs_gc_find_candidate(
// using fs->work area as sorted candidate memory, (spiffs_block_ix)cand_bix/(s32_t)score
int
max_candidates
=
MIN
(
fs
->
block_count
,
(
SPIFFS_CFG_LOG_PAGE_SZ
(
fs
)
-
8
)
/
(
sizeof
(
spiffs_block_ix
)
+
sizeof
(
s32_t
)));
*
candidate_count
=
0
;
c_
memset
(
fs
->
work
,
0xff
,
SPIFFS_CFG_LOG_PAGE_SZ
(
fs
));
memset
(
fs
->
work
,
0xff
,
SPIFFS_CFG_LOG_PAGE_SZ
(
fs
));
// divide up work area into block indices and scores
// todo alignment?
// YES DO PROPER ALIGNMENT !^@#%!@%!
if
(
max_candidates
&
1
)
++
max_candidates
;
// HACK WORKAROUND ICK for sizeof(spiffs_block_idx)==2
spiffs_block_ix
*
cand_blocks
=
(
spiffs_block_ix
*
)
fs
->
work
;
s32_t
*
cand_scores
=
(
s32_t
*
)(
fs
->
work
+
max_candidates
*
sizeof
(
spiffs_block_ix
));
// align cand_scores on s32_t boundary
cand_scores
=
(
s32_t
*
)(((
ptrdiff_t
)
cand_scores
+
sizeof
(
ptrdiff_t
)
-
1
)
&
~
(
sizeof
(
ptrdiff_t
)
-
1
));
*
block_candidates
=
cand_blocks
;
int
entries_per_page
=
(
SPIFFS_CFG_LOG_PAGE_SZ
(
fs
)
/
sizeof
(
spiffs_obj_id
));
...
...
@@ -385,7 +385,7 @@ s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {
SPIFFS_GC_DBG
(
"gc_clean: cleaning block %i
\n
"
,
bix
);
c_
memset
(
&
gc
,
0
,
sizeof
(
spiffs_gc
));
memset
(
&
gc
,
0
,
sizeof
(
spiffs_gc
));
gc
.
state
=
FIND_OBJ_DATA
;
if
(
fs
->
free_cursor_block_ix
==
bix
)
{
...
...
@@ -570,3 +570,4 @@ s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {
return
res
;
}
#endif // !SPIFFS_READ_ONLY
app/spiffs/spiffs_hydrogen.c
View file @
be047ff7
...
...
@@ -8,7 +8,17 @@
#include "spiffs.h"
#include "spiffs_nucleus.h"
#if SPIFFS_FILEHDL_OFFSET
#define SPIFFS_FH_OFFS(fs, fh) ((fh) != 0 ? ((fh) + (fs)->cfg.fh_ix_offset) : 0)
#define SPIFFS_FH_UNOFFS(fs, fh) ((fh) != 0 ? ((fh) - (fs)->cfg.fh_ix_offset) : 0)
#else
#define SPIFFS_FH_OFFS(fs, fh) (fh)
#define SPIFFS_FH_UNOFFS(fs, fh) (fh)
#endif
#if SPIFFS_CACHE == 1
static
s32_t
spiffs_fflush_cache
(
spiffs
*
fs
,
spiffs_file
fh
);
#endif
#if SPIFFS_BUFFER_HELP
u32_t
SPIFFS_buffer_bytes_for_filedescs
(
spiffs
*
fs
,
u32_t
num_descs
)
{
...
...
@@ -26,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
;
...
...
@@ -49,25 +63,35 @@ 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
,
spiffs_check_callback
check_cb_f
)
{
void
*
user_data
;
SPIFFS_LOCK
(
fs
);
c_memset
(
fs
,
0
,
sizeof
(
spiffs
));
c_memcpy
(
&
fs
->
cfg
,
config
,
sizeof
(
spiffs_config
));
user_data
=
fs
->
user_data
;
memset
(
fs
,
0
,
sizeof
(
spiffs
));
memcpy
(
&
fs
->
cfg
,
config
,
sizeof
(
spiffs_config
));
fs
->
user_data
=
user_data
;
fs
->
block_count
=
SPIFFS_CFG_PHYS_SZ
(
fs
)
/
SPIFFS_CFG_LOG_BLOCK_SZ
(
fs
);
fs
->
work
=
&
work
[
0
];
fs
->
lu_work
=
&
work
[
SPIFFS_CFG_LOG_PAGE_SZ
(
fs
)];
c_
memset
(
fd_space
,
0
,
fd_space_size
);
// align fd_space pointer to pointer size byte boundary
, below is safe
memset
(
fd_space
,
0
,
fd_space_size
);
// align fd_space pointer to pointer size byte boundary
u8_t
ptr_size
=
sizeof
(
void
*
);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
u8_t
addr_lsb
=
((
u8_t
)
fd_space
)
&
(
ptr_size
-
1
);
#pragma GCC diagnostic pop
u8_t
addr_lsb
=
((
u8_t
)(
intptr_t
)
fd_space
)
&
(
ptr_size
-
1
);
if
(
addr_lsb
)
{
fd_space
+=
(
ptr_size
-
addr_lsb
);
fd_space_size
-=
(
ptr_size
-
addr_lsb
);
...
...
@@ -75,11 +99,8 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
fs
->
fd_space
=
fd_space
;
fs
->
fd_count
=
(
fd_space_size
/
sizeof
(
spiffs_fd
));
// align cache pointer to 4 byte boundary, below is safe
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
addr_lsb
=
((
u8_t
)
cache
)
&
(
ptr_size
-
1
);
#pragma GCC diagnostic pop
// align cache pointer to 4 byte boundary
addr_lsb
=
((
u8_t
)(
intptr_t
)
cache
)
&
(
ptr_size
-
1
);
if
(
addr_lsb
)
{
u8_t
*
cache_8
=
(
u8_t
*
)
cache
;
cache_8
+=
(
ptr_size
-
addr_lsb
);
...
...
@@ -89,9 +110,10 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
if
(
cache_size
&
(
ptr_size
-
1
))
{
cache_size
-=
(
cache_size
&
(
ptr_size
-
1
));
}
#if SPIFFS_CACHE
fs
->
cache
=
cache
;
fs
->
cache_size
=
(
cache_size
>
(
config
->
log_page_size
*
32
))
?
config
->
log_page_size
*
32
:
cache_size
;
fs
->
cache_size
=
(
cache_size
>
(
SPIFFS_CFG_LOG_PAGE_SZ
(
fs
)
*
32
))
?
SPIFFS_CFG_LOG_PAGE_SZ
(
fs
)
*
32
:
cache_size
;
spiffs_cache_init
(
fs
);
#endif
...
...
@@ -152,43 +174,68 @@ void SPIFFS_clearerr(spiffs *fs) {
fs
->
err_code
=
SPIFFS_OK
;
}
s32_t
SPIFFS_creat
(
spiffs
*
fs
,
char
*
path
,
spiffs_mode
mode
)
{
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
);
if
(
strlen
(
path
)
>
SPIFFS_OBJ_NAME_LEN
-
1
)
{
SPIFFS_API_CHECK_RES
(
fs
,
SPIFFS_ERR_NAME_TOO_LONG
);
}
SPIFFS_LOCK
(
fs
);
spiffs_obj_id
obj_id
;
s32_t
res
;
res
=
spiffs_obj_lu_find_free_obj_id
(
fs
,
&
obj_id
,
(
u8_t
*
)
path
);
res
=
spiffs_obj_lu_find_free_obj_id
(
fs
,
&
obj_id
,
(
const
u8_t
*
)
path
);
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
res
=
spiffs_object_create
(
fs
,
obj_id
,
(
u8_t
*
)
path
,
SPIFFS_TYPE_FILE
,
0
);
res
=
spiffs_object_create
(
fs
,
obj_id
,
(
const
u8_t
*
)
path
,
SPIFFS_TYPE_FILE
,
0
);
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
SPIFFS_UNLOCK
(
fs
);
return
0
;
#endif // SPIFFS_READ_ONLY
}
spiffs_file
SPIFFS_open
(
spiffs
*
fs
,
char
*
path
,
spiffs_flags
flags
,
spiffs_mode
mode
)
{
spiffs_file
SPIFFS_open
(
spiffs
*
fs
,
const
char
*
path
,
spiffs_flags
flags
,
spiffs_mode
mode
)
{
(
void
)
mode
;
SPIFFS_API_CHECK_CFG
(
fs
);
SPIFFS_API_CHECK_MOUNT
(
fs
);
if
(
strlen
(
path
)
>
SPIFFS_OBJ_NAME_LEN
-
1
)
{
SPIFFS_API_CHECK_RES
(
fs
,
SPIFFS_ERR_NAME_TOO_LONG
);
}
SPIFFS_LOCK
(
fs
);
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
);
res
=
spiffs_object_find_object_index_header_by_name
(
fs
,
(
u8_t
*
)
path
,
&
pix
);
if
((
flags
&
SPIFFS_CREAT
)
==
0
)
{
res
=
spiffs_object_find_object_index_header_by_name
(
fs
,
(
const
u8_t
*
)
path
,
&
pix
);
if
((
flags
&
SPIFFS_
O_
CREAT
)
==
0
)
{
if
(
res
<
SPIFFS_OK
)
{
spiffs_fd_return
(
fs
,
fd
->
file_nbr
);
}
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
}
if
((
flags
&
SPIFFS_CREAT
)
&&
res
==
SPIFFS_ERR_NOT_FOUND
)
{
if
(
res
==
SPIFFS_OK
&&
(
flags
&
(
SPIFFS_O_CREAT
|
SPIFFS_O_EXCL
))
==
(
SPIFFS_O_CREAT
|
SPIFFS_O_EXCL
))
{
// creat and excl and file exists - fail
res
=
SPIFFS_ERR_FILE_EXISTS
;
spiffs_fd_return
(
fs
,
fd
->
file_nbr
);
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
}
if
((
flags
&
SPIFFS_O_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
);
...
...
@@ -196,12 +243,13 @@ spiffs_file SPIFFS_open(spiffs *fs, char *path, spiffs_flags flags, spiffs_mode
spiffs_fd_return
(
fs
,
fd
->
file_nbr
);
}
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
res
=
spiffs_object_create
(
fs
,
obj_id
,
(
u8_t
*
)
path
,
SPIFFS_TYPE_FILE
,
&
pix
);
res
=
spiffs_object_create
(
fs
,
obj_id
,
(
const
u8_t
*
)
path
,
SPIFFS_TYPE_FILE
,
&
pix
);
if
(
res
<
SPIFFS_OK
)
{
spiffs_fd_return
(
fs
,
fd
->
file_nbr
);
}
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
flags
&=
~
SPIFFS_TRUNC
;
flags
&=
~
SPIFFS_O_TRUNC
;
#endif // !SPIFFS_READ_ONLY
}
else
{
if
(
res
<
SPIFFS_OK
)
{
spiffs_fd_return
(
fs
,
fd
->
file_nbr
);
...
...
@@ -213,19 +261,21 @@ spiffs_file SPIFFS_open(spiffs *fs, char *path, spiffs_flags flags, spiffs_mode
spiffs_fd_return
(
fs
,
fd
->
file_nbr
);
}
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
if
(
flags
&
SPIFFS_TRUNC
)
{
#if !SPIFFS_READ_ONLY
if
(
flags
&
SPIFFS_O_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
;
SPIFFS_UNLOCK
(
fs
);
return
fd
->
file_nbr
;
return
SPIFFS_FH_OFFS
(
fs
,
fd
->
file_nbr
)
;
}
spiffs_file
SPIFFS_open_by_dirent
(
spiffs
*
fs
,
struct
spiffs_dirent
*
e
,
spiffs_flags
flags
,
spiffs_mode
mode
)
{
...
...
@@ -243,19 +293,67 @@ 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
(
flags
&
SPIFFS_TRUNC
)
{
#if !SPIFFS_READ_ONLY
if
(
flags
&
SPIFFS_O_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
;
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_O_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
;
SPIFFS_UNLOCK
(
fs
);
return
fd
->
file_nbr
;
return
SPIFFS_FH_OFFS
(
fs
,
fd
->
file_nbr
)
;
}
s32_t
SPIFFS_read
(
spiffs
*
fs
,
spiffs_file
fh
,
void
*
buf
,
s32_t
len
)
{
...
...
@@ -266,14 +364,21 @@ s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
spiffs_fd
*
fd
;
s32_t
res
;
fh
=
SPIFFS_FH_UNOFFS
(
fs
,
fh
);
res
=
spiffs_fd_get
(
fs
,
fh
,
&
fd
);
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
if
((
fd
->
flags
&
SPIFFS_RDONLY
)
==
0
)
{
if
((
fd
->
flags
&
SPIFFS_
O_
RDONLY
)
==
0
)
{
res
=
SPIFFS_ERR_NOT_READABLE
;
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
}
if
(
fd
->
size
==
SPIFFS_UNDEFINED_LEN
&&
len
>
0
)
{
// special case for zero sized files
res
=
SPIFFS_ERR_END_OF_OBJECT
;
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
}
#if SPIFFS_CACHE_WR
spiffs_fflush_cache
(
fs
,
fh
);
#endif
...
...
@@ -305,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
;
...
...
@@ -326,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
);
...
...
@@ -336,14 +447,19 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
s32_t
res
;
u32_t
offset
;
fh
=
SPIFFS_FH_UNOFFS
(
fs
,
fh
);
res
=
spiffs_fd_get
(
fs
,
fh
,
&
fd
);
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
if
((
fd
->
flags
&
SPIFFS_WRONLY
)
==
0
)
{
if
((
fd
->
flags
&
SPIFFS_
O_
WRONLY
)
==
0
)
{
res
=
SPIFFS_ERR_NOT_WRITABLE
;
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
}
if
((
fd
->
flags
&
SPIFFS_O_APPEND
))
{
fd
->
fdoffset
=
fd
->
size
==
SPIFFS_UNDEFINED_LEN
?
0
:
fd
->
size
;
}
offset
=
fd
->
fdoffset
;
#if SPIFFS_CACHE_WR
...
...
@@ -352,7 +468,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
fd
->
cache_page
=
spiffs_cache_page_get_by_fd
(
fs
,
fd
);
}
#endif
if
(
fd
->
flags
&
SPIFFS_APPEND
)
{
if
(
fd
->
flags
&
SPIFFS_
O_
APPEND
)
{
if
(
fd
->
size
==
SPIFFS_UNDEFINED_LEN
)
{
offset
=
0
;
}
else
{
...
...
@@ -366,7 +482,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
}
#if SPIFFS_CACHE_WR
if
((
fd
->
flags
&
SPIFFS_DIRECT
)
==
0
)
{
if
((
fd
->
flags
&
SPIFFS_
O_
DIRECT
)
==
0
)
{
if
(
len
<
(
s32_t
)
SPIFFS_CFG_LOG_PAGE_SZ
(
fs
))
{
// small write, try to cache it
u8_t
alloc_cpage
=
1
;
...
...
@@ -383,7 +499,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
spiffs_get_cache_page
(
fs
,
spiffs_get_cache
(
fs
),
fd
->
cache_page
->
ix
),
fd
->
cache_page
->
offset
,
fd
->
cache_page
->
size
);
spiffs_cache_fd_release
(
fs
,
fd
->
cache_page
);
SPIFFS_API_CHECK_RES
(
fs
,
res
);
SPIFFS_API_CHECK_RES
_UNLOCK
(
fs
,
res
);
}
else
{
// writing within cache
alloc_cpage
=
0
;
...
...
@@ -407,14 +523,14 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
offset
,
offset_in_cpage
,
len
);
spiffs_cache
*
cache
=
spiffs_get_cache
(
fs
);
u8_t
*
cpage_data
=
spiffs_get_cache_page
(
fs
,
cache
,
fd
->
cache_page
->
ix
);
c_
memcpy
(
&
cpage_data
[
offset_in_cpage
],
buf
,
len
);
memcpy
(
&
cpage_data
[
offset_in_cpage
],
buf
,
len
);
fd
->
cache_page
->
size
=
MAX
(
fd
->
cache_page
->
size
,
offset_in_cpage
+
len
);
fd
->
fdoffset
+=
len
;
SPIFFS_UNLOCK
(
fs
);
return
len
;
}
else
{
res
=
spiffs_hydro_write
(
fs
,
fd
,
buf
,
offset
,
len
);
SPIFFS_API_CHECK_RES
(
fs
,
res
);
SPIFFS_API_CHECK_RES
_UNLOCK
(
fs
,
res
);
fd
->
fdoffset
+=
len
;
SPIFFS_UNLOCK
(
fs
);
return
res
;
...
...
@@ -429,21 +545,22 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
spiffs_get_cache_page
(
fs
,
spiffs_get_cache
(
fs
),
fd
->
cache_page
->
ix
),
fd
->
cache_page
->
offset
,
fd
->
cache_page
->
size
);
spiffs_cache_fd_release
(
fs
,
fd
->
cache_page
);
SPIFFS_API_CHECK_RES
(
fs
,
res
);
SPIFFS_API_CHECK_RES
_UNLOCK
(
fs
,
res
);
res
=
spiffs_hydro_write
(
fs
,
fd
,
buf
,
offset
,
len
);
SPIFFS_API_CHECK_RES
(
fs
,
res
);
SPIFFS_API_CHECK_RES
_UNLOCK
(
fs
,
res
);
}
}
}
#endif
res
=
spiffs_hydro_write
(
fs
,
fd
,
buf
,
offset
,
len
);
SPIFFS_API_CHECK_RES
(
fs
,
res
);
SPIFFS_API_CHECK_RES
_UNLOCK
(
fs
,
res
);
fd
->
fdoffset
+=
len
;
SPIFFS_UNLOCK
(
fs
);
return
res
;
#endif // SPIFFS_READ_ONLY
}
s32_t
SPIFFS_lseek
(
spiffs
*
fs
,
spiffs_file
fh
,
s32_t
offs
,
int
whence
)
{
...
...
@@ -453,8 +570,9 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
spiffs_fd
*
fd
;
s32_t
res
;
fh
=
SPIFFS_FH_UNOFFS
(
fs
,
fh
);
res
=
spiffs_fd_get
(
fs
,
fh
,
&
fd
);
SPIFFS_API_CHECK_RES
(
fs
,
res
);
SPIFFS_API_CHECK_RES
_UNLOCK
(
fs
,
res
);
#if SPIFFS_CACHE_WR
spiffs_fflush_cache
(
fs
,
fh
);
...
...
@@ -469,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
);
...
...
@@ -491,9 +609,16 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
return
offs
;
}
s32_t
SPIFFS_remove
(
spiffs
*
fs
,
char
*
path
)
{
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
);
if
(
strlen
(
path
)
>
SPIFFS_OBJ_NAME_LEN
-
1
)
{
SPIFFS_API_CHECK_RES
(
fs
,
SPIFFS_ERR_NAME_TOO_LONG
);
}
SPIFFS_LOCK
(
fs
);
spiffs_fd
*
fd
;
...
...
@@ -503,7 +628,7 @@ s32_t SPIFFS_remove(spiffs *fs, char *path) {
res
=
spiffs_fd_find_new
(
fs
,
&
fd
);
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
res
=
spiffs_object_find_object_index_header_by_name
(
fs
,
(
u8_t
*
)
path
,
&
pix
);
res
=
spiffs_object_find_object_index_header_by_name
(
fs
,
(
const
u8_t
*
)
path
,
&
pix
);
if
(
res
!=
SPIFFS_OK
)
{
spiffs_fd_return
(
fs
,
fd
->
file_nbr
);
}
...
...
@@ -523,19 +648,25 @@ s32_t SPIFFS_remove(spiffs *fs, 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
);
spiffs_fd
*
fd
;
s32_t
res
;
fh
=
SPIFFS_FH_UNOFFS
(
fs
,
fh
);
res
=
spiffs_fd_get
(
fs
,
fh
,
&
fd
);
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
if
((
fd
->
flags
&
SPIFFS_WRONLY
)
==
0
)
{
if
((
fd
->
flags
&
SPIFFS_
O_
WRONLY
)
==
0
)
{
res
=
SPIFFS_ERR_NOT_WRITABLE
;
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
}
...
...
@@ -551,9 +682,11 @@ 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
)
{
(
void
)
fh
;
spiffs_page_object_ix_header
objix_hdr
;
spiffs_obj_id
obj_id
;
s32_t
res
=
_spiffs_rd
(
fs
,
SPIFFS_OP_T_OBJ_IX
|
SPIFFS_OP_C_READ
,
fh
,
...
...
@@ -566,23 +699,27 @@ 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
;
}
s32_t
SPIFFS_stat
(
spiffs
*
fs
,
char
*
path
,
spiffs_stat
*
s
)
{
s32_t
SPIFFS_stat
(
spiffs
*
fs
,
const
char
*
path
,
spiffs_stat
*
s
)
{
SPIFFS_API_CHECK_CFG
(
fs
);
SPIFFS_API_CHECK_MOUNT
(
fs
);
if
(
strlen
(
path
)
>
SPIFFS_OBJ_NAME_LEN
-
1
)
{
SPIFFS_API_CHECK_RES
(
fs
,
SPIFFS_ERR_NAME_TOO_LONG
);
}
SPIFFS_LOCK
(
fs
);
s32_t
res
;
spiffs_page_ix
pix
;
res
=
spiffs_object_find_object_index_header_by_name
(
fs
,
(
u8_t
*
)
path
,
&
pix
);
res
=
spiffs_object_find_object_index_header_by_name
(
fs
,
(
const
u8_t
*
)
path
,
&
pix
);
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
res
=
spiffs_stat_pix
(
fs
,
pix
,
0
,
s
);
...
...
@@ -600,6 +737,7 @@ s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s) {
spiffs_fd
*
fd
;
s32_t
res
;
fh
=
SPIFFS_FH_UNOFFS
(
fs
,
fh
);
res
=
spiffs_fd_get
(
fs
,
fh
,
&
fd
);
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
...
...
@@ -616,15 +754,18 @@ s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s) {
// Checks if there are any cached writes for the object id associated with
// given filehandle. If so, these writes are flushed.
#if SPIFFS_CACHE == 1
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
);
SPIFFS_API_CHECK_RES
(
fs
,
res
);
if
((
fd
->
flags
&
SPIFFS_DIRECT
)
==
0
)
{
if
((
fd
->
flags
&
SPIFFS_
O_
DIRECT
)
==
0
)
{
if
(
fd
->
cache_page
==
0
)
{
// see if object id is associated with cache already
fd
->
cache_page
=
spiffs_cache_page_get_by_fd
(
fs
,
fd
);
...
...
@@ -645,13 +786,16 @@ static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh) {
return
res
;
}
#endif
s32_t
SPIFFS_fflush
(
spiffs
*
fs
,
spiffs_file
fh
)
{
(
void
)
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
);
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
SPIFFS_UNLOCK
(
fs
);
...
...
@@ -660,38 +804,46 @@ s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) {
return
res
;
}
void
SPIFFS_close
(
spiffs
*
fs
,
spiffs_file
fh
)
{
if
(
!
SPIFFS_CHECK_CFG
((
fs
)))
{
(
fs
)
->
err_code
=
SPIFFS_ERR_NOT_CONFIGURED
;
return
;
}
s32_t
SPIFFS_close
(
spiffs
*
fs
,
spiffs_file
fh
)
{
SPIFFS_API_CHECK_CFG
(
fs
);
SPIFFS_API_CHECK_MOUNT
(
fs
);
if
(
!
SPIFFS_CHECK_MOUNT
(
fs
))
{
fs
->
err_code
=
SPIFFS_ERR_NOT_MOUNTED
;
return
;
}
s32_t
res
=
SPIFFS_OK
;
SPIFFS_LOCK
(
fs
);
fh
=
SPIFFS_FH_UNOFFS
(
fs
,
fh
);
#if SPIFFS_CACHE
spiffs_fflush_cache
(
fs
,
fh
);
res
=
spiffs_fflush_cache
(
fs
,
fh
);
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
#endif
spiffs_fd_return
(
fs
,
fh
);
res
=
spiffs_fd_return
(
fs
,
fh
);
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
SPIFFS_UNLOCK
(
fs
);
return
res
;
}
s32_t
SPIFFS_rename
(
spiffs
*
fs
,
char
*
old
,
char
*
new
)
{
s32_t
SPIFFS_rename
(
spiffs
*
fs
,
const
char
*
old_path
,
const
char
*
new_path
)
{
#if SPIFFS_READ_ONLY
(
void
)
fs
;
(
void
)
old_path
;
(
void
)
new_path
;
return
SPIFFS_ERR_RO_NOT_IMPL
;
#else
SPIFFS_API_CHECK_CFG
(
fs
);
SPIFFS_API_CHECK_MOUNT
(
fs
);
if
(
strlen
(
new_path
)
>
SPIFFS_OBJ_NAME_LEN
-
1
||
strlen
(
old_path
)
>
SPIFFS_OBJ_NAME_LEN
-
1
)
{
SPIFFS_API_CHECK_RES
(
fs
,
SPIFFS_ERR_NAME_TOO_LONG
);
}
SPIFFS_LOCK
(
fs
);
spiffs_page_ix
pix_old
,
pix_dummy
;
spiffs_fd
*
fd
;
s32_t
res
=
spiffs_object_find_object_index_header_by_name
(
fs
,
(
u8_t
*
)
old
,
&
pix_old
);
s32_t
res
=
spiffs_object_find_object_index_header_by_name
(
fs
,
(
const
u8_t
*
)
old
_path
,
&
pix_old
);
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
res
=
spiffs_object_find_object_index_header_by_name
(
fs
,
(
u8_t
*
)
new
,
&
pix_dummy
);
res
=
spiffs_object_find_object_index_header_by_name
(
fs
,
(
const
u8_t
*
)
new
_path
,
&
pix_dummy
);
if
(
res
==
SPIFFS_ERR_NOT_FOUND
)
{
res
=
SPIFFS_OK
;
}
else
if
(
res
==
SPIFFS_OK
)
{
...
...
@@ -708,7 +860,7 @@ s32_t SPIFFS_rename(spiffs *fs, char *old, char *new) {
}
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
res
=
spiffs_object_update_index_hdr
(
fs
,
fd
,
fd
->
obj_id
,
fd
->
objix_hdr_pix
,
0
,
(
u8_t
*
)
new
,
res
=
spiffs_object_update_index_hdr
(
fs
,
fd
,
fd
->
obj_id
,
fd
->
objix_hdr_pix
,
0
,
(
const
u8_t
*
)
new
_path
,
0
,
&
pix_dummy
);
spiffs_fd_return
(
fs
,
fd
->
file_nbr
);
...
...
@@ -718,9 +870,10 @@ s32_t SPIFFS_rename(spiffs *fs, char *old, char *new) {
SPIFFS_UNLOCK
(
fs
);
return
res
;
#endif // SPIFFS_READ_ONLY
}
spiffs_DIR
*
SPIFFS_opendir
(
spiffs
*
fs
,
char
*
name
,
spiffs_DIR
*
d
)
{
spiffs_DIR
*
SPIFFS_opendir
(
spiffs
*
fs
,
const
char
*
name
,
spiffs_DIR
*
d
)
{
(
void
)
name
;
if
(
!
SPIFFS_CHECK_CFG
((
fs
)))
{
...
...
@@ -744,9 +897,9 @@ static s32_t spiffs_read_dir_v(
spiffs_obj_id
obj_id
,
spiffs_block_ix
bix
,
int
ix_entry
,
u32_t
user_data
,
void
*
user_p
)
{
(
void
)
user_
data
;
const
void
*
user_const_p
,
void
*
user_
var_
p
)
{
(
void
)
user_
const_p
;
s32_t
res
;
spiffs_page_object_ix_header
objix_hdr
;
if
(
obj_id
==
SPIFFS_OBJ_ID_FREE
||
obj_id
==
SPIFFS_OBJ_ID_DELETED
||
...
...
@@ -762,10 +915,9 @@ static s32_t spiffs_read_dir_v(
objix_hdr
.
p_hdr
.
span_ix
==
0
&&
(
objix_hdr
.
p_hdr
.
flags
&
(
SPIFFS_PH_FLAG_DELET
|
SPIFFS_PH_FLAG_FINAL
|
SPIFFS_PH_FLAG_IXDELE
))
==
(
SPIFFS_PH_FLAG_DELET
|
SPIFFS_PH_FLAG_IXDELE
))
{
struct
spiffs_dirent
*
e
=
(
struct
spiffs_dirent
*
)
user_p
;
struct
spiffs_dirent
*
e
=
(
struct
spiffs_dirent
*
)
user_
var_
p
;
e
->
obj_id
=
obj_id
;
strncpy
((
char
*
)
e
->
name
,
(
char
*
)
objix_hdr
.
name
,
SPIFFS_OBJ_NAME_LEN
);
strcpy
((
char
*
)
e
->
name
,
(
char
*
)
objix_hdr
.
name
);
e
->
type
=
objix_hdr
.
type
;
e
->
size
=
objix_hdr
.
size
==
SPIFFS_UNDEFINED_LEN
?
0
:
objix_hdr
.
size
;
e
->
pix
=
pix
;
...
...
@@ -780,7 +932,7 @@ struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e) {
d
->
fs
->
err_code
=
SPIFFS_ERR_NOT_MOUNTED
;
return
0
;
}
SPIFFS_LOCK
(
fs
);
SPIFFS_LOCK
(
d
->
fs
);
spiffs_block_ix
bix
;
int
entry
;
...
...
@@ -804,7 +956,7 @@ struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e) {
}
else
{
d
->
fs
->
err_code
=
res
;
}
SPIFFS_UNLOCK
(
fs
);
SPIFFS_UNLOCK
(
d
->
fs
);
return
ret
;
}
...
...
@@ -815,6 +967,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
);
...
...
@@ -830,6 +986,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
)
{
...
...
@@ -856,91 +1013,96 @@ s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used) {
return
res
;
}
s32_t
SPIFFS_tell
(
spiffs
*
fs
,
spiffs_file
fh
)
{
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
);
SPIFFS_LOCK
(
fs
);
spiffs_fd
*
fd
;
s32_t
res
;
res
=
spiffs_fd_get
(
fs
,
fh
,
&
fd
);
SPIFFS_API_CHECK_RES
(
fs
,
res
);
#if SPIFFS_CACHE_WR
spiffs_fflush_cache
(
fs
,
fh
);
#endif
res
=
fd
->
fdoffset
;
res
=
spiffs_gc_quick
(
fs
,
max_free_pages
);
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
SPIFFS_UNLOCK
(
fs
);
return
res
;
return
0
;
#endif // SPIFFS_READ_ONLY
}
s32_t
SPIFFS_eof
(
spiffs
*
fs
,
spiffs_file
fh
)
{
SPIFFS_API_CHECK_MOUNT
(
fs
);
SPIFFS_LOCK
(
fs
);
spiffs_fd
*
fd
;
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
;
res
=
spiffs_fd_get
(
fs
,
fh
,
&
fd
);
SPIFFS_API_CHECK_RES
(
fs
,
res
);
#if SPIFFS_CACHE_WR
spiffs_fflush_cache
(
fs
,
fh
);
#endif
SPIFFS_API_CHECK_CFG
(
fs
);
SPIFFS_API_CHECK_MOUNT
(
fs
);
SPIFFS_LOCK
(
fs
);
res
=
(
fd
->
fdoffset
==
fd
->
size
);
res
=
spiffs_gc_check
(
fs
,
size
);
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
SPIFFS_UNLOCK
(
fs
);
return
res
;
return
0
;
#endif // SPIFFS_READ_ONLY
}
s32_t
SPIFFS_size
(
spiffs
*
fs
,
spiffs_file
fh
)
{
s32_t
SPIFFS_eof
(
spiffs
*
fs
,
spiffs_file
fh
)
{
s32_t
res
;
SPIFFS_API_CHECK_CFG
(
fs
);
SPIFFS_API_CHECK_MOUNT
(
fs
);
SPIFFS_LOCK
(
fs
);
fh
=
SPIFFS_FH_UNOFFS
(
fs
,
fh
);
spiffs_fd
*
fd
;
s32_t
res
;
res
=
spiffs_fd_get
(
fs
,
fh
,
&
fd
);
SPIFFS_API_CHECK_RES
(
fs
,
res
);
SPIFFS_API_CHECK_RES
_UNLOCK
(
fs
,
res
);
#if SPIFFS_CACHE_WR
spiffs_fflush_cache
(
fs
,
fh
);
res
=
spiffs_fflush_cache
(
fs
,
fh
);
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
#endif
res
=
fd
->
size
;
res
=
(
fd
->
fdoffset
>=
(
fd
->
size
==
SPIFFS_UNDEFINED_LEN
?
0
:
fd
->
size
))
;
SPIFFS_UNLOCK
(
fs
);
return
res
;
}
s32_t
SPIFFS_
gc_quick
(
spiffs
*
fs
,
u16_t
max_free_pages
)
{
s32_t
SPIFFS_
tell
(
spiffs
*
fs
,
spiffs_file
fh
)
{
s32_t
res
;
SPIFFS_API_CHECK_CFG
(
fs
);
SPIFFS_API_CHECK_MOUNT
(
fs
);
SPIFFS_LOCK
(
fs
);
res
=
spiffs_gc_quick
(
fs
,
max_free_pages
);
fh
=
SPIFFS_FH_UNOFFS
(
fs
,
fh
);
spiffs_fd
*
fd
;
res
=
spiffs_fd_get
(
fs
,
fh
,
&
fd
);
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
SPIFFS_UNLOCK
(
fs
);
return
0
;
}
#if SPIFFS_CACHE_WR
res
=
spiffs_fflush_cache
(
fs
,
fh
);
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
res
);
#endif
s32_t
SPIFFS_gc
(
spiffs
*
fs
,
u32_t
size
)
{
s32_t
res
;
SPIFFS_API_CHECK_CFG
(
fs
);
SPIFFS_API_CHECK_MOUNT
(
fs
);
SPIFFS_LOCK
(
fs
);
res
=
fd
->
fdoffset
;
res
=
spiffs_gc_check
(
fs
,
size
);
SPIFFS_UNLOCK
(
fs
);
return
res
;
}
SPIFFS_API_CHECK_RES_UNLOCK
(
fs
,
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
)
{
s32_t
res
=
SPIFFS_OK
;
...
...
@@ -1008,11 +1170,10 @@ s32_t SPIFFS_vis(spiffs *fs) {
spiffs_printf
(
"free_blocks: %i
\n
"
,
fs
->
free_blocks
);
spiffs_printf
(
"page_alloc: %i
\n
"
,
fs
->
stats_p_allocated
);
spiffs_printf
(
"page_delet: %i
\n
"
,
fs
->
stats_p_deleted
);
SPIFFS_UNLOCK
(
fs
);
u32_t
total
,
used
;
SPIFFS_info
(
fs
,
&
total
,
&
used
);
spiffs_printf
(
"used: %i of %i
\n
"
,
used
,
total
);
SPIFFS_UNLOCK
(
fs
);
return
res
;
}
#endif
app/spiffs/spiffs_nucleus.c
View file @
be047ff7
...
...
@@ -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
...
...
@@ -64,7 +66,7 @@ s32_t spiffs_phys_rd(
u32_t
addr
,
u32_t
len
,
u8_t
*
dst
)
{
return
fs
->
cfg
.
hal_read_f
(
addr
,
len
,
dst
);
return
SPIFFS_HAL_READ
(
fs
,
addr
,
len
,
dst
);
}
s32_t
spiffs_phys_wr
(
...
...
@@ -72,17 +74,19 @@ s32_t spiffs_phys_wr(
u32_t
addr
,
u32_t
len
,
u8_t
*
src
)
{
return
fs
->
cfg
.
hal_write_f
(
addr
,
len
,
src
);
return
SPIFFS_HAL_WRITE
(
fs
,
addr
,
len
,
src
);
}
#endif
#if !SPIFFS_READ_ONLY
s32_t
spiffs_phys_cpy
(
spiffs
*
fs
,
spiffs_file
fh
,
u32_t
dst
,
u32_t
src
,
u32_t
len
)
{
(
void
)
fh
;
s32_t
res
;
u8_t
b
[
SPIFFS_COPY_BUFFER_STACK
];
while
(
len
>
0
)
{
...
...
@@ -97,10 +101,11 @@ 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.
// When found, the visitor function is called with block index, entry index and user
_
data.
// When found, the visitor function is called with block index, entry index and user
data.
// If visitor returns SPIFFS_VIS_CONTINUE, the search goes on. Otherwise, the search will be
// ended and visitor's return code is returned to caller.
// If no visitor is given (0) the search returns on first entry with matching object id.
...
...
@@ -112,8 +117,8 @@ s32_t spiffs_phys_cpy(
// SPIFFS_VIS_NO_WRAP
// @param obj_id argument object id
// @param v visitor callback function
// @param user_
data
any
data
, passed to the callback visitor function
// @param user_
p
any pointer, passed to the callback visitor function
// @param user_
const_p
any
const pointer
, passed to the callback visitor function
// @param user_
var_p
any pointer, passed to the callback visitor function
// @param block_ix reported block index where match was found
// @param lu_entry reported look up index where match was found
s32_t
spiffs_obj_lu_find_entry_visitor
(
...
...
@@ -123,8 +128,8 @@ s32_t spiffs_obj_lu_find_entry_visitor(
u8_t
flags
,
spiffs_obj_id
obj_id
,
spiffs_visitor_f
v
,
u32_t
user_data
,
void
*
user_p
,
const
void
*
user_const_p
,
void
*
user_
var_
p
,
spiffs_block_ix
*
block_ix
,
int
*
lu_entry
)
{
s32_t
res
=
SPIFFS_OK
;
...
...
@@ -174,8 +179,8 @@ s32_t spiffs_obj_lu_find_entry_visitor(
(
flags
&
SPIFFS_VIS_CHECK_PH
)
?
obj_id
:
obj_lu_buf
[
cur_entry
-
entry_offset
],
cur_block
,
cur_entry
,
user_
data
,
user_p
);
user_
const_p
,
user_
var_
p
);
if
(
res
==
SPIFFS_VIS_COUNTINUE
||
res
==
SPIFFS_VIS_COUNTINUE_RELOAD
)
{
if
(
res
==
SPIFFS_VIS_COUNTINUE_RELOAD
)
{
res
=
_spiffs_rd
(
fs
,
SPIFFS_OP_T_OBJ_LU
|
SPIFFS_OP_C_READ
,
...
...
@@ -217,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
)
{
...
...
@@ -227,7 +233,8 @@ s32_t spiffs_erase_block(
// here we ignore res, just try erasing the block
while
(
size
>
0
)
{
SPIFFS_DBG
(
"erase %08x:%08x
\n
"
,
addr
,
SPIFFS_CFG_PHYS_ERASE_SZ
(
fs
));
(
void
)
fs
->
cfg
.
hal_erase_f
(
addr
,
SPIFFS_CFG_PHYS_ERASE_SZ
(
fs
));
SPIFFS_HAL_ERASE
(
fs
,
addr
,
SPIFFS_CFG_PHYS_ERASE_SZ
(
fs
));
addr
+=
SPIFFS_CFG_PHYS_ERASE_SZ
(
fs
);
size
-=
SPIFFS_CFG_PHYS_ERASE_SZ
(
fs
);
}
...
...
@@ -241,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
);
...
...
@@ -255,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
(
...
...
@@ -262,11 +322,11 @@ static s32_t spiffs_obj_lu_scan_v(
spiffs_obj_id
obj_id
,
spiffs_block_ix
bix
,
int
ix_entry
,
u32_t
user_data
,
void
*
user_p
)
{
const
void
*
user_const_p
,
void
*
user_
var_
p
)
{
(
void
)
bix
;
(
void
)
user_
data
;
(
void
)
user_p
;
(
void
)
user_
const_p
;
(
void
)
user_
var_
p
;
if
(
obj_id
==
SPIFFS_OBJ_ID_FREE
)
{
if
(
ix_entry
==
0
)
{
fs
->
free_blocks
++
;
...
...
@@ -309,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
;
...
...
@@ -348,7 +408,11 @@ s32_t spiffs_obj_lu_scan(
if
(
unerased_bix
!=
(
spiffs_block_ix
)
-
1
)
{
// found one unerased block, remedy
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
...
...
@@ -379,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
(
...
...
@@ -407,12 +472,13 @@ s32_t spiffs_obj_lu_find_free(
fs
->
free_blocks
--
;
}
}
if
(
res
==
SPIFFS_
VIS_END
)
{
if
(
res
==
SPIFFS_
ERR_FULL
)
{
SPIFFS_DBG
(
"fs full
\n
"
);
}
return
res
==
SPIFFS_VIS_END
?
SPIFFS_ERR_FULL
:
res
;
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
...
...
@@ -437,8 +503,8 @@ static s32_t spiffs_obj_lu_find_id_and_span_v(
spiffs_obj_id
obj_id
,
spiffs_block_ix
bix
,
int
ix_entry
,
u32_t
user_data
,
void
*
user_p
)
{
const
void
*
user_const_p
,
void
*
user_
var_
p
)
{
s32_t
res
;
spiffs_page_header
ph
;
spiffs_page_ix
pix
=
SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX
(
fs
,
bix
,
ix_entry
);
...
...
@@ -446,10 +512,10 @@ static s32_t spiffs_obj_lu_find_id_and_span_v(
SPIFFS_PAGE_TO_PADDR
(
fs
,
pix
),
sizeof
(
spiffs_page_header
),
(
u8_t
*
)
&
ph
);
SPIFFS_CHECK_RES
(
res
);
if
(
ph
.
obj_id
==
obj_id
&&
ph
.
span_ix
==
(
spiffs_span_ix
)
user_
data
&&
ph
.
span_ix
==
*
(
(
spiffs_span_ix
*
)
user_
var_p
)
&&
(
ph
.
flags
&
(
SPIFFS_PH_FLAG_FINAL
|
SPIFFS_PH_FLAG_DELET
|
SPIFFS_PH_FLAG_USED
))
==
SPIFFS_PH_FLAG_DELET
&&
!
((
obj_id
&
SPIFFS_OBJ_ID_IX_FLAG
)
&&
(
ph
.
flags
&
SPIFFS_PH_FLAG_IXDELE
)
==
0
&&
ph
.
span_ix
==
0
)
&&
(
user_p
==
0
||
*
((
spiffs_page_ix
*
)
user_p
)
!=
pix
))
{
(
user_
const_
p
==
0
||
*
((
const
spiffs_page_ix
*
)
user_
const_
p
)
!=
pix
))
{
return
SPIFFS_OK
;
}
else
{
return
SPIFFS_VIS_COUNTINUE
;
...
...
@@ -474,8 +540,8 @@ s32_t spiffs_obj_lu_find_id_and_span(
SPIFFS_VIS_CHECK_ID
,
obj_id
,
spiffs_obj_lu_find_id_and_span_v
,
(
u32_t
)
spix
,
exclusion_pix
?
&
exclusion_pix
:
0
,
&
spix
,
&
bix
,
&
entry
);
...
...
@@ -513,8 +579,8 @@ s32_t spiffs_obj_lu_find_id_and_span_by_phdr(
SPIFFS_VIS_CHECK_PH
,
obj_id
,
spiffs_obj_lu_find_id_and_span_v
,
(
u32_t
)
spix
,
exclusion_pix
?
&
exclusion_pix
:
0
,
&
spix
,
&
bix
,
&
entry
);
...
...
@@ -534,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
...
...
@@ -591,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
(
...
...
@@ -654,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
,
...
...
@@ -683,12 +754,14 @@ 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
,
spiffs_obj_id
obj_id
,
u8_t
name
[
SPIFFS_OBJ_NAME_LEN
],
const
u8_t
name
[
SPIFFS_OBJ_NAME_LEN
],
spiffs_obj_type
type
,
spiffs_page_ix
*
objix_hdr_pix
)
{
s32_t
res
=
SPIFFS_OK
;
...
...
@@ -719,7 +792,7 @@ s32_t spiffs_object_create(
oix_hdr
.
p_hdr
.
flags
=
0xff
&
~
(
SPIFFS_PH_FLAG_FINAL
|
SPIFFS_PH_FLAG_INDEX
|
SPIFFS_PH_FLAG_USED
);
oix_hdr
.
type
=
type
;
oix_hdr
.
size
=
SPIFFS_UNDEFINED_LEN
;
// keep ones so we can update later without wasting this page
strncpy
((
char
*
)
&
oix_hdr
.
name
,
(
char
*
)
name
,
SPIFFS_OBJ_NAME_LEN
);
strncpy
((
char
*
)
&
oix_hdr
.
name
,
(
const
char
*
)
name
,
SPIFFS_OBJ_NAME_LEN
);
// update page
...
...
@@ -735,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
...
...
@@ -746,7 +821,7 @@ s32_t spiffs_object_update_index_hdr(
spiffs_obj_id
obj_id
,
spiffs_page_ix
objix_hdr_pix
,
u8_t
*
new_objix_hdr_data
,
u8_t
name
[
SPIFFS_OBJ_NAME_LEN
],
const
u8_t
name
[
SPIFFS_OBJ_NAME_LEN
],
u32_t
size
,
spiffs_page_ix
*
new_pix
)
{
s32_t
res
=
SPIFFS_OK
;
...
...
@@ -770,7 +845,7 @@ s32_t spiffs_object_update_index_hdr(
// change name
if
(
name
)
{
strncpy
((
char
*
)
objix_hdr
->
name
,
(
char
*
)
name
,
SPIFFS_OBJ_NAME_LEN
);
strncpy
((
char
*
)
objix_hdr
->
name
,
(
const
char
*
)
name
,
SPIFFS_OBJ_NAME_LEN
);
}
if
(
size
)
{
objix_hdr
->
size
=
size
;
...
...
@@ -790,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
++
)
{
...
...
@@ -828,6 +904,22 @@ void spiffs_cb_object_event(
}
}
}
// 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
...
...
@@ -886,6 +978,7 @@ s32_t spiffs_object_open_by_page(
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
)
{
...
...
@@ -990,8 +1083,8 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
SPIFFS_CHECK_RES
(
res
);
spiffs_cb_object_event
(
fs
,
fd
,
SPIFFS_EV_IX_NEW
,
fd
->
obj_id
,
cur_objix_spix
,
cur_objix_pix
,
0
);
// quick "load" of new object index page
c_
memset
(
fs
->
work
,
0xff
,
SPIFFS_CFG_LOG_PAGE_SZ
(
fs
));
c_
memcpy
(
fs
->
work
,
&
p_hdr
,
sizeof
(
spiffs_page_header
));
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 %i
\n
"
,
fd
->
obj_id
,
cur_objix_pix
,
cur_objix_spix
,
written
);
}
else
{
...
...
@@ -1125,8 +1218,10 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
}
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
)
{
...
...
@@ -1326,16 +1421,17 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
}
return
res
;
}
}
// spiffs_object_modify
#endif // !SPIFFS_READ_ONLY
static
s32_t
spiffs_object_find_object_index_header_by_name_v
(
spiffs
*
fs
,
spiffs_obj_id
obj_id
,
spiffs_block_ix
bix
,
int
ix_entry
,
u32_t
user_data
,
void
*
user_p
)
{
(
void
)
user_
data
;
const
void
*
user_const_p
,
void
*
user_
var_
p
)
{
(
void
)
user_
var_p
;
s32_t
res
;
spiffs_page_object_ix_header
objix_hdr
;
spiffs_page_ix
pix
=
SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX
(
fs
,
bix
,
ix_entry
);
...
...
@@ -1349,7 +1445,7 @@ static s32_t spiffs_object_find_object_index_header_by_name_v(
if
(
objix_hdr
.
p_hdr
.
span_ix
==
0
&&
(
objix_hdr
.
p_hdr
.
flags
&
(
SPIFFS_PH_FLAG_DELET
|
SPIFFS_PH_FLAG_FINAL
|
SPIFFS_PH_FLAG_IXDELE
))
==
(
SPIFFS_PH_FLAG_DELET
|
SPIFFS_PH_FLAG_IXDELE
))
{
if
(
str
n
cmp
((
char
*
)
user_p
,
(
char
*
)
objix_hdr
.
name
,
SPIFFS_OBJ_NAME_LEN
)
==
0
)
{
if
(
strcmp
((
const
char
*
)
user_
const_
p
,
(
char
*
)
objix_hdr
.
name
)
==
0
)
{
return
SPIFFS_OK
;
}
}
...
...
@@ -1360,7 +1456,7 @@ static s32_t spiffs_object_find_object_index_header_by_name_v(
// Finds object index header page by name
s32_t
spiffs_object_find_object_index_header_by_name
(
spiffs
*
fs
,
u8_t
name
[
SPIFFS_OBJ_NAME_LEN
],
const
u8_t
name
[
SPIFFS_OBJ_NAME_LEN
],
spiffs_page_ix
*
pix
)
{
s32_t
res
;
spiffs_block_ix
bix
;
...
...
@@ -1372,8 +1468,8 @@ s32_t spiffs_object_find_object_index_header_by_name(
0
,
0
,
spiffs_object_find_object_index_header_by_name_v
,
0
,
name
,
0
,
&
bix
,
&
entry
);
...
...
@@ -1392,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
,
...
...
@@ -1400,8 +1497,16 @@ s32_t spiffs_object_truncate(
s32_t
res
=
SPIFFS_OK
;
spiffs
*
fs
=
fd
->
fs
;
res
=
spiffs_gc_check
(
fs
,
remove
?
0
:
SPIFFS_DATA_PAGE_SIZE
(
fs
));
SPIFFS_CHECK_RES
(
res
);
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
if
(
remove
==
0
)
{
res
=
spiffs_gc_check
(
fs
,
SPIFFS_DATA_PAGE_SIZE
(
fs
)
*
2
);
SPIFFS_CHECK_RES
(
res
);
}
spiffs_page_ix
objix_pix
=
fd
->
objix_hdr_pix
;
spiffs_span_ix
data_spix
=
(
fd
->
size
>
0
?
fd
->
size
-
1
:
0
)
/
SPIFFS_DATA_PAGE_SIZE
(
fs
);
...
...
@@ -1440,11 +1545,18 @@ s32_t spiffs_object_truncate(
SPIFFS_CHECK_RES
(
res
);
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 %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
);
// Update object index header page, unless we totally want to remove the file.
// If fully removing, we're not keeping consistency as good as when storing the header between chunks,
// would we be aborted. But when removing full files, a crammed system may otherwise
// report ERR_FULL a la windows. We cannot have that.
// Hence, take the risk - if aborted, a file check would free the lost pages and mend things
// as the file is marked as fully deleted in the beginning.
if
(
remove
==
0
)
{
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
);
}
fd
->
size
=
cur_size
;
}
}
...
...
@@ -1480,7 +1592,7 @@ s32_t spiffs_object_truncate(
SPIFFS_DBG
(
"truncate: got data pix %04x
\n
"
,
data_pix
);
if
(
cur_size
-
SPIFFS_DATA_PAGE_SIZE
(
fs
)
>=
new_size
)
{
if
(
new_size
==
0
||
remove
||
cur_size
-
new_size
>=
SPIFFS_DATA_PAGE_SIZE
(
fs
))
{
// 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
)
{
...
...
@@ -1575,7 +1687,7 @@ s32_t spiffs_object_truncate(
}
else
{
// make uninitialized object
SPIFFS_DBG
(
"truncate: reset objix_hdr page %04x
\n
"
,
objix_pix
);
c_
memset
(
fs
->
work
+
sizeof
(
spiffs_page_object_ix_header
),
0xff
,
memset
(
fs
->
work
+
sizeof
(
spiffs_page_object_ix_header
),
0xff
,
SPIFFS_CFG_LOG_PAGE_SZ
(
fs
)
-
sizeof
(
spiffs_page_object_ix_header
));
res
=
spiffs_object_update_index_hdr
(
fs
,
fd
,
fd
->
obj_id
,
objix_pix
,
fs
->
work
,
0
,
SPIFFS_UNDEFINED_LEN
,
&
new_objix_hdr_pix
);
...
...
@@ -1611,7 +1723,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
,
...
...
@@ -1691,6 +1804,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
;
...
...
@@ -1699,10 +1813,10 @@ typedef struct {
}
spiffs_free_obj_id_state
;
static
s32_t
spiffs_obj_lu_find_free_obj_id_bitmap_v
(
spiffs
*
fs
,
spiffs_obj_id
id
,
spiffs_block_ix
bix
,
int
ix_entry
,
u32_t
user_data
,
void
*
user_p
)
{
const
void
*
user_const_p
,
void
*
user_
var_
p
)
{
if
(
id
!=
SPIFFS_OBJ_ID_FREE
&&
id
!=
SPIFFS_OBJ_ID_DELETED
)
{
spiffs_obj_id
min_obj_id
=
user_data
;
u8_t
*
conflicting_name
=
(
u8_t
*
)
user_p
;
spiffs_obj_id
min_obj_id
=
*
((
spiffs_obj_id
*
)
user_var_p
)
;
const
u8_t
*
conflicting_name
=
(
const
u8_t
*
)
user_
const_
p
;
// if conflicting name parameter is given, also check if this name is found in object index hdrs
if
(
conflicting_name
&&
(
id
&
SPIFFS_OBJ_ID_IX_FLAG
))
{
...
...
@@ -1715,7 +1829,7 @@ static s32_t spiffs_obj_lu_find_free_obj_id_bitmap_v(spiffs *fs, spiffs_obj_id i
if
(
objix_hdr
.
p_hdr
.
span_ix
==
0
&&
(
objix_hdr
.
p_hdr
.
flags
&
(
SPIFFS_PH_FLAG_DELET
|
SPIFFS_PH_FLAG_FINAL
|
SPIFFS_PH_FLAG_IXDELE
))
==
(
SPIFFS_PH_FLAG_DELET
|
SPIFFS_PH_FLAG_IXDELE
))
{
if
(
str
n
cmp
((
char
*
)
user_p
,
(
char
*
)
objix_hdr
.
name
,
SPIFFS_OBJ_NAME_LEN
)
==
0
)
{
if
(
strcmp
((
const
char
*
)
user_
const_
p
,
(
char
*
)
objix_hdr
.
name
)
==
0
)
{
return
SPIFFS_ERR_CONFLICTING_NAME
;
}
}
...
...
@@ -1732,11 +1846,11 @@ static s32_t spiffs_obj_lu_find_free_obj_id_bitmap_v(spiffs *fs, spiffs_obj_id i
}
static
s32_t
spiffs_obj_lu_find_free_obj_id_compact_v
(
spiffs
*
fs
,
spiffs_obj_id
id
,
spiffs_block_ix
bix
,
int
ix_entry
,
u32_t
user_data
,
void
*
user_p
)
{
(
void
)
user_
data
;
const
void
*
user_const_p
,
void
*
user_
var_
p
)
{
(
void
)
user_
var_p
;
if
(
id
!=
SPIFFS_OBJ_ID_FREE
&&
id
!=
SPIFFS_OBJ_ID_DELETED
&&
(
id
&
SPIFFS_OBJ_ID_IX_FLAG
))
{
s32_t
res
;
spiffs_free_obj_id_state
*
state
=
(
spiffs_free_obj_id_state
*
)
user_p
;
const
spiffs_free_obj_id_state
*
state
=
(
const
spiffs_free_obj_id_state
*
)
user_
const_
p
;
spiffs_page_object_ix_header
objix_hdr
;
res
=
_spiffs_rd
(
fs
,
SPIFFS_OP_T_OBJ_LU2
|
SPIFFS_OP_C_READ
,
...
...
@@ -1745,7 +1859,7 @@ static s32_t spiffs_obj_lu_find_free_obj_id_compact_v(spiffs *fs, spiffs_obj_id
((
objix_hdr
.
p_hdr
.
flags
&
(
SPIFFS_PH_FLAG_INDEX
|
SPIFFS_PH_FLAG_FINAL
|
SPIFFS_PH_FLAG_DELET
))
==
(
SPIFFS_PH_FLAG_DELET
)))
{
// ok object look up entry
if
(
state
->
conflicting_name
&&
str
n
cmp
((
const
char
*
)
state
->
conflicting_name
,
(
char
*
)
objix_hdr
.
name
,
SPIFFS_OBJ_NAME_LEN
)
==
0
)
{
if
(
state
->
conflicting_name
&&
strcmp
((
const
char
*
)
state
->
conflicting_name
,
(
char
*
)
objix_hdr
.
name
)
==
0
)
{
return
SPIFFS_ERR_CONFLICTING_NAME
;
}
...
...
@@ -1764,10 +1878,10 @@ static s32_t spiffs_obj_lu_find_free_obj_id_compact_v(spiffs *fs, spiffs_obj_id
// Scans thru all object lookup for object index header pages. If total possible number of
// object ids cannot fit into a work buffer, these are grouped. When a group containing free
// object ids is found, the object lu is again scanned for object ids within group and bitmasked.
// Finally, the bitmask
ed
is searched for a free id
s32_t
spiffs_obj_lu_find_free_obj_id
(
spiffs
*
fs
,
spiffs_obj_id
*
obj_id
,
u8_t
*
conflicting_name
)
{
// Finally, the bitmask is searched for a free id
s32_t
spiffs_obj_lu_find_free_obj_id
(
spiffs
*
fs
,
spiffs_obj_id
*
obj_id
,
const
u8_t
*
conflicting_name
)
{
s32_t
res
=
SPIFFS_OK
;
u32_t
max_objects
=
(
SPIFFS_CFG_PHYS_SZ
(
fs
)
/
(
u32_t
)
SPIFFS_CFG_LOG_PAGE_SZ
(
fs
))
/
2
;
u32_t
max_objects
=
(
fs
->
block_count
*
SPIFFS_OBJ_LOOKUP_MAX_ENTRIES
(
fs
))
/
2
;
spiffs_free_obj_id_state
state
;
spiffs_obj_id
free_obj_id
=
SPIFFS_OBJ_ID_FREE
;
state
.
min_obj_id
=
1
;
...
...
@@ -1783,9 +1897,9 @@ s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id, u8_t *co
u32_t
i
,
j
;
SPIFFS_DBG
(
"free_obj_id: BITM min:%04x max:%04x
\n
"
,
state
.
min_obj_id
,
state
.
max_obj_id
);
c_
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_bitmap_v
,
state
.
min_obj_id
,
conflicting_name
,
0
,
0
);
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_bitmap_v
,
conflicting_name
,
&
state
.
min_obj_id
,
0
,
0
);
if
(
res
==
SPIFFS_VIS_END
)
res
=
SPIFFS_OK
;
SPIFFS_CHECK_RES
(
res
);
// traverse bitmask until found free obj_id
...
...
@@ -1848,8 +1962,8 @@ s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id, u8_t *co
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:%i
\n
"
,
state
.
min_obj_id
,
state
.
max_obj_id
,
state
.
compaction
);
c_
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
,
0
,
&
state
,
0
,
0
);
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
);
if
(
res
==
SPIFFS_VIS_END
)
res
=
SPIFFS_OK
;
SPIFFS_CHECK_RES
(
res
);
state
.
conflicting_name
=
0
;
// searched for conflicting name once, no need to do it again
...
...
@@ -1858,6 +1972,7 @@ s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id, u8_t *co
return
res
;
}
#endif // !SPIFFS_READ_ONLY
s32_t
spiffs_fd_find_new
(
spiffs
*
fs
,
spiffs_fd
**
fd
)
{
u32_t
i
;
...
...
app/spiffs/spiffs_nucleus.h
View file @
be047ff7
...
...
@@ -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)
...
...
@@ -264,26 +272,26 @@
#define SPIFFS_API_CHECK_MOUNT(fs) \
if (!SPIFFS_CHECK_MOUNT((fs))) { \
(fs)->err_code = SPIFFS_ERR_NOT_MOUNTED; \
return
-1
; \
return
SPIFFS_ERR_NOT_MOUNTED
; \
}
#define SPIFFS_API_CHECK_CFG(fs) \
if (!SPIFFS_CHECK_CFG((fs))) { \
(fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED; \
return
-1
; \
return
SPIFFS_ERR_NOT_CONFIGURED
; \
}
#define SPIFFS_API_CHECK_RES(fs, res) \
if ((res) < SPIFFS_OK) { \
(fs)->err_code = (res); \
return
-1
; \
return
(res)
; \
}
#define SPIFFS_API_CHECK_RES_UNLOCK(fs, res) \
if ((res) < SPIFFS_OK) { \
(fs)->err_code = (res); \
SPIFFS_UNLOCK(fs); \
return
-1
; \
return
(res)
; \
}
#define SPIFFS_VALIDATE_OBJIX(ph, objid, spix) \
...
...
@@ -311,6 +319,26 @@
// stop searching at end of all look up pages
#define SPIFFS_VIS_NO_WRAP (1<<2)
#if SPIFFS_HAL_CALLBACK_EXTRA
#define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \
(_fs)->cfg.hal_write_f((_fs), (_paddr), (_len), (_src))
#define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \
(_fs)->cfg.hal_read_f((_fs), (_paddr), (_len), (_dst))
#define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \
(_fs)->cfg.hal_erase_f((_fs), (_paddr), (_len))
#else // SPIFFS_HAL_CALLBACK_EXTRA
#define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \
(_fs)->cfg.hal_write_f((_paddr), (_len), (_src))
#define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \
(_fs)->cfg.hal_read_f((_paddr), (_len), (_dst))
#define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \
(_fs)->cfg.hal_erase_f((_paddr), (_len))
#endif // SPIFFS_HAL_CALLBACK_EXTRA
#if SPIFFS_CACHE
#define SPIFFS_CACHE_FLAG_DIRTY (1<<0)
...
...
@@ -416,9 +444,14 @@ typedef struct __attribute(( packed )) {
// object index header page header
typedef
struct
__attribute
((
packed
))
#if SPIFFS_ALIGNED_OBJECT_INDEX_TABLES
__attribute
((
aligned
(
sizeof
(
spiffs_page_ix
))
))
#endif
{
// common page header
spiffs_page_header
p_hdr
;
// alignment
u8_t
_align
[
4
-
((
sizeof
(
spiffs_page_header
)
&
3
)
==
0
?
4
:
(
sizeof
(
spiffs_page_header
)
&
3
))];
// size of object
u32_t
size
;
// type of object
...
...
@@ -430,11 +463,12 @@ typedef struct __attribute(( packed ))
// object index page header
typedef
struct
__attribute
((
packed
))
{
spiffs_page_header
p_hdr
;
u8_t
_align
[
4
-
((
sizeof
(
spiffs_page_header
)
&
3
)
==
0
?
4
:
(
sizeof
(
spiffs_page_header
)
&
3
))];
}
spiffs_page_object_ix
;
// callback func for object lookup visitor
typedef
s32_t
(
*
spiffs_visitor_f
)(
spiffs
*
fs
,
spiffs_obj_id
id
,
spiffs_block_ix
bix
,
int
ix_entry
,
u32_t
user_data
,
void
*
user_p
);
const
void
*
user_const_p
,
void
*
user_
var_
p
);
#if SPIFFS_CACHE
...
...
@@ -495,8 +529,8 @@ s32_t spiffs_obj_lu_find_entry_visitor(
u8_t
flags
,
spiffs_obj_id
obj_id
,
spiffs_visitor_f
v
,
u32_t
user_data
,
void
*
user_p
,
const
void
*
user_const_p
,
void
*
user_
var_
p
,
spiffs_block_ix
*
block_ix
,
int
*
lu_entry
);
...
...
@@ -504,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
(
...
...
@@ -512,7 +551,7 @@ s32_t spiffs_obj_lu_scan(
s32_t
spiffs_obj_lu_find_free_obj_id
(
spiffs
*
fs
,
spiffs_obj_id
*
obj_id
,
u8_t
*
conflicting_name
);
const
u8_t
*
conflicting_name
);
s32_t
spiffs_obj_lu_find_free
(
spiffs
*
fs
,
...
...
@@ -573,7 +612,7 @@ s32_t spiffs_page_delete(
s32_t
spiffs_object_create
(
spiffs
*
fs
,
spiffs_obj_id
obj_id
,
u8_t
name
[
SPIFFS_OBJ_NAME_LEN
],
const
u8_t
name
[
SPIFFS_OBJ_NAME_LEN
],
spiffs_obj_type
type
,
spiffs_page_ix
*
objix_hdr_pix
);
...
...
@@ -583,7 +622,7 @@ s32_t spiffs_object_update_index_hdr(
spiffs_obj_id
obj_id
,
spiffs_page_ix
objix_hdr_pix
,
u8_t
*
new_objix_hdr_data
,
u8_t
name
[
SPIFFS_OBJ_NAME_LEN
],
const
u8_t
name
[
SPIFFS_OBJ_NAME_LEN
],
u32_t
size
,
spiffs_page_ix
*
new_pix
);
...
...
@@ -635,7 +674,7 @@ s32_t spiffs_object_truncate(
s32_t
spiffs_object_find_object_index_header_by_name
(
spiffs
*
fs
,
u8_t
name
[
SPIFFS_OBJ_NAME_LEN
],
const
u8_t
name
[
SPIFFS_OBJ_NAME_LEN
],
spiffs_page_ix
*
pix
);
// ---------------
...
...
app/spiffs/test/main.c
deleted
100644 → 0
View file @
b580bfe7
#include "testrunner.h"
#include <stdlib.h>
int
main
(
int
argc
,
char
**
args
)
{
run_tests
(
argc
,
args
);
exit
(
EXIT_SUCCESS
);
}
Prev
1
2
3
4
5
6
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment