Is there a simple guide to how to use Em_EEPROM on a PSoC 4 ?

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

cross mob
ThBa_1159851
Level 3
Level 3
First like received First like given

Hi Everybody

I'm trying to implement a Em_EEPROM 2.0-Module with PSoC Creator 4.2. to store a calibration value novolatile on a PSoC 4 CY8C4247AXI-M485.

After searching for examples and fiddeling around with the found stuff I'm still lost at the beginning.

I'm not an expert in c-code, so I don't know for example where to put the lines...

const uint8 emEeprom[Em_EEPROM_1_PHYSICAL_SIZE]

__ALIGNED(CY_FLASH_SIZEOF_ROW) = {0u};

...that are mentioned in the component datasheet. Put in main.c I get the error "expected ';' after top level declarator"

With the example CE195313 I can't select my device, and other examples I found are for older components.

Any help appreciated

Thomas

0 Likes
1 Solution
Anonymous
Not applicable

Ah; Try making a new project in PSoC creator 4.2, select the device to be CY8C4247AXI-M485, then select the "EEPROM" example. The project should create the example project for EM_EEPROM already ready to be built. Build it, and watch all of the errors disappear. Fwiw:

This is what the example project shows:

/* EEPROM storage in work flash, this is defined in Em_EEPROM.c*/

#if defined (__ICCARM__)

#pragma data_alignment = CY_FLASH_SIZEOF_ROW

const uint8_t Em_EEPROM_em_EepromStorage[Em_EEPROM_PHYSICAL_SIZE] = {0u};

#else

const uint8_t Em_EEPROM_em_EepromStorage[Em_EEPROM_PHYSICAL_SIZE]

__ALIGNED(CY_FLASH_SIZEOF_ROW) = {0u};

#endif /* defined (__ICCARM__) */

The example project should be the "crane" for your proverbial "staircase"

View solution in original post

13 Replies
Anonymous
Not applicable

Something like this: http://www.cypress.com/file/144961/download ?

Here is a recently updated version of it: Emulated EEPROM

The error you encountered is this: Basically, after every line of code that doesn't end with an opening bracket of parenthesis you should have a semicolon to tell the compiler that the line of code is "complete".

I would expect that the error is referring to you missing a semicolon after the line: const uint8 emEeprom[Em_EEPROM_1_PHYSICAL_SIZE];

0 Likes

...Something like this: http://www.cypress.com/file/144961/download ?...

That deals with the module "E2PROM" for PSoC 1 and PSoC Designer. It doesn't exist in PSoC Creator.

...Here is a recently updated version of it: Emulated EEPROM...

That's the Datasheet I was refering to.

...you should have a semicolon...

I thought of that, but when I put a semicolon at the end

const uint8 emEeprom[Em_EEPROM_1_PHYSICAL_SIZE];

__ALIGNED(CY_FLASH_SIZEOF_ROW) = {0u};

I get an error in the next line: implicit declaration of function '__ALIGNED' is invalid in C99

That tells me that, with my level of experience, I can't just copy an paste code from the datasheet.

And so I'm looking for a staircase to the next level 😉

Thomas

0 Likes
Anonymous
Not applicable

Ah; Try making a new project in PSoC creator 4.2, select the device to be CY8C4247AXI-M485, then select the "EEPROM" example. The project should create the example project for EM_EEPROM already ready to be built. Build it, and watch all of the errors disappear. Fwiw:

This is what the example project shows:

/* EEPROM storage in work flash, this is defined in Em_EEPROM.c*/

#if defined (__ICCARM__)

#pragma data_alignment = CY_FLASH_SIZEOF_ROW

const uint8_t Em_EEPROM_em_EepromStorage[Em_EEPROM_PHYSICAL_SIZE] = {0u};

#else

const uint8_t Em_EEPROM_em_EepromStorage[Em_EEPROM_PHYSICAL_SIZE]

__ALIGNED(CY_FLASH_SIZEOF_ROW) = {0u};

#endif /* defined (__ICCARM__) */

The example project should be the "crane" for your proverbial "staircase"

lock attach
Attachments are accessible only for community members.

e.pratt_1639216

Thanks for this stepping stone. First choosing a device and afterwards creating the example worked. I wasn't aware of the fact, that choosing the device afterwards is a problem.

Anyway, I played arround with the project and adapted it to my custom made board for a PsOC 4 (CY8C4247AZI-M485) with a 2x16Char-LCD-Display.

In short I ...

- replaced the UART of the original example with a 2x16Char LCD component

- added two digital input ports for switches to save values to EEPROM

What it does now:

A counter is incremented and its value is displayed on the LCD. If the Save-switch is pressed, the value of the counter is

saved to the EEPROM. If the Restore-switch is pressed the value 0000 is saved to the EEPROM.

Like in the original example every time a value is written to the EEPROM, the number of writing cycles (two digits) is also written to EEPROM.

The LCD displays on the first line the counter-value that is increasing, and on the second line the bytes that were

written and read back from EEPROM. The 2x16 Character Display might look like this:

----------------

Counter: 1565

EEP 1214 Cy# 06

----------------

Cy# 06 means, there have been 6 write cycles so far. (This number is set to 0 after a reprogramming of the PSoC)

