NVMEMDRV

Detailed Description

(DEPRECATED) NVM Non-volatile Memory Wear-Leveling Driver

Deprecated:
This driver is deprecated and marked for removal in a later release. New code should use NVM3.


Introduction

This driver allows you to store application data in NVM. The driver supports wear leveling to maximize the lifetime of the underlying NVM system. CCITT CRC16 is used for data validation.

The size and layout of the data objects to be managed by this driver must be known at compile-time. Object may be composed of any primitive data type (8, 16 or 32-bit).

This driver consists of the files nvm.c, nvm.h and nvm_hal.h. Additionally, a implementation of nvm_hal.c is required for the specific NVM system to be used. A implementation of nvm_hal.c for EFM32/EZR32/EFR32 Flash memory is included with this driver. Driver configuration parameters and specification of the data objects are located in nvm_config.c and nvm_config.h.


Configuration Options

The files nvm_config.c and nvm_config.h contains compile-time configuration parameters and a specification of the user data structures to be managed by the driver, and how these are mapped to pages. A page can be of type normal or wear. A wear page can only contain a single object, but they provide better performance and drastically increase the lifetime of the memory if the object is known to have a low update frequency.

nvm_config.c implements an user data example. The arrays colorTable, coefficientTable, etc are defined and assigned to NVM pages. A pointer to each page is assigned to the page table nvmPages. The page table also contain a page type specifier. A page is either of type nvmPageTypeNormal or nvmPageTypeWear. Pages of type nvmPageTypeNormal are written to the unused page with the lowest erase count. For pages of type nvmPageTypeWear, the data is first attempted fitted in a already used page. If this fails, then a a new page is selected based on the lowest erase count. Pages of type nvmPageTypeWear can only contain one data object.

In nvm_config.h, driver features can be enabled or disabled. The following parameters may require special attention:

  • NVM_MAX_NUMBER_OF_PAGES: Maximum number of NVM pages allocated to the driver.
  • NVM_PAGES_SCRATCH: Configure extra pages to allocate for data security and wear leveling.
  • NVM_PAGE_SIZE: Page size for the NVM system. Default is the size of the flash.

Users have to be aware of the following limitations:

  • Maximum 254 objects in a page.
  • Maximum 256 pages allocated to the driver. The default is 32 pages.

Note that the different EFM32/EZR32/EFR32 families have different page sizes. Please refer to the reference manual for details.


The API

This section contain brief descriptions of the functions defined by the API. You will find detailed information on input and output parameters and return values by clicking on the hyperlinked function names. Most functions return an error code or ECODE_EMDRV_NVM_OK is returned on success. See ecode.h and nvm.h for other error codes.

Your application code must include one header file: nvm.h.

The application may define the data objects allocated in RAM (and defined in nvm_config.c) as extern if direct access to these objects is required, eg:

 extern uint32_t colorTable[];

The driver requires that the NVM system is erased by calling NVM_Erase() before the driver initialization function NVM_Init() is called. NVM_Init() requires a parameter to the configuration data. A pointer to the configuration data can be obtained by calling NVM_ConfigGet().

NVM_Write() takes two parameters, a page ID and a object ID. These two parameters must correspond to the definition of the user data in nvm_config.c. For example, colorTable is assigned to page 1 in the example version of nvm_config.c. To write the data in colorTable to NVM, call NVM_Write(MY_PAGE_1, COLOR_TABLE_ID).

NVM_Read() reads the a data object or an entire page in NVM back to the structures defined for the page in RAM.


Example

#include "em_chip.h"
#include "em_gpio.h"
#include "nvm.h"

// Data object extern declarations matching the example data defined in nvm_config.c
extern uint32_t colorTable[];
extern uint8_t coefficientTable[];
extern uint8_t primeNumberTable[];
extern uint16_t bonusTable[];
extern uint8_t privateKeyTable[];
extern uint16_t transformTable[];
extern int32_t safetyTable[];
extern uint8_t bigEmptyTable[450];
extern int8_t smallNegativeTable[];
extern uint16_t shortPositiveTable[];
extern uint32_t singleVariable;

// Object and page IDs maching the data defined in nvm_config.c
typedef enum {
  COLOR_TABLE_ID,
  COEFFICIENT_TABLE_ID,
  PRIME_NUMBER_TABLE_ID,
  BONUS_TABLE_ID,
  PRIVATE_KEY_TABLE_ID,
  TRANSFORM_TABLE_ID,
  SINGLE_VARIABLE_ID,
  SAFETY_TABLE_ID,
  BIG_EMPTY_TABLE_ID,
  SMALL_NEGATIVE_TABLE_ID,
  SHORT_POSITIVE_TABLE_ID
} NVM_Object_Ids;

