Hardware Abstraction Layer (HAL)
NVM (Onboard Non-Volatile Memory)

General Description

High level interface to the onboard Non-Volatile memory (Internal Flash, RRAM, OTP region).

Onboard NVM provides non-volatile storage for factory settings, secure data, user firmware, configuration, and bulk data.

This driver allows data to be read from and written to NVM. It also provides the ability to obtain information about the address and characteristics of the NVM block(s) contained on the device. During NVM write time, the device should not be reset (including XRES pin, software reset, and watchdog) or unexpected changes may be made to portions of the NVM. Also, the low-voltage detect circuits should be configured to generate an interrupt instead of a reset.

Note
A Read while Write violation may occur for some devices when a NVM Read operation is initiated in the same or neighboring NVM sector/region where the NVM Write, Erase(if applicable), or Program operation is working. Refer the device datasheet for more information. This violation may cause a HardFault exception. To avoid the Read while Write violation, the user must carefully split the Read and Write operations on NVM sectors/regions which are not neighboring, considering all cores in a multi-processor device. User may edit the linker script to place the code into neighboring sectors/regions. For example, use sectors number 0 and 1 for code and sectors 2 and 3 for data storage.

Features

Code Snippets

Snippet 1: Get NVM Characteristics

Following code snippet demonstrates how to fetch NVM characteristics. Refer cyhal_nvm_info_t for more information.

cyhal_nvm_t nvm_obj;
cyhal_nvm_info_t nvm_info;
uint32_t nvm_start_address = 0;
uint32_t nvm_size = 0;
uint32_t nvm_sector_size = 0;
uint32_t nvm_block_size = 0;
uint8_t nvm_erase_value = 0;
bool is_erase_required = false;
// Initialize NVM object
cyhal_nvm_init(&nvm_obj);
// Get NVM characteristics like NVM type, number of NVM regions and their organization
cyhal_nvm_get_info(&nvm_obj, &nvm_info);
for (int index = 0; index < nvm_info.region_count; index++)
{
const cyhal_nvm_region_info_t* region_info = nvm_info.regions;
region_info += index;
nvm_type = region_info->nvm_type;
nvm_start_address = region_info->start_address;
nvm_size = region_info->size;
nvm_sector_size = region_info->sector_size;
nvm_block_size = region_info->block_size;
is_erase_required = region_info->is_erase_required;
nvm_erase_value = region_info->erase_value;
}
NVM object.
Definition: cyhal_hw_types.h:726
uint8_t erase_value
NVM erase value (if applicable).
Definition: cyhal_nvm.h:136
bool is_erase_required
true = erase required before program, false = erase not required before program.
Definition: cyhal_nvm.h:135
uint32_t start_address
Base address of the distinct NVM region.
Definition: cyhal_nvm.h:130
uint32_t block_size
Block size (programming granularity) of the distinct NVM region.
Definition: cyhal_nvm.h:134
const cyhal_nvm_region_info_t * regions
Array of the distinct NVM regions.
Definition: cyhal_nvm.h:143
uint32_t sector_size
Sector size of the distinct NVM region.
Definition: cyhal_nvm.h:133
uint32_t size
Size of the distinct NVM region.
Definition: cyhal_nvm.h:132
uint8_t region_count
The number of distinct NVM regions.
Definition: cyhal_nvm.h:142
cyhal_nvm_type_t nvm_type
NVM type.
Definition: cyhal_nvm.h:129
void cyhal_nvm_get_info(cyhal_nvm_t *obj, cyhal_nvm_info_t *info)
Get details about the NVM memory regions such as NVM type, start address, size, is_erase_required,...
cyhal_nvm_type_t
Enum of Non-volatile memory (NVM) types.
Definition: cyhal_nvm.h:119
cy_rslt_t cyhal_nvm_init(cyhal_nvm_t *obj)
Initialize the cyhal_nvm_t object for accessing NVM through the HAL.
@ CYHAL_NVM_TYPE_FLASH
Internal Flash.
Definition: cyhal_nvm.h:121
Information about all of the regions of NVM memory.
Definition: cyhal_nvm.h:141
Information about a single region of NVM memory.
Definition: cyhal_nvm.h:128

Snippet 2: Blocking NVM Erase-Write and Read

Following code snippet demonstrates blocking NVM write. It uses a constant array with a size equaling the size of one NVM row/block. It uses blocking NVM write operation which blocks the caller until the write is completed. It then verifies the NVM data by comparing the NVM data with the written data.

