Microchip® Advanced Software Framework

 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
SAM Read While Write EEPROM (RWW EEPROM) Emulator Service

This driver for Atmel® | SMART ARM®-based microcontrollers provides an RWW emulated EEPROM memory area, for the storage and retrieval of user-application configuration data into and out of non-volatile memory.

The main array can therefore run code while EEPROM data is written.

The following peripheral is used by this module:

The following devices can use this module:

The outline of this documentation is as follows:

Prerequisites

There are no prerequisites for this module.

Module Overview

SAM devices embeds a separate read while write EEPROM emulation (RWWEE) array that can be programmed while the main array is not blocked. To use RWWEE memory, data must be written as a number of physical memory pages (of several bytes each) rather than being individually byte addressable, and entire rows of RWWEE must be erased before new data may be stored. To help abstract these characteristics away from the user application an emulation scheme is implemented to present a more user-friendly API for data storage and retrieval.

This module provides an RWW EEPROM emulation layer on top of the device's internal NVM controller, to provide a standard interface for the reading and writing of non-volatile configuration data. This data is placed into the RWW EEPROM emulated section. Emulated EEPROM is exempt from the usual device NVM region lock bits, so that it may be read from or written to at any point in the user application.

There are many different algorithms that may be employed for EEPROM emulation, to tune the write and read latencies, RAM usage, wear levelling, and other characteristics. As a result, multiple different emulator schemes may be implemented, so that the most appropriate scheme for a specific application's requirements may be used.

Implementation Details

The following information is relevant for RWW EEPROM Emulator scheme 1, version 1.0.0, as implemented by this module. Other revisions or emulation schemes may vary in their implementation details and may have different wear-leveling, latency, and other characteristics.

Emulator Characteristics

This emulator is designed for best reliability, with a good balance of available storage and write-cycle limits. It is designed to ensure that page data is updated by an atomic operation, so that in the event of a failed update the previous data is not lost (when used correctly). With the exception of a system reset with data cached to the internal write-cache buffer, at most only the latest write to physical non-volatile memory will be lost in the event of a failed write.

This emulator scheme is tuned to give best write-cycle longevity when writes are confined to the same logical RWW EEPROM page (where possible) and when writes across multiple logical RWW EEPROM pages are made in a linear fashion through the entire emulated RWW EEPROM space.

Physical Memory

RWW EEPROM emulator is divided into a number of physical rows, each containing four identically sized pages. Pages may be read or written to individually, however, pages must be erased before being reprogrammed and the smallest granularity available for erasure is one single row.

This discrepancy results in the need for an emulator scheme that is able to handle the versioning and moving of page data to different physical rows as needed, erasing old rows ready for re-use by future page write operations.

Physically, the emulated RWW EEPROM segment is a dedicated space that are memory mapped, as shown in the figure below.

Master Row

One physical row at the end of the emulated RWW EEPROM memory space is reserved for use by the emulator to store configuration data. The master row is not user-accessible, and is reserved solely for internal use by the emulator.

Spare Row

As data needs to be preserved between row erasures, a single row is kept unused to act as destination for copied data when a write request is made to an already full row. When the write request is made, any logical pages of data in the full row that need to be preserved are written to the spare row along with the new (updated) logical page data, before the old row is erased and marked as the new spare.

Row Contents

Each physical row initially stores the contents of one or two logical RWW EEPROM memory pages (it depends on application configuration file). This quarters or halves the available storage space for the emulated RWW EEPROM but reduces the overall number of row erases that are required, by reserving two or three pages within each row for updated versions of the logical page contents. See here for a visual layout of the RWW EEPROM Emulator physical memory.

As logical pages within a physical row are updated, the new data is filled into the remaining unused pages in the row. Once the entire row is full, a new write request will copy the logical page not being written to in the current row to the spare row with the new (updated) logical page data, before the old row is erased.

When it is configured, each physical row stores the contents of one logical RWW EEPROM memory page. This system will allow for the same logical page to be updated up to four times into the physical memory before a row erasure procedure is needed. In the case of multiple versions of the same logical RWW EEPROM page being stored in the same physical row, the right-most (highest physical memory page address) version is considered to be the most current.

Write Cache

As a typical EEPROM use case is to write to multiple sections of the same EEPROM page sequentially, the emulator is optimized with a single logical RWW EEPROM page write cache to buffer writes before they are written to the physical backing memory store. The cache is automatically committed when a new write request to a different logical RWW EEPROM memory page is requested, or when the user manually commits the write cache.

