After I update my firmware, set swap state to Complete and reboot my K64F system runs fine showing swap state as Ready and running out of the appropriate block. When I then set swap state to Prepare 0x02 system crashes with SRS1 showing the LOCKUP bit set. This happens occasionally and am trying to understand why this is happening.
Reading the flash_demo_frdmk64f code, and comparing to AN4533 app note - I see one discrepancy right away.
AN4533 4.1.1 First Swap states that if swap state is uninitialized, you:
(1) initialize the system (assume - PFlashSwapCtl set FTFx_SWAP_SET_INDICATOR_ADDR)
(2) Erase the nonactive (upper block) - in my case the upper 4K (PSWAP_INDICATOR + PFLASH_SIZE/2). My PSWAP_INDICATOR is set to 0x7F000.
In flash_swap.c, the code does the following:
(1) Erases BOTH the active and non-active block:
ret = FlashEraseSector(&flashSSDConfig,PSWAP_INDICATOR_ADDR + P_FLASH_SIZE/2, P_SECTOR_SIZE,g_FlashLaunchCommand);
ret |= FlashEraseSector(&flashSSDConfig,PSWAP_INDICATOR_ADDR, P_SECTOR_SIZE,g_FlashLaunchCommand);
(2) Initializes the system
/* after this call, swap state = UPDATE_ERS */
ret = PFlashSwapCtl(&flashSSDConfig, PSWAP_INDICATOR_ADDR, FTFx_SWAP_SET_INDICATOR_ADDR, ¤tSwapMode, ¤tSwapBlock, &nextSwapBlock, g_FlashLaunchCommand);
if ((FTFx_OK != ret)||(currentSwapMode!= FTFx_SWAP_UPDATE_ERASED))
My questions -
(1) Why does sample code erase the active block where PSWAP_INDICATOR is set?
(2) Why does sample code erase first then initialize?
I solved my issue and thought I'd share in case it's helpful to others or if people concur/disagree with my findings.
Reading the K64 Reference Manual, section 18.104.22.168 it states that :
0x01 (Initialize Swap System to UPDATE-ERASED State) - After verifying that the current swap state is UNINITIALIZED, and that both phrases which will contain the swap indicators (located in each half of the Program flash memory within the relative double-phrase flash address provided) are erased,
and therefore I need to erase both blocks and do it first as it's verifying - hence the demo app appears to be what I should do.
This however, didn't help when I issued the Prepare command to the swap controller. This was answered by AN4695 as my system is running interrupts in the same block as 0x7F000. Note- my code is well below 0x7F000 but runs in the same block.
2.2 Avoiding Read While Write violations: ISR code
If an interrupt occurs during a flash erase/program operation, the Read While Write restriction will be violated if the interrupt service routine (ISR) code is located in the same flash block as the erase/program operation is occurring on.
This situation can be avoided with three possible options:
The first option is to disable/enable interrupts before/after the flash command operation. If interrupts are disabled, any
interrupt that occurs during the flash operation will be pending when interrupts are re-enabled.
The second option is to ensure that the ISR code is never in the same block as in-software flash erase/programming is
The third option is to relocate the expected ISR into RAM for the duration of the erase or program time. See
Instructions for creating a RAM function for more details on how to create a RAM function.
So, I fenced the swap ctl function that sets system to prepare as follows:
error_code = PFlashSwapCtl(&_flash_ssd_config, PSWAP_INDICATOR_ADDR,
I think app note AN4533 should add these clarifications.