SWAP does not work from UPPER on SDK 2.4.1 flash driver?

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

SWAP does not work from UPPER on SDK 2.4.1 flash driver?

4,937 Views
robertoquilez
Contributor III

We are using a MK26 with flash swap feature for firmware updates.

The swap does not work on SDK 2.4.1 .Since we have migrated to the SDK 2.4.1 the swap feature does not work any more.

We can swap from block 0 (LOWER) but when we swap from the block 1 (UPPER block) the firmware keeps blocked on the swap state "kFTFx_SwapStateUpdate". 

Furthermore, the swap demo provided for the TowerK65f180m code seems wrong. The demo code does the swap as follows:

  • result = FLASH_Swap(&s_flashDriver, swapIndicatorAddress, false);

This disables the SWAP, the last parameter should be set to TRUE

With driver fsl_flash v.2.3.1 we did not have this issue.

You have done a lot of modifications/refactoring  on the flash driver since sdk  2.3.0, where can we find the changelog with this modifications (specially concerning the flash driver)

If we look at the documentation provided with the SDK 2.4.1, /MCUXpressoSDKReleaseNotes_MK66F18.pdf, on page 5  we can read: 

FLASH

The current FLASH driver version is 2.3.1.

• 2.3.1
Bug fixes:

* Unified Flash IFR design from K3.

* New encoding rule for K3 flash size.

The documentation does not correspond with the code provided in the SDK!??

Please note that this is critical feature  because it is the base  the over the air firmware update. 

23 Replies

3,603 Views
robertoquilez
Contributor III

Well, knovinger this issue seems to be "magically" solved with the new SDK_2.5.0_MK26 and MCUXpressoIDE v10.3.0. 

Swap demo provided for the TowerK65f180m has also been corrected.

There is no comment about this issue in the SDK changelog so I have no idea about what the problem was.

0 Kudos

3,604 Views
knovinger
Contributor III

That is good news.  When you evaluated on your project, did you update all drivers from the new SDK or only the flash drivers?  I've created a new project from scratch with SDK 2.5, imported the source files from my previous project, made the necessary changes for compatibility with the new drivers (they can't seem to leave the stuff that works alone), and am now worse off than I was.  I'm thinking I need to just try and update the flash drivers only.

0 Kudos

3,604 Views
robertoquilez
Contributor III

Hi Kevin, I had updated all drivers. For me, the easiest way to check that everything works  is the source main file from the  MK26FN2M0xxx18_Project.c.zip in this thread. It prints whether you are in the LOWER and the UPPER and perform a SWAP at the end. 

0 Kudos

3,606 Views
nxf42424
NXP Employee
NXP Employee

Hi

I have test SDK2.4.1 TWR-K65 flash swap with MCUXpresso v10.2.1, and it is successful , 

last time I test SDK2.4.1 flash swap haveProduced some strange mistakes,

May be due to the low version of the IDE.

0 Kudos

3,606 Views
knovinger
Contributor III

Ding, thank you for your response.  However, I don't understand. I'm already running v10.2.1.  Which I understand to be the latest version.  Are you stating that you now have experienced issues with v10.2.1 and SDK 2.4.1?  Please clarify.

Also, most of my testing has been done on a custom board.  However, I started further testing on a FRDMK64 until I inadvertently locked the flash by disabling mass erase.

0 Kudos

3,605 Views
nxf42424
NXP Employee
NXP Employee

 can I look your code, I don't know how you operate. I have not experienced that, 

I don't understand  how you "locked the flash by disabling mass erase", have you operate correctly?

0 Kudos

3,606 Views
nxf42424
NXP Employee
NXP Employee

1.The third parameter should be true “result = FLASH_Swap(&s_flashDriver, swapIndicatorAddress, true);”

2.I think twrk65 does not support swapping from the block 1 (UPPER block) to block 0 (LOWER),

the correct step is stap is  When you swap from block0 to block1, block1 becomes block0. then you can swap again.  

