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>
180 lines
5.0 KiB
C
180 lines
5.0 KiB
C
/* NVS: non volatile storage in flash
|
|
*
|
|
* Copyright (c) 2018 Laczen
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
#ifndef __NVS_H_
|
|
#define __NVS_H_
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include <sys/types.h>
|
|
/**
|
|
* @brief Non-volatile Storage
|
|
* @defgroup nvs Non-volatile Storage
|
|
* @{
|
|
* @}
|
|
*/
|
|
|
|
/**
|
|
* @brief Non-volatile Storage Data Structures
|
|
* @defgroup nvs_data_structures Non-volatile Storage Data Structures
|
|
* @ingroup nvs
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* @brief Non-volatile Storage File system structure
|
|
*
|
|
* @param magic File system magic, repeated at start of each sector
|
|
* @param write_location Next write location for entry header
|
|
* @param offset File system offset in flash
|
|
* @param sector_id Counter for sector
|
|
* @param sector_size File system is divided into sectors each sector should be
|
|
* multiple of pagesize and also a power of 2
|
|
* @param free_space Indicator for available space in the filesystem
|
|
* @param max_len Maximum size of storage items
|
|
* @param sector_count Amount of sectors in the file systems
|
|
* @param entry_sector Oldest sector in used
|
|
* @param write_block_size Alignment size in bytes_to_copy
|
|
* @param nvs_lock Mutex
|
|
* @param flash_device Flash Device
|
|
*/
|
|
struct nvs_fs {
|
|
u32_t magic; /* filesystem magic, repeated at start of each sector */
|
|
off_t write_location; /* next write location for entry header */
|
|
off_t offset; /* filesystem offset in flash */
|
|
u16_t sector_id; /* sector id, a counter for each created sector */
|
|
u16_t sector_size; /* filesystem is divided into sectors,
|
|
* sector size should be multiple of pagesize
|
|
* and a power of 2
|
|
*/
|
|
u16_t free_space; /* Indicator for available space in the file system.
|
|
* Writes are only allowed if free_space is equal to
|
|
* max_len. Is set to zero when the file system is
|
|
* full. Deletes increase free_space.
|
|
*/
|
|
u16_t max_len; /* maximum size of stored item, set to sector_size/4 */
|
|
u8_t sector_count; /* how many sectors in the filesystem */
|
|
|
|
u8_t entry_sector; /* oldest sector in use */
|
|
u8_t write_block_size; /* write block size for alignment */
|
|
|
|
struct k_mutex nvs_lock;
|
|
struct device *flash_device;
|
|
};
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
/**
|
|
* @brief Non-volatile Storage APIs
|
|
* @defgroup nvs_high_level_api Non-volatile Storage APIs
|
|
* @ingroup nvs
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* @brief nvs_init
|
|
*
|
|
* Initializes a NVS file system in flash.
|
|
*
|
|
* @param fs Pointer to file system
|
|
* @param dev_name Pointer to flash device name
|
|
* @param magic Magic number used in file system
|
|
* @retval 0 Success
|
|
* @retval -ERRNO errno code if error
|
|
*/
|
|
int nvs_init(struct nvs_fs *fs, const char *dev_name, u32_t magic);
|
|
|
|
/**
|
|
* @brief nvs_clear
|
|
*
|
|
* Clears the NVS file system from flash.
|
|
*
|
|
* @param fs Pointer to file system
|
|
* @retval 0 Success
|
|
* @retval -ERRNO errno code if error
|
|
*/
|
|
int nvs_clear(struct nvs_fs *fs);
|
|
|
|
/**
|
|
* @brief nvs_write
|
|
*
|
|
* Write an entry to the file system.
|
|
*
|
|
* @param fs Pointer to file system
|
|
* @param id Id of the entry to be written
|
|
* @param data Pointer to the data to be written
|
|
* @param len Number of bytes to be written
|
|
*
|
|
* @return Number of bytes written. On success, it will be equal to the number
|
|
* of bytes requested to be written. Any other value, indicates an error. Will
|
|
* return -ERRNO code on error.
|
|
*/
|
|
ssize_t nvs_write(struct nvs_fs *fs, u16_t id, const void *data, size_t len);
|
|
|
|
/**
|
|
* @brief nvs_delete
|
|
*
|
|
* Delete an entry from the file system
|
|
*
|
|
* @param fs Pointer to file system
|
|
* @param id Id of the entry to be deleted
|
|
* @retval 0 Success
|
|
* @retval -ERRNO errno code if error
|
|
*/
|
|
int nvs_delete(struct nvs_fs *fs, u16_t id);
|
|
|
|
/**
|
|
* @brief nvs_read
|
|
*
|
|
* Read an entry from the file system.
|
|
*
|
|
* @param fs Pointer to file system
|
|
* @param id Id of the entry to be read
|
|
* @param data Pointer to data buffer
|
|
* @param len Number of bytes to be read
|
|
*
|
|
* @return Number of bytes read. On success, it will be equal to the number
|
|
* of bytes requested to be read. Any other value, indicates an error. When
|
|
* the number of bytes read is larger than the number of bytes requested to
|
|
* read this indicates not all bytes were read, and more data is available.
|
|
* Return -ERRNO code on error.
|
|
*/
|
|
ssize_t nvs_read(struct nvs_fs *fs, u16_t id, void *data, size_t len);
|
|
|
|
/**
|
|
* @brief nvs_read_hist
|
|
*
|
|
* Read a history entry from the file system.
|
|
*
|
|
* @param fs Pointer to file system
|
|
* @param id Id of the entry to be read
|
|
* @param data Pointer to data buffer
|
|
* @param len Number of bytes to be read
|
|
* @param cnt History counter: 0: latest entry, 1:one before latest ...
|
|
*
|
|
* @return Number of bytes read. On success, it will be equal to the number
|
|
* of bytes requested to be read. Any other value, indicates an error. When
|
|
* the number of bytes read is larger than the number of bytes requested to
|
|
* read this indicates not all bytes were read, and more data is available.
|
|
* Return -ERRNO code on error.
|
|
*/
|
|
ssize_t nvs_read_hist(struct nvs_fs *fs, u16_t id, void *data, size_t len,
|
|
u16_t cnt);
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* __NVS_H_ */
|