EtherCAT SubDevice2.03.00
 
Loading...
Searching...
No Matches
Non-Volatile Memory (NVM)

Introduction

This page shall focus on the customer implementation of NVM (Non Volatile Memory) interface. The demo implementation is specifically designed for the TI reference design. However, it’s important to note that customization is required for the customer to adapt it to their specific needs. In other words, the customer must either create their own implementation or tailor the existing demo implementation to suit their requirements.

NVM Layer Architecture

Implementation Details

The application shall make use of the public functions related to the non-volatile memory interface from the header file nvm.h.

The application shall be able to specify the type of non-volatile memory used to store/retrieve the data, which is provided as an enumeration.

typedef enum NVM_type {
NVM_TYPE_EEPROM = 0,
NVM_TYPE_FLASH,
NVM_TYPE_END_NUM
} NVM_type_t;

The application can write data to the non-volatile memory in two modes.

  1. Blocking mode
    • The blocking API NVM_APP_write shall be used which directly triggers the TI drivers to write data into the non-volatile memory.
  2. Non blocking mode
    • The non blocking API NVM_APP_writeAsync shall be used which triggers the thread to write data into the non-volatile memory. The async write requests are always pushed to a protected queue.

In the non blocking mode before calling the API NVM_APP_writeAsync it is necessary to call the APIs NVM_APP_init which shall initialize the mutex lock for the queue, create the write task NVM_APP_writeTask with the specified priority and a semaphore for it. The NVM_APP_writeTask shall process the pending async write requests in a protected queue in FIFO sequence. The successfully processed write request is then removed from the queue.

uint32_t NVM_APP_init(const OSAL_TASK_Priority_t priority);

and NVM_APP_registerCallback to register the callback function to get the status of the async write process.

uint32_t NVM_APP_registerCallback(NVM_APP_writeCallback_t callback)

The callback function type shall be as specified below.

typedef void(*NVM_APP_writeCallback_t)(uint32_t status);

The write task NVM_APP_writeTask created for the non blocking NVM data write shall trigger the registered callback with the write status as a argument provided in the form of an enumeration specified below.

typedef enum NVM_err {
NVM_SUCCESS = 0,
NVM_ERR_FAIL,
NVM_ERR_BUSY,
NVM_ERR_REJECT,
NVM_ERR_INVALID,
NVM_ERR_MALLOC,
NVM_ERR_QUEUE_EMPTY,
NVM_ERR_QUEUE_FULL,
NVM_ERR_QUEUE_MTX,
NVM_ERR_END_ENUM
} NVM_err_t;

As a contradictory, the API NVM_APP_close kills the write task NVM_APP_writeTask and deinitialize the mutex and semaphore which were being created by the API NVM_APP_init

uint32_t NVM_APP_close(void);

The APIs NVM_APP_write and NVM_APP_writeAsync have similar set of parameters. The forceErase flag will decide the flash block erase frequency. A 'true' will always erase the flash block before writing data to the flash. A 'false' shall make the API to decide whether the flash block needs to be erased or not. Consecutive data write cycles to same flash block must set forceErase to 'false'. The NVM_APP_writeAsync has a additional parameter called isStaticData which indicates whether the application is passing a static data or not. The async write requests are always pushed to a queue and if the data is not not maintained by the application then a copy of data is saved in the queue.

uint32_t NVM_APP_write(
const NVM_type_t type,
const uint32_t id,
const uint32_t offset,
const uint32_t length,
const void * const pData,
const uint32_t forceErase);
uint32_t NVM_APP_writeAsync(
const NVM_type_t type,
const uint32_t id,
const uint32_t offset,
const uint32_t length,
const void * const pData,
const uint32_t forceErase,
const uint8_t isStaticData);

The parameter type can be NVM_TYPE_EEPROM or NVM_TYPE_FLASH depending on the implementation.
The parameter id can be CONFIG_EEPROM0 or CONFIG_FLASH0 or similar depending on the sysconfig adaptations.

SysConfig - EEPROM
SysConfig - Flash

The parameter offset shall be the data offset to write the data block into the non-volatile memory. For example, as per the AM64x/AM243x EVM User's Guide, the first 259 bytes of addressable EEPROM memory are pre-programmed with board identification information. In this case the offset shall be at least 259.

AM64x/AM243x EVM User's Guide

The parameter length shall the length of the data block and pData shall be the pointer to the data block to be written into the non-volatile memory.