If you want to go back to the starting state, you have to Erase all blocks to clear the swap system back to uninitialized .

   

3,606 Views
robertoquilez
Contributor III

1.- So the demo is effectively wrong.

2.-  The problem is that once that we have SWAPPED we can NOT SWAP again without doing a mass erase.

With previous SDK we did not have this issue. The status machine keeps blocked on "kFTFx_SwapStateUpdate"

The idea is to implement a "Robust Over-the-Air Firmware Updates Using Program Flash Memory Swap on Kinetis Microcontrollers" as described on  http://cache.freescale.com/files/microcontrollers/doc/app_note/AN4533.pdf 

The swap works the first time but not the second one (once already swapped) i.e. if we repeat  the procedure once swapped it wont work.

Can you confirm that is possible to swap back once swapped (we are using the MK26) with SDK 2.4.1?

(with sdk 2.3.0 we did not have this problem)

0 Kudos

3,606 Views
nxf42424
NXP Employee
NXP Employee

Hi

try this code, During the debugging, please make a breakpoint at BOARD_InitHardware(); and observe the change of the flash value.

/*
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/*******************************************************************************
* Includes
******************************************************************************/
#include "fsl_device_registers.h"
#include "fsl_debug_console.h"
#include "board.h"
#include "clock_config.h"
#include "pin_mux.h"
#include "app.h"
#include "fsl_flash.h"
/*******************************************************************************
* Definitions
******************************************************************************/

#define EXAMPLE_IMAGE_SIZE 0x8000 /* 32KB */
#define LOWER_PFLASH_BASE FSL_FEATURE_FLASH_PFLASH_START_ADDRESS
#define UPPER_PFLASH_BASE (FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE * (FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT >> 1))
#define FLASH_CONFIG_START 0x400

/*******************************************************************************
* Prototypes
******************************************************************************/

void error_trap(void);
void app_finalize(void);

/*******************************************************************************
* Variables
******************************************************************************/

/*! @brief Flash driver Structure */
static flash_config_t s_flashDriver;
/*! @brief 16 bytes Flash config data */
/* uint32_t flashConfigData[] = {0xffffffffU, 0xffffffffU, 0xffffffffU, 0xfffffffeU}; */
/*! @brief Test data used to validate swap result*/
uint8_t swapUpertData[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x5, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};

uint8_t swaplowerData[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
0x90, 0x91, 0x91, 0x93, 0x94, 0x95, 0x96, 0x97};

uint32_t pflashBaseAddr;

/*******************************************************************************
* Code
******************************************************************************/

/*
* @brief Gets called when an error occurs.
*
* @details Print error message and trap forever.
*/
void error_trap(void)
{
PRINTF("\r\n\r\n\r\n\t---- HALTED DUE TO FLASH ERROR! ----");
while (1)
{
}
}

/*
* @brief Gets called when the app is complete.
*
* @details Print finshed message and trap forever.
*/
void app_finalize(void)
{
/* Print finished message. */
PRINTF("\r\n End of PFlash Swap Example \r\n");
while (1)
{
}
}

