Reading from Flash

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

cross mob
SaGa_4641021
Level 5
Level 5
50 questions asked 50 replies posted 100 sign-ins

Hi

I found several code examples for blocking and unblocking writes to the flash.

In case I switch off and on the PSoC-6, how can retrieve the user data from the flash ?

I cannot find the function to read from flash and i am not sure how to keep track of the address in flash.

thanks

0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.
AlenAn14
Moderator
Moderator
Moderator
500 replies posted 100 solutions authored 250 replies posted

 

Hi @SaGa_4641021 ,

The read procedure is simple address based accessing which does not require any special functions. Only the write procedure to flash requires this because it is not desirable to modify the flash contents by accident.
I will explain the read procedure based on the CE220120 - PSoC 6 MCU: Blocking Mode Flash Write code example.

In the main_cm4.c file, you can see the initialization for flashData array as shown:

AlenAn14_0-1635400759293.png

Here the "const" key word is used which will tells the compiler that this array is to be stored in flash.
If you try and perform normal write to it in the main(), it will give errors saying "read-only location" during compilation due to const keyword.

But read from this array is allowed without any issues and you can write to this array using the PDL function Cy_Flash_WriteRow only (because this array is present in flash due to const keyword).

So to make sure that what you have written to flash is present in the flash, you can modify the code to do the following steps:
1. Read and print the flashData array just after entering main and before writing any data to flash.
2. Write the data to flashData array using the Cy_Flash_WriteRow

Observations:

1. After programming the board , the read from flashdata array will print 0's
2. Now power cycle the board by pressing the reset button
3. The data that is now read and printed out after this power cycle will contain the data that you had written into flashdata array in the previous power on i.e. before pressing the reset button/power cycle.

This means that the data that you had written to flash is still retained in flash after the power cycle.

NOTE: In the prrogramming stage, all flash locations are first erased, which is why you will see only 0's after programming. But power-cycling the board will not erase the flash and you will be able to read the data in flash.

I have attached the modified code here.
It was tested on PSoC 6 BLE Pioneer Kit using PSoC Creator.
I have used UART (P5_0 and P5_1) and retarget io to print out messages using printf.

Let me know if any further clarifications are necessary.

Hope this helps.

View solution in original post

0 Likes
3 Replies
lock attach
Attachments are accessible only for community members.
AlenAn14
Moderator
Moderator
Moderator
500 replies posted 100 solutions authored 250 replies posted

 

Hi @SaGa_4641021 ,

The read procedure is simple address based accessing which does not require any special functions. Only the write procedure to flash requires this because it is not desirable to modify the flash contents by accident.
I will explain the read procedure based on the CE220120 - PSoC 6 MCU: Blocking Mode Flash Write code example.

In the main_cm4.c file, you can see the initialization for flashData array as shown:

AlenAn14_0-1635400759293.png

Here the "const" key word is used which will tells the compiler that this array is to be stored in flash.
If you try and perform normal write to it in the main(), it will give errors saying "read-only location" during compilation due to const keyword.

But read from this array is allowed without any issues and you can write to this array using the PDL function Cy_Flash_WriteRow only (because this array is present in flash due to const keyword).

So to make sure that what you have written to flash is present in the flash, you can modify the code to do the following steps:
1. Read and print the flashData array just after entering main and before writing any data to flash.
2. Write the data to flashData array using the Cy_Flash_WriteRow

Observations:

1. After programming the board , the read from flashdata array will print 0's
2. Now power cycle the board by pressing the reset button
3. The data that is now read and printed out after this power cycle will contain the data that you had written into flashdata array in the previous power on i.e. before pressing the reset button/power cycle.

This means that the data that you had written to flash is still retained in flash after the power cycle.

NOTE: In the prrogramming stage, all flash locations are first erased, which is why you will see only 0's after programming. But power-cycling the board will not erase the flash and you will be able to read the data in flash.

I have attached the modified code here.
It was tested on PSoC 6 BLE Pioneer Kit using PSoC Creator.
I have used UART (P5_0 and P5_1) and retarget io to print out messages using printf.

Let me know if any further clarifications are necessary.

Hope this helps.

0 Likes
SaGa_4641021
Level 5
Level 5
50 questions asked 50 replies posted 100 sign-ins

Thank you Alen for the thorough explanation. Now I have a code that works reliably.

Still I have 2 more ambiguities:

1. What is the safe way to chose the address of the const variable so that it does not get allocated in a wat to waste memory?

2. After a reset or power cycle, how do I keep track of the const variable address. I know its name, but will the compiler allocate it in the same memory address every time ?

I used this code from the example, but I am not sure if this is the right way to define the address or if there are better ways to reduce memory waste:

====

#define LAST_FLASH_ROW 2047u

#define MAKE_FLASH_WRITE_FAIL 0u
#define CALCULATE_FLASH_ADDRESS(rowNum) (CY_FLASH_BASE + ((rowNum) * CY_FLASH_SIZEOF_ROW))
CY_ALIGN(CY_FLASH_SIZEOF_ROW)

#if(MAKE_FLASH_WRITE_FAIL == 0)
/* Make the address point to last user flash row */
const int16_t *flash_data = (int16_t *)CALCULATE_FLASH_ADDRESS(LAST_FLASH_ROW);
#else
/* Make the address point to some RAM location */
const uint8_t *flashData = (uint8_t *)CY_SRAM0_BASE;
#endif /* #if(MAKE_FLASH_WRITE_FAIL == 0) */

====

0 Likes
lock attach
Attachments are accessible only for community members.

Hi @SaGa_4641021 ,

Glad the read operation helps.

1. What is the safe way to chose the address of the const variable so that it does not get allocated in a wat to waste memory?
A. It is not necessary to explicitly give the address for this variable as the compiler will take care of allocating it in a suitable flash location. The reason for this is because assume the following declaration:
const uint8_t flashData[20];
When you make the above declaration, the compiler will assign the flashData array a suitable location in flash with 20 bytes and no more (they will be consecutive). So these 20 bytes are yours to modify in flash. But take care not to modify more than these 20 bytes as , the 21st byte and onward may be your program code. Can result in crash. 
Here you decide what size of flash memory is to be used, 20 bytes in this case, and hence there will be no other memory wastage. 
Make sure your const array size is not too big or you will run out of flash to store your program code resulting in errors.

2. After a reset or power cycle, how do I keep track of the const variable address. I know its name, but will the compiler allocate it in the same memory address every time ?
A. During programming (if and only if you have made changes in your code)  the compiler may relocate the const variable address location (this is when address is not explicitly assigned during declaration)
Otherwise,  once programmed, after a reset or power cycle the const variable address will never change, and you can access or track the same with the name of the const variable. (Compiler plays no role after programming so no worries on any address relocations during power cycle or reset)

const int16_t *flash_data = (int16_t *)CALCULATE_FLASH_ADDRESS(LAST_FLASH_ROW);
This code segment will assign only 16 bits of flash at the calculated flash address. Which means you have only 2 bytes for you to use in flash but it will be at your desired flash location. The array method allows you to add more bytes by specifying the array size but it will be difficult for you to specify the flash address location in this case.

You can also use a structure method as follows:

typedef struct{
uint8_t myFlashData[100];
}flashData_s;

const flashData_s *flashData= (int16_t *)CALCULATE_FLASH_ADDRESS(LAST_FLASH_ROW);

The above code will allow you to keep your flash data array of 100 bytes in your desired/calculated flash location because the size of the structure is 100 bytes which you use as the type for your const variable.

I have attached this structure based project here for your reference.
I display the address of flashData each time after power on/reset/programming so you can see that the address of the same does not change.

0 Likes