Hi,
I'm currently implementing an In-Application Programming (IAP) procedure for firmware updates in my project, but have some issues in the final step.
Note: I'm using S32 Design Studio for S32 platform, Build 201217 (Update 3) and SDK for S32K144, version S32SDK_S32K1XX_RTM_4.0.2
What am I doing ?
1) Receive a new firmware via CAN and store it in the DFlash block (The FW size is ~25k, so this fits well into the 64k block of the DFlash). I've verified the content of the DFlash after receiving it and it's identical to the generated and uploaded .bin file, so I assume this step is working
2) Disable all interrupts and call a function located in RAM, which erases the PFlash block and copy the Dflash content to PFlash (starting at address 0).
3) Issue a SW reset request
The MCU stalls somewhere at step 2. The PFlash memory is corrupted, the MCU won't start. Unfortunately it's hard to debug, so I'm asking for any helpful hints
Here are the important snippets of my code:
#define CODE_RAM __attribute__ ((section(".code_ram")))
void CODE_RAM copy_firmware(void);
I've checked the .map file and the copy_firmware() function is indeed placed into the .code_ram section.
*(.code_ram)
.code_ram 0x1fff8ab8 0x38 ./SDK/platform/drivers/src/flash/flash_driver.o
.code_ram 0x1fff8af0 0xcc ./src/can_operator.o
0x1fff8af0 copy_firmware
0x1fff8bbc . = ALIGN (0x4)
0x1fff8bbc __code_end__ = .
0x1fff8bbc __code_ram_end__ = .
0x0000644c __CODE_END = (__CODE_ROM + (__code_end__ - __code_start__))
0x0000644c __CUSTOM_ROM = __CODE_END
I'm calling the copy_firmware() function with these commands:
FLASH_DRV_SetPFlashProtection(0xFFFFFFFF);
DISABLE_INTERRUPTS()
copy_firmware();
...and here is the copy_firmware function. The length of the new firmware is stored in the FirmwareBlockBuffer.Current_Address variable (I've already verified that this value is correct)
void CODE_RAM copy_firmware() {
uint8_t *ptr8;
uint32_t regValue;
uint32_t i;
// Erase PFlash
while ((FTFC->FSTAT & FTFC_FSTAT_CCIF_MASK) == 0);
FTFC->FSTAT = FTFC_FSTAT_ACCERR_MASK | FTFC_FSTAT_FPVIOL_MASK;
FTFC->FCCOB[3] = 0x08; // Erase block cmd
FTFC->FCCOB[2] = 0; // Addr = 0 (= PFlash block)
FTFC->FCCOB[1] = 0;
FTFC->FCCOB[0] = 0;
FTFC->FSTAT = FTFC_FSTAT_CCIF_MASK; //execute command
while ((FTFC->FSTAT & FTFC_FSTAT_CCIF_MASK) == 0); //wait for done
// Program PFlash
ptr8 = (uint8_t *)Flash_InitConfig0.DFlashBase;
for(i=0;i<FirmwareBlockBuffer.Current_Address;i+=8) {
FTFC->FSTAT = FTFC_FSTAT_ACCERR_MASK | FTFC_FSTAT_FPVIOL_MASK;
FTFC->FCCOB[3] = 0x07; // Program 8 bytes
FTFC->FCCOB[2] = (uint8_t)((i & 0x00FF0000)>>16);
FTFC->FCCOB[1] = (uint8_t)((i & 0x0000FF00)>>8);
FTFC->FCCOB[0] = (uint8_t)( i & 0x000000FF);
FTFC->FCCOB[7] = *ptr8;
FTFC->FCCOB[6] = *(ptr8+1);
FTFC->FCCOB[5] = *(ptr8+2);
FTFC->FCCOB[4] = *(ptr8+3);
FTFC->FCCOB[11] = *(ptr8+4);
FTFC->FCCOB[10] = *(ptr8+5);
FTFC->FCCOB[9] = *(ptr8+6);
FTFC->FCCOB[8] = *(ptr8+7);
FTFC->FSTAT = FTFC_FSTAT_CCIF_MASK; //execute command
while ((FTFC->FSTAT & FTFC_FSTAT_CCIF_MASK) == 0);
ptr8 += 8;
}
// Reset microcontroller to activate new firmware
/* Read Application Interrupt and Reset Control Register */
regValue = S32_SCB->AIRCR;
/* Clear register key */
regValue &= ~( S32_SCB_AIRCR_VECTKEY_MASK);
/* Configure System reset request bit and Register Key */
regValue |= S32_SCB_AIRCR_VECTKEY(FEATURE_SCB_VECTKEY);
regValue |= S32_SCB_AIRCR_SYSRESETREQ(0x1u);
/* Write computed register value */
S32_SCB->AIRCR = regValue;
while(1); // Wait for reset
}
Any support/answer/explanation, why this code isn't working is highly appreciated, as I'm currently stuck...
Thank you very much