After powering up of the device, the bytes are read back from EEPROM and the counter starts counting from that number.

I attached a workspace-bundle. Anyone who points out dangerous code or suggests  an improvement is welcome.

Cheers
Thomas

Anonymous
Not applicable

@user_1815019

You're welcome!

Glad you got it working for your project!

Some comments on your project:

You could potentially read the entire EEPROM array when checking for the ASCII_E as the first char, and then only write values if necessary afterwards. This would reduce the overhead and redundancy of reading the first EEPROM value twice, but not really much of an improvement so much as a trade-off depending on what you want the project to do in the future

Your switch doesn't have debouncing from what I can see. This could cause multiple presses each time you physically move the switch. One method around this is to count the time a switch is on/off to force a "minimum on" or "minimum off" time before the switch is acknowledged by software. Especially when you are using flash directly with the switch activation, the flash might wear out really fast if you are reading/writing dozens of times on each switch activation rather than just the one time.

But these are minor things to consider, otherwise your project looks very solid and well done

e.pratt_1639216​ Thanks for following my journey

I guess in my application I will save calibration values about every other week. So I don't worry much about efficiency.

Concerning the bouncing of the switches: I thought I covered that with my if-statement. But you're right, that can be improved!

Thomas

0 Likes
Anonymous
Not applicable

You are using a set/reset switch for the switches, which does work due to the LCD update function delaying 1 second before doing the next iteration. This does mean that you need to hold down the switch for at least a whole second to make sure the EEPROM updates.

I guess I should have finished reading the code first

Nvm then, the debouncing won't be an issue if you only check the switch every second. This does mean you need to hold down the switch for a whole second to trigger the switch however, which is a long time for pressing a switch (Not to mention an erroneous save/restore due to RF triggering the switch at the time it is measure by the CPU).

0 Likes

I wanted to use an interrupt to trigger a "save" or a "restore" event, but I have no luck. The isr doesn't seem to get started.

the two switches a still on port 4[4] and 4[5] but because it's not possible to connect an isr to these ports directly I joined them in a pin-component. See picture below.

Pins_and_isr.png

In main I write:

....

....

/*Interrupt*/

    CY_ISR_PROTO(isr_switches_Function);

    uint8 isrFlag = 0u;// status of the Interrupt

    uint8 Switches = 0u; // status of the "Switches"-pins 

    CY_ISR(isr_switches_Function)

    {

        isrFlag = 1u;

        isr_switches_ClearPending();   

    }

int main(void)

{   

     __enable_irq();

   

    isr_switches_StartEx(isr_switches_Function);   

    CyGlobalIntEnable;      /* Enable global interrupts */

    LCD_Char_1_Start();

....

....

Any Idea why the interrupt isn't working? Is it because port 4 can't make interrupts?

Thanks
Thomas

0 Likes
Anonymous
Not applicable

If you open the "isr_switches" component in the schematic, there is a setting for "LEVEL", "DERIVED", "PULSE" for which one will trigger the interrupt. Potentially, you will need to verify that is set to the correct setting. Also, you will want to make sure the debounce component is working based on the directions in its datasheet

I would guess there are APIs for the debouncer component. Possibly you will need to call some of these APIs for it to function correctly.

Also, you could make a small ms timer that checks the status every so often, and if it gets a number of highs or lows in a row then the state of the pin has changed for the switch. See here for debouncing techniques for generic microchips: Switch Bounce and How to Deal with It

0 Likes
Anonymous
Not applicable

My guess would be it is not the port 4 being uninterruptible; The component for the debouncer has a clock and I would suspect it is polling the pins instead.

0 Likes

And the phe problem was: I had to clear the interrupt after I handled it

Now it works and doesn't seem to bounce a bit.

Thanks!
Thomas

.......

.......

/*Interrupt*/

    CY_ISR_PROTO(isr_switches_Function);

    uint8 isrFlag = 0u; // status of the Interrupt

    uint8 Switches = 0u; // status of the "Switches"-pins 

    CY_ISR(isr_switches_Function)

    {

        Switches = Switches_Read();

        if (0x03 != Switches) // otherwise we get also an interrupt after releasing the button

        {

        isrFlag = 1u;

        }

        isr_switches_ClearPending();

        Switches_ClearInterrupt(); // The interrupt isn't cleared just by reading the switches

    }

int main(void)

{   

     __enable_irq();

   

    isr_switches_StartEx(isr_switches_Function);   

    CyGlobalIntEnable;      /* Enable global interrupts */

    LCD_Char_1_Start();

......

......

for(;;)

{

    //read the switches

   if (isrFlag == 1u)// an Interrupt has occured

   {

     switch (Switches)

     {

      case 0x01: // Save

      .....

      break;

               

      case 0x02: // Restore

      .....

      break;

      }

    ....

    }

   ....

    isrFlag = 0u;// reset interrupt-Flag

   }

Switches with interrupt.png

Anonymous
Not applicable

Nice! Sounds perfect now

0 Likes

After updating the libraries, projects including EEPROM module stop working. This should not be, if CYPRESS extends the functionality, then they should guarantee backward compatibility.


I cannot confirm email and add messages due to a bug on your site, the email section is not active
0 Likes