Microchip® Advanced Software Framework

Quick Start Guide for the XMEGA NVM Driver

This is the quick start guide for the NVM Driver, with step-by-step instructions on how to configure and use the driver for specific use cases.

The section described below can be compiled into e.g. the main application loop or any other function that will need to interface non-volatile memory.

Basic usage of the NVM driver

This section will present three use cases of the NVM driver. The first will write a page to EEPROM and verify that it has been written, the second will access the BOD-level fuse to verify that the level is correctly set, and the third will read a chunk from the user signature row.

Use case 1: EEPROM

The NVM driver has functions for interfacing many types of non-volatile memory, including flash, EEPROM, fuses and lock bits. The example code below will write a page to the internal EEPROM, and read it back to verify, using memory mapped I/O.

Setup steps

There are no setup steps required for this use case.

Example code

#define EXAMPLE_PAGE 2
#define EXAMPLE_ADDR EXAMPLE_PAGE * EEPROM_PAGE_SIZE
uint8_t write_page[EEPROM_PAGE_SIZE];
uint8_t read_page[EEPROM_PAGE_SIZE];
fill_page_with_known_data(write_page);
fill_page_with_zeroes(read_page);
read_page, EEPROM_PAGE_SIZE);
check_if_pages_are_equal(write_page, read_page);

Workflow

  1. We define where we would like to store our data, and we arbitrarily choose page 2 of EEPROM:
    • #define EXAMPLE_PAGE 2
      #define EXAMPLE_ADDR EXAMPLE_PAGE * EEPROM_PAGE_SIZE
  2. Define two tables, one which contains the data which we will write, and one which we will read the data into:
    • uint8_t write_page[EEPROM_PAGE_SIZE];
      uint8_t read_page[EEPROM_PAGE_SIZE];
  3. Fill the tables with our data, and zero out the read table:
    • fill_page_with_known_data(write_page);
      fill_page_with_zeroes(read_page);
    • Note
      These functions are undeclared, you should replace them with your own appropriate functions.
  4. We load our page into a temporary EEPROM page buffer:
  5. Do an atomic write of the page from buffer into the specified page:
  6. Read the page back into our read_page[] table:
  7. Verify that the page is equal to the one that was written earlier:
    • check_if_pages_are_equal(write_page, read_page);
    • Note
      This function is not declared, you should replace it with your own appropriate function.

Use case 2: Fuses

The NVM driver has functions for reading fuses. See NVM driver fuse and lock bits handling.

We would like to check whether the Brown-out Detection level is set to 2.1V. This is set by programming the fuses when the chip is connected to a suitable programmer. The fuse is a part of FUSEBYTE5. If the BODLVL is correct, we turn on LED0.

Setup steps

There are no setup steps required for this use case.

Example code

uint8_t fuse_value;
fuse_value = nvm_fuses_read(FUSEBYTE5);
if ((fuse_value & NVM_FUSES_BODLVL_gm) == BODLVL_2V1_gc) {
gpio_set_pin_low(LED0_GPIO);
}

Workflow

  1. Create a variable to store the fuse contents:
    • uint8_t fuse_value;
  2. The fuse value we are interested in, BODLVL, is stored in FUSEBYTE5. We call the function nvm_fuses_read() to read the fuse into our variable:
  3. This ends the reading portion, but we would like to see whether the BOD-level is correct, and if it is, light up an LED:
    • if ((fuse_value & NVM_FUSES_BODLVL_gm) == BODLVL_2V1_gc) {
      gpio_set_pin_low(LED0_GPIO);
      }

Use case 3: Signature row

The NVM driver has functions for reading the signature row of the device. Here we will simply read 16 bytes from the user signature row, assuming we need what is stored there.

Setup steps

There are no setup steps required for this use case.

Example code

#define START_ADDR 0x10
#define DATA_LENGTH 16
uint8_t values[LENGTH];
uint8_t i;
for (i = 0; i < DATA_LENGTH; i++) {
values[i] = nvm_read_user_signature_row(START_ADDR + i);
}

Workflow

  1. Define starting address and length of data segment, and create variables needed to store and process the data:
    • #define START_ADDR 0x10
      #define DATA_LENGTH 16
      uint8_t values[LENGTH];
      uint8_t i;
  2. Iterate through the user signature row, and store our desired data: