EEPROM Usage Note for PSoC® 1 Family Devices - KBA82882

Version: **


Question: What are the important factors to remember while using the EEPROM User Module?



The EEPROM User Module is a very handy user module for emulating an EEPROM in the Flash program memory. Here are some key points to remember while using the EEPROM User Module.

User Module Parameters

Starting Block: This specifies the flash block number where the EEPROM begins. Always place the EEPROM in the last blocks of the flash. For example, in a 32K device, a 256 byte (four blocks) EEPROM should be placed in blocks 508 to 511. So, the first block should be 508. This ensures that maximum space is available for the code memory and prevents clash between code memory and EEPROM.

Remember to modify the flashsecurity.txt file and set the protection level of the flash blocks to “U” or “R”.

w w w w w w w w w w w w w w w w ; Base Address 7800  w w w w w w w w w w w w u u u u ; Base Address 7C00  ; End 32K parts

Length: This parameter sets the size of the EEPROM in bytes. For the above example, the length parameter would be 256.

EEPROM Write Function

To write data to the EEPROM, use the EEPROM_bE2Write function. The prototype of the function is:

char EEPROM_bE2Write(WORD wAddr, BYTE *pbData, WORD wByteCount, char Temperature);

wAddr: This is the location in the EEPROM where you would like to write the data. A very common mistake is to enter the physical address of the flash location. The value should be a relative location in the EEPROM, not in flash. For the example mentioned above, to write data to the first location in the EEPROM, the value of wAddr should be 0x0000, not 0x7F00.

*pbData: This is the pointer to the buffer that holds the data you want to write to the EEPROM. If the data is not in a char buffer, then you use typecasting. For example, to write a structure MyStruct, typecast the pointer to (char*)&MyStruct.

wByteCount: This is the number of bytes to be written to the EEPROM.

Temperature: The Temperature parameter is used by the EEPROM API to calculate the flash write pulse width. At higher temperatures the flash has to be written with a smaller pulse width and at lower temperatures with a longer pulse width. The flash will meet its maximum endurance and write cycles if it is written with the correct pulse width. If the device is going to operate within a temperature range of 0 to 50 degrees, it is okay to pass the value of 25 for temperature. But for operation over the full temperature range, use the FlashTemp User Module and pass the correct die temperature. If this is not done, either the data retention or the flash endurance will be compromised. If the temperature value passed is less than the operating temperature, the flash will be written with a longer pulse width than required. This will reduce the flash endurance. On the other hand, if the temperature value passed is higher than the operating temperature, the flash will be written with a lower pulse width than required. While this does not affect the endurance, the data retention will be less than the guaranteed 10 years.

The bE2Write function returns the status of the write operation. A return value of 0x00 means the write was successful. -1 means error in writing, which could be because the flash is write-protected. -2 means stack overflow. Always check the return value in your program to make sure that the write was successful.

Full Block Write vs. Partial Write

EEPROM writes always take place in 64 byte blocks. When you write less than 64 bytes of data, it is called a partial write. The flash write API first reads all the 64 bytes from the flash block into RAM, modifies the desired bytes and writes back the 64 bytes of data to Flash. This results in a heavy RAM overhead requiring 103 bytes of stack space, whereas a full block write takes only 32 bytes of stack. In devices with only one RAM page, the global variables and stack share the 256 bytes. If the RAM usage of the globals is high, this could lead to stack overflow errors while performing partial writes. Under such conditions, it is always advisable to perform a 64-byte write. Even if you are writing, say, 10 bytes of data, set the ByteCount to 64. The first 10 bytes will be the actual data followed by data from subsequent RAM locations. Check out the EEPROM User Module Data Sheet under the section “Efficient Memory Usage” for more details.

Initializing the EEPROM with Data

Many times you will be using the EEPROM to store calibration data (or any other system related data), where you would like to load the EEPROM with some initial values while the device is programmed. The following method may be used to achieve this.

In C: Use the #pragma abs_address directive. For example, if the EEPROM is placed in the last flash block in a 32K device, and if you wanted to initialize the first 10 bytes with some value:

#pragma abs_address 0x7FC0  const char InitialValues[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09};  #pragma end_abs_address

In assembly:

area eeprom(rom, abs)  org 0x7FC0  db 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09

A Practical Situation—Storing and Retrieving a Structure

Let us take a look at a practical EEPROM usage where a calibration structure is stored, read, and written in the EEPROM.

Create a typedef for the structure:

typedef struct CAL_STRUCT  {  int Offset;  float Scale;  }CAL_STRUCT;

RAM variable to store the calibration values:

CAL_STRUCT CalValuesRam;

Initialize the EEPROM with initial values:

#pragma abs_address 0x7FC0  const CAL_STRUCT CalValuesEeprom = {  0x0023, // Initial value for offset  2.5456 // Initial value for scale  };

Now to read the value from the EEPROM to the RAM, you can use either the EEPROM_Read function:

EEPROM_E2Read(0x0000, char* &CalValuesRam, sizeof(CalValuesRam));


CalValuesRam = CalValuesEeprom;

To write the values from the RAM to EEPROM

EEPROM_bE2Write(0x0000,(char*)&CalValuesRam, 64, 25);

The EEPROM Datasheet has more detailed information about EEPROM usage and simple example code.