Atmel Software Framework

Quick Start Guide for the Emulated EEPROM Module - Basic Use Case

In this use case, the EEPROM emulator module is configured and a sample page of data read and written.

The first byte of the first EEPROM page is toggled, and a LED is turned on or off to reflect the new state. Each time the device is reset, the LED should toggle to a different state to indicate correct non-volatile storage and retrieval.

Prerequisites

The device's fuses must be configured to reserve a sufficient number of FLASH memory rows for use by the EEPROM emulator service, before the service can be used. That is: NVMCTRL_FUSES_EEPROM_SIZE has to be set to less than 0x5 in the fuse setting, then there will be more than 8 pages size for EEPROM. Atmel Studio can be used to set this fuse(Tools->Device Programming).

Setup

Prerequisites

There are no special setup requirements for this use-case.

Code

Copy-paste the following setup code to your user application:

void configure_eeprom(void)
{
/* Setup EEPROM emulator service */
enum status_code error_code = eeprom_emulator_init();
if (error_code == STATUS_ERR_NO_MEMORY) {
while (true) {
/* No EEPROM section has been set in the device's fuses */
}
}
else if (error_code != STATUS_OK) {
/* Erase the emulated EEPROM memory (assume it is unformatted or
* irrecoverably corrupt) */
}
}
#if (SAMD || SAMR21)
void SYSCTRL_Handler(void)
{
if (SYSCTRL->INTFLAG.reg & SYSCTRL_INTFLAG_BOD33DET) {
SYSCTRL->INTFLAG.reg = SYSCTRL_INTFLAG_BOD33DET;
}
}
#endif
static void configure_bod(void)
{
#if (SAMD || SAMR21)
struct bod_config config_bod33;
bod_get_config_defaults(&config_bod33);
config_bod33.action = BOD_ACTION_INTERRUPT;
/* BOD33 threshold level is about 3.2V */
config_bod33.level = 48;
bod_set_config(BOD_BOD33, &config_bod33);
bod_enable(BOD_BOD33);
SYSCTRL->INTENSET.reg = SYSCTRL_INTENCLR_BOD33DET;
system_interrupt_enable(SYSTEM_INTERRUPT_MODULE_SYSCTRL);
#endif
}

Add to user application initialization (typically the start of main()):

configure_eeprom();

Workflow

  1. Attempt to initialize the EEPROM emulator service, storing the error code from the initialization function into a temporary variable.
    enum status_code error_code = eeprom_emulator_init();
  2. Check if the emulator failed to initialize due to the device fuses not being configured to reserve enough of the main FLASH memory rows for emulated EEPROM usage - abort if the fuses are mis-configured.
    if (error_code == STATUS_ERR_NO_MEMORY) {
    while (true) {
    /* No EEPROM section has been set in the device's fuses */
    }
    }
  3. Check if the emulator service failed to initialize for any other reason; if so assume the emulator physical memory is unformatted or corrupt and erase/re-try initialization.
    else if (error_code != STATUS_OK) {
    /* Erase the emulated EEPROM memory (assume it is unformatted or
    * irrecoverably corrupt) */
    }
    Config BOD to give an early warning, so that we could prevent data loss.
    configure_bod();

Use Case

Code

Copy-paste the following code to your user application:

uint8_t page_data[EEPROM_PAGE_SIZE];
page_data[0] = !page_data[0];
port_pin_set_output_level(LED_0_PIN, page_data[0]);
page_data[1]=0x1;
while (true) {
}

Workflow

  1. Create a buffer to hold a single emulated EEPROM page of memory, and read out logical EEPROM page zero into it.
    uint8_t page_data[EEPROM_PAGE_SIZE];
  2. Toggle the first byte of the read page.
    page_data[0] = !page_data[0];
  3. Output the toggled LED state onto the board LED.
    port_pin_set_output_level(LED_0_PIN, page_data[0]);
  4. Write the modified page back to logical EEPROM page zero, flushing the internal emulator write cache afterwards to ensure it is immediately written to physical non-volatile memory.
  5. Modify data and write back to logical EEPROM page zero. The data is not committed and should call eeprom_emulator_commit_page_buffer to ensure that any outstanding cache data is fully written to prevent data loss when detecting a BOD early warning.
    page_data[1]=0x1;