NVM3
Detailed Description
NVM3 Non-Volatile Memory Management driver.
- Note
- Using NVM3 to store data in external Flash is beta tested only. Silicon Labs will NOT support any production deployments with this Beta release. Production deployments will only be supported with the GA version of this feature. This version is intended for lab and evaluation purpose only.
- Introduction
- Objects
- Repacking
- Caching
- Global Data (variables)
- Stack Usage
- The API
- Memory Placement
- Configuration Options
- Bad NVM Page Handling
- Error Handling
- Storing objects in internal Flash
- Storing objects in external Flash
- NVM3 Libraries
- Examples
Introduction
The NVM3 driver provides a way for an application to safely store and retrieve variable size objects in a page-based non-volatile memory. Objects are identified with 20-bit object identifiers denoted as keys.
The driver is designed to use pages in a sequential order to provide equal usage and wear. The driver is resilient to power loss or reset events, ensuring that objects retrieved from the driver are in a valid state. A valid object will always be the last successfully stored object. NVM3 can detect NVM defects and mark pages as unusable. NVM3 will continue to operate on good pages after defect pages are detected.
Objects
An NVM3 object is data that can be stored in NVM. The object is handled as an array of bytes up to NVM3_MAX_OBJECT_SIZE in size. NVM3 can handle two types of objects.
- Regular data objects. Data objects can store information of any size up to maximum NVM3_MAX_OBJECT_SIZE bytes.
- 32-bit counter objects. Counter objects can store 32-bit counters that are accessed with a separate set of API functions. The counter object is designed to be compact while minimizing memory wear in applications that require frequent persistent counter increments.
See The API for more details on the API.
Repacking
As the NVM fills up, it reaches a point where it can no longer store additional objects and a repacking operation is required to release out-of-date objects to free up NVM. Because erasing pages takes a long time, the NVM3 driver does not trigger the process by itself unless free memory reaches a critical low level. As an alternative, the application can trigger the repacking process by calling the nvm3_repack() function. During the call, NVM3 will either move data to a new page or erase pages that can be reused. At most, the call will block for a period equal to a page erasure time plus a small execution overhead. Page erasure time for the EFM32 or EFR32 parts can be found in the data sheet.
The application can use nvm3_repackNeeded() to determine if repacking is needed. To initiate repacks, call nvm3_repack() . Note that this function will perform repacks only if they are needed.
NVM3 uses two thresholds for repacking:
- Forced threshold. This is the threshold used to force automatic repacking when free memory reaches a critical low level.
- User threshold. This is the threshold used by nvm3_repackNeeded() . nvm3_repack() will not perform repacking unless free memory is below this threshold.
An NVM3 function that deletes or modifies a data or counter object will trigger an automatic repack operation when free memory is below the forced threshold. The check is done before the object is modified, not after.
The user can define the user threshold by entering a value in the repackHeadroom member of the nvm3_Init_t structure used by the nvm3_open() function. The repackHeadroom value defines the difference between the user and forced threshold. The forced threshold is the minimum low memory threshold defined by the page size and maximum object size and cannot be changed by the user. The default value for the repack headroom is 0, meaning that the forced and user thresholds are equal.
- Note
- The repack threshold can be changed to prevent multiple modifications of objects between user called repacks from causing automatic repacks. Note that "high" values of the repack headroom may cause increased NVM wear from increased number of repacks.
Caching
Caching is an optional feature. The NVM3 cache is an object location lookup cache. Data is not stored in the cache. Using cache speeds up object access and the performance will very much depend on objects being available in the cache. To ensure that cache can hold all necessary information, it must be configured to a size equivalent to or larger than the number of objects stored in NVM including those deleted as long as they are not discarded by the repack function. If the cache is available, the driver will first look in the cache to find the position of the object in NVM. If the object position is not found in the cache, the object position will be found by searching the NVM. The search will start at the last stored object and search all the way to the oldest object. If the object is found, the cache is updated accordingly.
The application must allocate and support data for the cache. See the nvm3_open function for more details. The size of each cache element is one uint32_t and one pointer giving a total of 8 bytes (2 words) pr. entry for EFM32 and EFR32 devices.
- Note
- The cache is fully initialized by nvm3_open() and automatically updated by any subsequent write, read, or delete function call.
Global Data (variables)
The NVM3 library is using global variables to store intermediate data during open, read, write, increment, and delete calls. Because the actual memory configuration is not defined at the time the NVM3 library is built, but rather at the time the user application is built, the size of data structures must be determined by the application configuration. Also, the application must set the value of the nvm3MaxFragmentCount at run-time before any NVM3 functions are called.
NVM3 does not support overlapped calls. If there is any chance that the application can issue overlapped calls, the NVM3 locking mechanism must be present and protect from that.
- Note
- If the application is using more than one NVM3 instance, the variables will be shared between the instances. Be sure to allocate data that have a size that is large enough for the largest usage.
Stack Usage
NVM3 library function calls are nested several levels deep. The stack usage has been measured on some EFM32 and EFR32 targets with library builds for IAR and armgcc. The maximum stack usage measured was 420 bytes for IAR and 472 bytes for ARM GCC builds. The unit test used to validate the stack usage has a 10% margin and is using a stack limit at 462 bytes for IAR and 520 for ARM GCC. Please note that the actual stack usage is a little different on the Cortex M0 Plus, M3, M4 and M33 versions of the library.
The API
The NVM3 API is defined in the
nvm3.h
file, and the application code must include the
nvm3.h
header file to get access to all definitions, datatypes, and function prototypes defined by NVM3.
This section contains brief descriptions of NVM3 functions. For more information about parameters and return values see the Function Documentation section. Most functions return an
Ecode_t
that has the value
ECODE_NVM3_OK
on success or see
nvm3.h
for other values.
nvm3_open()
and
nvm3_close()
.
Functions to open and close an NVM3 instance.
nvm3_open()
takes a handle of type nvm3_Handle_t and initialization data of type
nvm3_Init_t
. The helper macro pair
NVM3_DEFINE_SECTION_STATIC_DATA()
and
NVM3_DEFINE_SECTION_INIT_DATA()
are provided to simplify initialization data definition. For usage examples, see the
Examples
section.
nvm3_getObjectInfo()
,
nvm3_enumObjects()
,
nvm3_deleteObject()
and
nvm3_countObjects()
These functions work on all objects.
nvm3_enumObjects()
gets a list of keys to valid objects in the NVM. The search can also be constrained by the function parameters.
nvm3_countObjects()
can be useful at startup to distinguish between a first startup without any valid objects present and later reboots with valid objects persistently stored in NVM.
nvm3_writeData()
and
nvm3_readData()
Write and read data objects.
nvm3_writeCounter()
,
nvm3_readCounter()
and
nvm3_incrementCounter()
Write, read, and increment 32-bit counter objects.
nvm3_eraseAll()
Erase all objects in NVM.
nvm3_getEraseCount()
Return the erasure count for the most erased page in NVM.
nvm3_repack()
and
nvm3_repackNeeded()
Manage NVM3 repacking operations.
nvm3_resize()
Resize the NVM area used by an open NVM3 instance.
Memory Placement
The application is responsible for placing the NVM area correctly. Minimum requirements for memory placement are:
- NVM area start address must be aligned with a page of the underlying memory system.
- NVM area size must be a multiple of the page size.
The minimum required NVM size is dependent on both the NVM page size and the NVM3_MAX_OBJECT_SIZE value. For a device with 2 kB page size and some typical values for NVM3_MAX_OBJECT_SIZE, the following is the minimum required number of pages:
- For NVM3_MAX_OBJECT_SIZE=208: 3 pages
- For NVM3_MAX_OBJECT_SIZE=1900: 4 pages
- For NVM3_MAX_OBJECT_SIZE=4096: 5 pages
NVM3_DEFINE_SECTION_STATIC_DATA() and NVM3_DEFINE_SECTION_INIT_DATA() macros are provided to support the creation of the NVM area and initialization data. A linker section called 'name'_section is defined by NVM3_DEFINE_SECTION_STATIC_DATA() . The NVM area is placed within the linker section. The application linker script must place the section according to the requirements above. An error is returned by nvm3_open() on alignment or size violation.
Configuration Options
There are no compile-time configuration options for NVM3. All configuration parameters are contained in nvm3_Init_t .
- Note
- The Global Data (variables) must however be configured for correct size and have correct values for NVM3 to behave correctly.
Bad NVM Page Handling
NVM3 has been designed to detect page erase and write errors during normal operation and mark failing pages as BAD. If a write operation fails, all objects that have been written to the page prior to the write error are copied to the next free page before the page is marked as BAD and the write operation resumes. If the recover operation is successful, the operation is regarded as complete and the function will return ECODE_NVM3_OK status.
- Note
- Erase and write errors may not be detected by NVM3 if the device is used until end of life where the failure mode can be that the NVM content is changing during a power cycle.
Error Handling
The NVM3 error handling involves most functions returning an error code. The nvm3_countObjects is different because it returns the actual number of objects found.
The behavior and return values for most functions, such as nvm3_readData , nvm3_writeData , and so on should be self explanatory, while the nvm3_open is slightly different. nvm3_open will always try to recover from the previous state and continue without an error, if possible. In other words, if a valid NVM3 instance is established, nvm3_open will recover from brown outs and power cycles at any time in any operation and bring the system to a valid state where all pages and objects are in a known state and return success whenever possible. From this state, normal operation can resume. If nvm3_open returns an error, it's an indication of either a design or coding error, or that many of the NVM pages have been marked as BAD leaving insufficient space in the NVM to progress. Operation may not resume if nvm3_open returns an error.
- Note
- Because the nvm3_open may need to do recovery operations, the execution time will occasionally vary.
Storing objects in internal Flash
NVM3 has support for writing and reading objects in internal i.e., memory mapped Flash memory through the nvm3_hal_flash.c "driver". nvm3_hal_flash.c is using EMLIB functions to write and erase data, while using regular memory functions to read data from Flash.
The "driver" for internal Flash is selected by setting the halHandle in the nvm3_open initialization structure to point to nvm3_halFlashHandle.
Storing objects in external Flash
MNV3 has support for writing and reading objects in external Flash by using the nvm3_hal_extflash.c "driver". The nvm3_hal_extflash.c is using the Gecko Bootloader to read, write, and erase data in the Flash. By using this scheme, NVM3 does not deal with the hardware directly. All Flash communication must be handled by the bootloader. As long as the bootloader is configured and built for hardware, supports raw reads, writes and erases, NVM3 should be good to go.
nvm3_hal_extflash.c
is using the "raw" read and write functions. It does not use the slot feature supported by the Gecko Bootloader. Be careful when configuring the bootloader memory map to avoid conflicts between NVM3 and other usage, including slot configuration.
All data objects are encrypted using CCM encryption and counter base values are encrypted using AES encryption. NVM3 encryption keys are stored in internal Flash. Reading the external memory alone will not give access to the unencrypted data or counter values.
The "driver" for external Flash is selected by setting the halHandle in the nvm3_open initialization structure to point to nvm3_halExtFlashHandle.
NVM3 Libraries
The NVM3 comes with pre-compiled libraries for Cortex M0, M3, M4 and M33 compiled with either Arm GCC or IAR toolchains. In addition, there are versions with and without encryption support. The versions without encryption support can only be used to store data in internal Flash, while the ones with encryption support can be used for both internal and external Flash. Objects in internal Flash will never be encrypted, while objects in external Flash must always be encrypted.
Examples
Example 1 shows initialization, usage of data objects and repacking.
nvm3.h
"
nvm3_hal_flash.h
"
Example 2 shows initialization and usage of counter objects. The counter object uses a compact way of storing a 32-bit counter value while minimizing NVM wear.
nvm3.h
"
nvm3_hal_flash.h
"
Modules |
|
NVM3Hal | |
NVM3 HAL module.
|
|
NVM3Lock | |
NVM3 lock module.
|
|
Data Structures |
|
struct | nvm3_CacheEntry |
The datatype for each cache entry. The cache must be an array of these.
|
|
struct | nvm3_Init_t |
NVM3 initialization data.
|
|
Macros |
|
#define | ECODE_NVM3_ERR_ADDRESS_RANGE ( ECODE_EMDRV_NVM3_BASE | 0x00000017U) |
Address and size is out of range of available NVM.
|
|
#define | ECODE_NVM3_ERR_ALIGNMENT_INVALID ( ECODE_EMDRV_NVM3_BASE | 0x00000001U) |
Invalid data alignment.
|
|
#define | ECODE_NVM3_ERR_ENCRYPTION_DECODE ( ECODE_EMDRV_NVM3_BASE | 0x0000001CU) |
Encryption decode failed.
|
|
#define | ECODE_NVM3_ERR_ENCRYPTION_ENCODE ( ECODE_EMDRV_NVM3_BASE | 0x0000001BU) |
Encryption encode failed.
|
|
#define | ECODE_NVM3_ERR_ENCRYPTION_INIT ( ECODE_EMDRV_NVM3_BASE | 0x0000001AU) |
Initialization of encryption functions failed.
|
|
#define | ECODE_NVM3_ERR_ENCRYPTION_KEY_ERROR ( ECODE_EMDRV_NVM3_BASE | 0x0000001EU) |
Encryption key is missing.
|
|
#define | ECODE_NVM3_ERR_ENCRYPTION_NOT_SUPPORTED ( ECODE_EMDRV_NVM3_BASE | 0x0000001DU) |
Encryption is not supported.
|
|
#define | ECODE_NVM3_ERR_ERASE_COUNT_ERROR ( ECODE_EMDRV_NVM3_BASE | 0x00000016U) |
Erase counts are not valid.
|
|
#define | ECODE_NVM3_ERR_ERASE_FAILED ( ECODE_EMDRV_NVM3_BASE | 0x0000000EU) |
Erase failed.
|
|
#define | ECODE_NVM3_ERR_INIT_WITH_FULL_NVM ( ECODE_EMDRV_NVM3_BASE | 0x00000013U) |
The module was opened with a full NVM.
|
|
#define | ECODE_NVM3_ERR_INT_ADDR_INVALID ( ECODE_EMDRV_NVM3_BASE | 0x00000021U) |
Internal error trying to access invalid memory.
|
|
#define | ECODE_NVM3_ERR_INT_EMULATOR ( ECODE_EMDRV_NVM3_BASE | 0x00000024U) |
Internal Emulator error.
|
|
#define | ECODE_NVM3_ERR_INT_KEY_MISMATCH ( ECODE_EMDRV_NVM3_BASE | 0x00000022U) |
Key validation failure.
|
|
#define | ECODE_NVM3_ERR_INT_SIZE_ERROR ( ECODE_EMDRV_NVM3_BASE | 0x00000023U) |
Internal size mismatch error.
|
|
#define | ECODE_NVM3_ERR_INT_TEST ( ECODE_EMDRV_NVM3_BASE | 0x00000030U) |
Internal Test error.
|
|
#define | ECODE_NVM3_ERR_INT_WRITE_TO_NOT_ERASED ( ECODE_EMDRV_NVM3_BASE | 0x00000020U) |
Write to memory that is not erased.
|
|
#define | ECODE_NVM3_ERR_KEY_INVALID ( ECODE_EMDRV_NVM3_BASE | 0x0000000AU) |
Invalid key value.
|
|
#define | ECODE_NVM3_ERR_KEY_NOT_FOUND ( ECODE_EMDRV_NVM3_BASE | 0x0000000BU) |
Key not found.
|
|
#define | ECODE_NVM3_ERR_NO_VALID_PAGES ( ECODE_EMDRV_NVM3_BASE | 0x00000003U) |
Initialization aborted, no valid page found.
|
|
#define | ECODE_NVM3_ERR_NOT_OPENED ( ECODE_EMDRV_NVM3_BASE | 0x00000007U) |
The module has not been successfully opened.
|
|
#define | ECODE_NVM3_ERR_NVM_ACCESS ( ECODE_EMDRV_NVM3_BASE | 0x00000019U) |
A NVM function call was failing.
|
|
#define | ECODE_NVM3_ERR_NVM_NOT_AVAILABLE ( ECODE_EMDRV_NVM3_BASE | 0x00000018U) |
The NVM interface is not available like GBL for ext Flash.
|
|
#define | ECODE_NVM3_ERR_OBJECT_IS_NOT_A_COUNTER ( ECODE_EMDRV_NVM3_BASE | 0x0000000DU) |
Trying to access a counter object which is currently a data object.
|
|
#define | ECODE_NVM3_ERR_OBJECT_IS_NOT_DATA ( ECODE_EMDRV_NVM3_BASE | 0x0000000CU) |
Trying to access a data object which is currently a counter object.
|
|
#define | ECODE_NVM3_ERR_OBJECT_SIZE_NOT_SUPPORTED ( ECODE_EMDRV_NVM3_BASE | 0x00000005U) |
The object size is not supported.
|
|
#define | ECODE_NVM3_ERR_OPENED_WITH_OTHER_PARAMETERS ( ECODE_EMDRV_NVM3_BASE | 0x00000008U) |
The module has already been opened with other parameters.
|
|
#define | ECODE_NVM3_ERR_PAGE_SIZE_NOT_SUPPORTED ( ECODE_EMDRV_NVM3_BASE | 0x00000004U) |
The page size is not supported.
|
|
#define | ECODE_NVM3_ERR_PARAMETER ( ECODE_EMDRV_NVM3_BASE | 0x00000009U) |
Illegal parameter.
|
|
#define | ECODE_NVM3_ERR_RANDOM_NUMBER ( ECODE_EMDRV_NVM3_BASE | 0x0000001FU) |
Error in obtaining random number.
|
|
#define | ECODE_NVM3_ERR_READ_DATA_SIZE ( ECODE_EMDRV_NVM3_BASE | 0x00000011U) |
Trying to read with a length different from actual object size.
|
|
#define | ECODE_NVM3_ERR_READ_FAILED ( ECODE_EMDRV_NVM3_BASE | 0x00000012U) |
Error in the read operation.
|
|
#define | ECODE_NVM3_ERR_RESIZE_NOT_ENOUGH_SPACE ( ECODE_EMDRV_NVM3_BASE | 0x00000015U) |
Not enough NVM to complete resize.
|
|
#define | ECODE_NVM3_ERR_RESIZE_PARAMETER ( ECODE_EMDRV_NVM3_BASE | 0x00000014U) |
Illegal parameter.
|
|
#define | ECODE_NVM3_ERR_SIZE_TOO_SMALL ( ECODE_EMDRV_NVM3_BASE | 0x00000002U) |
Not enough NVM memory specified.
|
|
#define | ECODE_NVM3_ERR_STORAGE_FULL ( ECODE_EMDRV_NVM3_BASE | 0x00000006U) |
No more NVM space available.
|
|
#define | ECODE_NVM3_ERR_WRITE_DATA_SIZE ( ECODE_EMDRV_NVM3_BASE | 0x0000000FU) |
The object is too large.
|
|
#define | ECODE_NVM3_ERR_WRITE_FAILED ( ECODE_EMDRV_NVM3_BASE | 0x00000010U) |
Error in the write operation.
|
|
#define | ECODE_NVM3_OK ( ECODE_OK ) |
Success return value.
|
|
#define | NVM3_DEFINE_SECTION_INIT_DATA (name, flashHandle) |
NVM3 initialization data helper macro to be used with
NVM3_DEFINE_SECTION_STATIC_DATA()
. The
name
parameter in both macros must match.
Call nvm3_open() after this macro to initialize NVM3. See Examples section for code examples. |
|
#define | NVM3_DEFINE_SECTION_STATIC_DATA (name, nvmSize, cacheSize) |
NVM3 static data definition helper macro for applications using linker script placement of the NVM memory area. This macro exports the section 'name'_section to the linker. The user must place the section name in a linker script at an address aligned with the page size of the underlying memory system. The size of the NVM area must be a multiple of the page size.
This macro also allocates the static NVM3 cache. Use this macro with NVM3_DEFINE_SECTION_INIT_DATA() to create initialization data for nvm3_open() . See Examples section for usage examples. |
|
#define | NVM3_KEY_INVALID 0xFFFFFFFFU |
Invalid key identifier.
|
|
#define | NVM3_KEY_MASK ((1U << NVM3_KEY_SIZE) - 1U) |
Unique object key identifier mask.
|
|
#define | NVM3_KEY_MAX NVM3_KEY_MASK |
Maximum object key value.
|
|
#define | NVM3_KEY_MIN 0U |
Minimum object key value.
|
|
#define | NVM3_KEY_SIZE 20U |
Unique object key identifier size in number of bits.
|
|
#define | NVM3_MAX_OBJECT_SIZE NVM3_MAX_OBJECT_SIZE_DEFAULT |
#define | NVM3_MAX_OBJECT_SIZE_DEFAULT 1900U |
The default value for the maximum object size.
|
|
#define | NVM3_MAX_OBJECT_SIZE_HIGH_LIMIT 4096U |
The maximum value for the maximum object size.
|
|
#define | NVM3_MAX_OBJECT_SIZE_LOW_LIMIT 204U |
The minimum value for the maximum object size.
|
|
#define | NVM3_MIN_FRAGMENT_COUNT (2U) |
#define | NVM3_MIN_PAGE_SIZE 512U |
Definitions of NVM3 constraints.
|
|
#define | NVM3_OBJECTTYPE_COUNTER 1U |
The object is a counter.
|
|
#define | NVM3_OBJECTTYPE_DATA 0U |
The object is data.
|
|
Typedefs |
|
typedef struct nvm3_CacheEntry | nvm3_CacheEntry_t |
The datatype for each cache entry. The cache must be an array of these.
|
|
typedef uint32_t | nvm3_ObjectKey_t |
The data type for object keys. Only the 20 least significant bits are used.
|
|
Functions |
|
Ecode_t | nvm3_close (nvm3_Handle_t *h) |
Close the NVM3 driver instance.
|
|
__STATIC_INLINE size_t | nvm3_countDeletedObjects (nvm3_Handle_t *h) |
Count deleted objects.
|
|
__STATIC_INLINE size_t | nvm3_countObjects (nvm3_Handle_t *h) |
Count valid objects.
|
|
Ecode_t | nvm3_deleteObject (nvm3_Handle_t *h, nvm3_ObjectKey_t key) |
Delete an object from NVM.
|
|
size_t | nvm3_enumDeletedObjects (nvm3_Handle_t *h, nvm3_ObjectKey_t *keyListPtr, size_t keyListSize, nvm3_ObjectKey_t keyMin, nvm3_ObjectKey_t keyMax) |
Create a list of object keys for deleted objects in NVM.
|
|
size_t | nvm3_enumObjects (nvm3_Handle_t *h, nvm3_ObjectKey_t *keyListPtr, size_t keyListSize, nvm3_ObjectKey_t keyMin, nvm3_ObjectKey_t keyMax) |
Create a list of object keys for valid objects in NVM.
|
|
Ecode_t | nvm3_eraseAll (nvm3_Handle_t *h) |
Delete all objects in NVM.
|
|
Ecode_t | nvm3_getEraseCount (nvm3_Handle_t *h, uint32_t *eraseCnt) |
Get the number of page erases of the most erased page in the NVM area since the first initialization.
|
|
Ecode_t | nvm3_getObjectInfo (nvm3_Handle_t *h, nvm3_ObjectKey_t key, uint32_t *type, size_t *len) |
Find the type and size of an object in NVM.
|
|
Ecode_t | nvm3_incrementCounter (nvm3_Handle_t *h, nvm3_ObjectKey_t key, uint32_t *newValue) |
Increment a counter object value by 1 and read out optionally.
|
|
Ecode_t | nvm3_open (nvm3_Handle_t *h, const nvm3_Init_t *i) |
Open an NVM3 driver instance, which is represented by a handle keeping information about the state. A successful open will initialize the handle and the cache with information about the objects already in the NVM-memory. Several NVM3 instances using different handles must NOT overlap NVM-memory. To change some of the parameters, first call
nvm3_close
and then
nvm3_open
.
|
|
Ecode_t | nvm3_readCounter (nvm3_Handle_t *h, nvm3_ObjectKey_t key, uint32_t *value) |
Read a counter value from NVM.
|
|
Ecode_t | nvm3_readData (nvm3_Handle_t *h, nvm3_ObjectKey_t key, void *value, size_t maxLen) |
Read the object data identified with a given key from NVM.
|
|
Ecode_t | nvm3_repack (nvm3_Handle_t *h) |
Execute a repack operation. NVM3 will copy data or erase pages when repacking is needed. Calling
nvm3_repack()
may block access to the non-volatile memory for up to one page erasure time plus an small execution overhead. The exact worst-case timing characteristics can be found in the data sheet for the part.
|
|
bool | nvm3_repackNeeded (nvm3_Handle_t *h) |
Check the internal status of NVM3 and return true if a repack operation is required. The application must call
nvm3_repack()
to perform the actual repack operation.
|
|
Ecode_t | nvm3_resize (nvm3_Handle_t *h, nvm3_HalPtr_t newAddr, size_t newSize) |
Resize the NVM area used by an open NVM3 instance. The area can be resized by changing the start or end address either up or down in memory. Because the input parameters to NVM3 are start address and size, users should be cautious. Either move the start address up or down in memory and adjust the size accordingly to keep the end address, or keep the address and change the size only. It is not possible to resize the area by doing changes in both ends of the NVM address range at the same time. If the resize operation returns
ECODE_NVM3_OK
, the instance is still open and can be used to access objects in the resized NVM. If the resize operation fails, the instance will still be open but with unchanged size.
|
|
void | nvm3_setEraseCount (uint32_t eraseCnt) |
Set the page erase count. Normally, the application should not be concerned with the erase count value. If NVM3 is substituting a previous solution, it is possible to transfer the erase count to NVM3 when initializing the NVM for the first time. The erase count must be set before the
nvm3_open
is called and will only take effect if the NVM is completely erased or contains unknown data to NVM3. In that case, all pages will be initialized with the supplied erase count. After
nvm3_open
is called, the value will be consumed and will have no effect on further calls to
nvm3_open
.
|
|
Ecode_t | nvm3_writeCounter (nvm3_Handle_t *h, nvm3_ObjectKey_t key, uint32_t value) |
Store a counter in NVM.
|
|
Ecode_t | nvm3_writeData (nvm3_Handle_t *h, nvm3_ObjectKey_t key, const void *value, size_t len) |
Write the object value identified with the key to NVM. If the data object exist with the same lenght, its old content is compared with the new and only if the new content is different from the old it will be written.
|
|
Variables |
|
uint8_t | nvm3_ccmBuf [] |
nvm3_Obj_t | nvm3_internalObjectHandleA |
A variable used by the NVM3 functions.
|
|
nvm3_Obj_t | nvm3_internalObjectHandleB |
A variable used by the NVM3 functions.
|
|
nvm3_Obj_t | nvm3_internalObjectHandleC |
A variable used by the NVM3 functions.
|
|
nvm3_Obj_t | nvm3_internalObjectHandleD |
A variable used by the NVM3 functions.
|
|
const uint8_t | nvm3_maxFragmentCount |
A variable that must contain the maximum number of object fragments.
|
|
const size_t | nvm3_objHandleSize |
Macro Definition Documentation
#define NVM3_DEFINE_SECTION_INIT_DATA | ( |
name,
|
|
flashHandle
|
|||
) |
NVM3 initialization data helper macro to be used with
NVM3_DEFINE_SECTION_STATIC_DATA()
. The
name
parameter in both macros must match.
Call
nvm3_open()
after this macro to initialize NVM3. See
Examples
section for code examples.
Definition at line
178
of file
nvm3.h
.
#define NVM3_DEFINE_SECTION_STATIC_DATA | ( |
name,
|
|
nvmSize,
|
|||
cacheSize
|
|||
) |
nvm3.h:204
NVM3 static data definition helper macro for applications using linker script placement of the NVM memory area. This macro exports the section 'name'_section to the linker. The user must place the section name in a linker script at an address aligned with the page size of the underlying memory system. The size of the NVM area must be a multiple of the page size.
This macro also allocates the static NVM3 cache.
Use this macro with
NVM3_DEFINE_SECTION_INIT_DATA()
to create initialization data for
nvm3_open()
. See
Examples
section for usage examples.
Definition at line
138
of file
nvm3.h
.
#define NVM3_MIN_PAGE_SIZE 512U |
Definitions of NVM3 constraints.
The minimum page size supported
Definition at line
112
of file
nvm3.h
.
Function Documentation
Ecode_t nvm3_close | ( | nvm3_Handle_t * |
h
|
) |
Close the NVM3 driver instance.
- Parameters
-
[in] h
A pointer to the NVM3 driver handle.
- Returns
- ECODE_NVM3_OK is always returned.
__STATIC_INLINE size_t nvm3_countDeletedObjects | ( | nvm3_Handle_t * |
h
|
) |
Count deleted objects.
- Parameters
-
[in] h
A pointer to an NVM3 driver handle.
- Returns
- The number of deleted objects.
Definition at line
716
of file
nvm3.h
.
References nvm3_enumDeletedObjects() , NVM3_KEY_MAX , and NVM3_KEY_MIN .
__STATIC_INLINE size_t nvm3_countObjects | ( | nvm3_Handle_t * |
h
|
) |
Count valid objects.
- Parameters
-
[in] h
A pointer to an NVM3 driver handle.
- Returns
- The number of valid objects.
Definition at line
701
of file
nvm3.h
.
References nvm3_enumObjects() , NVM3_KEY_MAX , and NVM3_KEY_MIN .
Ecode_t nvm3_deleteObject | ( | nvm3_Handle_t * |
h,
|
nvm3_ObjectKey_t |
key
|
||
) |
Delete an object from NVM.
- Parameters
-
[in] h
A pointer to an NVM3 driver handle. [in] key
A 20-bit object identifier.
- Returns
- ECODE_NVM3_OK on success or a NVM3 Ecode_t on failure.
size_t nvm3_enumDeletedObjects | ( | nvm3_Handle_t * |
h,
|
nvm3_ObjectKey_t * |
keyListPtr,
|
||
size_t |
keyListSize,
|
||
nvm3_ObjectKey_t |
keyMin,
|
||
nvm3_ObjectKey_t |
keyMax
|
||
) |
Create a list of object keys for deleted objects in NVM.
- Note
- The function nvm3_countDeletedObjects() is also provided to count the number of deleted objects.
- Parameters
-
[in] h
A pointer to an NVM3 driver handle. [out] keyListPtr
A pointer to a buffer for the key list. [in] keyListSize
The number of elements in the key list buffer. If the keyListSize = 0, the keyListPtr
can be NULL and the function will return the total number of objects.[in] keyMin
The lower search key. Set to NVM3_KEY_MIN to match all keys. [in] keyMax
The upper search key. Set to NVM3_KEY_MAX to match all keys.
- Returns
-
The number of keys written to the key list. This value is less than or equal to
keyListSize
. If thekeyListSize
= 0, the function will return the total number of objects matching the key Min - Max pattern.
Referenced by nvm3_countDeletedObjects() .
size_t nvm3_enumObjects | ( | nvm3_Handle_t * |
h,
|
nvm3_ObjectKey_t * |
keyListPtr,
|
||
size_t |
keyListSize,
|
||
nvm3_ObjectKey_t |
keyMin,
|
||
nvm3_ObjectKey_t |
keyMax
|
||
) |
Create a list of object keys for valid objects in NVM.
- Note
- The function nvm3_countObjects() is also provided to count the number of valid objects.
- Parameters
-
[in] h
A pointer to an NVM3 driver handle. [out] keyListPtr
A pointer to a buffer for the key list. [in] keyListSize
The number of elements in the key list buffer. If the keyListSize = 0, the keyListPtr
can be NULL and the function will return the total number of objects.[in] keyMin
The lower search key. Set to NVM3_KEY_MIN to match all keys. [in] keyMax
The upper search key. Set to NVM3_KEY_MAX to match all keys.
- Returns
-
The number of keys written to the key list. This value is less than or equal to
keyListSize
. If thekeyListSize
= 0, the function will return the total number of objects matching the key Min - Max pattern.
Referenced by nvm3_countObjects() .
Ecode_t nvm3_eraseAll | ( | nvm3_Handle_t * |
h
|
) |
Delete all objects in NVM.
- Note
- Users don't need to call this function to get NVM3 into an initial valid state.
- Warning
- The execution time depends on the configured NVM size and may therefore be significant.
- Parameters
-
[in] h
A pointer to an NVM3 driver handle.
- Returns
- ECODE_NVM3_OK on success or a NVM3 Ecode_t on failure.
Ecode_t nvm3_getEraseCount | ( | nvm3_Handle_t * |
h,
|
uint32_t * |
eraseCnt
|
||
) |
Get the number of page erases of the most erased page in the NVM area since the first initialization.
- Note
- Except for pages marked as bad, pages will have an erase count equal to the most erased or one less because of the wear leveling algorithm.
- Parameters
-
[in] h
A pointer to an NVM3 driver handle. [in] eraseCnt
A pointer to the location where the NVM3 shall place the page erasure counter value.
- Returns
- ECODE_NVM3_OK on success or a NVM3 Ecode_t on failure.
Ecode_t nvm3_getObjectInfo | ( | nvm3_Handle_t * |
h,
|
nvm3_ObjectKey_t |
key,
|
||
uint32_t * |
type,
|
||
size_t * |
len
|
||
) |
Find the type and size of an object in NVM.
- Parameters
-
[in] h
A pointer to an NVM3 driver handle. [in] key
A 20-bit object identifier. [out] type
A pointer to the location where NVM3 shall write the object type. The type can be either NVM3_OBJECTTYPE_DATA or NVM3_OBJECTTYPE_COUNTER . [out] len
A pointer to the location where NVM3 writes the object size.
- Returns
- ECODE_NVM3_OK on success or a NVM3 Ecode_t on failure.
Ecode_t nvm3_incrementCounter | ( | nvm3_Handle_t * |
h,
|
nvm3_ObjectKey_t |
key,
|
||
uint32_t * |
newValue
|
||
) |
Increment a counter object value by 1 and read out optionally.
- Parameters
-
[in] h
A pointer to an NVM3 driver handle. [in] key
A 20-bit object identifier. [out] newValue
A pointer to the counter readout location. The counter is incremented before the value is written to this location. Set this value to NULL to ignore readout.
- Returns
- ECODE_NVM3_OK on success or a NVM3 Ecode_t on failure.
Ecode_t nvm3_open | ( | nvm3_Handle_t * |
h,
|
const nvm3_Init_t * |
i
|
||
) |
Open an NVM3 driver instance, which is represented by a handle keeping information about the state. A successful open will initialize the handle and the cache with information about the objects already in the NVM-memory. Several NVM3 instances using different handles must NOT overlap NVM-memory. To change some of the parameters, first call nvm3_close and then nvm3_open .
- Note
- The driver handle must be initialized to zero before it is used the first time. The nvm3_open can be called repeatedly with the same handle and initialization data. In that case, the next calls will be regarded as a "no operation" and the function will return the same status as the previous call.
- Parameters
-
[out] h
A pointer to an NVM3 driver handle. [in] i
A pointer to NVM3 driver initialization data.
- Returns
- ECODE_NVM3_OK on success and a NVM3 Ecode_t on failure.
Ecode_t nvm3_readCounter | ( | nvm3_Handle_t * |
h,
|
nvm3_ObjectKey_t |
key,
|
||
uint32_t * |
value
|
||
) |
Read a counter value from NVM.
- Parameters
-
[in] h
A pointer to an NVM3 driver handle. [in] key
A 20-bit object identifier. [out] value
A pointer to the counter location. The read function will copy the counter value to this location.
- Returns
- ECODE_NVM3_OK on success or a NVM3 Ecode_t on failure.
Ecode_t nvm3_readData | ( | nvm3_Handle_t * |
h,
|
nvm3_ObjectKey_t |
key,
|
||
void * |
value,
|
||
size_t |
maxLen
|
||
) |
Read the object data identified with a given key from NVM.
- Parameters
-
[in] h
A pointer to an NVM3 driver handle. [in] key
A 20-bit object identifier. [out] value
A pointer to the application data buffer. The read function will copy data to this location. [in] maxLen
The maximum object size in number of bytes. The nvm3_getObjectInfo() function can be used to find the actual size.
- Returns
- ECODE_NVM3_OK on success or a NVM3 Ecode_t on failure.
Ecode_t nvm3_repack | ( | nvm3_Handle_t * |
h
|
) |
Execute a repack operation. NVM3 will copy data or erase pages when repacking is needed. Calling nvm3_repack() may block access to the non-volatile memory for up to one page erasure time plus an small execution overhead. The exact worst-case timing characteristics can be found in the data sheet for the part.
- Note
- Calling nvm3_repack() is not mandatory because the functions that write data to NVM will trigger a repack if needed. Because a repack operation may be time consuming, the application may want to be in control of when repacking occurs by calling this function.
More information about the repack operation can be found in the Repacking section.
- Parameters
-
[in] h
A pointer to an NVM3 driver handle.
- Returns
- ECODE_NVM3_OK on success or a NVM3 Ecode_t on failure.
bool nvm3_repackNeeded | ( | nvm3_Handle_t * |
h
|
) |
Check the internal status of NVM3 and return true if a repack operation is required. The application must call nvm3_repack() to perform the actual repack operation.
- Parameters
-
[in] h
A pointer to an NVM3 driver handle.
- Returns
- true if repacking is needed, false if repacking is not needed.
Ecode_t nvm3_resize | ( | nvm3_Handle_t * |
h,
|
nvm3_HalPtr_t |
newAddr,
|
||
size_t |
newSize
|
||
) |
Resize the NVM area used by an open NVM3 instance. The area can be resized by changing the start or end address either up or down in memory. Because the input parameters to NVM3 are start address and size, users should be cautious. Either move the start address up or down in memory and adjust the size accordingly to keep the end address, or keep the address and change the size only. It is not possible to resize the area by doing changes in both ends of the NVM address range at the same time. If the resize operation returns ECODE_NVM3_OK , the instance is still open and can be used to access objects in the resized NVM. If the resize operation fails, the instance will still be open but with unchanged size.
- Note
- It is possible to decrease the NVM area to a new size that is not capable of keeping the already stored objects. The result is loss of data.
- Parameters
-
[in] h
A pointer to an NVM3 driver handle. [in] newAddr
The start address of the NVM after resize. [in] newSize
The size of the NVM after resize.
- Returns
- ECODE_NVM3_OK on success or a NVM3 Ecode_t on failure.
void nvm3_setEraseCount | ( | uint32_t |
eraseCnt
|
) |
Set the page erase count. Normally, the application should not be concerned with the erase count value. If NVM3 is substituting a previous solution, it is possible to transfer the erase count to NVM3 when initializing the NVM for the first time. The erase count must be set before the nvm3_open is called and will only take effect if the NVM is completely erased or contains unknown data to NVM3. In that case, all pages will be initialized with the supplied erase count. After nvm3_open is called, the value will be consumed and will have no effect on further calls to nvm3_open .
- Parameters
-
[in] eraseCnt
The erase count.
Ecode_t nvm3_writeCounter | ( | nvm3_Handle_t * |
h,
|
nvm3_ObjectKey_t |
key,
|
||
uint32_t |
value
|
||
) |
Store a counter in NVM.
- Parameters
-
[in] h
A pointer to an NVM3 driver handle. [in] key
A 20-bit object identifier. [in] value
The counter value to write.
- Returns
- ECODE_NVM3_OK on success or a NVM3 Ecode_t on failure.
Ecode_t nvm3_writeData | ( | nvm3_Handle_t * |
h,
|
nvm3_ObjectKey_t |
key,
|
||
const void * |
value,
|
||
size_t |
len
|
||
) |
Write the object value identified with the key to NVM. If the data object exist with the same lenght, its old content is compared with the new and only if the new content is different from the old it will be written.
- Parameters
-
[in] h
A pointer to an NVM3 driver handle. [in] key
A 20-bit object identifier. [in] value
A pointer to the object data to write. [in] len
The size of the object data in number of bytes.
- Returns
- ECODE_NVM3_OK on success or a NVM3 Ecode_t on failure.