PSOC™ C1 Emulated EEPROM Middleware Library
Em_EEPROM Middleware Library

The Emulated EEPROM (Em_EEPROM) middleware emulates an EEPROM storage in PSOC™ C1 internal flash memory. The Em_EEPROM middleware operates on the top of the flash driver included in the PSC1M3 Peripheral Driver Library.

Use the Em_EEPROM to store non-volatile data on a target device when increasing flash memory endurance is required.

Please note the Internal Flash reserved by EEPROM middleware when using this asset.

Features:

  • EEPROM-Like Non-Volatile Storage
  • Easy to use Read and Write

General Description

The PSOC™ C1 emulated EEPROM support is provided with the APIs described below.

It should be noted that the non-volatile memory required to store the EEPROM Data is mapped to Internal Flash. In the PSOC™ C1 emulated EEPROM Middleware the Flash region required for EEPROM is allocated at the very End of Internal Flash. It is advisable for user(s) of emulated EEPROM to update (modify) their Linker file (script) to reduce the amount of Flash available for code and initialized data.

Linker Script Updates

It should be noted that the non-volatile memory required to store the EEPROM Data is mapped to Internal Flash. In the PSOC™ C1 emulated EEPROM Middleware the Flash region required for EEPROM is allocated at the very End of Internal Flash. The amount of Flash space reserved can be calculated using the macro: E_EEPROM_PSC1_FLASH_TOTAL_SIZE an internal usage macro defined in code. It is advisable for user(s) of emulated EEPROM to update (modify) their Linker file (script) to reduce the amount of Flash available for code and initialed data by the size reserved for EEPROM size desired by application. This will remove the mapped region of Flash form being used for code or initialized data. When properly updated linker script is used and if the user application grows such that it overlaps the Flash region utilized by EEPROM, there will linking errors during the build.

For the Kit/PSC device you are using, please select the proper Linker script. For Infineon ModusToolbox targets, the GCC_ARM and ARM linker scripts are present in target for the kit under TOOLCHAIN_GCC_ARM and TOOLCHAIN_ARM. For IAR, please make a copy of the IAR linker script from the IAR toolchain and edit it for the Project using PSOC™ C1 Emulated EEPROM. Note - the ModusToolBox allows use of custom Linker script by editing in Makefile the tag LINKER_SCRIPT=<path to custom linker script>.

Examples of how the linker scripts be modified is provided below. Assumption for the explanation of Linker scripts changes is that the Flash reserved for EEPROM is 4 KBytes (0x1000). For user required EEPROM size please determine the size of Flash needed to be reserved from the the output of macro: E_EEPROM_PSC1_FLASH_TOTAL_SIZE for given EEPROM size and make appropriate changes..

Example of GCC_ARM Linker script for PSOC™ C1 Kit/Device (PSC1M-0200.ld):

Original Linker script Memory map and sections:

MEMORY
{
FLASH(RX) : ORIGIN = 0x10001000, LENGTH = 0x32000
SRAM(!RX) : ORIGIN = 0x20000000, LENGTH = 0x4000
}

Modified Linker script Memory map (4 KBytes reserved for EEPROM):

MEMORY
{
FLASH(RX) : ORIGIN = 0x10001000, LENGTH = 0x31000
SRAM(!RX) : ORIGIN = 0x20000000, LENGTH = 0x4000
}

Example of ARM Linker script for PSOC™ C1 Kit/Device (PSC1M-0200.sct):

Original Linker Memory map:

#define __ROM_BASE 0x10001000
#define __ROM_SIZE 0x00032000

Modified Linker Memory map (4 KBytes reserved for EEPROM):

#define __ROM_BASE 0x10001000
#define __ROM_SIZE 0x00031000

Example of IAR Linker script for PSOC™ C1 Kit/Device (PSC1M-0200.icf):

Original Linker Memory map:

define symbol __ICFEDIT_region_ROM_start__ = 0x10001000;
define symbol __ICFEDIT_region_ROM_end__ = 0x10032FFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__ = 0x20003FFF;

Modified Linker Memory map (4 KBytes reserved for EEPROM):

