CE220120 – PSoC 6 MCU: Blocking Mode Flash Write

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

cross mob
CaKu_4284131
Level 5
Level 5
50 replies posted 25 replies posted 10 likes received

I'd like to use some flash memory for storing fault data, and I was hoping that it would persist across resets. However, when I run CE220120 and look at the memory at 0x10081400 it's all zeros until the Cy_Flash_WriteRow. The flash memory is declared thusly:

 

 

CY_ALIGN(CY_FLASH_SIZEOF_ROW) const uint8_t flashData[CY_FLASH_SIZEOF_ROW] = {0};

 

 

After the Cy_Flash_WriteRow, the count data is shown, but if I do a reset, the debugger shows all zeros again. 

I tried moving the flash storage to 

 

 

CY_SECTION(".cy_sflash_user_data") const uint8_t flashData[CY_FLASH_SIZEOF_ROW];

 

 

and got the same results. 

How can I store some persistent data?

 

 

0 Likes
1 Solution

@Rakshith wrote:

Hi @CaKu_4284131,

...

So, as you have rightly mentioned, you can save data persistently using 3 methods - 

  • In Flash memory
  • In SFlash memory
  • Using EEPROM

The recommended method is to use EEPROM. Would that be a viable option for you?


I know that the BLE_PDL Component uses the cy_em_eeprom section, and my project uses BLE, so I am leery of using EEPROM if I don't need to.


@Rakshith wrote:

Hi @CaKu_4284131,

Incidentally, I don't understand how this declaration: 
places flashData at 
flashData [512] 0x10081400 (All) const uint8_t [512]

 The array is stored at the beginning of rodata. You can find this information/location in the map file.


I'm trying to understand the declaration in the example source code:

 

CY_ALIGN(CY_FLASH_SIZEOF_ROW) 
const uint8_t flashData[CY_FLASH_SIZEOF_ROW] = {0}; /* The array will be placed in Flash */

 

It expands as 

 

__attribute__((aligned((128u * 4u))))
const uint8_t flashData[(128u * 4u)] = {0};

 

I don't understand how that points it at address 0x10081400, or how it puts in in section .rodata.

I also don't understand why the example attempts to zero it with "= {0}";

EDIT: Oh, wait, I get it now. Since flashData is declared "const" the compiler considers it a constant, and therefore read-only, so it places it in section .rodata in the .text section and puts it into flash along with the executable code.  The ={0} is redundant, I think, because static data always is implicitly zeroed by the compiler (unless it is explicitly initialized), but it any case, it means that when you program the device the data will be cleared to 0. This approach does seem to depend on the compiler not taking some optimizations believing that the data really is constant.

I think I will go with this declaration:

 

CY_SECTION(".cy_sflash_user_data") volatile uint8_t flashData[CY_FLASH_SIZEOF_ROW];

 

I was worried about C static initialization zeroing this, but since that section is NOLOAD in the linker script, I guess I don't have to worry about that.

View solution in original post

4 Replies
Rakshith
Moderator
Moderator
Moderator
250 likes received 1000 replies posted 750 replies posted

Hi @CaKu_4284131

Can you please connect the device to PSoC Programmer and perform a Read to Hex Read to Log action? Once you have the flash contents search for the address and let me know if you are able to see the contents of the array in the flash location instead of 0s. I also tried reconnecting power and then reading the flash contents and I could still observe that the data is intact.
When you debug the device and then press reset, PSoC Creator reprograms the device which is why you see all 0s when you reset the debugger. 

Thanks and Regards,
Rakshith M B
0 Likes

If I go back to the original example, PSoC Programmer does show:

 

                                                                                  	| 10081400: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
                                                                                  	| 10081410: 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
                                                                                  	| 10081420: 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
                                                                                  	| 10081430: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
                                                                                  	| 10081440: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
                                                                                  	| 10081450: 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f

 

Incidentally, I don't understand how this declaration:

CY_ALIGN(CY_FLASH_SIZEOF_ROW) 
const uint8_t flashData[CY_FLASH_SIZEOF_ROW] = {0}; /* The array will be placed in Flash */

 

 

places flashData at 

 

flashData [512] 0x10081400 (All) const uint8_t [512]

 

I do see how the  = {0} would result in it getting zeroed, and yet it does not appear to get zeroed in flash, which makes sense, I guess, since it would have to do a Cy_Flash_WriteRow to accomplish that.

Anyway, I'm interested in "User data." From cy8c6xx7_cm4_dual.ld:

sflash_user_data (rx) : ORIGIN = 0x16000800, LENGTH = 0x800 /* Supervisory flash: User data */

(I'm worried about blindly writing to 0x10080000, since my application uses BLE and stuff. I guess it's all the same flash, but the addresses seem so different: 0x10080000 vs. 0x16000800.)

PSoC Programmer only seems to dump flash from 10000000 to 100ffff0.

                                                                                  	| Reading 1048576 bytes of Main Flash
Note:                                                                             	| Load or scan memory types to perform Read operation for WFlash/SFlash/SMIF
                                                                                  	| Unchecked sections will be skipped for Read operation