typedef enum {
  MY_PAGE_1,
  MY_PAGE_2,
  MY_PAGE_3,
  MY_PAGE_4,
  MY_PAGE_5,
  MY_PAGE_6,
} NVM_Page_Ids;

CHIP_Init();

// Erase all pages managed by the driver and set the erase count
// for each page to 0. To retain the erase count, pass NVM_ERASE_RETAINCOUNT.
NVM_Erase(0);

if (ECODE_EMDRV_NVM_NO_PAGES_AVAILABLE == NVM_Init(NVM_ConfigGet()) {
  // The driver could not initialize any pages
}

// Write all pages to NVM
NVM_Write(MY_PAGE_1, NVM_WRITE_ALL_CMD));
NVM_Write(MY_PAGE_2, NVM_WRITE_ALL_CMD));
NVM_Write(MY_PAGE_3, NVM_WRITE_ALL_CMD));
NVM_Write(MY_PAGE_4, NVM_WRITE_ALL_CMD));
NVM_Write(MY_PAGE_5, NVM_WRITE_ALL_CMD));
NVM_Write(MY_PAGE_6, NVM_WRITE_ALL_CMD));

// Set some data elements to 0
for (i = 0; i < 4; i++) {
  bonusTable[i] = 0;
  primeNumberTable[i] = 0;
}

// Read back from NVM and check
NVM_Read(MY_PAGE_1, NVM_READ_ALL_CMD));
NVM_Read(MY_PAGE_4, PRIME_NUMBER_TABLE_ID));

for (i = 0; i < 4; i++) {
  if (bonusTable[i] == 0) {
    // Should not happen because bonusTable[] in NVM should contain the
    // constants set in nvm_config.c
  }
  if (primeNumberTable[i] == 0) {
    // Should not happen because primeNumberTable[] in NVM should contain the
    // constants set in nvm_config.c
  }
}

Macros

#define ECODE_EMDRV_NVM_ADDR_INVALID   (ECODE_EMDRV_NVM_BASE | 0x00000001)
 Invalid address.
 
#define ECODE_EMDRV_NVM_ALIGNMENT_INVALID   (ECODE_EMDRV_NVM_BASE | 0x00000002)
 Invalid data alignment.
 
#define ECODE_EMDRV_NVM_DATA_INVALID   (ECODE_EMDRV_NVM_BASE | 0x00000003)
 Invalid input data or format.
 
#define ECODE_EMDRV_NVM_ERROR   (ECODE_EMDRV_NVM_BASE | 0x00000007)
 General error.
 
#define ECODE_EMDRV_NVM_NO_PAGES_AVAILABLE   (ECODE_EMDRV_NVM_BASE | 0x00000005)
 Initialization didn't find any pages available to allocate.
 
#define ECODE_EMDRV_NVM_OK   (ECODE_OK)
 Success return value.
 
#define ECODE_EMDRV_NVM_PAGE_INVALID   (ECODE_EMDRV_NVM_BASE | 0x00000006)
 Could not find the page specified.
 
#define ECODE_EMDRV_NVM_WRITE_LOCK   (ECODE_EMDRV_NVM_BASE | 0x00000004)
 A write is currently in progress.
 
#define NVM_ERASE_RETAINCOUNT   0xffffffffUL
 
#define NVM_PAGE_TERMINATION   { NULL, 0, (NVM_Object_Ids) 0 }
 
#define NVM_READ_ALL_CMD   0xff
 
#define NVM_WRITE_ALL_CMD   0xff
 
#define NVM_WRITE_NONE_CMD   0xfe
 

Functions

Ecode_t NVM_Erase (uint32_t eraseCount)
 Erase the entire allocated NVM area.
 
Ecode_t NVM_Init (NVM_Config_t const *nvmConfig)
 Initialize the NVM manager.
 
Ecode_t NVM_Read (uint16_t pageId, uint8_t objectId)
 Read an object or an entire page.
 
Ecode_t NVM_Write (uint16_t pageId, uint8_t objectId)
 Write an object or a page.
 

Macro Definition Documentation

#define ECODE_EMDRV_NVM_OK   (ECODE_OK)

Success return value.

Return/error codes

Definition at line 45 of file nvm.h.

Referenced by NVM_Erase(), NVM_Init(), NVM_Read(), and NVM_Write().

#define NVM_ERASE_RETAINCOUNT   0xffffffffUL