/*!
* @brief Use Standard Software Drivers (SSD) to enable flash swap feature.
*
* @details This function uses SSD to demonstrate flash mode:
* + Check flash information.
* + Program swap test data on upper pflash.
* + Swap the flash system
* + Check lower pflash to see whether swap test data is over there.
*/
int main(void)
{
ftfx_security_state_t securityStatus = kFTFx_SecurityStateNotSecure; /* Return protection status */
status_t result; /* Return code from each flash driver function */

uint32_t pflashTotalSize = 0;
uint32_t pflashBlockCount = 0;
uint32_t pflashSectorSize = 0;

/* Init hardware */
BOARD_InitHardware();

/* Clean up structures*/
memset(&s_flashDriver, 0, sizeof(flash_config_t));

/* Setup flash driver structure for device and initialize variables. */
result = FLASH_Init(&s_flashDriver);
if (kStatus_FTFx_Success != result)
{
error_trap();
}
/* Get flash properties*/
FLASH_GetProperty(&s_flashDriver, kFLASH_PropertyPflash0TotalSize, &pflashTotalSize);
FLASH_GetProperty(&s_flashDriver, kFLASH_PropertyPflash0BlockCount, &pflashBlockCount);
FLASH_GetProperty(&s_flashDriver, kFLASH_PropertyPflash0SectorSize, &pflashSectorSize);

/* print welcome message */
PRINTF("\r\n PFlash Swap Example Start \r\n");
/* Print flash information - PFlash. */
PRINTF("\r\n PFlash Information: ");
PRINTF("\r\n Total Program Flash Size:\t%d KB, Hex: (0x%x)", (pflashTotalSize / 1024), pflashTotalSize);
PRINTF("\r\n Total Program Flash Block Count:\t%d", pflashBlockCount);
PRINTF("\r\n Program Flash Sector Size:\t%d KB, Hex: (0x%x) ", (pflashSectorSize / 1024), pflashSectorSize);

/* Check security status. */
result = FLASH_GetSecurityState(&s_flashDriver, &securityStatus);
if (kStatus_FTFx_Success != result)
{
error_trap();
}
/* Print security status. */
switch (securityStatus)
{
case kFTFx_SecurityStateNotSecure:
PRINTF("\r\n Flash is UNSECURE!");
break;
case kFTFx_SecurityStateBackdoorEnabled:
PRINTF("\r\n Flash is SECURE, BACKDOOR is ENABLED!");
break;
case kFTFx_SecurityStateBackdoorDisabled:
PRINTF("\r\n Flash is SECURE, BACKDOOR is DISABLED!");
break;
default:
break;
}
PRINTF("\r\n");

#if defined(FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP) && FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP

/* Debug message for user. */
/* Test pflash swap feature only if flash is unsecure. */
if (kFTFx_SecurityStateNotSecure != securityStatus)
{
PRINTF("\r\n Flash swap opeation will not be executed, as Flash is SECURE!");
app_finalize();
}
else
{
struct _flash_swap_ifr_field_config
{
uint16_t swapIndicatorAddress; /*!< A Swap indicator address field.*/
uint16_t swapEnableWord; /*!< A Swap enable word field.*/
uint8_t reserved0[4]; /*!< A reserved field.*/
uint8_t reserved1[2]; /*!< A reserved field.*/
uint16_t swapDisableWord; /*!< A Swap disable word field.*/
uint8_t reserved2[4]; /*!< A reserved field.*/
} flashSwapIfrFieldData;
uint32_t swapIndicatorAddress;
ftfx_swap_state_config_t returnSwapInfo;
uint32_t failedAddress;
uint32_t failedData;
uint32_t tempData[2];

/* Clean up structures*/
memset(&flashSwapIfrFieldData, 0, sizeof(flashSwapIfrFieldData));
memset(&returnSwapInfo, 0, sizeof(ftfx_swap_state_config_t));

/* Get original swap indicator address */
result = FLASH_ReadResource(&s_flashDriver, s_flashDriver.ftfxConfig[0].ifrDesc.resRange.pflashSwapIfrStart,
(uint8_t *)&flashSwapIfrFieldData, sizeof(flashSwapIfrFieldData),
kFTFx_ResourceOptionFlashIfr);

/* The high bits value of Swap Indicator Address is stored in Program Flash Swap IFR Field,
* the low severval bit value of Swap Indicator Address is always 1'b0 */
swapIndicatorAddress = (uint32_t)flashSwapIfrFieldData.swapIndicatorAddress *
s_flashDriver.ftfxConfig[0].opsConfig.addrAligment.swapCtrlCmd;
if (kStatus_FTFx_Success != result)
{
error_trap();
}
else
{
PRINTF("\r\n Original swap indicator address:\t0x%x", swapIndicatorAddress);
}

/* It doesn't matter what the provided address is, when option is kFlashSwap_ReportStatus*/
result = FTFx_CMD_SwapControl(&s_flashDriver.ftfxConfig[0],
FSL_FEATURE_FLASH_PFLASH_SWAP_CONTROL_CMD_ADDRESS_ALIGMENT,
kFTFx_SwapControlOptionReportStatus, &returnSwapInfo);
if (kStatus_FTFx_Success != result)
{
error_trap();
}
/* Check current flash swap status*/
switch (returnSwapInfo.flashSwapState)
{
case kFTFx_SwapStateUninitialized:
PRINTF("\r\n Current swap system status: Uninitialized \r\n");
swapIndicatorAddress = UPPER_PFLASH_BASE - pflashSectorSize;
PRINTF("\r\n Set swap indicator address as 0x%x \r\n", swapIndicatorAddress);
break;
case kFTFx_SwapStateReady:
PRINTF("\r\n Current swap system status: Ready \r\n");
break;
case kFTFx_SwapStateUpdate:
PRINTF("\r\n Current swap system status: Update \r\n");
break;
case kFTFx_SwapStateUpdateErased:
PRINTF("\r\n Current swap system status: UpdateErased \r\n");
break;
case kFTFx_SwapStateComplete:
PRINTF("\r\n Current swap system status: Complete \r\n");
break;
case kFTFx_SwapStateDisabled:
PRINTF("\r\n Current swap system status: Disabled \r\n");
//app_finalize();
break;
default:
error_trap();
break;
}

/* Check if the original indicator address is valid */
if (returnSwapInfo.flashSwapState != kFTFx_SwapStateUninitialized)
/* if (flashSwapIfrField.swapIndicatorAddress != (uint16_t)(~0)) */
{
if ((swapIndicatorAddress < EXAMPLE_IMAGE_SIZE) || (swapIndicatorAddress >= UPPER_PFLASH_BASE))
{
PRINTF("\r\n Original swap indicator address couldn't be used for this example \r\n");
PRINTF(
"\r\n Swap system needs to be cleared back to uninitialized, This example cannot clear swap system "
"\r\n");
app_finalize();
}
}

result = FLASH_Erase(&s_flashDriver, pflashBaseAddr + EXAMPLE_IMAGE_SIZE, sizeof(swaplowerData),
kFTFx_ApiEraseKey);
result = FLASH_Program(&s_flashDriver, pflashBaseAddr + EXAMPLE_IMAGE_SIZE, &swaplowerData[0], sizeof(swaplowerData));

result = FLASH_VerifyProgram( &s_flashDriver, pflashBaseAddr + EXAMPLE_IMAGE_SIZE, sizeof(swaplowerData), &swaplowerData[0],
kFTFx_MarginValueUser, &failedAddress, &failedData);
if (kStatus_FTFx_Success != result)
{
error_trap();
}

PRINTF("\r\n Backup example image is invalid \r\n");
PRINTF("\r\n Start to program backup example image \r\n");
pflashBaseAddr = LOWER_PFLASH_BASE;
memcpy((uint8_t *)(&tempData[0]), (uint8_t *)pflashBaseAddr, sizeof(tempData));
/* Need to program the backup image */
result = FLASH_Erase(&s_flashDriver, UPPER_PFLASH_BASE, EXAMPLE_IMAGE_SIZE, kFTFx_ApiEraseKey);
if (kStatus_FTFx_Success != result)
{
error_trap();
}
result = FLASH_Program(&s_flashDriver, UPPER_PFLASH_BASE, &tempData[0], sizeof(tempData));
result = FLASH_Program(&s_flashDriver, UPPER_PFLASH_BASE + sizeof(tempData),
(uint8_t *)(LOWER_PFLASH_BASE + sizeof(tempData)), EXAMPLE_IMAGE_SIZE - sizeof(tempData));
if (kStatus_FTFx_Success != result)
{
error_trap();
}
result = FLASH_VerifyProgram(&s_flashDriver, UPPER_PFLASH_BASE + sizeof(tempData), EXAMPLE_IMAGE_SIZE - sizeof(tempData),
(uint8_t *)(LOWER_PFLASH_BASE + sizeof(tempData)) , kFTFx_MarginValueUser, &failedAddress, &failedData);
if (kStatus_FTFx_Success != result)
{
error_trap();
}

result = FLASH_Erase(&s_flashDriver, UPPER_PFLASH_BASE + EXAMPLE_IMAGE_SIZE, sizeof(swapUpertData),
kFTFx_ApiEraseKey);
if (kStatus_FTFx_Success != result)
{
error_trap();
}
result = FLASH_Program(&s_flashDriver, UPPER_PFLASH_BASE + EXAMPLE_IMAGE_SIZE, &swapUpertData[0],
sizeof(swapUpertData));

PRINTF("\r\n Finish programming backup example image \r\n");
// Enable swap system
PRINTF("\r\n Start to swap the system \r\n");
result = FLASH_Swap(&s_flashDriver, swapIndicatorAddress, true);

NVIC_SystemReset();
}

#else
PRINTF("\r\n Current device doesn't support flash swap feature \r\n");

app_finalize();
#endif

return 0;
}

