Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
9 years, 9 months ago.
Reading and Writing Flash memory with FreescaleIAP
I'm trying to read data from an upper sector in Flash memory and then write the same data to a lower Flash sector inside a for loop.
I'm not sure why the code below fails to return the correct values and instead returns -1 and Error. I think I'm failing to understand the relationship of SECTOR_SIZE to bytes written with program_flash() in terms of the bit boundaries. I guess
int *data = (int*)addressUpper;
is 32 bits.
SECTOR_SIZE is in bytes?
Also the data as a pointer is something I fail to understand.
int *data = (int*)address;
What am I doing wrong?
//Erase upper sectors for (int i = 1; i < 9; i++) { int addressUpper = flash_size() - (SECTOR_SIZE * i); erase_sector(addressUpper); } //Write some data in the upper sectors int addressUpper = flash_size() - (SECTOR_SIZE * 8); int numbers[8] = {1, 10, 100, 1000, 10000, 1000000, 10000000, 100000000}; program_flash(addressUpper, (char*)&numbers, 32); //8 integers of 4 bytes each: 32 bytes length printf("Checking Data in Upper Sectors!\r\n"); //Check if the data is returned correctly for (int i = 1; i < 8; i++) { int addressUpper = flash_size() - (SECTOR_SIZE * i); int *data = (int*)addressUpper; printf("%d\r\n", data[i]); } //Copy from Upper sectors to Lower sectors for (int i = 1; i < 9; i++) { int addressUpper = flash_size() - (SECTOR_SIZE * i); int *data = (int*)addressUpper; int addressLower = flash_size() - (SECTOR_SIZE * i * 8); //Copy from Upper to Lower sectors if (program_flash(addressLower, (char*)&data, 4) != 0) { //Is 4 the correct no of bytes? printf("Error!\r\n"); break; } } printf("Checking Data in Lower Sectors!\r\n"); //Check if the data is returned correctly for (int i = 1; i < 8; i++) { int addressUpper = flash_size() - (SECTOR_SIZE * i); int *data = (int*)addressUpper; printf("%d\r\n", data[i]); }
Question relating to:
1 Answer
9 years, 9 months ago.
Question 1: Did you check which step it is failing at? And preferably if it is an IAP error code which error it is returning?
Question 2: Is this the K64F or another one? The K64F should only be capable of programming in multiples of 8-byte (don't ask, in mind of Freescale engineers it probably made sense to make that different for pretty much identical MCUs), although for the bootloader code I had issues also with 8-byte sizes, so I want for 16-byte at a time.
Also you do realise for this program you are erasing 8 sectors to store 8 integers? Which is slightly overkill. In general I think you made an error with your SECTOR_SIZE * i, a sector on the K64F is 4096 bytes. Your checking data in upper sectors for example first reads one integer at flash_size - SECTOR_SIZE * 1, then times 2, etc. So it jumps in steps of 4096 through the memory (plus the array offset you get with data[i]), while the programmed integers are directly after each other in steps of 4.
SECTOR_SIZE is just a useful tool to have, so you can know when you need to erase a new sector for example. But in this case everything fits in one sector, so you can just stick to one sector as for upper one, and one for lower one.
In general a question: Do you really need this? Since it isn't the easiest to do as you found out, if this is just a personal project you might be better of connecting the USB Cable when you need new firmware :).
Thank you Erik.
Its good to know that there are issues with 8-byte sizes, and we need to program 16-bytes at a time.
In terms of questions:
1. No IAP error
2. This is a K64F
I realize the overkill, and wonder if there is a way to erase just the 8 integers (32 bytes) instead of 4096 bytes at a time. I have found the errors you mention with looping through data[i] so I'm refactoring and testing new code based on your suggestion.
posted by 06 Apr 2015Nop, flash memory has three weaknesses:
1. Limitted write endurance (something like 100k cycles, so no issue for reprogramming).
2. Slow erasing/writing (for a processor, for a human it still goes instantanious).
3. While reading/writing can be done at small sizes, erasing can only be done per sector. Sector sizes vary, but they are often way larger than what you want. There is no way to erase less than one sector.
posted by 06 Apr 2015It seems as though it is not possible to copy from one flash memory location to another flash memory location directly without first copying to RAM memory?
The new code based on your help works. I found I had to create a new int called dataNew[8] and copy the dataUpper into dataNew before writing to dataLower.
I found that this code after write returns bogus date:
if (program_flash(addressLower, (char*)&dataUpper, 32) != 0) {
.
This code works:
printf("\r\nFlash Size: %d\r\n", flash_size()); printf("Sector Size: %d\r\n", SECTOR_SIZE); int addressUpper = flash_size() - SECTOR_SIZE; int addressLower = flash_size() - (SECTOR_SIZE * 2); int *dataUpper = (int*)addressUpper; int *dataLower = (int*)addressLower; //Erase upper sectors of 4096 bytes printf("Address Upper: %d\r\n", addressUpper); erase_sector(addressUpper); //Erase lower sectors of 4096 bytes printf("Address Lower: %d\r\n", addressLower); erase_sector(addressLower); //Write data in the upper sectors int numbers[8] = {1, 11, 110, 1000, 10000, 1000000, 10000000, 100000000}; if (program_flash(addressUpper, (char*)&numbers, 32) != 0) {//8 integers of 4 bytes each: 32 bytes length printf("Upper Data Write Error!\r\n"); } else { printf("Upper Data Write Success!\r\n"); } int dataNew[8]; //need to copy to this int because dataUpper cannot be copied to dataLower directly printf("Checking Data in Upper Sectors!\r\n"); //Check if the data is returned correctly for (int i = 0; i < 8; i++) { printf("%d\r\n", dataUpper[i]); dataNew[i] = dataUpper[i]; } //Copy from Upper to Lower sectors printf("Copy Data from Upper to Lower Sectors!\r\n"); if (program_flash(addressLower, (char*)&dataNew, 32) != 0) { printf("Lower Data Write Error!\r\n"); } else { printf("Lower Data Write Success!\r\n"); } printf("Checking Data in Lower Sectors!\r\n"); //Check if the data is returned correctly for (int i = 0; i < 8; i++) { printf("%d\r\n", dataLower[i]); }