Retains the registered erase count when eraseing a page.

Definition at line 62 of file nvm.h.

Referenced by NVM_Erase().

#define NVM_PAGE_TERMINATION   { NULL, 0, (NVM_Object_Ids) 0 }

Structure defining end of pages table.

Definition at line 65 of file nvm.h.

#define NVM_READ_ALL_CMD   0xff

All objects are read to RAM.

Definition at line 59 of file nvm.h.

Referenced by NVM_Read().

#define NVM_WRITE_ALL_CMD   0xff

All objects are written from RAM.

Definition at line 55 of file nvm.h.

Referenced by NVM_Write().

#define NVM_WRITE_NONE_CMD   0xfe

All objects are copied from the old page.

Definition at line 57 of file nvm.h.

Function Documentation

Ecode_t NVM_Erase ( uint32_t  eraseCount)

Erase the entire allocated NVM area.

Use this function to erase the entire non-volatile memory area allocated to the NVM system. It is possible to set a fixed erase count for all the pages, or retain the existing one. To retain the erase count might not be advisable if an error has occurred since this data may also have been damaged.

Parameters
[in]eraseCountSpecifies which erase count to set for the blank pages. Pass NVM_ERASE_RETAINCOUNT to retain the erase count.
Returns
Returns the result of the erase operation.

Definition at line 352 of file nvm.c.

References ECODE_EMDRV_NVM_ERROR, ECODE_EMDRV_NVM_OK, NVM_ERASE_RETAINCOUNT, NVMHAL_PageErase(), NVMHAL_Read(), and NVMHAL_Write().

Ecode_t NVM_Init ( NVM_Config_t const *  config)

Initialize the NVM manager.

Use this function to initialize and validate the NVM. Should be run on startup. The result of this process is then returned in the form of a Ecode_t.

If ECODE_EMDRV_NVM_OK is returned, everything went according to plan and you can use the API right away. If ECODE_EMDRV_NVM_NO_PAGES_AVAILABLE is returned this is a device that validates, but is empty. The proper way to handle this is to first reset the memory using NVM_Erase, and then write any initial data.

If a ECODE_EMDRV_NVM_ERROR, or anything more specific, is returned something irreparable happened, and the system cannot be used reliably. A simple solution to this would be to erase and reinitialize, but this will then cause data loss.

Parameters
[in]configPointer to structure defining NVM area.
Returns
Returns the result of the initialization.

Definition at line 182 of file nvm.c.

References ECODE_EMDRV_NVM_ERROR, ECODE_EMDRV_NVM_NO_PAGES_AVAILABLE, ECODE_EMDRV_NVM_OK, NVMHAL_Init(), and NVMHAL_Read().

Ecode_t NVM_Read ( uint16_t  pageId,
uint8_t  objectId 
)

Read an object or an entire page.

Use this function to read an object or an entire page from memory. It takes a page id and an object id (or the NVM_READ_ALL constant to read everything) and reads data from flash and puts it in the memory locations given in the page specification.

Parameters
[in]pageIdIdentifier of the page to read from.
[in]objectIdIdentifier of the object to read. Can be set to NVM_READ_ALL to read an entire page.
Returns
Returns the result of the read operation.

Definition at line 766 of file nvm.c.

References ECODE_EMDRV_NVM_DATA_INVALID, ECODE_EMDRV_NVM_OK, ECODE_EMDRV_NVM_PAGE_INVALID, NVM_READ_ALL_CMD, and NVMHAL_Read().

Ecode_t NVM_Write ( uint16_t  pageId,
uint8_t  objectId 
)

Write an object or a page.

Use this function to write an object or an entire page to NVM. It takes a page and an object and updates this object with the data pointed to by the corresponding page entry. All the objects in a page can be written simultaneously by using NVM_WRITE_ALL instead of an object ID. For normal pages it simply finds an unused page in flash with the lowest erase count and copies all objects belonging to this page updating objects defined by objectId argument. For wear pages, this function tries to find spare place in already used page and write object here. If there is no free space, it uses a new page while invalidating previously used one.

Parameters
[in]pageIdIdentifier of the page you want to write to NVM.
[in]objectIdIdentifier of the object you want to write. May be set to NVM_WRITE_ALL to write the entire page to memory.
Returns
Returns the result of the write operation.

Definition at line 426 of file nvm.c.

References ECODE_EMDRV_NVM_ERROR, ECODE_EMDRV_NVM_OK, NVM_WRITE_ALL_CMD, NVMHAL_Read(), and NVMHAL_Write().