3,606 Views
robertoquilez
Contributor III

Hi, 

I just tried your code. I just made two modifications:

  • I had to comment BOARD_InitHardware();
  • I included following code to know wether I am on the upper or lower:

switch (returnSwapInfo.currentSwapBlockStatus)

{

case kFTFx_SwapBlockStatusLowerHalfProgramBlocksAtZero:

printf("Current Swap block status is LOWER half program block at zero\r\n");

break;

case kFTFx_SwapBlockStatusUpperHalfProgramBlocksAtZero:

printf("Current Swap block status is UPPER half program block at zero\r\n");

break;

}

The result is that first time (after flash mass erase) that your code is executed, we are in "Current Swap block status is LOWER half program block at zero" and the swap works properly.

Nevertheless, If I start a new debug session (without doing a mass erase),I will be in "Current Swap block status is UPPER half program block at zero" and SWAP does NOT work.

The output printfs are the following:

EGGER J-Link GDB Server V6.32h - Terminal output channel

PFlash Swap Example Start

PFlash Information:

Total Program Flash Size: 2048 KB, Hex: (0x200000)

Total Program Flash Block Count: 4

Program Flash Sector Size: 4 KB, Hex: (0x1000)

Flash is UNSECURE!

Original swap indicator address: 0xff000

Current Swap block status is UPPER half program block at zero