Device set to CY8C6347BZI-BLD53 at 8:44:37 AM                                     	| 1048576  FLASH bytes
Device Family set to CY8C63xx at 8:44:37 AM                                       	| 
                                                                                  	| Automatically Detected Device: CY8C6347BZI-BLD53
                                                                                  	| Silicon: 0xE207, Family: 0x100, Rev.: 0x23 (*C)
                                                                                  	| SROM Firmware: 4.01, Flash Boot: 1.20.1.42 (*C)
                                                                                  	| Protection state: 0x02 (NORMAL), Life Cycle stage: 0x01 (NORMAL)
Read Requested at 8:44:37 AM                                                      	| 

 

So, I went back to my modified version. My latest attempt to declare flashData:

CY_SECTION(".cy_sflash_user_data") const uint8_t flashData[0];

 (zero length to avoid C static initialization trying to zero it). Now, it seems to be working perfectly! The debugger shows what I expect:

0x16000800	00	01	02	03	04	05	06	07	........
0x16000808	08	09	0a	0b	0c	0d	0e	0f	........
0x16000810	10	11	12	13	14	15	16	17	........
0x16000818	18	19	1a	1b	1c	1d	1e	1f	........
0x16000820	20	21	22	23	24	25	26	27	 !"#$%&'
0x16000828	28	29	2a	2b	2c	2d	2e	2f	()*+,-./

I can't think of anything that changed except unless running PSoC Programmer did something.


@Rakshith wrote:

...
When you debug the device and then press reset, PSoC Creator reprograms the device which is why you see all 0s when you reset the debugger. 


I don't follow you here. It wouldn't be messing with sflash_user_data, would it?

Thanks for your help!

           Carl

 

lock attach
Attachments are accessible only for community members.
Rakshith
Moderator
Moderator
Moderator
250 likes received 1000 replies posted 750 replies posted

Hi @CaKu_4284131,

Incidentally, I don't understand how this declaration: 
places flashData at 
flashData [512] 0x10081400 (All) const uint8_t [512]

 The array is stored at the beginning of rodata. You can find this information/location in the map file.

PSoC Programmer only seems to dump flash from 10000000 to 100ffff0.

Once you have connected to the device, please click on Load from device under Memory Types. Enable SFlash and eFuse as shown:

image.png

Then click on Read to Log. You should now be able to see the SFlash data too.image.png

I don't follow you here. It wouldn't be messing with sflash_user_data, would it?

 I apologize for the confusion because of my previous comment. The debugger does not reprogram when it is just reset. The device is reprogrammed only when the debugger is stopped and then you click on Debug again. 

I created 2 crude projects to save data in flash persistently. In both projects, I have created a section to save the array (flashData). The first project, Persistent Flash Blinky, checks whether data exists in the flashData array. If flashData is not 0, the blue LED is turned on. It then writes the data into the array. If the flash write is successful, the green LED turns on, or else the red LED turns on. 

The first time the device is programmed, only the green LED turns on. If you reset the device, both blue and green LEDs are turned on.

Similarly, in the second project, Persistent Flash Blinky Button, flash writes occur on button press and indicated by the blue LED. If flashData array is 0, the red LED is on. If it is not 0, the green LED is turned ON.

Please try out these projects and let me know if they work for you.

So, as you have rightly mentioned, you can save data persistently using 3 methods - 

  • In Flash memory
  • In SFlash memory
  • Using EEPROM

The recommended method is to use EEPROM. Would that be a viable option for you?

Thanks and Regards,
Rakshith M B
0 Likes

@Rakshith wrote:

Hi @CaKu_4284131,

...

So, as you have rightly mentioned, you can save data persistently using 3 methods - 

  • In Flash memory
  • In SFlash memory
  • Using EEPROM

The recommended method is to use EEPROM. Would that be a viable option for you?


I know that the BLE_PDL Component uses the cy_em_eeprom section, and my project uses BLE, so I am leery of using EEPROM if I don't need to.


@Rakshith wrote:

Hi @CaKu_4284131,

Incidentally, I don't understand how this declaration: 
places flashData at 
flashData [512] 0x10081400 (All) const uint8_t [512]

 The array is stored at the beginning of rodata. You can find this information/location in the map file.


I'm trying to understand the declaration in the example source code:

 

CY_ALIGN(CY_FLASH_SIZEOF_ROW) 
const uint8_t flashData[CY_FLASH_SIZEOF_ROW] = {0}; /* The array will be placed in Flash */

 

It expands as 

 

__attribute__((aligned((128u * 4u))))
const uint8_t flashData[(128u * 4u)] = {0};

 

I don't understand how that points it at address 0x10081400, or how it puts in in section .rodata.

I also don't understand why the example attempts to zero it with "= {0}";

EDIT: Oh, wait, I get it now. Since flashData is declared "const" the compiler considers it a constant, and therefore read-only, so it places it in section .rodata in the .text section and puts it into flash along with the executable code.  The ={0} is redundant, I think, because static data always is implicitly zeroed by the compiler (unless it is explicitly initialized), but it any case, it means that when you program the device the data will be cleared to 0. This approach does seem to depend on the compiler not taking some optimizations believing that the data really is constant.

I think I will go with this declaration:

 

CY_SECTION(".cy_sflash_user_data") volatile uint8_t flashData[CY_FLASH_SIZEOF_ROW];

 

I was worried about C static initialization zeroing this, but since that section is NOLOAD in the linker script, I guess I don't have to worry about that.