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 */
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 (SAMD21) || (SAMDA1)
void SYSCTRL_Handler(void)
{
if (SYSCTRL->INTFLAG.reg & SYSCTRL_INTFLAG_BOD33DET) {
SYSCTRL->INTFLAG.reg = SYSCTRL_INTFLAG_BOD33DET;
}
}
#endif
static void configure_bod(void)
{
#if (SAMD21) || (SAMDA1)
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.
  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[RWW_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[RWW_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;