Current swap system status: Update

Start while erase: 8000-8fff (1000)

Erasing: 9000

End erase

Backup example image is invalid

Start to program backup example image

Start while erase: 100000-107fff (1000)

Erasing: 101000

Erasing: 102000

Erasing: 103000

Erasing: 104000

Erasing: 105000

Erasing: 106000

Erasing: 107000

Erasing: 108000

End erase

Start while erase: 108000-108fff (1000)

Erasing: 109000

End erase

Finish programming backup example image

Start to swap the system

Start while erase: 108000-108fff (1000)

Erasing: 109000

End erase

Start while erase: 108000-108fff (1000)

Erasing: 109000

End erase

Start while erase: 108000-108fff (1000)

Erasing: 109000

End erase

Start while erase: 108000-108fff (1000)

Erasing: 109000

End erase

Start while erase: 108000-108fff (1000)

Erasing: 109000

End erase...

And the code keeps blocked there, because the status machine keeps blocked on "kFTFx_SwapStateUpdate", and no swap is done.

Again, in order to implement a firmware update ( as in AN4533) I need to be able to swap once I have already swapped and block 0 is  on UPPER. Actually I have already done that with the old SDK but does not work anymore since migrated to the new sdk.

Thank you in advance for your support,

Roberto

0 Kudos

3,606 Views
nxf42424
NXP Employee
NXP Employee

Hi,

Are you sure you erase the high address block before the second swap?

I have tested it many times and it can be swap normally.

