Freescale indicates the issue with the MK60DN512VLQ10 flash program section (PGMSEC, 0x0b) command (it would actually be rejected on 2N30D v1.2 silicon) has been fixed on 4N30D v1.4 silicon.
On the v1.4 devices I am working with I am still having trouble with this command. Mind you I had no problems with the same code on v1.0. The problem now is not that the command is rejected, but rather the command never completes and the processor remain stuck in an endless loop waiting for the FTFL FSTAT register CCIF bit. This has been on multiple devices and I have not seen any actually work yet.
I guess what I am asking is if anyone else has had this issue or do I just have a code bug or maybe a bad batch of chips?
To that end, here is my flash writing code (always called after a successful erase)...
bool ftflPgmSec(UInt32 flAddr, UInt16 num64s)
{
if(flAddr & 0xff000007)
return false;
if(num64s == 0)
return false;
if(flAddr < 0x00040000 || flAddr > 0x0007ffff)
return false;
#ifdef SI_2N30D_PGMSEC_PROBLEM { UInt32 subWrAddr, subRdAddr; for(subWrAddr = flAddr, subRdAddr = 0x14000000; subWrAddr < flAddr + 8 * num64s; subWrAddr += 4, subRdAddr += 4) { while(!(FTFL_BASE_PTR->FSTAT & FTFL_FSTAT_CCIF_MASK)); // wait for any previous command to complete (required to proceed) if(FTFL_BASE_PTR->FSTAT & (FTFL_FSTAT_ACCERR_MASK | FTFL_FSTAT_FPVIOL_MASK)) // check for previous command error flags FTFL_BASE_PTR->FSTAT = (FTFL_FSTAT_ACCERR_MASK | FTFL_FSTAT_FPVIOL_MASK); // write 1 to clear error flags (required to proceed) FTFL_BASE_PTR->FCCOB0 = 0x06; // program longword command FTFL_BASE_PTR->FCCOB1 = (UInt08)((subWrAddr & 0x00ff0000) >> 16); FTFL_BASE_PTR->FCCOB2 = (UInt08)((subWrAddr & 0x0000ff00) >> 8); FTFL_BASE_PTR->FCCOB3 = (UInt08)(subWrAddr & 0x000000fc); FTFL_BASE_PTR->FCCOB4 = *((UInt08 *)subRdAddr + 3); FTFL_BASE_PTR->FCCOB5 = *((UInt08 *)subRdAddr + 2); FTFL_BASE_PTR->FCCOB6 = *((UInt08 *)subRdAddr + 1); FTFL_BASE_PTR->FCCOB7 = *((UInt08 *)subRdAddr + 0); FTFL_BASE_PTR->FSTAT = FTFL_FSTAT_CCIF_MASK; // write 1 to clear flag (executes command) while(!(FTFL_BASE_PTR->FSTAT & FTFL_FSTAT_CCIF_MASK)); // wait for command to complete if(FTFL_BASE_PTR->FSTAT & (FTFL_FSTAT_ACCERR_MASK | FTFL_FSTAT_FPVIOL_MASK | FTFL_FSTAT_MGSTAT0_MASK)) return false; // return command error flag status } return true; }#else while(!(FTFL_BASE_PTR->FSTAT & FTFL_FSTAT_CCIF_MASK)); // wait for any previous command to complete (required to proceed) if(FTFL_BASE_PTR->FSTAT & (FTFL_FSTAT_ACCERR_MASK | FTFL_FSTAT_FPVIOL_MASK)) // check for previous command error flags FTFL_BASE_PTR->FSTAT = (FTFL_FSTAT_ACCERR_MASK | FTFL_FSTAT_FPVIOL_MASK); // write 1 to clear error flags (required to proceed) FTFL_BASE_PTR->FCCOB0 = 0x0b; // program section command FTFL_BASE_PTR->FCCOB1 = (UInt08)((flAddr & 0x00ff0000) >> 16); FTFL_BASE_PTR->FCCOB2 = (UInt08)((flAddr & 0x0000ff00) >> 8); FTFL_BASE_PTR->FCCOB3 = (UInt08)(flAddr & 0x000000f8); FTFL_BASE_PTR->FCCOB4 = (UInt08)(num64s >> 8); FTFL_BASE_PTR->FCCOB5 = (UInt08)(num64s & 0x00ff); FTFL_BASE_PTR->FSTAT = FTFL_FSTAT_CCIF_MASK; // write 1 to clear flag (executes command) while(!(FTFL_BASE_PTR->FSTAT & FTFL_FSTAT_CCIF_MASK)); // wait for command to complete return((FTFL_BASE_PTR->FSTAT & (FTFL_FSTAT_ACCERR_MASK | FTFL_FSTAT_FPVIOL_MASK | FTFL_FSTAT_MGSTAT0_MASK)) == 0); // return command error flag status#endif
}