Without the write cache, each write request to an EEPROM memory page would require a full page write, reducing the system performance and significantly reducing the lifespan of the non-volatile memory.

Memory Layout

A single logical RWW EEPROM page is physically stored as the page content and a header inside a single physical page, as shown in the following figure.

page_layout.svg
Internal Layout of an Emulated RWW EEPROM Page
Note
In the following memory layout example, each physical row stores the contents of one logical RWW EEPROM page. Refer to "AT03265: SAM EEPROM Emulator Service (EEPROM)" for the example of two logical EEPROM pages in one row.

Within the RWW EEPROM memory reservation section at the top of the NVM memory space, this emulator will produce the layout as shown in the figure below when initialized for the first time.

init_layout.svg
Initial Physical Layout of the Emulated RWW EEPROM Memory

When an RWW EEPROM page needs to be committed to physical memory, the next free page in the same row will be chosen. This makes recovery simple, as the right-most version of a logical page in a row is considered the most current. With four pages to a physical NVM row, this allows for up to four updates to the same logical page to be made before an erase is needed. The figure below shows the result of the user writing an updated version of logical EEPROM page N-1 to the physical memory.

nm1_page_write.svg
First Write to Logical RWW EEPROM Page N-1

A second write of the same logical RWW EEPROM page results in the layout shown in the figure below.

nm1_page_write2.svg
Second Write to Logical RWW EEPROM Page N-1

A third write of the same logical RWW EEPROM page results in the layout shown in the figure below.

nm1_page_write3.svg
Third Write to Logical RWW EEPROM Page N-1

A fourth write of the same logical page requires that the RWW EEPROM emulator erase the row, as it has become full. Prior to this, the content of the unmodified page in the same row as the page being updated will be copied into the spare row, along with the new version of the page being updated. The old (full) row is then erased, resulting in the layout shown in the figure below.

nm1_page_write4.svg
Third Write to Logical RWW EEPROM Page N-1

Special Considerations

NVM Controller Configuration

The RWW EEPROM Emulator service will initialize the NVM controller as part of its own initialization routine; the NVM controller will be placed in Manual Write mode, so that explicit write commands must be sent to the controller to commit a buffered page to physical memory. The manual write command must thus be issued to the NVM controller whenever the user application wishes to write to a NVM page for its own purposes.

Logical RWW EEPROM Page Size

As a small amount of information needs to be stored in a header before the content of a logical EEPROM page in memory (for use by the emulation service), the available data in each RWW EEPROM page is less than the total size of a single NVM memory page by several bytes.

Committing of the Write Cache

A single-page write cache is used internally to buffer data written to pages in order to reduce the number of physical writes required to store the user data, and to preserve the physical memory lifespan. As a result, it is important that the write cache is committed to physical memory as soon as possible after a BOD low power condition, to ensure that enough power is available to guarantee a completed write so that no data is lost.

The write cache must also be manually committed to physical memory if the user application is to perform any NVM operations using the NVM controller directly.

RWW EEPROM Page Checksum

For each page, a checksum function is used to verify the integrity of the page data. When reading the page data, using rww_eeprom_emulator_read_page(). When its checksum is not correct, an error can be detected. This function can be enabled or disabled through the configuration file.

Extra Information

For extra information, see Extra Information. This includes:

Examples

For a list of examples related to this driver, see Examples for Emulated RWW EEPROM Service.

API Overview

Modules

 Quick Start Guide(s)
 In this section you can find a list of all Quick Start guides related to the SAM Read While Write EEPROM (RWW EEPROM) Emulator Service.
 

Data Structures

struct  rww_eeprom_emulator_parameters
 RWW EEPROM memory parameter structure. More...
 

Enumerations

enum  rwwee_logical_page_num_in_row {
  RWWEE_LOGICAL_PAGE_NUM_1 = 1,
  RWWEE_LOGICAL_PAGE_NUM_2 = 2
}
 RWW EEPROM Logical Page in Each Row. More...
 

RWW EEPROM Emulator Information

#define RWW_EEPROM_EMULATOR_ID   1
 Emulator scheme ID, identifying the scheme used to emulated EEPROM storage. More...
 
#define RWW_EEPROM_MAJOR_VERSION   1
 Emulator major version number, identifying the emulator major version. More...
 
