New Kinetis Flash SWAP mechanism

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

New Kinetis Flash SWAP mechanism

7,684 Views
egoodii
Senior Contributor III

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

29 Replies

2,024 Views
dave408
Senior Contributor 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!

0 Kudos

2,024 Views
egoodii
Senior Contributor III

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.

0 Kudos

2,024 Views
dave408
Senior Contributor II

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:

0 Kudos

2,024 Views
egoodii
Senior Contributor III

You might try the uTasker-bootloader support.

0 Kudos

2,024 Views
mjbcswitzerland
Specialist V

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 ...;-)

0 Kudos

2,027 Views
egoodii
Senior Contributor III

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

0 Kudos

2,027 Views
LuisCasado
NXP Employee
NXP Employee

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

•  When swap system is initialized Erase-All-Blocks is disabled
•  Swap system cannot go back to uninitialized

Rev 1.2

•  Same as rev 1.1 except slight change to initialization

Rev 1.4 – swap enhancement

• Erase-All-Blocks is not disabled when swap is initialized
• Swap system can be set back to uninitialized

     (using mass erase / erase-all-blocks command) 

 

Best Regards,

0 Kudos

2,027 Views
Zack
Contributor I

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

  • In the “Uninitialized State”
  • Current Flash bank is 0
  • Next swap bank is zero.

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.

0 Kudos

2,027 Views
egoodii
Senior Contributor III

What is the mask code on your chip?

0 Kudos

2,027 Views
Zack
Contributor I

The mask code is 4N30D. I belive that is Rev 1.4 silicon.

0 Kudos

2,027 Views
egoodii
Senior Contributor III

Sounds like it.  I haven't tried since 1.2, so maybe it is different again?

0 Kudos

2,027 Views
egoodii
Senior Contributor III

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

}

0 Kudos

2,027 Views
Zack
Contributor I

Thanks for the code. It looks like my code does what your code does. The problem remains.

0 Kudos

2,027 Views
egoodii
Senior Contributor III

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

0 Kudos

2,027 Views
egoodii
Senior Contributor III

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

0 Kudos

2,027 Views
rtlaka
Contributor I
Hi,

I've experinced the exact same problem described by Zack on a Rev 1.4 k10, MK10 DN512 ZVLQ 10, 144 pin. Program flash only, meaning it should support it, right?

I use address 0x500 as swap indicator, alignment ok, not in Configuration fields and bank0.
After trying to init I get FTFL_STAT changes to 0xa0 an ACCERR condition as Zack mentioned. I did read resource and IFR in bank 0 say, 0x0500 FFFF. The status bits FCCOB5-7 get 0'ed.

Did anyone get past those kind of problems

//rtlaka


0 Kudos

2,027 Views
egoodii
Senior Contributor III

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

0 Kudos

2,027 Views
rtlaka
Contributor I
I have the same FCCB sequence, more or less. I think the problem is erase related then.

If I've never succesfully Init swap , do I need to run Erase-All-Blocks? The IFR seems to have been modified with the correct address but still UnInit 0xFFFF


0 Kudos

2,027 Views
egoodii
Senior Contributor III

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

0 Kudos

2,026 Views
rtlaka
Contributor I

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

 

 

 

0 Kudos