cyhal_nvm_t nvm_obj;
cyhal_nvm_info_t nvm_info;
cy_rslt_t result = CY_RSLT_SUCCESS; // NVM Write Status
uint8_t ram_data[512]; // RAM data to be written to NVM
uint8_t nvm_read_data[512]; // RAM data read from NVM for validation
bool compare_status = false; // Compare Status
uint32_t nvm_addr;
// Initialize NVM object
cyhal_nvm_init(&nvm_obj);
// Get NVM characteristics like number of NVM regions, type, and their organization
cyhal_nvm_get_info(&nvm_obj, &nvm_info);
// NVM region 0 last block
uint32_t block_num = (nvm_info.regions[0].size/nvm_info.regions[0].block_size) - 1;
// NVM region 0 last block address
nvm_addr = nvm_info.regions[0].start_address + (block_num * nvm_info.regions[0].block_size);
// Initialize the data in RAM that will be written into NVM
for (size_t index = 0; index < sizeof(ram_data); index++)
{
ram_data[index] = (uint8_t)index;
}
if (nvm_info.regions[0].is_erase_required) // Check if erase is required on the given NVM type
{
// Blocking NVM erase prior to NVM write
result = cyhal_nvm_erase(&nvm_obj, nvm_addr);
}
if (result == CY_RSLT_SUCCESS)
{
// Blocking NVM write
result = cyhal_nvm_program(&nvm_obj, nvm_addr, (const uint32_t*)ram_data);
if (result == CY_RSLT_SUCCESS)
{
// Read NVM data
result =
cyhal_nvm_read(&nvm_obj, (uint32_t)nvm_addr, nvm_read_data, sizeof(nvm_read_data));
if (result == CY_RSLT_SUCCESS)
{
// Verify the data written into NVM by comparing it with the RAM data
if (0 == memcmp(ram_data, nvm_read_data, sizeof(nvm_read_data)))
{
compare_status = true;
}
}
}
}
else
{
// Error erasing NVM
}
cy_rslt_t cyhal_nvm_erase(cyhal_nvm_t *obj, uint32_t address)
Erase one block of NVM starting at the given address.
cy_rslt_t cyhal_nvm_program(cyhal_nvm_t *obj, uint32_t address, const uint32_t *data)
Program one block with the provided data starting at the given address.
cy_rslt_t cyhal_nvm_read(cyhal_nvm_t *obj, uint32_t address, uint8_t *data, size_t size)
Read size amount of data starting from the given address of NVM.
uint32_t cy_rslt_t
Provides the result of an operation as a structured bitfield.
Definition: cy_result.h:426
#define CY_RSLT_SUCCESS
cy_rslt_t return value indicating success
Definition: cy_result.h:453

Snippet 3: Non-blocking NVM Erase-Write and Read

Following code snippet implements the non-blocking NVM write using polling to complete the NVM write operation. It uses a constant array with a size equaling the size of one NVM row/block. It uses a polling method to complete the NVM write operation. It then verifies the NVM data by comparing the NVM data with the written data.

