10 Replies Latest reply on Feb 28, 2019 12:45 PM by niprc_3742601

    Saving to flash

    niprc_3742601

      Hello,

       

      I would like to be able to permanently store data to flash of my PSoC5 processor and being able to retrieve it after rebooting the processor.  I found sample project "Flash Example" that seems to be doing just that.

       

      This is the code snippet how they store data to flash:

      ...

                  CySetTemp();

                  returnValue = CyWriteRowData(ARRAY_ID, ARRAY_ID_ROW_ADDR, rowPattern);

       

       

                  /* Check if operration is successful */

                  if (returnValue != CYRET_SUCCESS)

                  {

                      LED_Error_Write(LIGHT_ON);

                      CyHalt(0x00u);

      ...

       

       

      It writes data to the flash and then immediately reads it and matches to what was stored.  Everything works fine here.  But if I modify this code such that when it runs first time it ONLY writes the data and the second it ONLY reads the data then the stored data is lost.  So it looks like the stored data didn't survive the reboot OR reprogramming of the chip (I had to do it to comment out the code that writes data to flash).

       

      Is there a way to burn something to flash so it stays there until explicitly erased?

       

      Thanks!

      Nikolay

        • 1. Re: Saving to flash
          KyTr_1955226

          Have you tried using the EEPROM component?  I think it just emulates EEPROM in flash, but it might make interfacing a little nicer than working with the flash directly.

          Also have a look at these threads:

          Limitations with Emulated EEPROM

          EEPROM write and read back

          Lost EEPROM settings

          1 of 1 people found this helpful
          • 2. Re: Saving to flash
            ScottA_91

            There is another advantage of using the EmEEPROM component, wear leveling.  Basically you can write to flash too many times and it will stick.

             

            That said you are likely to lose your data when reprogramming the chip, unless you implement a custom program step.  (There are other ways, but I don't have the documentation handy right now.)

             

            If you just want to debug without programming, there is that option as well as attaching to a running target.

            • 3. Re: Saving to flash
              niprc_3742601

              I just verified that writing to flash saves the data that survives a reboot.  However, programming the chip clears the data.

               

              So my original question comes to this one: can I protect a flash region from being cleared during chip programming?

               

              Thank you, everybody, for help!

              Nikolay

              • 4. Re: Saving to flash
                KyTr_1955226

                I didn't think it would write over the EEPROM unless "Include EEPROM image in hex file" was checked in the EEPROM section of the design-wide resources.  But it could be the case of it just writes 0xFF to all those EEPROM addresses unless you tick the box and give it something custom.

                 

                If you know exactly what addresses in flash you're saving into, you could perhaps mark it protected in the "Flash Security" tab in the design-wide resources.  Mark the addresses 'R' and no external device should be able to clear it.  I think the PSoC CPU should still be able to modify it.  Check the PSoC Creator Help (search for "Flash Security") for more info on it.

                • 5. Re: Saving to flash
                  niprc_3742601

                  In the "Flash Security" tab I marked the row as "external write protect", but the result is the same.

                   

                  The output of my program is below: when booted the first time the no data is saved in flash (expected).  Then I hit Reset button a few times and the program can read the data from flash.  Then I program the chip, it boots and the data is lost despite the flash row is marked as "external write protected"

                   

                  What am I doing wrong?

                   

                  Thanks!

                  Nikolay

                   

                  P.S.

                   

                  My test project is attached.

                   

                  • 6. Re: Saving to flash
                    KyTr_1955226

                    Dang I thought the Flash Protection would have been it.

                     

                    Are you running a Release or Debug build?

                    Does the same thing happen if you program via PSoC Programmer rather than through Creator?  It seems unlikely but might be worth trying.  Maybe Creator wipes it but Programmer wouldn't for some reason?

                     

                    Just throwing stuff out there to try, since Flash Protection, as described in the help documentation, sounds like exactly what you want.  it's really strange that didn't work.

                    • 7. Re: Saving to flash
                      niprc_3742601

                      Programming with the Release build and/or PSoC Programmer didn't fix the problem.

                       

                      Did I select the correct flash row to protect?  I used the computations from the "Flash Example".  Those macros, that they used, have a bit weird names and I keep confusing one with another.  I think that the global row ID is 1022 which corresponds to array 3 with array's row ID 254.  So I protected row 1022.  Does it seem to be correct to you?

                       

                      Thank you for your help!

                      Nikolay

                      • 8. Re: Saving to flash
                        MoTa_728816

                        Hi,

                         

                        If you don't mind using an EEPROM,

                        this seems to be working, too.

                         

                        Note: Before the last line, I cycled the power of CY8CKIT-050.

                        001-TeraTerm-log.JPG

                        schematic

                        002-schematic.JPG

                         

                        main.c

                        ===================

                        #include "project.h"

                        #include <CyFlash.h>

                        #include <stdio.h>

                         

                        /* added on 28-Feb-2019 */

                        void print(char *str)

                        {

                            Debug_PutString(str) ;

                        }

                         

                        int erase_EEPROM(void)

                        {

                            int sector_number = 0 ;

                            cystatus result ;   

                            print("Erasing EEPROM ...") ;

                            EEPROM_UpdateTemperature();

                            result = EEPROM_StartErase(sector_number) ; /* use sectorNumber = 0 */

                            if (result != CYRET_SUCCESS) {

                                return( result ) ;

                            }

                            while((result = EEPROM_Query()) == CYRET_STARTED) {

                                ; /* wait erase to finish */

                            }

                            if (result != CYRET_SUCCESS) {

                                print("Failed\n\r") ;

                                return( result ) ;

                            }

                            print("Done\n\r") ;  

                            return( result ) ;

                        }

                         

                        int blank_check_EEPROM(int address, int bytes)

                        {

                            int i ;

                            uint8_t data ;

                            int is_blank = 1 ;

                            EEPROM_UpdateTemperature();

                            for (i = 0 ; i < bytes ; i++ ) {

                                data = EEPROM_ReadByte(address + i) ;

                                if (data != 0) {

                                    is_blank = 0 ;

                                    break ;

                                }

                            }

                            return( is_blank ) ;

                        }

                         

                        int

                        eeprom_store( uint8 *buf, uint16 sz )

                        {

                            cystatus result ;

                            uint16_t i ;

                           

                            EEPROM_UpdateTemperature();

                            for (i = 0 ; i < sz ; i++ ) {

                                result = EEPROM_WriteByte(buf[i], i) ;

                                if (result != CYRET_SUCCESS) {

                                    break;

                                }

                            }

                            return( result ) ;

                        }

                         

                        void

                        eeprom_read( uint8 *buf, uint16 sz )

                        {

                            uint16_t i ;

                           

                            EEPROM_UpdateTemperature();

                            for (i = 0 ; i < sz ; i++ ) {

                                buf[i] = EEPROM_ReadByte(i) ;

                            }

                        }

                         

                        /************************/

                         

                         

                        #define CY_TEST_FLASH_ROW       (CY_FLASH_NUMBER_ROWS - 2u)                           //  global ID of the row of interest

                        #define CY_TEST_FLASH_ADDR      (CY_TEST_FLASH_ROW * CY_FLASH_SIZEOF_ROW)             //  address if the global row of interest

                        #define ARRAY_ID                ((uint8)(CY_TEST_FLASH_ROW / CY_FLASH_SIZEOF_ROW))    //  ID of the array that contains the row of interest

                        #define ARRAY_ID_ROW_ADDR       ((uint16)(CY_FLASH_SIZEOF_ROW - 2u))                  //  address offset of the row of interest

                         

                        //------------------------------------------------------------------------------

                        //

                        void

                        flash_store( uint8* buf, uint16 sz )

                        {

                        #ifndef CY_PSOC5

                           

                            return;

                         

                        #else

                         

                         

                            if( sz > CYDEV_FLS_ROW_SIZE )  return;

                         

                         

                            uint8 flash_row[ CYDEV_FLS_ROW_SIZE ];

                            memmove( flash_row, buf, sz );

                           

                            cystatus ret = CYRET_SUCCESS;

                         

                         

                            CySetTemp();

                            ret = CyWriteRowData( ARRAY_ID, ARRAY_ID_ROW_ADDR, flash_row );

                         

                         

                            if( ret != CYRET_SUCCESS )

                            {

                                Debug_PutString( "CyWriteRowData(...) failed\n\r\b" );

                                //CyHalt( 0x00u );

                                return;

                            }

                           

                           

                        #endif  // (CY_PSOC5)

                         

                         

                        }

                         

                         

                         

                         

                        //------------------------------------------------------------------------------

                        //

                        void

                        flash_read( uint8* buf, uint16 sz )

                        {

                        #ifndef CY_PSOC5

                         

                         

                            return;

                           

                        #else

                           

                            uint16 i = 0;

                            volatile uint8 flash_byte = 0;

                           

                            if( sz > CYDEV_FLS_ROW_SIZE )  return;

                         

                         

                           

                            for( i = 0u; i < sz; i++)

                            {

                                flash_byte = ( *( (uint8*) ( CYDEV_FLS_BASE + CY_TEST_FLASH_ADDR + i ) ) );

                                buf[ i ] = flash_byte;

                            } 

                               

                        #endif

                        }

                         

                        //------------------------------------------------------------------------------

                        //

                        int

                        main( void )

                        {

                            CyGlobalIntEnable; /* Enable global interrupts. */

                           

                            EEPROM_Start() ;

                            Debug_Start();

                           

                            LED1_Write( 1 );

                            LED2_Write( 0 );

                         

                         

                            const static uint16 SZ = 8;

                            uint8 buf1[] = { 0x0a, 0x0b, 0x0c, 0x0d, 0x01, 0x02, 0x03, 0x04 };

                        //    uint8 buf1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // for testing

                            uint8 buf2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

                         

                         

                            Debug_ClearTxBuffer();

                         

                         

                            Debug_PutString( "booted: " );

                           

                            if (blank_check_EEPROM(0, SZ)) {

                                erase_EEPROM() ;

                            }

                           

                            eeprom_read(buf2, SZ) ;

                         

                         

                        //    flash_read( buf2, SZ );

                            if( 0 == memcmp( buf2, buf1, SZ ) )

                            {

                                Debug_PutString( "data is stored\n\r\b" );

                            }

                            else

                            {

                                Debug_PutString( "data is not stored, storing ..." );

                        //        flash_store( buf1, SZ );

                                erase_EEPROM() ;

                                eeprom_store(buf1, SZ) ;

                               

                        //            flash_read( buf2, SZ );

                                eeprom_read(buf2, SZ) ;

                                if( 0 == memcmp( buf2, buf1, SZ ) )

                                {

                                    Debug_PutString( " stored\n\r\b" );

                                }

                                else

                                {

                                    Debug_PutString( " not stored\n\r\b" );

                                }

                            }

                         

                            for( ;; )

                            {

                                LED1_Write( ! LED1_Read() );

                                LED2_Write( ! LED2_Read() );

                         

                         

                                CyDelay( 250 );

                               

                            }

                        }

                        ===================

                         

                        moto

                        1 of 1 people found this helpful
                        • 9. Re: Saving to flash
                          XiaoweiZ_71

                          Question: Can I protect a flash region from being cleared during chip programming?

                          Answer: If you program the device use PSOC Programmer or Creator(include a mini programmer), you cannot protect a flash region from being cleared during chip programming because device flash is erased all first before program, this process is preset and fixed in software tool.  Change the flash block protection level cannot prevent protected flash block be erased from external.

                          1.jpg

                          I think there are two ways to fix this issue:

                          (1) Store data in EEPROM of PSoC5LP, erase flash won't change EEPROM region.

                          (2) Design device program script use cli (command line),  custom you own programming steps instead of use ready-made programming tools. Post 6. Re: Saving to flash also mentioned this method("unless you implement a custom program step).  You can search "PSoC Programmer CLI User Guide.pdf" file on your PC to know how to do that.

                           

                          If your design is a bootloader-bootlodable system, you can define a checksum-exclude region which won't be modified when bootlodable is upgrading by bootloader.

                          • 10. Re: Saving to flash
                            niprc_3742601

                            Writing to EEPROM solves the problem!

                             

                            Thank you everybody!