I am trying to work with the 'new' FLASH-controller-based Flash-block SWAP mechanism, as described in the new section 28.4.12.14 in Rev 5 of the Family Reference Manual (I am working with the 144-pin K60, as it happens).
Firstly, while this section may be a decent description of the chip functions, it is rather poor at describing how one would best USE this functionality to implement a reliable system update process. For instance, table 28-67 details a number of combinations of 'fault' the system as a whole must contend with, but I THINK it is sufficient to test MGSTAT0 for '0' and a State Code of '1' to indicate a 'non fault' condition coming out of reset -- anything else means something happened along the way.
One thing that is NOT defined in ANY reasonable way I can discern is the use of the 'Flash Address' in each command. It sort of reads like this is some kind of 'password' that is set by the initialize command and must match in all other commands, BUT I set this to a non-random 0xA530 pattern, and NOW my IAR debug-download (thru Segger Jlink 4.34a tools) complains that it can't erase the sector starting at 0xA000, and I can no longer download code! (Although it appears to me that all 496K from 0x4000 to 0x7FFFF is erased.) So, one question is, is there any way to return this SWAP state machine to the uninitialized state so I can get my chip working again???
In any case, my issues might stem from a deeper issue relative to how this swap mechanism is designed to work, as opposed to how I WANT to use it. The previous swap mechanism (a battery-backed bit in the RTC section) did nothing more or less than fully swap the 256K flash blocks. SO, how I HAD been using 'swap' functions was as a 'safety catch' mechanism to reliably update the bootloader. That is, I have the first 16K block (minimum FPROT register protection size), as contains the reset vector, dedicated to bootloader space. The remaining 496K is all application space which the bootloader can update, in our case from external SPI memory downloaded previously (two total images there for necessary protection from a fatally flawed update). So, the SWAP function would come in when I need to update the actual bootloader itself as part of some major system change. For that, what I HAD been doing is to:
1 - copy the current bootloader out to 0x40000 (start of second 256K).
2 - if that works, set the 'swap' bit so that from this point ANY reset will restart the original bootloader
3 - erase the first 16K and load in the new bootloader image.
4 - if that all goes well (CRC passes) then clear the 'swap' bit and hit reset to run the new code.
5 - for ANY failure, including a reset while the banks are swapped, indicates a need to restore the original bootloader
This way the system is almost ALWAYS running the banks in 'normal' 0/1 order.
Firstly, I don't see that I can use the new 'swap' function for just this 'backup' function as I was doing -- the diagram clearly indicates a need for 'resets' and erase operations in each bank to move around the states. But I do have a fundamental concern here as well -- while this mechanism is discussed as a SWAP process, the descriptions talk mostly of which bank is 'active' (at address 0) as if the 'other bank' were somehow not 'fully normally accessible' at the 256K address. Can I still get my full 496K application space with this new SWAP initialized? Or is this whole operation geared directly at applications that have two 256K 'application spaces' that one would ping-pong between?
Earl Goodrich II
Hi egoodii, sorry for the late noob question here, but is it safe to assume that if I can't find anything regarding FTFL_* registers in the reference manual for my Kinetis processor that the swap feature isn't supported? Might be a moot point anyway, since my application won't fit in 1/2 of the flash space. Can you suggest any good ANs for implementing a flash update feature? So far, I am planning on reviewing a bootloader option (AN2295) as well as possible leverage of EzPort (AN4835). Thanks!
Sorry, all my experience with the ‘flash swap’ mechanism were with the original 1.0-silicon design, where I had ‘more direct’ control over the usage of the two image-areas. Now there is a requirement for dedicated ‘application space’ flags, and built in ‘smarts’, that pretty much limits the application to true half-memory ‘usage swap’.
And no, I have NO information on which Kinetis parts have the swap functions.
Ok, no problem, thanks a bunch for your response. Maybe someone from FSL can comment on which parts support this feature. Though it's probably not worth changing the design to support it. I'll just have to bite the bullet and finally be forced to write a bootloader once in my career. :smileyhappy:
You might try the uTasker-bootloader support.
Hi Dave and Earl
Coincidentally I added the Flash Swap mechanism as an option to the uTasker serial loader today. Although I am not fully convinced yet, there may be some cases where the swap could be of interest (mainly swapping between two installed versions and also using applications that don't need to be linked to a boot loader address).
In this thread you can find more details as well as operating code (that is, real loader/application and not just an example of a dummy swap):
Re: Development of Swap in FRDM_K64
Regards
Mark
P.S. The subject of boot loaders comes up time and time again and it is quite frustrating to see hundered of companies porting and redeveloping effectively the same solution (often derivatives of AN2295, AN4764, AN4379, AN4368, or Kboot) - it must cost the industry millions in man power costs to re-develop the same wheel so often and to port examples from one processor to another or from one IDE to another.
Don't forget that the uTasker serial loader does all of these, for almost all Kinetis parts/families and all standard IDEs. It even allows mixing them. if you can't decide whether a USB-MSD device is what you need or a USB-MSD host (memory stick) you can simply enable both and allow the board to automatcially detect the mode it should use - or mix with Kboot at the same time - or even enable the old developer's serial loader (AN2295) on a UART, just for the hell of it...Complete flexibility - no porting - completely validated and proven solutions. And now with Swap Block support too ...;-)
Thanks for the tidbits! I have been doing some more experimentation and I now have a better understanding of the Flash Address supplied in each command -- we actually have to dedicate that area of USER flash memory in BOTH banks that will contain the one flag word that tracks the stages of update for each bank, AND is used at reset to evaluate said results -- which is to say that word MUST be dedicated, which at the very least breaks the 'contiguous flash addressing' of 'user space' if (like me!) you are trying to use MOST of the flash for one application-image. It certainly looks like any attempt to use this new SWAP feature for anything other than true ping-pong (256K max application!) will be extremely complicated.
And I see what you mean about JTAG tools! The 'implicit protection' of the WHOLE SECTOR containing at LEAST the 'active bank' flag word, and ALSO that in the 'other bank' if it's not set into 'update mode', certainly prevents a 'debug' tool access to one or two whole 2K sectors, further complicating any attempt to use this feature. I can't understand why these 'flag words' couldn't have been stored 'somewhere else' to stay out of our way!
And this seems to be yet another irreversible flash process that lets programmers and tools create permanently broken assemblies! I truly don't understand the lack of at least JTAG-capable erase-recovery modes...
Earl Goodrich II
Hello,
Kinetis silicon Rev1.4 change the swap flash mechanism:
Kinetis (100MHz devices)
Rev 1.0 – old swap method
Rev 1.1 – new swap method - more robust to power loss
Rev 1.2
Rev 1.4 – swap enhancement
(using mass erase / erase-all-blocks command)
Best Regards,
What code do you use to take the swap system from "uninitialized" to UPDATE-ERASED?
I tried the following register values but it did not work. Any suggestions?
Problem: An FTFL_FSTAT ACCERR violation occurs when the ”Initialize Swap System to UPDATE_ERASED State” FTFL command is issued.
FTFL is functional for programming and erasing FLASH as Flash copy routines can copy from Flash Bank 0 to Flash Bank 0 and from Flash Bank 0 to Flash bank 1.
The “Report Swap System Status” SWAP system command reports the K60 is
Note: An ACCERR is not issued when this command is executed
The FTFL registers are set as follows for the Initialize Swap System to UPDATE-ERASED state:
FTFL_FCCOB0 = 0x46; /* The opcode for performing a FLASH Swap */
FTFL_FCCOB1 = 0x03; /* Use 0x3FFF0 as the “Swap Indicator” address */
FTFL_FCCOB2 = 0xFF;
FTFL_FCCOB3 = 0xF0;
FTFL_FCCOB4 = 0x01; /* Initialize the Swap System */
Then a ram function is called to clear CCIF by writing a ‘1’ to the bit. FTFL_STAT changes to 0xA0 immediately after clearing CCIF which indicates an ACCERR condition.
Addresses other than 0x03FFF0 were tried, 0x30000, 0x20000, and 0x10000, all with the same result.
Flash at 0x3FFF0- 0x3FFFF and 0x7FFF0 – 7FFFF are 0xFFs.
The Swap Indicator address is phrase aligned and in the lower FLASH bank but not in the Flash Configuration Field. The Swap system reports it is in UNITITIALIZED state. I believe all conditions have been properly met.
What is the mask code on your chip?
The mask code is 4N30D. I belive that is Rev 1.4 silicon.
Sounds like it. I haven't tried since 1.2, so maybe it is different again?
For reference, this is the code I started to write to test/initialize the new swap mechanism, which 'bricked' my 1.2 part (which means it set up the swap mechanism, which I then couldn't use for my purposes, and in that rev was irreversable).
I BELIEVE this sequence will set address 0x3F0 (and the mirror address at 0x403F0 in the other bank) for the swap system flags. I don't know if this is a particularly 'good' address to use, but note that whatever address you dedicate for this specifically protects the enclosing sector from erase activity except in the very specific sequence to run from one bank and erase the other in prep for this whole update-then-swap scenario.
if( (fnFlashNow(FCMD_SWAP_CONTROL, 0x3F0, 0x08FF) & FTFL_FSTAT_MGSTAT0_MASK) == 0 )
//Command 8 == report swap status
{
if(FTFL_FCCOB5 == 0 )
fnFlashNow(FCMD_SWAP_CONTROL, 0x3F0, 0x01FF); //'virgin', initialize swap system
//Command 1 == set swap indicator address
else if(FTFL_FCCOB5 == 1 ) //'Normal' ready state -- swap process NOT started
{ //FTFL_FCCOB6 indicates which block is at address 0
}else //If we had a reset while the swap state machine was not 'Ready', we can't count on the new image
{
}
}else //Nonzero MGSTAT0 bit indicates some kind of fault during a swap-command execution
{
}
static int fnFlashNow(uint8_t ucCommand, uint32_t ptrWord, uint32_t ulWord)
{
do{
}while (!(FTFL_FSTAT & FTFL_FSTAT_CCIF_MASK)); // wait for previous commands to complete
if (FTFL_FSTAT & (FTFL_FSTAT_ACCERR_MASK | FTFL_FSTAT_FPVIOL_MASK))
{ // check for errors in previous command
FTFL_FSTAT = (FTFL_FSTAT_ACCERR_MASK | FTFL_FSTAT_FPVIOL_MASK); // clear old errors
}
switch (FTFL_FCCOB0 = ucCommand) { // enter the command sequence
case FCMD_ERASE_ALL_BLOCKS: // single command word required with the erase all blocks command
break;
case FCMD_SWAP_CONTROL:
FTFL_FCCOB6 = 0xFF; //Clear these status bytes, in case of fault
FTFL_FCCOB7 = 0xFF;
case FCMD_PROGRAM_SECTION:
if( ucCommand == FCMD_PROGRAM_SECTION )
ulWord >>= 3; //Convert to dual-dword count
FTFL_FCCOB4 = (uint8_t)(ulWord >> 8);
FTFL_FCCOB5 = (uint8_t)(ulWord);
case FCMD_ERASE_FLASH_SECTOR:
FTFL_FCCOB1 = (uint8_t)(ptrWord >> 16);
FTFL_FCCOB2 = (uint8_t)(ptrWord >> 8);
FTFL_FCCOB3 = (uint8_t)ptrWord;
break;
}
Disable_Interrupt(); // protect this region from interrupts
FTFL_FSTAT = FTFL_FSTAT_CCIF_MASK;
// launch the command - this clears the FTFL_STAT_CCIF flag (register is FTFL_FSTAT)
while (!(FTFL_FSTAT & FTFL_FSTAT_CCIF_MASK)) {} // wait for the command to terminate
return (FTFL_FSTAT & (FTFL_FSTAT_ACCERR_MASK | FTFL_FSTAT_FPVIOL_MASK | FTFL_FSTAT_MGSTAT0_MASK)); // if there was an error this will be non-zero
}
Thanks for the code. It looks like my code does what your code does. The problem remains.
I can see only two particular differences. My code presets FCCOB5/6/7 to 0xFF prior to each command, per the note preceding Table 28-66. Second, I let the IAR linker run my entire bootloader from RAM to avoid ANY bank access conflicts. I have no idea how the 'initialize' command interacts with Flash banks, if at all.
I might get brave and try this process on a new 1.4 part, on the expectation the 'erase all' will reset it all for me.
--ERGII
So, I breakpoint my code just after the call to SWAP status, and the virgn state leads to the call to init, and afterwards the FCCOB reads:
460003f0 01030000
and the byte at 0x3F4 is cleared to zero.
If I reset and run to that breakpoint again, the status returned is now:
460003f0 08030000
which appears to mean, in both cases, that I am in state 'Update erased'.
Attempts now to upload full code thru JTAG find the affected sectors write protected, and the IAR upload is severely unhappy.
Fortunately for me, this 1.4 silicon does indeed respond to 'unlock kinetis' and returns to a programmable state, and Swap status is back to zero.
So, without developing the whole ping/pong process further, it looks like what I have works as advertised.
--ERGII
You say 'address 0x500 in bank 0' for the indicator, but of course this new Kinetis mechanism also involves offset 0x500 in Bank 1 as the indicator for that bank, and that area must ALSO be erased prior to initializing the swap mechanism.
You didn't supply any full command sequences -- is your code following more-or-less exactly the codes, FCCB contents and status checks as my code?
Also, since this swap initialization writes to BOTH flash banks, the commands MUST run from RAM.
Egoodii
Unfortunately, I can't really use this new swap mechanism, so I can't really be an 'expert' on the exact requirements. The placement of these two 'status flag bytes', one each in each bank WITHIN processor address space makes a real complication to my environment where I need 90% of the flash for my application size. This is TRULY meant to only work for the ping-pong one-actve/one-backup application images in flash, not with the 'small bootloader' approach. Now if they would've just put those flags in some other 'extra' flash space (like iFR!) I wouldn't have this memory map problem...
That being said, I can only know that the phrases each containing this flag byte, at the offset you specify in both banks, must be erased before you run the 'init' command to place the flash-update mechanism in this whole ping-pong-swap mode. I went with 0x3f4 in my example simply because there is a 'hole' between the top of usable vectors and the config space that is otherwise difficult to use (and easy to see that the linker is 'ignoring').
For my money, I would certainly start out with an empty chip, in fact I would go so far as to start with that 'mass erase' as with Jlink 'unlock kinetis' to insure the swap mechanism is un-initialized to start with, and as in my code will return such a status. If you can't then 'init swap' I will have to assume it is a bank conflict due to processor-access to either bank during init.
By the way, you haven't said but I assume you are running Rev 1.4 silicon.
--ERGII
Hi,
I'm running Rev 1.4.
Seems it was erase related, to confirm I created a swap section size 2K that I erased just before Init. Then it worked.
My original code and idea was to keep a size 0x4 area free of code in the text section from the linker script to be used as swap indicator, I assumed it would work due to the fact I kept it 0xFF by FILL(0xFF). But seems it didn't
//rtlaka