cyhal_nvm_t nvm_obj;
cyhal_nvm_info_t nvm_info;
cy_rslt_t result = CY_RSLT_SUCCESS; // NVM Write Status
uint8_t ram_data[512]; // RAM data to be written to NVM
uint8_t nvm_read_data[512]; // RAM data read from NVM for validation
bool compare_status = false; // Compare Status
uint32_t nvm_addr;
// Wait for 100ms for the NVM write to complete
uint32_t timeout = 100;
// Initialize NVM object
cyhal_nvm_init(&nvm_obj);
// Get NVM characteristics like number of NVM regions, type, and their organization
cyhal_nvm_get_info(&nvm_obj, &nvm_info);
// NVM region 0 last block
uint32_t block_num = (nvm_info.regions[0].size/nvm_info.regions[0].block_size) - 1;
// NVM region 0 last block address
nvm_addr = nvm_info.regions[0].start_address + (block_num * nvm_info.regions[0].block_size);
// Initialize the data in RAM that will be written into NVM
for (size_t index = 0; index < sizeof(ram_data); index++)
{
ram_data[index] = (uint8_t)index;
}
if (nvm_info.regions[0].is_erase_required) // Check if erase is required on the given NVM type
{
// Non-blocking NVM erase prior to NVM write
result = cyhal_nvm_start_erase(&nvm_obj, nvm_addr);
if (result == CY_RSLT_SUCCESS)
{
while (true != cyhal_nvm_is_operation_complete(&nvm_obj))
{
// Wait for the NVM erase to be successful
}
}
else
{
// Error erasing NVM
}
}
if (result == CY_RSLT_SUCCESS)
{
// Non-blocking NVM write
result = cyhal_nvm_start_program(&nvm_obj, nvm_addr, (const uint32_t*)ram_data);
if (result == CY_RSLT_SUCCESS)
{
// Wait for the successful NVM write
while ((true != cyhal_nvm_is_operation_complete(&nvm_obj)) && (0 < timeout))
{
timeout--;
cyhal_system_delay_ms(1); // delay one millisecond each iteration
}
// Flag error if the expected NVM write status not returned within timeout period
if (0 != timeout)
{
// Read NVM data
result = cyhal_nvm_read(&nvm_obj, nvm_addr, nvm_read_data, sizeof(nvm_read_data));
if (result == CY_RSLT_SUCCESS)
{
// Verify the data written into NVM by comparing it with the RAM data
if (0 == memcmp(ram_data, nvm_read_data, sizeof(nvm_read_data)))
{
compare_status = true;
}
}
}
}
}
cy_rslt_t cyhal_nvm_start_erase(cyhal_nvm_t *obj, uint32_t address)
Start an asynchronous erase of a single block of NVM starting at the given address.
cy_rslt_t cyhal_nvm_start_program(cyhal_nvm_t *obj, uint32_t address, const uint32_t *data)
Start asynchronous programming of a single block of NVM starting at the given address.
bool cyhal_nvm_is_operation_complete(cyhal_nvm_t *obj)
Reports status of the last NVM operation.
cy_rslt_t cyhal_system_delay_ms(uint32_t milliseconds)
Requests that the current operation delays for at least the specified length of time.

API Reference

 NVM HAL Results
 NVM specific return codes.
 

Data Structures

struct  cyhal_nvm_region_info_t
 Information about a single region of NVM memory. More...
 
struct  cyhal_nvm_info_t
 Information about all of the regions of NVM memory. More...
 

Enumerations

enum  cyhal_nvm_type_t {
  CYHAL_NVM_TYPE_INVALID = 0U ,
  CYHAL_NVM_TYPE_FLASH = 1U ,
  CYHAL_NVM_TYPE_RRAM = 2U ,
  CYHAL_NVM_TYPE_OTP = 3U
}
 Enum of Non-volatile memory (NVM) types. More...
 

Functions

cy_rslt_t cyhal_nvm_init (cyhal_nvm_t *obj)
 Initialize the cyhal_nvm_t object for accessing NVM through the HAL. More...
 
void cyhal_nvm_free (cyhal_nvm_t *obj)
 Free resources associated with the NVM HAL driver. More...
 
void cyhal_nvm_get_info (cyhal_nvm_t *obj, cyhal_nvm_info_t *info)
 Get details about the NVM memory regions such as NVM type, start address, size, is_erase_required, and erase values etc. More...
 
cy_rslt_t cyhal_nvm_read (cyhal_nvm_t *obj, uint32_t address, uint8_t *data, size_t size)
 Read size amount of data starting from the given address of NVM. More...
 
cy_rslt_t cyhal_nvm_erase (cyhal_nvm_t *obj, uint32_t address)
 Erase one block of NVM starting at the given address. More...
 
cy_rslt_t cyhal_nvm_write (cyhal_nvm_t *obj, uint32_t address, const uint32_t *data)
 This function erases the block, if required, and writes the new data into the block starting at the given address. More...
 
cy_rslt_t cyhal_nvm_otp_write (cyhal_nvm_t *obj, uint32_t address, uint8_t data)
 Write one-time data to the given byte location in the provided block of NVM OTP region. More...
 
cy_rslt_t cyhal_nvm_program (cyhal_nvm_t *obj, uint32_t address, const uint32_t *data)
 Program one block with the provided data starting at the given address. More...
 
cy_rslt_t cyhal_nvm_start_erase (cyhal_nvm_t *obj, uint32_t address)
 Start an asynchronous erase of a single block of NVM starting at the given address. More...
 
cy_rslt_t cyhal_nvm_start_write (cyhal_nvm_t *obj, uint32_t address, const uint32_t *data)
 Start an asynchronous write (Erase if required + Program) on single block of NVM starting at the given address. More...
 
