Emulated EEPROM on 4247-M485

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

I am using a CY8C4247AZI-M485 and want to use the emulated EEPROM that is mentioned in both the data sheet and TRM.

   

However, in PSoC Creator 3.3 there is no Em_EEPROM component listed.

   

Any ideas?

   

- Jim

0 Likes
3 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Jim, I would suggest you to file a support case. To do so, at top of this page "Design Support -> Create a Support Case".

   

It would be nice when you keep us informed of the answers form Cypress.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Thanks for your input, and that of other posts. I get a lot from the forum, so hopefully I can add something for a change...

   

It isn't as difficult as I first thought, but there are some things to keep in mind.

   

You need a block of flash for use as EEPROM, it needs to:

   
        
  • Be a multiple of flash row size
  •     
  • Be aligned to a flash row
  •     
  • Be allocated in flash address space
  •    
   

Here is how I made this happen:

   

static const uint8 CYCODE eeprom_array[CY_FLASH_SIZEOF_ROW] CY_ALIGN(CY_FLASH_SIZEOF_ROW) = { 250, 0 };

   

The "const" and initializer are what makes the compiler allocate this in flash. I didn't need the CYCODE but left it in for illustration, and some compilers might need it (I am using GCC)

   

REMEMBER: This initialization is only performed when you FLASH the chip, NOT every time it RESETS. See the warning below.

   

WARNING: Every time you start the debugger it flashes the chip, so it will look like the code is not working... It only took about an hour for me to realize this... 😉

   

Since you are dealing with rows at a time, you will need some sort of RAM buffer:

   

static uint8 eeprom_row_image[CY_FLASH_SIZEOF_ROW];

   

Also since the write function wants to know the flash row, you will need to calculate it:

   

static uint32 my_eeprom_row;

   

my_eeprom_row = ( (uint32)eeprom_array - CY_FLASH_BASE ) / CY_FLASH_SIZEOF_ROW;

   

That's pretty much the entire set up. In my case I only need one 16-bit constant in EEPROM, and here is how I dealt with this simple case. To read the value, I go directly to flash:

   

    max_count_value = *(volatile uint16 *)&eeprom_array[ENCODER_LIMIT_OFFSET];

   

To alter the value in flash I copy the flash array to RAM, modify RAM, then write the row back to flash:

   

    memcpy( eeprom_row_image,  eeprom_array, sizeof(eeprom_row_image) );
    *(uint16*)&eeprom_row_image[ENCODER_LIMIT_OFFSET] = max_count_value;
    status = CySysFlashWriteRow ( my_eeprom_row, eeprom_row_image );

   

This is all pretty simple since I am dealing with one value in one row of flash. I actually execute the above code inside an interrupt, which I think is undesirable, but it works. What I have done in similar cases is set a "dirty flag" in the ISR, and to the actual updating in the main loop or another thread. However, in that case you do ALL accesses on the RAM image, then keep it synchronized with the actual flash. Also, I didn't see any function for reading the chip temperature for program timing, so I assume it is handled in the write row function...

   

To deal with larger array sizes, I recommend using multidimensional arrays. I have not tested this code, but it might look like this:

   

#define EE_ROWS   3

   

static const uint8 CYCODE eeprom_array[EE_ROWS][CY_FLASH_SIZEOF_ROW] CYCODE CY_ALIGN(CY_FLASH_SIZEOF_ROW) = { 250, 0 };

   

static uint8 eeprom_array_image[EE_ROWS][CY_FLASH_SIZEOF_ROW];

   

I think it is easier in this case to make a RAM copy of the entire block, not just one row.

   

To actually deal with the block you can cast a pointer to a linear array or structure:

   

uint8 * linear_ptr = (uint8*)eeprom_array_image;

   

struct config_struct * config_struct_ptr = (config_sturct*)eeprom_array_image;

   

Then you can just get at the elements directly:

   

x = linear_ptr[OFFSET];

   

x = config_struct_ptr->field1;

   

If you do this with a multi-row array, then you will not know which row is dirty, so you will need to write the entire image back to flash. There are many ways to make this more efficient and I won't go into that here...

   

I haven't covered every possible configuration, but hopefully this helps someone.

   

If there are mistakes or improvements, I humbly accept any input...

0 Likes