NVM Non-volatile Memory driver


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 and data validation. The driver performs wear leveling by writing objects to the least used locations in the NVM system. The driver uses CCITT CRC16 for data validation.

It is also possible for the user to specify certain pages as wear pages. These pages 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 a low update frequency.

The size and layout of the data objects to be managed by this driver must be known at compile-time.

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 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 structure to be managed by the driver.

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 can either be 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:

Users have to be aware of the following limitations:

Note that the different EFM32 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 uint8_t bonusTable[];    
  extern uint8_t privateKeyTable[];
  extern uint8_t transformTable[];
  extern int32_t safetyTable[];      
  extern uint8_t bigEmptyTable[450];
  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
  } NVM_Object_Ids;

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

  CHIP_Init();

  // Erase all pages managed by the driver and set the erasure count
  // for each page to 0. To retain the erasure 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));

  // 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
    }
    if (primeNumberTable[i] == 0)
    {
      // Should not happen
    }  
  }