You'd better send me the code you tested, I can't reproduce your mistake now.

Regards

Ding

0 Kudos

3,606 Views
robertoquilez
Contributor III

Ding, thank you very much for your detailed doc.

Please find enclosed  my source code and a similar document to yours with the results I get. 

0 Kudos

3,606 Views
knovinger
Contributor III

Roberto, were you able to find a solution to this issue?  I'm having the same troubles with SDK 2.4.2.

3,606 Views
robertoquilez
Contributor III

Kevin, sadly I am still blocked with this issue.

I am still looking for somebody to confirm that it is possible to swap back once swapped using the MK26 with SDK 2.4.1

It is really a pity because it blocks all my developments as it breaks the firmware update feature.

Is good to know that I am not alone in the desert. Please come back to this thread if you do any progress.

0 Kudos

3,606 Views
nxf42424
NXP Employee
NXP Employee

Hi have you tested successful with   IDE = MCUXpresso v10.2.1

0 Kudos

3,605 Views
robertoquilez
Contributor III

I have always been testing with IDE = MCUXpresso v10.2.1 with with unsuccessful results.

0 Kudos

3,605 Views
nxf42424
NXP Employee
NXP Employee

Hi

I think you need to reinstall a newer IDE,

I have test the SDK2.4.1 flash swap on the TWR-K65F180 platform with MCUXpresso v10.2.1

Aan it is successful,

0 Kudos

3,605 Views
robertoquilez
Contributor III

Thank you for your response, Ding, but from the beginning I have been using MCUXpresso v10.2.1 (the latest version to my knowledge).

I see that you can swap twice with the TWR-K65F180, nevertheless either of us is using this  MCU exactly.

Could be possible that this issue only concerns the  MK26 (my case) or MK64 (as Kevin's)?  

0 Kudos

3,605 Views
knovinger
Contributor III

Some more information from my struggles.

IDE = MCUXpresso v10.2.1

MCU = Kinetis MK64FN1M0xxxx12

SDK = v2.4.2

I was able to capture an error while performing the swap.  My process is to first flash the device thru BDM, then allow the device to run the app as intended.  I first checked the FlashSwap state machine and would find it to be in the Uninitialized state, as expected.  I would then enter our In-System-Programming process thru an external UART.  Upon loading a new flash image to Flash Block 1 (upper block), the app would request the flash swap, then reboot the device. After boot, the newly loaded app version took affect.  So, swap attempt one worked. 

However, prior to attempting swap 2, I checked the FlashSwap state machine. Instead of being in the Ready state, it was in the Update state.  I connected the debugger to the running target and set a break point just prior to the call to FLASH_Swap.  I then commenced with our ISP process and awaited the break.  Once at the break point, i proceeded to step thru the FLASH_Swap routine at which time I received error 103 (kStatus_FTFx_AccessError) after the call to FTFx_CMD_Erase under the kFTFxSwapStateUpdate case.  From the K64 reference manual, "The non-active swap indicator will be checked at the erase verify level and if the check fails, the current swap state will be changed to UPDATE and ACCERR set".  So, this appears to be the area where something is going wrong.  My question is, when is the erase verified?  Is verification buried in the supplied driver or is it required as part of user app code?

In order to get something working, I have removed the flash driver files provided with SDK2.4.2 from my project and replaced them with the flash driver files used in a previous project from SDK2.2.0 (a KDS project).  With these driver files, the process works flawlessly.

Can anyone clarify the difference between v2.2.0 and v2.4.2 with respect to the flash drivers?  Is there additional support required by the user app code for full compatibility with v2.4.2?  Are there compiler switches that need to be configured to further define how the v2.4.2 drivers function?

From what I can tell the FLASH_Swap function should be handling everything.  But then again, there is no documentation anywhere that I can find which helps to explain it's function.

0 Kudos

3,605 Views
nxf42424
NXP Employee
NXP Employee

I think you can try IAR platform download and debug the flash_swap,  

0 Kudos