Note:The API NVM_APP_writeAsync does NOT copy the data to another buffer when isStaticData is TRUE, therefore please ensure that the buffer is not destroyed after calling this API.

Below are the APIs that handle the NVM write request queue.

uint32_t NVM_APP_pushWriteReqToQueue(
const NVM_type_t type,
const uint32_t id,
const uint32_t offset,
const uint32_t length,
const void * const pData,
const uint32_t forceErase,
const uint8_t isStaticData)
{
// Acquire the write request queue mutex lock.
// Add write request to the queue.
// Release the write request queue mutex lock.
}
uint32_t NVM_APP_pullWriteReqFromQueue(NVM_APP_writeParam_t* pWriteReq)
{
// Acquire the write request queue mutex lock.
// fetch the write request from the queue in the order FIFO.
// Release the write request queue mutex lock.
}
uint32_t NVM_APP_removeWriteReqFromQueue(void)
{
// Acquire the write request queue mutex lock.
// remove the write request from the queue which has been successfully processed.
// Release the write request queue mutex lock.
}
uint32_t NVM_APP_getPendingWriteReqCount(void)
{
// return the pending write requests count in the queue.
}

Below is the sample implementation of the API NVM_APP_write in a application.

#define EEPROM_DATA_OFFSET (0x200U)
uint32_t buffer_length = 0x10;
// Allocate a memory block for the buffer used to store the data to be written into NVM.
buffer = OSAL_MEMORY_calloc(buffer_length,sizeof(uint8_t));
// Fill the allocated memory with valid data to be written into NVM.
NVM_APP_write( NVM_TYPE_EEPROM,
CONFIG_EEPROM0,
EEPROM_DATA_OFFSET,
buffer_length,
buffer,
true);

Below is the sample implementation of the API NVM_APP_read in a application.

#define EEPROM_DATA_OFFSET (0x200U)
uint32_t buffer_length = 0x10;
// Allocate a memory block for the buffer used to store the data read from the NVM.
buffer = OSAL_MEMORY_calloc(buffer_length,sizeof(uint8_t));
NVM_APP_read( NVM_TYPE_EEPROM,
CONFIG_EEPROM0,
EEPROM_DATA_OFFSET,
buffer_length,
buffer);

Below is the sample implementation of the API NVM_APP_writeAsync in a application where data is not maintained.

// Callback function to be attached to get the status of async NVM write.
// Hint: Use the registered callback to free the data buffer.
void myWriteAsyncCallback(uint32_t status)
{
if (status != NVM_SUCCESS)
{
// handle the error status
}
// free any allocated buffers etc..
}
#define EEPROM_DATA_OFFSET (0x200U)
uint32_t buffer_length = 0x10;
// Allocate a memory block for the buffer used to store the data to be written into NVM.
buffer = OSAL_MEMORY_calloc(buffer_length,sizeof(uint8_t));
NVM_err_t error;
error = NVM_APP_init(OSAL_TASK_Prio_Normal);
if (error != NVM_SUCCESS)
{
// handle the errors
}
error = NVM_APP_registerCallback(myWriteAsyncCallback);
if (error != NVM_SUCCESS)
{
// handle the errors
}
// Fill the allocated memory with valid data to be written into NVM.
error = NVM_APP_writeAsync( NVM_TYPE_EEPROM,
CONFIG_EEPROM0,
EEPROM_DATA_OFFSET,
buffer_length,
buffer,
true,
false);
if (error != NVM_SUCCESS)
{
// handle the busy or error state
}
// Release the allocated memory
OSAL_MEMORY_free(buffer);

Below is the sample implementation of the API NVM_APP_writeAsync in a application where data is maintained.

#define EEPROM_DATA_OFFSET (0x200U)
uint32_t buffer_length = 0x10;
// buffer used to store the data to be written into NVM.
static uint8_t buffer[buffer_length];
NVM_err_t error;
error = NVM_APP_init(OSAL_TASK_Prio_Normal);
if (error != NVM_SUCCESS)
{
// handle the errors
}
// Fill the 'buffer' with valid data to be written into NVM.
error = NVM_APP_writeAsync( NVM_TYPE_EEPROM,
CONFIG_EEPROM0,
EEPROM_DATA_OFFSET,
buffer_length,
buffer,
true,
true);
if (error != NVM_SUCCESS)
{
// handle the busy or error state
}