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:
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.
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.
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.
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.
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.
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.
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?
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 .
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)
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();
#endifreturn 0;
}
Hi,
I just tried your code. I just made two modifications:
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
Roberto, were you able to find a solution to this issue? I'm having the same troubles with SDK 2.4.2.
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.
Hi have you tested successful with IDE = MCUXpresso v10.2.1
I have always been testing with IDE = MCUXpresso v10.2.1 with with unsuccessful results.
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)?
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.
I think you can try IAR platform download and debug the flash_swap,