#define RWW_EEPROM_MINOR_VERSION   0
 Emulator minor version number, identifying the emulator minor version. More...
 
#define RWW_EEPROM_REVISION   0
 Emulator revision version number, identifying the emulator revision. More...
 
#define RWW_EEPROM_PAGE_SIZE   (NVMCTRL_PAGE_SIZE - RWW_EEPROM_HEADER_SIZE)
 Size of the user data portion of each logical EEPROM page, in bytes. More...
 

Configuration and Initialization

enum status_code rww_eeprom_emulator_init (void)
 Initializes the RWW EEPROM Emulator service. More...
 
void rww_eeprom_emulator_erase_memory (void)
 Erases the entire emulated RWW EEPROM memory space. More...
 
enum status_code rww_eeprom_emulator_get_parameters (struct rww_eeprom_emulator_parameters *const parameters)
 Retrieves the parameters of the RWW EEPROM Emulator memory layout. More...
 

Logical RWW EEPROM Page Reading/Writing

enum status_code rww_eeprom_emulator_commit_page_buffer (void)
 Commits any cached data to physical non-volatile memory. More...
 
enum status_code rww_eeprom_emulator_write_page (const uint8_t logical_page, const uint8_t *const data)
 Writes a page of data to an emulated RWW EEPROM memory page. More...
 
enum status_code rww_eeprom_emulator_read_page (const uint8_t logical_page, uint8_t *const data)
 Reads a page of data from an emulated RWW EEPROM memory page. More...
 

Buffer RWW EEPROM Reading/Writing

enum status_code rww_eeprom_emulator_write_buffer (const uint16_t offset, const uint8_t *const data, const uint16_t length)
 Writes a buffer of data to the emulated RWW EEPROM memory space. More...
 
enum status_code rww_eeprom_emulator_read_buffer (const uint16_t offset, uint8_t *const data, const uint16_t length)
 Reads a buffer of data from the emulated RWW EEPROM memory space. More...
 

#define RWW_EEPROM_EMULATOR_ID   1

Emulator scheme ID, identifying the scheme used to emulated EEPROM storage.

Referenced by _rww_eeprom_emulator_create_master_page(), and _rww_eeprom_emulator_verify_master_page().

#define RWW_EEPROM_MAJOR_VERSION   1

Emulator major version number, identifying the emulator major version.

Referenced by _rww_eeprom_emulator_create_master_page(), and _rww_eeprom_emulator_verify_master_page().

#define RWW_EEPROM_MINOR_VERSION   0

Emulator minor version number, identifying the emulator minor version.

Referenced by _rww_eeprom_emulator_create_master_page(), and _rww_eeprom_emulator_verify_master_page().

#define RWW_EEPROM_PAGE_SIZE   (NVMCTRL_PAGE_SIZE - RWW_EEPROM_HEADER_SIZE)
#define RWW_EEPROM_REVISION   0

Emulator revision version number, identifying the emulator revision.

Referenced by _rww_eeprom_emulator_create_master_page().

RWW EEPROM Logical Page in Each Row.

Enum for the possible logical pages that are stored in each physical row.

Enumerator
RWWEE_LOGICAL_PAGE_NUM_1 

One logical page stored in a physical row.

RWWEE_LOGICAL_PAGE_NUM_2 

Two logical pages stored in a physical row.

enum status_code rww_eeprom_emulator_commit_page_buffer ( void  )

Commits any cached data to physical non-volatile memory.

Commits the internal SRAM caches to physical non-volatile memory, to ensure that any outstanding cached data is preserved. This function should be called prior to a system reset or shutdown to prevent data loss.

Note
This should be the first function executed in a BOD33 Early Warning callback to ensure that any outstanding cache data is fully written to prevent data loss.
This function should also be called before using the NVM controller directly in the user-application for any other purposes to prevent data loss.
Returns
Status code indicating the status of the operation.

References _rww_eeprom_emulator_nvm_commit_cache(), barrier, _rww_eeprom_module::cache, _rww_eeprom_module::cache_active, _rww_eeprom_page::header, _rww_eeprom_page::logical_page, _rww_eeprom_module::page_map, and STATUS_OK.

Referenced by _rww_eeprom_emulator_move_data_to_spare(), and rww_eeprom_emulator_write_page().

void rww_eeprom_emulator_erase_memory ( void  )

