This driver for Atmel® | SMART ARM®-based microcontrollers provides an interface for the configuration and management of non-volatile memories within the device, for partitioning, erasing, reading, and writing of data.
The following peripheral is used by this module:
The following devices can use this module:
The outline of this documentation is as follows:
There are no prerequisites for this module.
The Non-Volatile Memory (NVM) module provides an interface to the device's Non-Volatile Memory controller, so that memory pages can be written, read, erased, and reconfigured in a standardized manner.
Driver feature macro | Supported devices |
---|---|
FEATURE_NVM_RWWEE | SAM L21/L22, SAM D21-64K, SAM DA1, SAM C20/C21, SAM R30 , SAM R34/R35 |
FEATURE_BOD12 | SAM L21, SAMR30/R34 |
The NVM memory space of the SAM devices is divided into two sections: a Main Array section, and an Auxiliary space section. The Main Array space can be configured to have an (emulated) EEPROM and/or boot loader section. The memory layout with the EEPROM and bootloader partitions is shown in the figure below.
The Main Array is divided into rows and pages, where each row contains four pages. The size of each page may vary from 8-1024 bytes dependent of the device. Device specific parameters such as the page size and total number of pages in the NVM memory space are available via the nvm_get_parameters() function.
An NVM page number and address can be computed via the following equations:
\[ PageNum = (RowNum \times 4) + PagePosInRow \]
\[ PageAddr = PageNum \times PageSize \]
The figure below shows an example of the memory page and address values associated with logical row 7 of the NVM memory space.
As mentioned in Memory Regions, the main block of the NVM memory is divided into a number of individually addressable pages. These pages are grouped into 16 equal sized regions, where each region can be locked separately issuing an NVM_COMMAND_LOCK_REGION command or by writing the LOCK bits in the User Row. Rows reserved for the EEPROM section are not affected by the lock bits or commands.
Reading from the NVM memory can be performed using direct addressing into the NVM memory space, or by calling the nvm_read_buffer() function.
Writing to the NVM memory must be performed by the nvm_write_buffer() function - additionally, a manual page program command must be issued if the NVM controller is configured in manual page writing mode.
Before a page can be updated, the associated NVM memory row must be erased first via the nvm_erase_row() function. Writing to a non-erased page will result in corrupt data being stored in the NVM memory space.
The granularity of an erase is per row, while the granularity of a write is per page. Thus, if the user application is modifying only one page of a row, the remaining pages in the row must be buffered and the row erased, as an erase is mandatory before writing to a page.
The user must ensure that the driver is configured with a proper number of wait states when the CPU is running at high frequencies.
The User Row in the Auxiliary Space cannot be read or written when the Security Bit is set. The Security Bit can be set by using passing NVM_COMMAND_SET_SECURITY_BIT to the nvm_execute_command() function, or it will be set if one tries to access a locked region. See Region Lock Bits.
The Security Bit can only be cleared by performing a chip erase.
For extra information, see Extra Information for NVM Driver. This includes:
For a list of examples related to this driver, see Examples for NVM Driver.
Data Structures | |
struct | nvm_config |
NVM controller configuration structure. More... | |
struct | nvm_fusebits |
NVM user row fuse setting structure. More... | |
struct | nvm_parameters |
NVM memory parameter structure. More... | |
Configuration and Initialization | |
static void | nvm_get_config_defaults (struct nvm_config *const config) |
Initializes an NVM controller configuration structure to defaults. More... | |
enum status_code | nvm_set_config (const struct nvm_config *const config) |
Sets the up the NVM hardware module based on the configuration. More... | |
static bool | nvm_is_ready (void) |
Checks if the NVM controller is ready to accept a new command. More... | |
NVM Access Management | |
void | nvm_get_parameters (struct nvm_parameters *const parameters) |
Reads the parameters of the NVM controller. More... | |
enum status_code | nvm_write_buffer (const uint32_t destination_address, const uint8_t *buffer, uint16_t length) |
Writes a number of bytes to a page in the NVM memory region. More... | |
enum status_code | nvm_read_buffer (const uint32_t source_address, uint8_t *const buffer, uint16_t length) |
Reads a number of bytes from a page in the NVM memory region. More... | |
enum status_code | nvm_update_buffer (const uint32_t destination_address, uint8_t *const buffer, uint16_t offset, uint16_t length) |
Updates an arbitrary section of a page with new data. More... | |
enum status_code | nvm_erase_row (const uint32_t row_address) |
Erases a row in the NVM memory space. More... | |
enum status_code | nvm_execute_command (const enum nvm_command command, const uint32_t address, const uint32_t parameter) |
Executes a command on the NVM controller. More... | |
enum status_code | nvm_get_fuses (struct nvm_fusebits *fusebits) |
Get fuses from user row. More... | |
enum status_code | nvm_set_fuses (struct nvm_fusebits *fb) |
Set fuses from user row. More... | |
bool | nvm_is_page_locked (uint16_t page_number) |
Checks whether the page region is locked. More... | |
static enum nvm_error | nvm_get_error (void) |
Retrieves the error code of the last issued NVM operation. More... | |
enum nvm_bod33_action |
enum nvm_bootloader_size |
Bootloader size.
Available bootloader protection sizes in kilobytes.
enum nvm_cache_readmode |
NVM controller cache readmode configuration.
Control how the NVM cache prefetch data from flash.
enum nvm_command |
NVM controller commands.
EEPROM emulator size.
Available space in flash dedicated for EEPROM emulator in bytes.
enum nvm_error |
enum nvm_sleep_power_mode |
NVM controller power reduction mode configurations.
Power reduction modes of the NVM controller, to conserve power while the device is in sleep.
WDT Early warning offset.
This setting determine how many GCLK_WDT cycles before a watchdog time-out period an early warning interrupt should be triggered.
WDT Window time-out period.
Window mode time-out period in clock cycles.
enum status_code nvm_erase_row | ( | const uint32_t | row_address | ) |
Erases a row in the NVM memory space.
Erases a given row in the NVM memory region.
[in] | row_address | Address of the row to erase |
STATUS_OK | Requested NVM memory row was successfully erased |
STATUS_BUSY | NVM controller was busy when the operation was attempted |
STATUS_ERR_BAD_ADDRESS | The requested row address was outside the acceptable range of the NVM memory region or not aligned to the start of a row |
STATUS_ABORTED | NVM erased error |
References _nvm_dev, _nvm_module::number_of_pages, NVM_COMMAND_ERASE_ROW, NVM_ERROR_NONE, nvm_is_ready(), NVM_MEMORY, _nvm_module::page_size, STATUS_ABORTED, STATUS_BUSY, STATUS_ERR_BAD_ADDRESS, and STATUS_OK.
Referenced by nvm_update_buffer(), and program_memory().
enum status_code nvm_execute_command | ( | const enum nvm_command | command, |
const uint32_t | address, | ||
const uint32_t | parameter | ||
) |
Executes a command on the NVM controller.
Executes an asynchronous command on the NVM controller, to perform a requested action such as an NVM page read or write operation.
[in] | command | Command to issue to the NVM controller |
[in] | address | Address to pass to the NVM controller in NVM memory space |
[in] | parameter | Parameter to pass to the NVM controller, not used for this driver |
STATUS_OK | If the command was accepted and execution is now in progress |
STATUS_BUSY | If the NVM controller was already busy executing a command when the new command was issued |
STATUS_ERR_IO | If the command was invalid due to memory or security locking |
STATUS_ERR_INVALID_ARG | If the given command was invalid or unsupported |
STATUS_ERR_BAD_ADDRESS | If the given address was invalid |
References _nvm_dev, _nvm_module::number_of_pages, NVM_COMMAND_ENTER_LOW_POWER_MODE, NVM_COMMAND_ERASE_AUX_ROW, NVM_COMMAND_ERASE_ROW, NVM_COMMAND_EXIT_LOW_POWER_MODE, NVM_COMMAND_LOCK_REGION, NVM_COMMAND_PAGE_BUFFER_CLEAR, NVM_COMMAND_SET_SECURITY_BIT, NVM_COMMAND_UNLOCK_REGION, NVM_COMMAND_WRITE_AUX_ROW, NVM_COMMAND_WRITE_PAGE, nvm_is_ready(), NVM_MEMORY, _nvm_module::page_size, STATUS_BUSY, STATUS_ERR_BAD_ADDRESS, STATUS_ERR_INVALID_ARG, STATUS_ERR_IO, and STATUS_OK.
Referenced by nvm_set_fuses(), and nvm_write_buffer().
|
inlinestatic |
Initializes an NVM controller configuration structure to defaults.
Initializes a given NVM controller configuration structure to a set of known default values. This function should be called on all new instances of these configuration structures before being modified by the user application.
The default configuration is as follows:
[out] | config | Configuration structure to initialize to default values |
References Assert, nvm_config::cache_readmode, nvm_config::disable_cache, nvm_config::manual_page_write, NVM_CACHE_READMODE_NO_MISS_PENALTY, NVM_SLEEP_POWER_MODE_WAKEONACCESS, nvm_config::sleep_power_mode, and nvm_config::wait_states.
Referenced by main().
|
inlinestatic |
Retrieves the error code of the last issued NVM operation.
Retrieves the error code from the last executed NVM operation. Once retrieved, any error state flags in the controller are cleared.
NVM_ERROR_NONE | No error occurred in the last NVM operation |
NVM_ERROR_LOCK | The last NVM operation attempted to access a locked region |
NVM_ERROR_PROG | An invalid NVM command was issued |
enum status_code nvm_get_fuses | ( | struct nvm_fusebits * | fusebits | ) |
Get fuses from user row.
Read out the fuse settings from the user row.
[in] | fusebits | Pointer to a 64-bit wide memory buffer of type struct nvm_fusebits |
STATUS_OK | This function will always return STATUS_OK |
References nvm_is_ready(), NVM_MEMORY, and STATUS_OK.
void nvm_get_parameters | ( | struct nvm_parameters *const | parameters | ) |
Reads the parameters of the NVM controller.
Retrieves the page size, number of pages, and other configuration settings of the NVM region.
[out] | parameters | Parameter structure, which holds page size and number of pages in the NVM memory |
References Assert, nvm_parameters::bootloader_number_of_pages, nvm_parameters::eeprom_number_of_pages, nvm_parameters::nvm_number_of_pages, NVM_USER_MEMORY, and nvm_parameters::page_size.
bool nvm_is_page_locked | ( | uint16_t | page_number | ) |
Checks whether the page region is locked.
Extracts the region to which the given page belongs and checks whether that region is locked.
[in] | page_number | Page number to be checked |
true | Page is locked |
false | Page is not locked |
References _nvm_dev, Assert, and _nvm_module::number_of_pages.
|
inlinestatic |
Checks if the NVM controller is ready to accept a new command.
Checks the NVM controller to determine if it is currently busy execution an operation, or ready for a new command.
true | If the hardware module is ready for a new command |
false | If the hardware module is busy executing a command |
Referenced by nvm_erase_row(), nvm_execute_command(), nvm_get_fuses(), nvm_read_buffer(), nvm_set_config(), and nvm_write_buffer().
enum status_code nvm_read_buffer | ( | const uint32_t | source_address, |
uint8_t *const | buffer, | ||
uint16_t | length | ||
) |
Reads a number of bytes from a page in the NVM memory region.
Reads a given number of bytes from a given page address in the NVM memory space into a buffer.
[in] | source_address | Source page address to read from |
[out] | buffer | Pointer to a buffer where the content of the read page will be stored |
[in] | length | Number of bytes in the page to read |
STATUS_OK | Requested NVM memory page was successfully read |
STATUS_BUSY | NVM controller was busy when the operation was attempted |
STATUS_ERR_BAD_ADDRESS | The requested address was outside the acceptable range of the NVM memory region or not aligned to the start of a page |
STATUS_ERR_INVALID_ARG | The supplied read length was invalid |
References _nvm_dev, _nvm_module::number_of_pages, nvm_is_ready(), NVM_MEMORY, _nvm_module::page_size, STATUS_BUSY, STATUS_ERR_BAD_ADDRESS, STATUS_ERR_INVALID_ARG, and STATUS_OK.
Referenced by nvm_update_buffer().
enum status_code nvm_set_config | ( | const struct nvm_config *const | config | ) |
Sets the up the NVM hardware module based on the configuration.
Writes a given configuration of an NVM controller configuration to the hardware module, and initializes the internal device struct.
[in] | config | Configuration settings for the NVM controller |
STATUS_OK | If the initialization was a success |
STATUS_BUSY | If the module was busy when the operation was attempted |
STATUS_ERR_IO | If the security bit has been set, preventing the EEPROM and/or auxiliary space configuration from being altered |
References _nvm_dev, Assert, nvm_config::cache_readmode, nvm_config::disable_cache, _nvm_module::manual_page_write, nvm_config::manual_page_write, _nvm_module::number_of_pages, nvm_is_ready(), _nvm_module::page_size, nvm_config::sleep_power_mode, STATUS_BUSY, STATUS_ERR_IO, STATUS_OK, system_apb_clock_set_mask(), SYSTEM_CLOCK_APB_APBB, and nvm_config::wait_states.
Referenced by main().
enum status_code nvm_set_fuses | ( | struct nvm_fusebits * | fb | ) |
Set fuses from user row.
Set fuse settings from the user row.
[in] | fusebits | Pointer to a 64-bit wide memory buffer of type struct nvm_fusebits |
STATUS_OK | This function will always return STATUS_OK |
STATUS_BUSY | If the NVM controller was already busy executing a command when the new command was issued |
STATUS_ERR_IO | If the command was invalid due to memory or security locking |
STATUS_ERR_INVALID_ARG | If the given command was invalid or unsupported |
STATUS_ERR_BAD_ADDRESS | If the given address was invalid |
References nvm_fusebits::bod33_action, nvm_fusebits::bod33_enable, nvm_fusebits::bod33_hysteresis, nvm_fusebits::bod33_level, nvm_fusebits::bootloader_size, nvm_fusebits::eeprom_size, nvm_fusebits::lockbits, NVM_COMMAND_ERASE_AUX_ROW, NVM_COMMAND_PAGE_BUFFER_CLEAR, NVM_COMMAND_WRITE_AUX_ROW, nvm_execute_command(), STATUS_ERR_INVALID_ARG, STATUS_OK, nvm_fusebits::wdt_always_on, nvm_fusebits::wdt_early_warning_offset, nvm_fusebits::wdt_enable, nvm_fusebits::wdt_timeout_period, nvm_fusebits::wdt_window_mode_enable_at_poweron, and nvm_fusebits::wdt_window_timeout.
enum status_code nvm_update_buffer | ( | const uint32_t | destination_address, |
uint8_t *const | buffer, | ||
uint16_t | offset, | ||
uint16_t | length | ||
) |
Updates an arbitrary section of a page with new data.
Writes from a buffer to a given page in the NVM memory, retaining any unmodified data already stored in the page.
[in] | destination_address | Destination page address to write to |
[in] | buffer | Pointer to buffer where the data to write is stored |
[in] | offset | Number of bytes to offset the data write in the page |
[in] | length | Number of bytes in the page to update |
STATUS_OK | Requested NVM memory page was successfully read |
STATUS_BUSY | NVM controller was busy when the operation was attempted |
STATUS_ERR_BAD_ADDRESS | The requested address was outside the acceptable range of the NVM memory region |
STATUS_ERR_INVALID_ARG | The supplied length and offset was invalid |
References _nvm_dev, nvm_erase_row(), nvm_read_buffer(), nvm_write_buffer(), _nvm_module::page_size, STATUS_BUSY, STATUS_ERR_INVALID_ARG, STATUS_OK, system_interrupt_enter_critical_section(), and system_interrupt_leave_critical_section().
enum status_code nvm_write_buffer | ( | const uint32_t | destination_address, |
const uint8_t * | buffer, | ||
uint16_t | length | ||
) |
Writes a number of bytes to a page in the NVM memory region.
Writes from a buffer to a given page address in the NVM memory.
[in] | destination_address | Destination page address to write to |
[in] | buffer | Pointer to buffer where the data to write is stored |
[in] | length | Number of bytes in the page to write |
SAMD21_64K
, command NVM_COMMAND_RWWEE_WRITE_PAGE
must be executed before any other commands after writing a page, refer to errata 13588.STATUS_OK | Requested NVM memory page was successfully read |
STATUS_BUSY | NVM controller was busy when the operation was attempted |
STATUS_ERR_BAD_ADDRESS | The requested address was outside the acceptable range of the NVM memory region or not aligned to the start of a page |
STATUS_ERR_INVALID_ARG | The supplied write length was invalid |
References _nvm_dev, _nvm_module::manual_page_write, _nvm_module::number_of_pages, NVM_COMMAND_PAGE_BUFFER_CLEAR, NVM_COMMAND_WRITE_PAGE, nvm_execute_command(), nvm_is_ready(), NVM_MEMORY, _nvm_module::page_size, STATUS_BUSY, STATUS_ERR_BAD_ADDRESS, STATUS_ERR_INVALID_ARG, and STATUS_OK.
Referenced by nvm_update_buffer(), and program_memory().