-deleted-
9 years, 1 month 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:

IAP code for Freescale platforms

1 Answer

9 years, 1 month 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 :).

Accepted Answer

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 -deleted- 06 Apr 2015

Nop, 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 Erik - 06 Apr 2015

It 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]);
    }
posted by -deleted- 06 Apr 2015

Makes sense, didn't think of it myself, but indeed you are not allowed to access flash memory during write operations. So it needs to come from RAM.

posted by Erik - 07 Apr 2015