cy_rslt_t cyhal_nvm_start_program (cyhal_nvm_t *obj, uint32_t address, const uint32_t *data)
 Start asynchronous programming of a single block of NVM starting at the given address. More...
 
bool cyhal_nvm_is_operation_complete (cyhal_nvm_t *obj)
 Reports status of the last NVM operation. More...
 

Data Structure Documentation

◆ cyhal_nvm_region_info_t

struct cyhal_nvm_region_info_t
Data Fields
cyhal_nvm_type_t nvm_type NVM type.
uint32_t start_address Base address of the distinct NVM region.
uint32_t offset Offset to the address in the distinct NVM region.
uint32_t size Size of the distinct NVM region.
uint32_t sector_size Sector size of the distinct NVM region.
uint32_t block_size Block size (programming granularity) of the distinct NVM region.
bool is_erase_required true = erase required before program, false = erase not required before program.
uint8_t erase_value NVM erase value (if applicable).

◆ cyhal_nvm_info_t

struct cyhal_nvm_info_t
Data Fields
uint8_t region_count The number of distinct NVM regions.
const cyhal_nvm_region_info_t * regions Array of the distinct NVM regions.

Enumeration Type Documentation

◆ cyhal_nvm_type_t

Enum of Non-volatile memory (NVM) types.

Enumerator
CYHAL_NVM_TYPE_INVALID 

Invalid type of NVM.

CYHAL_NVM_TYPE_FLASH 

Internal Flash.

CYHAL_NVM_TYPE_RRAM 

RRAM.

CYHAL_NVM_TYPE_OTP 

OTP.

Function Documentation

◆ cyhal_nvm_init()

cy_rslt_t cyhal_nvm_init ( cyhal_nvm_t obj)

Initialize the cyhal_nvm_t object for accessing NVM through the HAL.

Parameters
[in]objPointer to a NVM object. The caller must allocate the memory for this object but the init function will initialize its contents.
Returns
The status of the init request. Returns CY_RSLT_SUCCESS on successful operation.

◆ cyhal_nvm_free()

void cyhal_nvm_free ( cyhal_nvm_t obj)

Free resources associated with the NVM HAL driver.

Parameters
[out]objThe NVM object.

◆ cyhal_nvm_get_info()

void cyhal_nvm_get_info ( cyhal_nvm_t obj,
cyhal_nvm_info_t info 
)

Get details about the NVM memory regions such as NVM type, start address, size, is_erase_required, and erase values etc.

Refer cyhal_nvm_info_t, cyhal_nvm_region_info_t for more information.

Parameters
[in]objThe NVM object.
[out]infoThe NVM characteristic info.

Refer Snippet 1: Get NVM Characteristics for more information.

◆ cyhal_nvm_read()

cy_rslt_t cyhal_nvm_read ( cyhal_nvm_t obj,
uint32_t  address,
uint8_t *  data,
size_t  size 
)

Read size amount of data starting from the given address of NVM.

Parameters
[in]objThe NVM object.
[in]addressAddress to begin reading from.
[out]dataThe buffer to read data into.
[in]sizeThe number of bytes to read.
Returns
The status of the read request. Returns CY_RSLT_SUCCESS on successful operation.

Refer Snippet 2: Blocking NVM Erase-Write and Read for more information.

◆ cyhal_nvm_erase()

cy_rslt_t cyhal_nvm_erase ( cyhal_nvm_t obj,
uint32_t  address 
)

Erase one block of NVM starting at the given address.

The address must be at block boundary. This will block until the erase operation is complete.

See also
cyhal_nvm_get_info() to get the NVM characteristics for legal address values, is erase required/applicable, and the erase block size(if applicable).
Parameters
[in]objThe NVM object
[in]addressThe block address to be erased
Returns
The status of the erase request. Returns CY_RSLT_SUCCESS on successful operation.

Refer Snippet 2: Blocking NVM Erase-Write and Read for more information.

◆ cyhal_nvm_write()

cy_rslt_t cyhal_nvm_write ( cyhal_nvm_t obj,
uint32_t  address,
const uint32_t *  data 
)

This function erases the block, if required, and writes the new data into the block starting at the given address.

The address must be at block boundary. This will block until the write operation is complete.

See also
cyhal_nvm_get_info() to get the NVM characteristics for legal address values and the write block size. The provided data buffer must be at least as large as the NVM block_size.
Note
Generally the data to be written must be located in the SRAM memory region.
Parameters
[in]objThe NVM object
[in]addressThe address of the block to be written
[in]dataThe data buffer to be written to the NVM block
Returns
The status of the write request. Returns CY_RSLT_SUCCESS on successful operation.

