NVS

Introduction

Non-Volatile Storage (NVS) is a driver that provides a way to store data in a non-volatile memory, such as flash memory. This allows applications to save data that needs to persist across device reboots or power cycles. NVS uses low level driverlib APIs to read, write and erase data on flash memory. It is commonly used for storing configuration settings, calibration data, user preferences, and other small pieces of information that need to be retained even when the device is powered off. NVS is designed to be lightweight and efficient, making it suitable for use in embedded systems with limited resources.

NVOCMP Module

Non-Volatile On Chip Multiple Page (NVOCMP) is a module that provides an abstraction layer for managing non-volatile storage (NVS) in embedded systems. It is designed to handle the complexities of writing and reading data to and from flash. The NVOCMP module provides a set of APIs that allow developers to easily read, write, and manage data in NVS without needing to deal with the low-level details of the memory hardware. NVOCMP offers the following features:

  • Thread safe access to non volatile memory
  • ID based system that decouples a storage item from its address in memory
  • Space efficient storage with automatic compaction
  • Power loss tolerant data preservation

Non Volatile Interface (NVINT)

The NVINTF is an abstraction layer that defines a common set of APIs for interacting with NVOCMP using an ID system. This common set of APIs allow for new methods of NV storage to be implemented without changing the API calls in the stack and application. The ID system is most efficient because it decouples the data stored from its address in flash. This is necessary because flash banks must have the entire sector erased before writing again. Using the ID system, when an NV item needs to be updated, it can simply be invalidated and stored again at a different address. Once the NV system becomes full of unused items, a compaction will occur. A compaction is the removal of unused items.

This interface is defined in nvint.h header file. The NVINTF is not intended to be changed by the customer, but instead used as is.

The implementation of the NVINTF is done in the NVOCMP module. This software relies on several layers which are illustrated below.

../_images/nvintf_architecture.png

NVOCMP Operation

The NVOCMP module implements a non-volatile memory system that utilizes multiple consecutive pages of Flash memory. After initialization, all pages except one are “active” and the remaining one page is available for “compaction” when the active pages do not have enough empty space for data write operation. Compaction can occur “just in time” during a data write operation or “on demand” at application request. The compaction process is designed to survive a power cycle before it completes. It will resume where it was interrupted and complete the process. The number of NV pages can be set by the NVOCMP_NVPAGES preprocessor define. If this is not set, it will default to 2.

Each flash page contains a “page header” which indicates its current state. The page header is located at the first byte of the flash page. Following the page header is the “compact header”, which indicates the flash page’s compaction state. The remainder of the flash page contains NV data items which are packed together.

Each NV data item is unique and has two parts:

  1. A data block which is stored first (lower memory address)
  2. An item header following the data block (higher memory address)

The item header (defined by NVOCMP_itemHdr_t) contains status information required to traverse packed data items in the flash page. An example of the NV item memory layout storing a single byte of data is illustrated below.

../_images/nvintf_header.png

NV Item Header breakdown:

Field Size (bits) Purpose
System ID 6 Indicates the system component identifier
Item ID 10 Indicates the item data identifier
Sub ID 10 Identifier of the sub-data related to the NV item
Length 12 Length of the NV item data in bytes
CRC 8 CRC checksum of the NV item
Status Bits 2 Indicates CRC integrity and if item is active
Signature 8 Used to detect presence of a NV item in flash

For each NV item that is added or updated in NV storage, the item is written to the next lowest available memory address in the active flash page. If the NV item is being updated, the old NV item will be marked as inactive. Inactive items are removed from memory when a memory compaction takes place.

For more information, see the API documentation in nvocmp.h and the design description in nvocmp_cc35xx.c.

NVOCMP APIs

The interface to NVOCMP is function pointer based. The function pointers are defined in the NVINTF_nvFuncts_t structure.

//! Structure of NV API function pointers
typedef struct nvintf_nvfuncts_t
{
    //! Initialization function
    NVINTF_initNV initNV;
    //! Compact NV function
    NVINTF_compactNV compactNV;
    //! Create item function
    NVINTF_createItem createItem;
    //! Update item function
    NVINTF_updateItem updateItem;
    //! Delete NV item function
    NVINTF_deleteItem deleteItem;
    //! Read item function based on ID
    NVINTF_readItem readItem;
    //! Read item function based on Content
    NVINTF_readContItem readContItem;
    //! Write item function
    NVINTF_writeItem writeItem;
    //! Get item length function
    NVINTF_getItemLen getItemLen;
    //! Iterator Like doNext function
    NVINTF_doNext doNext;
    //! Lock item function
    NVINTF_lockNV lockNV;
    //! Unlock item function
    NVINTF_unlockNV unlockNV;
    //! Expect compact function
    NVINTF_expectComp expectComp;
    //! Erase NV function
    NVINTF_eraseNV eraseNV;
    //! Get Free NV function
    NVINTF_getFreeNV getFreeNV;
#ifdef ENABLE_SANITY_CHECK
    //! Sanity Check function
    NVINTF_sanityCheck sanityCheck;
#endif
} NVINTF_nvFuncts_t;

Code examples

The following code snippet illustrates how to initialize the NVOCMP module and create, read, update, and delete an NV item.

#include "nv/nvint.h"
#include "nv/nvocmp.h"

// Defines for Item ID structure
// Change to appropriate values for the application
#define APPLICATION_SYSID   100
#define APPLICATION_ITEMID  2
#define APPLICATION_SUBID   4

static NVINTF_nvFuncts_t NVIF;
NVINTF_itemID_t item;
char payloadRead[256];
char payloadWrite[] = "Hello, NVS!";
uint8_t ret;

NVOCMP_loadApiPtrs(&NVIF);
if (NVIF.initNV) {

    // Set appropriate values for Item ID structure
    item.systemID = APPLICATION_SYSID;
    item.itemID = APPLICATION_ITEMID;
    item.subID = APPLICATION_SUBID;

    ret=NVIF.initNV(NULL);

    ret = NVIF.readItem(item, 0, strlen(payloadWrite), payloadRead);
    if (ret == NVINTF_SUCCESS) {
        // Item is successfully read.
        // Overwrite the item
        ret = NVIF.writeItem(item, strlen(payloadWrite), payloadWrite);
    } else {
        // Item does not exist, create it
        ret = NVIF.createItem(item, strlen(payloadWrite), payloadWrite);
    }

    // To delete an item
    ret = NVIF.deleteItem(item);
}