Erases the entire emulated RWW EEPROM memory space.

Erases and re-initializes the emulated RWW EEPROM memory space, destroying any existing data.

Master page should be created during uninitialized status

References _rww_eeprom_emulator_create_master_page(), _rww_eeprom_emulator_format_memory(), _rww_eeprom_emulator_update_page_mapping(), and _rww_eeprom_module::initialized.

enum status_code rww_eeprom_emulator_get_parameters ( struct rww_eeprom_emulator_parameters *const  parameters)

Retrieves the parameters of the RWW EEPROM Emulator memory layout.

Retrieves the configuration parameters of the RWW EEPROM Emulator, after it has been initialized.

Parameters
[out]parametersRWW EEPROM Emulator parameter struct to fill
Returns
Status of the operation.
Return values
STATUS_OKIf the emulator parameters were retrieved successfully
STATUS_ERR_NOT_INITIALIZEDIf the RWW EEPROM Emulator is not initialized

References rww_eeprom_emulator_parameters::eeprom_number_of_pages, _rww_eeprom_module::initialized, _rww_eeprom_module::logical_pages, rww_eeprom_emulator_parameters::page_size, RWW_EEPROM_PAGE_SIZE, STATUS_ERR_NOT_INITIALIZED, and STATUS_OK.

enum status_code rww_eeprom_emulator_init ( void  )

Initializes the RWW EEPROM Emulator service.

Initializes the emulated RWW EEPROM memory space. If the emulated RWW EEPROM memory has not been previously initialized, it will need to be explicitly formatted via rww_eeprom_emulator_erase_memory(). The RWW EEPROM memory space will not be automatically erased by the initialization function. Partial data may be recovered by the user application manually if the service is unable to initialize successfully.

Returns
Status code indicating the status of the operation.
Return values
STATUS_OKRWW EEPROM emulation service was successfully initialized
STATUS_ERR_BAD_FORMATEmulated RWW EEPROM memory is corrupt or not formatted
STATUS_ERR_IORWW EEPROM data is incompatible with this version or scheme of the RWW EEPROM emulator
STATUS_ERR_INVALID_ARGInvalid logical page configuration

References _rww_eeprom_emulator_update_page_mapping(), _rww_eeprom_emulator_verify_master_page(), _rww_eeprom_module::cache_active, CONF_LOGICAL_PAGE_NUM_IN_ROW, _rww_eeprom_module::initialized, _rww_eeprom_module::logical_pages, nvm_config::manual_page_write, nvm_get_config_defaults(), nvm_get_parameters(), nvm_set_config(), _rww_eeprom_module::physical_pages, RWW_EEPROM_MAX_LOGICAL_PAGES, nvm_parameters::rww_eeprom_number_of_pages, _rww_eeprom_module::rwwee_addr, RWWEE_LOGICAL_PAGE_NUM_1, RWWEE_LOGICAL_PAGE_NUM_2, _rww_eeprom_module::spare_row, STATUS_BUSY, STATUS_ERR_BAD_FORMAT, STATUS_ERR_INVALID_ARG, and STATUS_OK.

enum status_code rww_eeprom_emulator_read_buffer ( const uint16_t  offset,
uint8_t *const  data,
const uint16_t  length 
)

Reads a buffer of data from the emulated RWW EEPROM memory space.

Reads a buffer of data from a section of emulated RWW EEPROM memory space. The destination buffer may be of any size, and the source may lie outside of an emulated RWW EEPROM page boundary.

Parameters
[in]offsetStarting byte offset to read from, in emulated RWW EEPROM memory space
[out]dataPointer to the data buffer containing source data to read
[in]lengthLength of the data to read, in bytes
Returns
Status code indicating the status of the operation.
Return values
STATUS_OKIf the page was successfully read
STATUS_ERR_NOT_INITIALIZEDIf the RWW EEPROM emulator is not initialized
STATUS_ERR_BAD_ADDRESSIf an address outside the valid emulated RWW EEPROM memory space was supplied

Perform the initial page read

References buffer, c, _rww_eeprom_page::logical_page, rww_eeprom_emulator_read_page(), RWW_EEPROM_PAGE_SIZE, and STATUS_OK.

enum status_code rww_eeprom_emulator_read_page ( const uint8_t  logical_page,
uint8_t *const  data 
)

Reads a page of data from an emulated RWW EEPROM memory page.