Refer Snippet 2: Blocking NVM Erase-Write and Read for more information.

◆ cyhal_nvm_otp_write()

cy_rslt_t cyhal_nvm_otp_write ( cyhal_nvm_t obj,
uint32_t  address,
uint8_t  data 
)

Write one-time data to the given byte location in the provided block of NVM OTP region.

The block must be within the defined block range of the OTP (refer the device datasheet for more information).

Note
You can only ONCE write data at desired byte in specific block, if you will try to do it more times, you can have broken data at this location.
See also
cyhal_nvm_get_info() to get the NVM OTP region characteristics for legal address values, size and the OTP block size.
Parameters
[in]objThe NVM object
[in]addressThe address of the block to be written
[in]dataThe data to be written to the OTP memory
Returns
The status of the program request. Returns CY_RSLT_SUCCESS on successful operation.

◆ cyhal_nvm_program()

cy_rslt_t cyhal_nvm_program ( cyhal_nvm_t obj,
uint32_t  address,
const uint32_t *  data 
)

Program one block with the provided data starting at the given address.

The address must be at block boundary. This will block until the write operation is complete.

Note
This function does not erase the block prior to writing. The block must be erased first via a separate call to erase.
See also
cyhal_nvm_get_info() to get the NVM characteristics for legal address values and the total block size. The provided data buffer must be at least as large as the NVM block_size.
Note
Generally the data to be programmed must be located in the SRAM memory region.
Parameters
[in]objThe NVM object
[in]addressThe address of the block to be programmed
[in]dataThe data buffer to be programmed to the NVM block
Returns
The status of the program request. Returns CY_RSLT_SUCCESS on successful operation.

◆ cyhal_nvm_start_erase()

cy_rslt_t cyhal_nvm_start_erase ( cyhal_nvm_t obj,
uint32_t  address 
)

Start an asynchronous erase of a single block of NVM starting at the given address.

Returns immediately and reports a successful start or reason for failure. The address must be aligned on a block boundary.

See also
cyhal_nvm_get_info() to get the NVM characteristics for legal address values, is erase required/applicable, and the erase block size(if applicable).
Parameters
[in]objThe NVM object
[in]addressThe block address to be erased
Returns
The status of the start_erase request.

Refer Snippet 3: Non-blocking NVM Erase-Write and Read for more information.

◆ cyhal_nvm_start_write()

cy_rslt_t cyhal_nvm_start_write ( cyhal_nvm_t obj,
uint32_t  address,
const uint32_t *  data 
)

Start an asynchronous write (Erase if required + Program) on single block of NVM starting at the given address.

Returns immediately and reports a successful start or reason for failure. The address must be aligned on a block boundary.

See also
cyhal_nvm_get_info() to get the NVM characteristics for legal address values and the write block size. The provided data buffer must be at least as large as the NVM block_size.
Note
Generally the data to be written must be located in the SRAM memory region.
Parameters
[in]objThe NVM object
[in]addressThe address of the block to be written
[in]dataThe data buffer to be written to the NVM block
Returns
The status of the start_write request.

Refer Snippet 3: Non-blocking NVM Erase-Write and Read for more information.

◆ cyhal_nvm_start_program()

cy_rslt_t cyhal_nvm_start_program ( cyhal_nvm_t obj,
uint32_t  address,
const uint32_t *  data 
)

Start asynchronous programming of a single block of NVM starting at the given address.

Returns immediately and reports a successful start or reason for failure.

Note
This function does not erase the block prior to writing. The block must be erased first via a separate call to erase.
See also
cyhal_nvm_get_info() to get the NVM characteristics for legal address values and the total block size. The provided data buffer must be at least as large as the NVM block_size.
Note
Generally the data to be programmed must be located in the SRAM memory region.
Parameters
[in]objThe NVM object
[in]addressThe address of the block to be programmed
[in]dataThe data buffer to be programmed to the NVM block
Returns
The status of the program request. Returns CY_RSLT_SUCCESS on successful operation.

◆ cyhal_nvm_is_operation_complete()

bool cyhal_nvm_is_operation_complete ( cyhal_nvm_t obj)

Reports status of the last NVM operation.

Parameters
[in]objThe NVM object
Returns
true if NVM operation is complete. false otherwise.