We are using the MK70FN1M0VMJ15 chip for our product. To implement a program flash upgrade mechanism, we use FTFE module commands to upgrade the flash. The function runs entirely from Ram, as recommended. It works for the most part. But, we are facing a lot of cases where the upgrade leaves the device unusable. This is probably due to the upgrade failing mid process, and device left with incomplete image.
The existing process looks something like this (simplified for clarity, original code takes care of boundary conditions):
//Function running from flash
void upgrade_flash(*flash_array, length)
{
//Wait for flash to be ready
while (!(FTFE_FSTAT & FTFE_FSTAT_CCIF_MASK)) {}
//Erase the flash
FTFE_FCCOB0 = 0x44;
FTFE_FSTAT |= FTFE_FSTAT_CCIF_MASK;
while (!(FTFE_FSTAT & FTFE_FSTAT_CCIF_MASK)) {}
address = 0;
while(length > 0) {
//Read 8 bytes from flash_array at a time, run command to write the bytes to flash
FCCOB0 = 0x7
//Load address (64 bit alligned) onto FCCOB1, FCCOB2, FCCOB3;
//Load 8 bytes of data onto FCCOB4 to FCCOBB
FTFE_FSTAT |= FTFE_FSTAT_CCIF_MASK;
while (!(FTFE_FSTAT & FTFE_FSTAT_CCIF_MASK)) {}
length -=8
address += 8
flash_array += 8
}
REBOOT device.
}
Clearly, there is a problem here. There is no error flag checking. So, even if one of the above command fails, the rest of the flash
will stay erased causing the device to be unusable.
I am trying to implement error checking and possible corrections here to fix the issues.
I am attempting to change it to something like this:
void upgrade_flash(*flash_array, length)
{
//Wait for flash to be ready
while (!(FTFE_FSTAT & FTFE_FSTAT_CCIF_MASK)) {}
if (FTFE_FSTAT & (FTFE_FSTAT_ACCERR_MASK | FTFE_FSTAT_FPVIOL_MASK))
FTFE_FSTAT |= (FTFE_FSTAT_ACCERR_MASK | FTFE_FSTAT_FPVIOL_MASK);
//Erase the flash
while(1) {
FTFE_FCCOB0 = 0x44;
FTFE_FSTAT |= FTFE_FSTAT_CCIF_MASK;
while (!(FTFE_FSTAT & FTFE_FSTAT_CCIF_MASK)) {}
if (FTFE_FSTAT & (FTFE_FSTAT_ACCERR_MASK | FTFE_FSTAT_FPVIOL_MASK))
FTFE_FSTAT |= (FTFE_FSTAT_ACCERR_MASK | FTFE_FSTAT_FPVIOL_MASK);
if (!(FTFE_FSTAT & FTFE_FSTAT_MGSTAT0_MASK))
break;
}
address = 0;
while(length > 0) {
while (1) {
//Read 8 bytes from flash_array at a time, run command to write the bytes to flash
FCCOB0 = 0x7
Load address (64 bit alligned) onto FCCOB1, FCCOB2, FCCOB3;
Load 8 bytes of data onto FCCOB4 to FCCOBB
FTFE_FSTAT |= FTFE_FSTAT_CCIF_MASK;
while (!(FTFE_FSTAT & FTFE_FSTAT_CCIF_MASK)) {}
if (FTFE_FSTAT & (FTFE_FSTAT_ACCERR_MASK | FTFE_FSTAT_FPVIOL_MASK))
FTFE_FSTAT |= (FTFE_FSTAT_ACCERR_MASK | FTFE_FSTAT_FPVIOL_MASK);
if (!(FTFE_FSTAT & FTFE_FSTAT_MGSTAT0_MASK))
break;
}
length -=8
address += 8
flash_array += 8
}
REBOOT device.
}
My main concern is, what is the correct way to handle runtime errors reported by MGSTAT0 bit? My new approach is just attempting to re run the command if it occurs. But, the documentation says that we cannot reprogram the same addresses without erase. But there is no command to erase just 8 bytes. Does that mean that we need to erase the complete block and start over again? Also, does checking the 3 error flags guarantee that the data was programmed correctly? Or should I read 1's and 0's using the block read commands at the end or programming the complete flash.
My goal is to make a failure proof procedure. Execution time is not that big a concern. A few minutes of program time is expected. Accuracy is more important, so that device can be upgraded without fear of corruption.