Reads an emulated RWW EEPROM page of data from the emulated RWW EEPROM memory space.

Parameters
[in]logical_pageLogical RWW EEPROM page number to read from
[out]dataPointer to the destination data buffer to fill
Returns
Status code indicating the status of the operation.
Return values
STATUS_OKIf the page was successfully read
STATUS_ERR_NOT_INITIALIZEDIf the RWW EEPROM emulator is not initialized
STATUS_ERR_BAD_ADDRESSIf an address outside the valid emulated RWW EEPROM memory space was supplied
STATUS_ERR_BAD_FORMATPage data checksum is not correct, maybe data is damaged

References _rww_eeprom_emulator_nvm_read_page(), _rww_eeprom_module::cache, _rww_eeprom_module::cache_active, _rww_eeprom_page::data, _rww_eeprom_page::header, _rww_eeprom_module::initialized, _rww_eeprom_page::logical_page, _rww_eeprom_module::logical_pages, _rww_eeprom_module::page_map, RWW_EEPROM_PAGE_SIZE, STATUS_ERR_BAD_ADDRESS, STATUS_ERR_BAD_FORMAT, STATUS_ERR_NOT_INITIALIZED, and STATUS_OK.

Referenced by rww_eeprom_emulator_read_buffer(), and rww_eeprom_emulator_write_buffer().

enum status_code rww_eeprom_emulator_write_buffer ( const uint16_t  offset,
const uint8_t *const  data,
const uint16_t  length 
)

Writes a buffer of data to the emulated RWW EEPROM memory space.

Writes a buffer of data to a section of emulated RWW EEPROM memory space. The source buffer may be of any size, and the destination may lie outside of an emulated RWW EEPROM page boundary.

Note
Data stored in pages may be cached in volatile RAM memory; to commit any cached data to physical non-volatile memory, the rww_eeprom_emulator_commit_page_buffer() function should be called.
Parameters
[in]offsetStarting byte offset to write to, in emulated RWW EEPROM memory space
[in]dataPointer to the data buffer containing source data to write
[in]lengthLength of the data to write, in bytes
Returns
Status code indicating the status of the operation.
Return values
STATUS_OKIf the page was successfully read
STATUS_ERR_NOT_INITIALIZEDIf the RWW EEPROM emulator is not initialized
STATUS_ERR_BAD_ADDRESSIf an address outside the valid emulated RWW EEPROM memory space was supplied

Perform the initial page read if necessary

References buffer, c, _rww_eeprom_page::logical_page, rww_eeprom_emulator_read_page(), rww_eeprom_emulator_write_page(), RWW_EEPROM_PAGE_SIZE, and STATUS_OK.

enum status_code rww_eeprom_emulator_write_page ( const uint8_t  logical_page,
const uint8_t *const  data 
)

Writes a page of data to an emulated RWW EEPROM memory page.

Writes an emulated RWW EEPROM page of data to the emulated RWW EEPROM memory space.

Note
Data stored in pages may be cached in volatile RAM memory; to commit any cached data to physical non-volatile memory, the rww_eeprom_emulator_commit_page_buffer() function should be called.
Parameters
[in]logical_pageLogical RWW EEPROM page number to write to
[in]dataPointer to the data buffer containing source data to write
Returns
Status code indicating the status of the operation.
Return values
STATUS_OKIf the page was successfully read
STATUS_ERR_NOT_INITIALIZEDIf the RWW EEPROM emulator is not initialized
STATUS_ERR_BAD_ADDRESSIf an address outside the valid emulated RWW EEPROM memory space was supplied

References _rww_eeprom_emulator_is_page_free_on_row(), _rww_eeprom_emulator_move_data_to_spare(), _rww_eeprom_emulator_nvm_fill_cache(), barrier, _rww_eeprom_module::cache, _rww_eeprom_module::cache_active, _rww_eeprom_page::data, _rww_eeprom_page::header, _rww_eeprom_module::initialized, _rww_eeprom_page::logical_page, _rww_eeprom_module::logical_pages, _rww_eeprom_module::page_map, rww_eeprom_emulator_commit_page_buffer(), RWW_EEPROM_PAGE_SIZE, STATUS_ERR_BAD_ADDRESS, STATUS_ERR_NOT_INITIALIZED, and STATUS_OK.

Referenced by rww_eeprom_emulator_write_buffer().