Hello,
I am trying to implement a flash over the air, and most of it is ok. The issue is when initializing the flag of swap.
Here are my steps, based on the driver C90TFS in KSDK 1.2.0 over a K64F120M with 1MB flash :
- call the relocate function :
g_FlashLaunchCommand = (pFLASHCOMMANDSEQUENCE)RelocateFunction((uint32_t)ramFunc , LAUNCH_CMD_SIZE ,(uint32_t)FlashCommandSequence);
Then get the current swap status :
result = PFlashSwapCtl(&flashSSDConfig,FLASH_SWAP_INDICATOR_ADDR,FTFx_SWAP_REPORT_STATUS,¤tSwapMode, \
¤tSwapBlockStatus, &nextSwapBlockStatus ,g_FlashLaunchCommand);
I can then see that the currentSwapMode is FTFx_SWAP_UNINIT.
Then I call the flash function :
result = PFlashSwap(&flashSSDConfig, FLASH_SWAP_INDICATOR_ADDR, SwapCallback, g_FlashLaunchCommand);
Unfortunately, this function creates a reboot (or more exactly, a jump to the startup...
The flash function is the one of the driver :
uint32_t SIZE_OPTIMIZATION PFlashSwap(PFLASH_SSD_CONFIG pSSDConfig, \
uint32_t addr, \
PFLASH_SWAP_CALLBACK pSwapCallback, \
pFLASHCOMMANDSEQUENCE pFlashCommandSequence)
{
uint32_t ret = FTFx_OK; /* Return code */
uint8_t currentSwapMode , currentSwapBlockStatus , nextSwapBlockStatus;
bool swapContinue;
currentSwapMode = currentSwapBlockStatus = nextSwapBlockStatus = 0xFFU;
swapContinue = FALSE;
/* Report current swap state */
ret = PFlashSwapCtl(pSSDConfig,addr,FTFx_SWAP_REPORT_STATUS,¤tSwapMode, \
¤tSwapBlockStatus, &nextSwapBlockStatus ,pFlashCommandSequence);
if (FTFx_OK == ret)
{
if ((FTFx_SWAP_UNINIT == currentSwapMode) || (FTFx_SWAP_READY == currentSwapMode) || \
(FTFx_SWAP_UPDATE == currentSwapMode))
{
/* If current swap mode is Uninitialized */
if (FTFx_SWAP_UNINIT == currentSwapMode)
{
/* Initialize Swap to Initialized/READY state */
ret = PFlashSwapCtl(pSSDConfig, addr, FTFx_SWAP_SET_INDICATOR_ADDR,¤tSwapMode, \
¤tSwapBlockStatus, &nextSwapBlockStatus , pFlashCommandSequence);
}[...]
and what is really curious is, it calls PFlashSwapCtl() a first time (line 14) then a second time (line 26) but only the second time, there is a failure. And if I follow until it fails, it's in the call to pFlashCommandSequence here :
uint32_t SIZE_OPTIMIZATION PFlashSwapCtl(PFLASH_SSD_CONFIG pSSDConfig,uint32_t addr, uint8_t swapcmd,uint8_t* pCurrentSwapMode, \
uint8_t* pCurrentSwapBlockStatus, \
uint8_t* pNextSwapBlockStatus, \
pFLASHCOMMANDSEQUENCE pFlashCommandSequence)
{
uint32_t ret; /* Return code variable */
uint32_t temp; /* temporary variable */
addr = WORD2BYTE(addr - pSSDConfig->PFlashBase);
/* clear RDCOLERR & ACCERR & FPVIOL flag in flash status register. Write 1 to clear*/
temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FSTAT_OFFSET;
REG_WRITE(temp, FTFx_SSD_FSTAT_ERROR_BITS);
/* passing parameter to the command */
temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB0_OFFSET;
REG_WRITE(temp, FTFx_PFLASH_SWAP);
temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB1_OFFSET;
REG_WRITE(temp, GET_BIT_16_23(addr));
temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB2_OFFSET;
REG_WRITE(temp, GET_BIT_8_15(addr));
temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB3_OFFSET;
REG_WRITE(temp, GET_BIT_0_7(addr));
temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB4_OFFSET;
REG_WRITE(temp, swapcmd);
temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB5_OFFSET;
REG_WRITE(temp, 0xFFU);
temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB6_OFFSET;
REG_WRITE(temp, 0xFFU);
temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB7_OFFSET;
REG_WRITE(temp, 0xFFU);
/* calling flash command sequence function to execute the command */
ret = pFlashCommandSequence(pSSDConfig);
if (FTFx_OK == ret) [...]
By looking into it with the debugger, I can see that g_FlashLaunchCommand is still pointing to the same adress in ram. I am using a multilink, but should I supposed to be able to follow step by step the execution in the ram function ?
Does anyone has any idea about why this command FTFx_SWAP_INDICATOR_ADDR fails ?
Thanks
Hello Samuel Boivineau:
You are calling the functions with a macro called "FLASH_SWAP_INDICATOR_ADDR". Could you tell me what address is that?
For instructions on what address to use please check the application note AN4533, in particular the chapter 5.1 Flash Swap Indicators. In your case for K64 the address must be 128-bit aligned and usually it is placed in the last sector of each flash block.
Regards!
Jorge Gonzalez
Hello Jorge,
the adress is defined as below :
#define FLASH_SWAP_INDICATOR_ADDR 0x7F000 //last sector of lower half
Actually I have solved this issue but by putting _time_delay(50) after each call to PFlashSwapCtl. And I have been able to flash many times without any failure. But I am still curious about it, because I am evaluating the board for industrial purpose, and adding some delays is not a good sign by experience :-)
Regards
Hello samuel:
Good to know it is solved.
This may be a data synchronization issue. See the next interesting article about it:
Serialization of memory operations and events
Actually I found this code in the flash driver from MQX:
/********************************************************************
*
* Code required to run in SRAM to perform flash commands.
* All else can be run in flash.
* Parameter is an address of flash status register and function to invalidate cache.
*
********************************************************************/
static void ftfe_ram_function
(
/* [IN] Flash info structure */
volatile uint8_t *ftfe_fstat_ptr,
/* [IN] Pointer to function of invalidate cache*/
void (* invalidate_cache)(volatile uint32_t)
)
{
/* start flash write */
*ftfe_fstat_ptr |= FTFE_FSTAT_CCIF_MASK;
/* wait until execution complete */
while (0 == ((*ftfe_fstat_ptr) & FTFE_FSTAT_CCIF_MASK))
{ };
if(invalidate_cache != NULL)
{
invalidate_cache((uint32_t)FLASHX_INVALIDATE_CACHE_ALL);
}
/* Flush the pipeline and ensures that all previous instructions are completed
* before executing new instructions in flash */
#ifdef ISB
ISB();
#endif
#ifdef DSB
DSB();
#endif
}
And the macros are defined like this:
#define ISB() __asm volatile ("isb")
#define DSB() __asm volatile ("dsb")
isb and dsb are instructions of the ARM core which help to synchronize code execution and data accesses to avoid undesired behaviors.
Regards!
Jorge Gonzalez