12 Replies Latest reply on Apr 10, 2018 7:53 AM by e.pratt_1639216

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

    user_1815019

      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

        • 1. Re: Is there a simple guide to how to use Em_EEPROM on a PSoC 4 ?
          e.pratt_1639216

          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];

           

          • 2. Re: Is there a simple guide to how to use Em_EEPROM on a PSoC 4 ?
            user_1815019

            ...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

             

             

            • 3. Re: Is there a simple guide to how to use Em_EEPROM on a PSoC 4 ?
              e.pratt_1639216

              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"

              • 4. Re: Is there a simple guide to how to use Em_EEPROM on a PSoC 4 ?
                user_1815019

                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

                • 5. Re: Is there a simple guide to how to use Em_EEPROM on a PSoC 4 ?
                  e.pratt_1639216

                  @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

                  • 6. Re: Is there a simple guide to how to use Em_EEPROM on a PSoC 4 ?
                    user_1815019

                    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

                    • 7. Re: Is there a simple guide to how to use Em_EEPROM on a PSoC 4 ?
                      e.pratt_1639216

                      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).

                      • 8. Re: Is there a simple guide to how to use Em_EEPROM on a PSoC 4 ?
                        user_1815019

                        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

                        • 9. Re: Is there a simple guide to how to use Em_EEPROM on a PSoC 4 ?
                          e.pratt_1639216

                          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

                          • 10. Re: Is there a simple guide to how to use Em_EEPROM on a PSoC 4 ?
                            e.pratt_1639216

                            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.

                            • 11. Re: Is there a simple guide to how to use Em_EEPROM on a PSoC 4 ?
                              user_1815019

                              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