Looking at the bootloader sample code, i have some doubt. I am using it with a FRDM-KL05Z and the KL05 has one flash block. The reference document says we cannot execute from a block and write to the same block at the same time (27.4.5 Flash Reads and Ignored Writes). Trying that would cause a read collision error (RDCOLERR). But exactly that happens in the sample code and it works, except i don't understand why. The sample code mentions "copy code to RAM" but doesn't do it. The procedure Command_Lanuch() is executed from flash, which appears to be out of specs.
Does it happen to work because of cache memory?
Is this guaranteed to work (once interrupts are disabled)? What other conditions to observe?
This situation appears similar to setting the NVIC table base pointer. According to ARM Cortex M0+ documents that operation should be followed by a cache barrier instruction that i have never seen in Freescale samples.
Solved! Go to Solution.
// The procedure Command_Lanuch() is executed from flash, which appears to be out of specs.
// Does it happen to work because of cache memory?
Yes.
The command sequence to program a flash area should be executed in RAM. You may take a look at the sample code of MKL25_EEPROM_CW103.zip at https://community.freescale.com/docs/DOC-94593 which has implemented copy FlashCommandSequence to RAM.
as you test before, the cause that it can work is that it use instruction cache, so it don't generate read flash collision, and I also disable the interrupt in lauch command, so it can read cache when flash is busy and don't generate interrupt to read flash, so your conclusion is correct.
addition, it also has a bit register "stalling flash control" to avoid read collision, it can enable stalling flash controller when flash is busy.
// The procedure Command_Lanuch() is executed from flash, which appears to be out of specs.
// Does it happen to work because of cache memory?
Yes.
The command sequence to program a flash area should be executed in RAM. You may take a look at the sample code of MKL25_EEPROM_CW103.zip at https://community.freescale.com/docs/DOC-94593 which has implemented copy FlashCommandSequence to RAM.
Thanks for the link. That software even supports ReadOnce and ProgramOnce features. Anyway, as long as i don't want a device erase, i don't see what should be the advantage of copying code to RAM, once i have the cache. Our flash OS always remains. We just need to support field updates of application code over the host interface. For OS updates, we can do it with a debugger.
Hi Dieter,
The execute from block and writing to the same block is not possible, because if you want to write some data the flash controller must enable charge pump and in this time is not possible any additional activity.
What bootloader sample code do you studied or could you share it with me ?
Pavel
I am using a FRDM-KL05Z with the KL05-SC package. That bootloader sample is very similar to application note AN4655. The procedure Command_Lanuch() in flash_FTFL.c is executed from flash and successfully executes SectorErase and ProgramLongWord commands. In the meantime i looked a little closer and verified that this fails:
a) when i turn off instruction cache before. Then the wait loop is executed 6 times before it fails. Apparently there is no clean error exit from the read collision, instead the debugger shows a reset. There may be a hardfault exception in between. BTW: The wait loop should in the sample should have a timeout counter.
b) when i insert more instructions into the wait loop to make it more than about 30 code words. According to the reference document the cache has 64 Bytes, a reasonable match.
My conclusion is that the method proposed in that bootloader sample is safe as long as there is a wait loop that fits into the instruction cache and interrupts are disabled. What i am missing now is the requirements for self-modifying code documented in the ARM manual DAI0321 and support for Kinetis flash protection.