define symbol __ICFEDIT_region_ROM_start__ = 0x10001000;
define symbol __ICFEDIT_region_ROM_end__ = 0x10031FFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__ = 0x20003FFF;

Application Configuration and API Usage

The PSOC™ C1 Emulated EEPROM asset can be used to store non-volatile data in Flash with improved resiliency. In PSOC™ C1 emulated eeprom is stored in Flash at the very end. When compiling the PSOC™ C1 eeprom asset the macro: E_EEPROM_PSC1_FLASH_EEPROM_SIZE has to be defined to the size of the EEPROM region required. This definition can be provided through the EEPROM Personality in ModusToolbox or passed as DEFINE+=E_EEPROM_PSC1_FLASH_EEPROM_SIZE="desired size". Note - the size of EEPROM should be larger than the sum of All the blocks that are configured in the PSOC™ C1 EEPROM configuration structure. This will allow multiple updates in current flash bank before need for Garbage collection to next bank. This improves the flash resiliency. The region of flash that will be used for storage should be erased before the first time it is used to map EEPROM data. After using region for EEPROM, this region should not be erased unless it is explicitly desired to get rid of previously stored EEPROM data.

The PSOC™ C1 EEPROM has a complex configuration and handle data structure which passes in the initial configuration information and it also stores the run-time data needed for subsequent API execution. The PSOC™ C1 Configuration data structure is:

Data structure to configure the APP properties. Use E_EEPROM_PSC1_t type for accessing the members * typedef struct E_EEPROM_PSC1 { E_EEPROM_PSC1_BLOCK_t *block_config_ptr; // **< Pointer to user block configurations *

E_EEPROM_PSC1_DATA_t *data_ptr; // **< Pointer to the state variable data structure *

#ifdef E_EEPROM_PSC1_CRC_SW_ENABLED

CRC_SW_t* const crc_handle_ptr; // **< CRC APP handle pointer*

#endif

E_EEPROM_PSC1_STATUS_t state; // **< Current state of the APP instance*

const uint8_t block_count; // **< Number of configured user data blocks *

const uint8_t erase_all_auto_recovery; // **< Erase Complete emulation area and recover to default state *

const uint8_t data_block_crc; // **< Allow to calculate CRC for each data block on write *

const uint8_t garbage_collection; // **< Enables garbage collection when no space available for new write*

} E_EEPROM_PSC1_t;

The application should decide the number of blocks that are needed by it (block_count) and provide 2 arrays of size block_count, namely: block_config_ptr[block_count] and data_ptr[block_count]. Note: the maximum block_count supported is 10.

The first array block_config_ptr[block_count] is the configuration information of "block number" and "size" for each block in EEPROM. Note the Size of EEPROM (E_EEPROM_PSC1_FLASH_EEPROM_SIZE) provided by Personality/Define via Makefile should definitely be much larger than the sum of All the block sizes defined in this configuration data structure. Giving a much larger value will reserve more Flash at the end of Flash block but will increase the flash resiliency. The maximum block size size supported is 32 KBytes bytes and the minimum is 1 byte.

The configuration parameter "crc_handle_ptr" can be set to "CRC_SW_0" to use the CRC sw bundled with the asset if CRC is to be enabled.

The data structure parameter: state is Not a configuration parameter.

The Configuration parameter "block_count" denotes the number of user "blocks" Note PSOC™ C1 API support read/write only on block basis.

The configuration parameter: erase_all_auto_recovery" should be usually 0 (off). It can be used to erase Flash but should Not be set (1) during regular execution otherwise EEPROM data will be lost on every reboot.

The configuration parameter: data_black_crc, should be set if CRC protection is required. Note - when setting this, the "crc_handle_ptr" should also be enabled.

The configuration parameter: garbage_collection, when set to 1, will enable Automatic garbage collection. If user does Not want automatic garbage collection, then they have to explicitly check in run time code, whether garbage collection is needed and explicitly call it.

Typical EEPROM asset API sequence can be: E_EEPROM_PSC1_Init(&E_EEPROM_PSC1_handle); and then read/write APIs: E_EEPROM_PSC1_Write(blockNum, data_wbuffer); E_EEPROM_PSC1_Read(blockNum, 0U, data_rbuffer, block_size);