This patch fixes following bug:
After first GC operation the 1st sector had become scratch
and the 2nd sector had became write sector. After that NVS
was initialize (via reboot) again - it recognized the 1st
sector as write sector and 2nd as undone GC destination sector,
therefore it cleared 2nd sector and re-run GC, which implied data loss.
Signed-off-by: Andrzej Puzdrowski <andrzej.puzdrowski@nordicsemi.no>
Aligned format specifiers for the NVS FS. Now, the format specifier
matches the variable type for qemu_x86 types.
Signed-off-by: Kamil Piszczek <Kamil.Piszczek@nordicsemi.no>
Update the files which contain no license information with the
'Apache-2.0' SPDX license identifier. Many source files in the tree are
missing licensing information, which makes it harder for compliance
tools to determine the correct license.
By default all files without license information are under the default
license of Zephyr, which is Apache version 2.
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
Rename reserved function names in the subsys/ subdirectory except
for static _mod_pub_set and _mod_unbind functions in bluetooth mesh
cfg_srv.c which clash with the similarly named global functions.
Signed-off-by: Patrik Flykt <patrik.flykt@intel.com>
This patch removes the free space calculation from nvs initialization.
The available space can be calculated if required using the routine
nvs_calc_free_space.
This patch also removes the locked state of nvs, it is not possible to
get in a locked state.
This patch adds an extra check on the sector_size configuration and only
allows operation on nvs when nvs has been initialized.
This patch also solves issue #13369, the usage of FLASH_ERASE_BLOCK_SIZE
has been replaced with the flash page api.
Changes:
Removed locked state and free_space from the nvs structure.
nvs_reinit(): has been replaced with by an internal only function
_nvs_startup().
nvs_write(): removed the possibility to place the file system in a
locked state, if to many gc operations are required it will return
-ENOSPC.
ssize_t nvs_calc_free_space(): introduced, calculates the free space
that is available in the nvs file system.
Removed define LOG_LEVEL.
Rebased to current master.
Signed-off-by: Laczen JMS <laczenjms@gmail.com>
This patch removes the free space calculation from nvs initialization.
The available space can be calculated if required using the routine
nvs_calc_free_space.
This patch also removes the locked state of nvs, it is not possible to
get in a locked state.
Changes:
Removed locked state and free_space from the nvs structure.
nvs_reinit(): has been replaced with by an internal only function
_nvs_startup().
nvs_write(): removed the possibility to place the file system in a
locked state, if to many gc operations are required it will return
-ENOSPC.
ssize_t nvs_calc_free_space(): introduced, calculates the free space
that is available in the nvs file system.
Signed-off-by: Laczen JMS <laczenjms@gmail.com>
There are issues using lowercase min and max macros when compiling a C++
application with a third-party toolchain such as GNU ARM Embedded when
using some STL headers i.e. <chrono>.
This is because there are actual C++ functions called min and max
defined in some of the STL headers and these macros interfere with them.
By changing the macros to UPPERCASE, which is consistent with almost all
other pre-processor macros this naming conflict is avoided.
All files that use these macros have been updated.
Signed-off-by: Carlos Stuart <carlosstuart1970@gmail.com>
Commit 41f86c3db2 ("nvs: fix warnings in logger") wrongly changed the
"%d" into "%x" while it was only supposed to suppress the warning.
This patch switches back the format string to "%x".
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
When compiling NVS with NEWLIB_LIBC=y, GCC outputs the following
warning:
In file included from $ZEPHYR/include/logging/log.h:11:0,
from $ZEPHYR/subsys/fs/nvs/nvs.c:17:
$ZEPHYR/subsys/fs/nvs/nvs.c: In function 'nvs_init':
$ZEPHYR/subsys/fs/nvs/nvs.c:748:10: warning: format '%lx' expects
argument of type 'long unsigned int', but argument 3 has type 'u32_t
{aka unsigned int}' [-Wformat=]
LOG_INF("alloc wra: %d, %" PRIx32 "",
^
fs->ate_wra and fs->data_wra are both defined as u32_t, so they need to
be printed with '%d'.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Following the recent NVS changes, the following warning now appear with
GCC 7.3 when building with -O2:
ZEPHYROOT/subsys/fs/nvs/nvs.c: In function 'nvs_reinit':
ZEPHYROOT/subsys/fs/nvs/nvs.c:92:36: warning: 'addr' may be used
uninitialized in this function [-Wmaybe-uninitialized]
offset += fs->sector_size * (addr >> ADDR_SECT_SHIFT);
~~~~~~^~~~~~~~~~~~~~~~~~~
ZEPHYROOT/subsys/fs/nvs/nvs.c:606:8: note: 'addr' was declared here
u32_t addr;
^~~~
This was already reported by Coverity earlier as CID:187903.
In practice this can only happen if fs->sector_count equals 0, which is
not possible as checked in nvs_init(). At least in the GCC case, it
believes that k_mutex_lock(&fs->nvs_lock, K_FOREVER) could modify
fs->sector_count.
Workaround the issue by initializing addr to 0.
Fixes#9767
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
The current NVS code checks for an empty ATE using th
_nvs_flash_cmp_const() function. This function loads the data and
compare them to a value. This means that when executed multiple on the
same area, the data get reloaded multiple time. This might have a
noticeable performance impact with an SPI flash.
Instead define a function _nvs_ate_cmp_const to compare an already read
struct nvs_ate with a constant value. Then replace the calls to
_nvs_flash_cmp_const() on struct nvs_ate by _nvs_flash_ate_rd() followed
by _nvs_ate_cmp_const(). This also has the advantage of explicitly
checking for errors instead of testing the error and the result of the
comparison at the same time.
Tested on a Nucleo L432KC board with the nvs sample. The maximum
initialization time (ie just before running the first garbage collector)
goes down to 6213 µs from 7350 µs.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
NVS with modified flash layout. At the end of a sector a special ate is
placed that points to the last ate that was written. This special ate
is written when a sector is closed. This allows nvs to travel through
the fs much quicker as it doesn't have to search for the last ate in
a sector.
This modification also speeds up the nvs_init procedure that was very
slow on external (spi) flash.
Remark: As the layout of data in flash is changed old data in the flash
cannot be recovered. It is advised to erase the nvs flash area before
using the changed nvs.
Modification after review by @nvlsianpu applied
Modification after review by @aurel32:
_nvs_prev_ate(): provide a backup search of a valid ate when the sector
close_ate has a bad CRC8. Tested on nrf81522 by making flash writing
bad data to the sector closing ate. Also validated that if a valid ate
is overwritten the filesystem keeps working.
_nvs_gc(): return error if _nvs_flash_cmp_const() is < 0.
Signed-off-by: Laczen JMS <laczenjms@gmail.com>
The Atmel SAM E70 flash has a 16-byte write block size. Increase the
NVS_BLOCK_SIZE a bit and take some margin. This might also improve the
performances by reducing the calls to the flash driver when moving data
during garbage collection.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
When the write block size is bigger than sizeof(nvs_ate), which is 8
bytes, we should not read or write more than the ATE. The
_nvs_flash_al_wrt() function will take care of padding the write with
0xff up to write_block_size. Of course the addresses should still be
incremented by write_block_size.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
VLA are usually not recommended and are a MISRA C violation. Replace
fs->write_block_size by NVS_BLOCK_SIZE as we now have a check at
initialization that ensures that fs->write_block_size <= NVS_BLOCK_SIZE.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
In case the write block size is bigger than NVS_BLOCK_SIZE, some
functions end up in an endless loop. Detect the unsupported cases
at initialization.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Under GNU C, sizeof(void) = 1. This commit merely makes it explicit u8.
Pointer arithmetics over void types is:
* A GNU C extension
* Not supported by Clang
* Illegal across all ISO C standards
See also: https://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html
Signed-off-by: Mark Ruvald Pedersen <mped@oticon.com>
In case a write to the flash failed, do not leave the flash unprotected.
Always call flash_write_protection_set in that case.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Avoid unsetting and setting the flash protection if there is nothing to
write to the flash. This happens for example when deleting data from the
flash using nvs_delete.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
In case a sector is not empty nor properly closed (ie it never contains
8 times 0xff nor 0x00), the _nvs_prev_ate will loop indefinitely and
will start adressing memory outside of the flash area.
Fix that by stopping the loop when the address matches the beginning of
the sector.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Instead of forcing the crc8 entry to 0xff for the crc8 computation, just
ignore this field in the computation as it is the last one. This avoid
having to set it back to the original value for _nvs_ate_crc8_check.
Add a build assertion to ensure crc8 is kept last.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
The allocation table entry should be as small as possible in the flash,
so declare it as packed to avoid that the compiler pads it.
Note that this doesn't change anything on ARM, but it might help for
other (future) architectures.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
- Add a missing plural.
- Use a comma to separate the sector number with the offset to not
confuse that with a range.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
The return of memset is never checked. This patch explicitly ignore
the return to avoid MISRA-C violations.
The only directory excluded directory was ext/* since it contains
only imported code.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
The current code computes the block-aligned len by ANDing the len with
~write_block_size instead of ~(write_block_size - 1).
In addition the compute value can be 0 (for lengths that are less than
the block size), so the first flash write might have to be skipped.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
On flash NVS was stored one entry after another including the metadata
of each entry. This has the disadvantage that when an incomplete write
is performed (e.g. due to power failure) the complete sector had to be
rewritten to get a completely functional system.
The present rewrite changed the storage in flash of the data. For each
sector the data is now written as follows: the data itself at the
beginning of the sector (one after the other), the metadata (id, length,
data offset in the sector, and a crc of the metadata) is written from
the end of the sector. The metadata is of fixed size (8 byte) and for
a sector that is completely occupied a metadata entry of all zeros is
used.
Writing data to flash always is done by:
1. Writing the data,
2. Writing the metadata.
If an incomplete write is done NVS will ignore this incomplete write.
At the same time the following improvements were done:
1. NVS now support 65536 sectors of each 65536 byte.
2. The sector size no longer requires to be a power of 2 (but it
still needs to be a multiple of the flash erase page size).
3. NVS now also keeps track of the free space available.
Signed-off-by: Laczen JMS <laczenjms@gmail.com>
The nvs module has some disadvantages for larger block size. The data
header and slot are taking up to much space. A rewrite is proposed that
reduces the used storage space for systems with write block size > 4.
The data storage in flash is now one unit consisting of: data_length,
data_id, data and data_length again in a multiple of the write block
size. The data_length at the end is used to validate the correctness of
the flash write and also allows to travel backwards in the filesystem.
As a comparison, on a system with block size 8 byte, a 32 bit values
now fits 1 block including the metadata (length and id). This used to
be 3 blocks.
The data_length will occupy 1 byte if the data length is less than 128
byte, it will occupy 2 byte if the data length is 128 byte or more. The
data length is limited to 16383 byte.
Each write to flash is verified by a read back of the data.
The read performance is improved because reading is done backwards so
the latest items are found first.
When the filesystem is locked it can be unlocked by calling
reinit(), this will clear flash and setup everything for storage.
add sample documentation - README.rst
Update dtsi to include erase_block_size, use erase_block_size in sample
Update prj.conf to include CONFIG_MPU_ALLOW_FLASH_WRITE
Signed-off-by: Laczen JMS <laczenjms@gmail.com>
Bool symbols implicitly default to 'n'.
A 'default n' can make sense e.g. in a Kconfig.defconfig file, if you
want to override a 'default y' on the base definition of the symbol. It
isn't used like that on any of these symbols though.
Remove some 'default ""' properties on string symbols too.
Also make definitions more consistent by converting some
config FOO
<type>
prompt "foo"
definitions to a shorter form:
config FOO
<type> "foo"
This shorthand works for int/hex/string symbols too, not just for bool
symbols.
Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
_nvs_sector_is_used() never uses the offset argument. As a consequence,
it only check the first sector of the flash. Fix that.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
The two functions that compute the crc16 when writing (nvs_append_close)
and when reading (nvs_check_crc) currently assume that the flash is
also mapped in read mode at address 0. This is not true on all SoCs, and
even less on an SPI flash.
Fix this by adding a new nvs_compute_crc() function which compute the
CRC16 of an entry using the flash using nvs_flash_read, in blocks of
write_block_size. This might not be the optimal size, but it keeps the
stack usage small.
Use this function in both nvs_append_close() and nvs_check_crc() instead
of accessing the flash from address 0.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
GCC complains that last_entry.len and last_entry.data_addr might be
uninitialized in _nvs_gc. Fix that.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Now that the flash writes are padded up to the write block size, there
is no need to have explicit padding fields in the _nvs_sector_hdr and
_nvs_data_slt structure. This allow to save space when the write block
size equals to 1 or 2
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Writing more than the source buffer means that some random data,
possibly coming from the stack, ends-up in the flash. This could be
a security issue.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Reading more than the destination buffer means that data is overwritten
possibly on the stack. This causes unpredictable behaviours like
crashes.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Some SoCs do not allow shorter writes than the write block size, usually
when they have ECC memory. This patch first write all data in multiple
of the write block size and then do a last write with the data padded.
It uses 0xff as the padding byte to avoid wearing-out the flash.
nvs_append_close() is slightly modified to compute the crc16 that will
be put in the slot over the size defined in the header, to match the way
it is checked on read.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Zephyr supports fatfs, nffs and fcb as storage layer. fatfs and nffs
are less suited for application in memory restricted IC's. fcb has a
smaller footprint but has a complex api.
The proposed module is a module with a even smaller footprint compared
to fcb and a simple interface for reading and writing entries. The
module provides wear levelling of flash. This allows the module to be
used not only to store configuration settings but to store device state
(e.g. state of a light switch over reboots) of a zephyr device.
Fixes buffer overflow by introducing maximum read length in nvs_read()
and nvs_read_hist().
Fixes nvs_write() not to reflash the same data. Allows the user to do
call nvs_write() for all defined entries without worries about flash
wear.
Fixes garbage collection error where wrong data could be copied.
Add nvs_delete() to allow deleting a stored entry. A deleted entry will
not be copied to a new flash sector
Include flash wear information in the README.md documentation
0/25 Update module after reviewers remarks, added documentation to
nvs.h, removed README.md by nvs.rst in doc/subsystems folder
04/26 Update module after reviewers remarks, updated nvs.rst, added more
documentation to samples/subsys/nvs/src/main.c, updated doxygen info
in nvs.h (hope this time it works).
04/26 Update subsystems.rst to include nvs.restart
04/27 Updated nvs.c and nvs.h to avoid a possible flash deletion loop
when the file system is full.
04/29 Updated nvs_write to detect and ignore deletes of non-existing
items
05/06 Update NVS module to return standard error codes, removed low
level API, added configuration options. NVS now uses the board dts to
determine the flash storage location (FLASH_AREA_STORAGE_OFFSET).
05/06 Update nvs.rst. Updated intendation and added intermediate
variables in nvs.c to make the code easier to read.
05/06 Update nvs.rst.
05/07 Update nvs.rst
05/08 Changed the API to a more standard file system API.
05/08 Removed cnt_max from nvs_read() as it is not used.
05/08 Removed #ifdef(CONFIG_NVS_LOG) from nvs_priv.h, now the module can
be build with debugging off.
05/09 Removed configuration options for SECTOR_SIZE, SECTOR_COUNT and
MAX_ELEM_SIZE. It is now easy to support multiple NVS filesystems on
one or multiple devices. Changed logging to support newlib systems.
Thanks to Olivier Martin for reporting and proposed changes.
Signed-off-by: Laczen JMS <laczenjms@gmail.com>