cancel
Showing results for 
Search instead for 
Did you mean: 

IAP: Multiple application firmware in main flash memory

gmate1
Associate II
Posted on December 03, 2015 at 11:07

Lately, I've been trying IAP over UART using Ymodem protocol for STM32F072C8 SOC based custom board. The goal is to try IAP with this mode with different upgrade scenarios and later transform these into my actual requirement. I was able to successfully perform IAP using ST provided libraries, IAP driver and template (More information can be found

/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a//my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Query%20on%20IAP%20over%20UART%20for%20STM32F072C8&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=27

) After this, I tried to put two different application firmware along with IAP driver in the main flash memory and was also able to jump from IAP driver to application f/w1 or f/w2. The memory layout that I'm using currently is as below: Table1: memory map of main flash memory (Total 64 kB)

Table2: memory map of SRAM (Total 16 kB)

</colgroup>

Component

main flash memory

Block number

Size

Bootloader

0x08000000 – 0x08003FFF

0

16 kB

fw 1

0x08004000 – 0x08009FFF

0

24 kB

fw 2

0x0800A000 – 0x0800FFFF

0

24 kB

Note 0690X00000605HHQAY.png

#if (defined ( __CC_ARM ))
 __IO uint32_t VectorTable[48] __attribute__((at(0x20000000)));
#elif (defined (__ICCARM__))
#pragma location = 0x20000000
 __no_init __IO uint32_t VectorTable[48];
#elif defined ( __GNUC__ )
 __IO uint32_t VectorTable[48] __attribute__((section(''.RAMVectorTable'')));
#elif defined ( __TASKING__ )
 __IO uint32_t VectorTable[48] __at(0x20000000);
#endif
void
FLASH_If_Init(
void
)
{ 
/* Unlock the Program memory */
FLASH_Unlock();
/* Clear all FLASH flags */
FLASH_ClearFlag(FLASH_FLAG_EOP|FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR | FLASH_FLAG_BSY); 
}
int
main(
void
)
{
uint32_t i = 0;
FLASH_Status status; 
for
(i = 0; i < 48; i++)
{
VectorTable[i] = *(__IO uint32_t*)(APPLICATION_ADDRESS + (i<<2));
}
/* Enable the SYSCFG peripheral clock*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
/* Remap SRAM at 0x00000000 */
SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);
/***************** Add your application code here ***************************/
FLASH_If_Init(); 
/* set flag to trigger IAP after a reset. this flag will be cleared by IAP driver after a successful update */
status = FLASH_ProgramWord(0x0800E000, 0x1);
while
(status != FLASH_COMPLETE);
while
(1) 
{
// do something 
}
}

Please advise on what could be going wrong here and also any pointers on this overall design. Basically I would like to have

  1. The IAP driver do the upgrade part and application fimrwares should be only triggering IAP process by setting some flag.
  2. Safely store this flag(0x1) at some address that is beyond code or data region of any of the three images
  3. Flow should be System startup -> bootloader -> Initiate IAP or jump to fw1 or fw2 (based on flag value)
Environment

status = FLASH_ErasePage(0x0800E000);
while
(status != FLASH_COMPLETE){}
status = FLASH_ProgramWord(0x0800E000, 0xDEADBEEF);
while
(status != FLASH_COMPLETE){}

0x08004000, instead of the default location (0x08000000)?

</colgroup>

Component

Physical

Block number

Size

Purpose

Bootloader

NA

NA

NA

NA

fw {1|2}

0x20000000

1

0x4000

Vector table relocation to SRAM

that I'm using the same SRAM location for both application firmware (fw1, fw2)I'm able to put the three(IAP driver, fw1, fw2) images in the main flash memory and was also able to jump from IAP driver to fw1 or fw2. Now I would like to implement the following logic (See the flow below)To achieve this, I should be able to store a variable in main flash memory at an address accessible from each of the three images (IAP driver, fw1, fw2). However, when I tried to set a flag at some address, which I think is not being utilized at the moment,in flash memory from application firmware 1 (fw1), the system hung (I think I'm getting a hard fault here, but I need to check). Code snip for storing 0x1 at some random address (note that this main flash memory address is within the overall range i.e.0x0800 0000 - 0x0800 FFFF)SOC: STM32F072C8 64kB Flash memory (ARM cortex M0 based SOC)Main flash memory requirement: IAP driver + fw1 + fw2Application f/w size: ~20 kB (Theoratically, I should be able to fit in IAP driver and two differnt application firmware in 64kB flash memory)IDE: KEIL uVision5 for windowsIAP Mode: UARTUtilities: fromelf.exe (For converting .hex files into .bin file), ST Programmer (for In-circuit programming using SWD interface) and Hyperterminal [1]Reference document: AN4065 [2]Update #1:I'm able to program the main flash memory from the IAP driver, i.e. the following works when I invoke these in the IAP driver, but not when I try to do the same in application firmware.Also, now I'm not able to debug the application fimrware using the KEIL uVision5 debugger window. None of the single stepping, step over, etc tabs are getting activated. Do I need to configure some changes for debugger, since my application now is loaded at #iap #iap #iap #solved
16 REPLIES 16
Posted on December 09, 2015 at 13:51

The size should shrink by the amount you advance the base.

For 0x200000C0 this would be 0x3F40, not 0x4000

If you advanced all of them to 0x20000100 [0x3F00] you'd have 64 bytes at 0x200000C0 to place parameters you want to pass back and forth. And the loader wouldn't tread on the copy of the App's vectors

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
gmate1
Associate II
Posted on January 20, 2016 at 17:37

After spending some time over IAP over GSM network, I'm coming back to this older thread that I had started sometime back.

Environment: SOC: STM32F072C8T6 (64 kB main flash memory) Dev environment: KEIL uVison5 Stack size increased to 4k (Stack_Size EQU 0x00001000 in startup file) The idea is same to have two different application firmware and the IAP driver reside in the main flash memory. A system reboot transfer control to IAP driver, which then jumps to the application firmware and normal operation then begins. A trigger to do firmware upgrade is done in the application firmware, followed by a soft reset. Once again the IAP driver kicks in, finds a flag set in RAM that indicates the firmware upgrade process to initiate, copies the current application firmware into a different memory region (say APP_AREA2), downloads the new application firmware, updates, the application by erasing and programming application area (say APP_AREA1), and then jumps to the application. As suggested to me before, I'm using SRAM to pass few information between the IAP driver and the application firmware and I'm using the memory layout as below:

Component

Start (IRAM1)

Size

IAP driver

0x20000100

0x3F00

Firmware 1

0x20000100

0x3F00

Firmware 2

0x20000100

0x3F00

Component

Start (IROM1)

Size

IAP driver

0x8000000

0x4000 (16 kB)

Firmware 1

0x8004000

0x6000 (24 kB)

Firmware X

0x8004000

0x6000 (24 kB)

Firmware X here means that any new application firmware is loaded always at 0x08004000. The current application firmware is first copied to a separate area in the flash (starting from 0x0800A000) to keep a backup so that if anything goes bad during the upgrade process, a rollback could be initiated by just copying the older firmware from 0x0800A000 to 0x08004000. This requires a simple copy and rollback routine. However I've few issues: 1: The copy and rollback are not working. 2: I don't think this is the right way to calculate the CRC for the entire firmware, how to do it right ? 3: The IAP flag does get set by the application, however during the boot, IAP driver does not see it as being set (see code below) and gets into the else if branch (iff the application exist at address 0x08004000) instead. However this check for IAP flag works when I go into single stepping by going into the debugger. Why so ? ----------------snip from application firmware---------------------

#define APPLICATION1_ADDRESS (uint32_t)0x08004000
#define APPLICATION_SIZE 0x6000
#define IAP_FLAG_ADDRESS 0x20003000
#define IAP_FLAG 0x1
#define IAP_RETRY_ADDRESS 0x20003001
#if (defined ( __CC_ARM ))
__IO uint32_t VectorTable[48] __attribute__((at(0x20000000)));
#elif (defined (__ICCARM__))
#pragma location = 0x20000000
__no_init __IO uint32_t VectorTable[48];
#elif defined ( __GNUC__ )
__IO uint32_t VectorTable[48] __attribute__((section(
''.RAMVectorTable''
)));
#elif defined ( __TASKING__ )
__IO uint32_t VectorTable[48] __at(0x20000000);
#endif
void
init_fw_upgrade(
void
)
{
/* IAP flag and retry count set to 1 */
*(uint32_t *)IAP_FLAG_ADDRESS = IAP_FLAG; 
/* Trigger IAP */
*(uint32_t *)IAP_RETRY_ADDRESS = 0x1; 
/* retry count for IAP */
NVIC_SystemReset(); 
/* soft reset */
}
int
main(
void
)
{
uint32_t i = 0;
/* Relocate by software the vector table to the internal SRAM at 0x20000000 */
/* Copy the vector table from the Flash (mapped at the base of the application
* load address 0x08004000) to the base address of the SRAM at 0x20000000.
*/
for
(i = 0; i < 48; i++)
{
VectorTable[i] = *(__IO uint32_t*)(APPLICATION1_ADDRESS + (i<<2));
}
/* Enable the SYSCFG peripheral clock*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
/* Remap SRAM at 0x00000000 */
SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);
/* Setup systick for delay function: actual clock speed is 8000000*/
SysTick_Config(SystemCoreClock /8000);
while
(1)
{
/* do some stuff */
if
(notification_about_new_fw_received) {
init_fw_upgrade();
}
}
}

----------------snip from application firmware--------------------- ----------------snip from IAP driver------------------------------

typedef 
void
(*pFunction)(
void
);
pFunction Jump_To_Application;
uint32_t JumpAddress;
void
boot(
void
)
{
/* Jump to user application */
JumpAddress = *(__IO uint32_t*) (APPLICATION1_ADDRESS + 4);
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) APPLICATION1_ADDRESS);
/* Jump to application */
Jump_To_Application();
}
int
main(
void
)
{
int
ret;
/* clock, periperhal etc initialization */
init_clk_periph();
/* OTA flag has been set, initiate firmware download procedure */
if
(*(uint32_t *)IAP_FLAG_ADDRESS == IAP_FLAG)
{
/* ota_over_gsm download the firmware over GSM, programs the flash
* region starting from APPLICATION1_ADDRESS */
ret = ota_over_gsm();
/* Everything went well, reset the IAP flag and boot from new application */
if
(ret == SUCCESS)
{
SerialPutString(
''

Booting from new firmware

''
);
/* Reset IAP flag */
*(uint32_t *)IAP_FLAG_ADDRESS = 0x0;
boot();
}
/* network issues, retry once */
else
{
SerialPutString(
''

OTA failed

''
);
if
(*(uint32_t *)IAP_RETRY_ADDRESS)
{
*(uint32_t *)IAP_RETRY_ADDRESS = 0;
NVIC_SystemReset();
}
}
}
else
if
(((*(__IO uint32_t*)APPLICATION1_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
{
SerialPutString(
''

Application1 found

''
);
/* Jump to user application */
boot();
}
else
{
SerialPutString(
''

FATAL error

''
);
/* try rollback later here */
}
while
(1)
{
}
}

----------------snip from IAP driver------------------------------ Despite the application firmware setting the flag (as shown above) the first If condition never gets run in the IAP driver, though it works if I go into debugging mode!!! 2: Copying, rollback and Checksum calculation part,

int
copy_image(
void
)
{
__IO uint32_t dst = APPLICATION2_ADDRESS;
__IO uint32_t src = APPLICATION1_ADDRESS;
uint32_t crc[2];
__IO 
int
i;
/*
* Calculate CRC, The size should be in multiples of 32 bit data 
*/
crc[0] = CRC_CalcBlockCRC((uint32_t *)APPLICATION1_ADDRESS,(APPLICATION_SIZE/4));
if
(FLASH_If_Erase(APPLICATION2_ADDRESS)) 
{
SerialPutString(
''

 Flash erase error 


''
);
return
ERROR;
}
/* start copying */
for
(i = 0; i < (APPLICATION_SIZE/4); ++i)
{
while
(FLASH_ProgramWord(dst, *(uint32_t *)src) != FLASH_COMPLETE) {} 
if
((*(uint32_t *)dst) != (*(uint32_t *)src)) 
{
SerialPutString(
''

Error writing image

''
);
return
ERROR;
}
src +=4;
dst +=4;
}
/* verify the data */
CRC_ResetDR();
crc[1] = CRC_CalcBlockCRC((uint32_t *)(APPLICATION2_ADDRESS), (APPLICATION_SIZE/4));
if
(crc[0] != crc[1]) 
{
SerialPutString(
''

 error in backing up firmware 


''
);
return
ERROR;
}
return
SUCCESS;
}
int
rollback(
void
)
{
__IO uint32_t dst = APPLICATION1_ADDRESS;
__IO uint32_t src = APPLICATION2_ADDRESS;
uint32_t crc[2];
__IO 
int
i;
/*
* Calculate CRC, The size should be in multiples of 32 bit data 
*/
crc[0] = CRC_CalcBlockCRC((uint32_t *)APPLICATION2_ADDRESS, (APPLICATION_SIZE/4));
if
(FLASH_If_EraseAppArea(APPLICATION1_ADDRESS)) 
{
SerialPutString(
''

 Flash erase error 


''
);
return
ERROR;
}
/* start copying */
for
(i = 0; i < (APPLICATION_SIZE/4); ++i)
{
while
(FLASH_ProgramWord(dst, *(uint32_t *)src) != FLASH_COMPLETE) {} 
if
((*(uint32_t *)dst) != (*(uint32_t *)src)) 
{
SerialPutString(
''

Error writing image

''
);
return
ERROR;
}
src +=4;
dst +=4;
}
/* verify the data */
CRC_ResetDR();
crc[1] = CRC_CalcBlockCRC((uint32_t *)(APPLICATION1_ADDRESS), (APPLICATION_SIZE/4));
if
(crc[0] != crc[1]) 
{
SerialPutString(
''

 error in backing up firmware 


''
);
return
ERROR;
}
return
SUCCESS;
}

Posted on January 20, 2016 at 19:47

1) Not working how? What messages do you see? What data actually gets written, or not? Add more instrumentation until you can explain what is happening.

2) Probably want to reset it every time rather than make assumptions. Print out values and confirm they correlate with the ones you calculate on the PC side images.

3) Don't know. Is the startup code, or any other variables, stack, or heap conflicting with or clearing the data areas being utilized?

Add serial output until you understand the flow of your own code, and the values it is computing, and encountering. It's going to be hard to key-hole debug this without seeing the source, counter-pointed with the output it generates.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
gmate1
Associate II
Posted on January 23, 2016 at 16:18

Flashing the application firmware (at address 0x0800 4000) that sets a FLAG in SRAM at 0x2000 00C0 (Since first 48 words starting from 0x2000 0000 is being reserved for vector relocation), and then * powering-off and powering On* so that IAP driver (that sits at address 0x0800 0000) be able to see the flag set, will never work, for the simple reason that SRAM contents are lost during power cycle(I must admit, it was very very stupid of me). So instead of a power cycle, a software reset should work and does work (i.e. flag in SRAM at 0x2000 00C0 is seen by the IAP driver).

This problem is partially fixed, since it seems that my actual application which is about 23 kB in size and also has 4kB stack size (remember, I've set 4kB stack size in IAP driver startup file as well) seem to be messing up the region starting from 0x2000 00C0. As suggested before to me, setting the following in IRAM1 for IAP driver and application firmware *WORKS* only if I remove a big chunk of code, bringing down the application firmware size to about 12 kB. So it seems that the logic is correct, but somewhere in the code, the SRAM is getting messed up.

Memory layout in Keil uVision 5:

+---------------------------------------------------------------------------+

+ Role | IROM1 | IRAM1 +

+---------------------------------------------------------------------------+

+ | START | SIZE | START | SIZE +

+---------------------------------------------------------------------------+

+ IAP | 0x0800 0000 | 0x4000 | 0x2000 0100 | 0x3F40 +

+---------------------------------------------------------------------------+

+ App | 0x0800 4000 | 0x6000 | 0x2000 0100 | 0x3F40 +

+---------------------------------------------------------------------------+

My current understanding on the SRAM layout is as below:

0x2000 0000 - 0x2000 4000 : Entire SRAM region of 16kB

0x2000 0000 - 0x2000 00BF : First 48 words reserved for Vector relocation

0x2000 00C0 - 0x2000 00FF : 16 words (64 bytes) reserved for passing parameters between IAP and application

So, theoretically, I've about 64 bytes starting from 0x2000 00C0. So, in my application code, I do something like:

*(uint32_t *)IAP_FLAG_ADDRESS = IAP_FLAG; 
/* Trigger IAP */
*(uint32_t *)IAP_RETRY_ADDRESS = 0x1; 
/* retry count for IAP */
NVIC_SystemReset();

and in IAP driver code:

if
(*(uint32_t *)IAP_FLAG_ADDRESS == IAP_FLAG)
{
SerialPutString(
''\r\nIAP flag is set\n\r''
);
// do some stuff here
}
else
if
(((*(__IO uint32_t*)APPLICATION1_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
{
SerialPutString(
''\r\nApplication1 found\n\r''
);
/* Jump to user application */
JumpAddress = *(__IO uint32_t*) (APPLICATION1_ADDRESS + 4);
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) APPLICATION1_ADDRESS);
/* Jump to application */
Jump_To_Application();
}
else
{
SerialPutString(
''\r\nFATAL: Neither iap set, nor is there any application\n\r''
);
}
while
(1)
{
}

Where:

#define IAP_FLAG_ADDRESS 0x200000C0
#define IAP_FLAG 0x1
#define IAP_RETRY_ADDRESS 0x200000C4

Note: The above works (flag gets set -> soft reset -> IAP kicks in -> sees the flag as set at 0x2000 00C0) ) for a smaller application, but

NOT for my complete application, which is about 23kB in size.

Attached here are the debug session's memory values (starting from 0x2000 0000) for both cases (When the SRAM region for passing the parameter is not getting overwritten and when it gets overwritten)

How, should I debug this problem, or in another way, how should I make sure that the linker does not access the SRAM region that i wish to set aside for passing the parameters between IAP driver and Application firmware?

Rest of the issues (CRC calculation) will discuss later.

________________

Attachments :

IAP_drv_flag_seen_as_set.png : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I0jT&d=%2Fa%2F0X0000000bis%2F5HcWiqqYFqmbChFF_vuphxsyO3RXH31mZOhThF2Jk0g&asPdf=false

IAP_drv_flag_set_as_NOT_set.png : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I0vU&d=%2Fa%2F0X0000000bir%2FQpzeEMQ3S8RYgcDcRkj3rylto1H25xSBwrEQT7nBwZo&asPdf=false
gmate1
Associate II
Posted on January 25, 2016 at 16:55

There seem to be some issue with the build or some wrong setup in Keil uVision5 (I cannot pinpoint at the root of the issue of SRAM area getting overwritten, since I've been doing some ad-hoc changes here and there) and now passing the parameters between the IAP driver and application firmware works (Using same exact addresses, that I've mentioned before)

Now moving to copying and rolling back the application firmware problem. My questions is that is the following code for copying the application firmware to a different area in flash is syntactically correct ? Main flash memory is divided into three areas: 0x0800 0000 - 0x0800 3FFF : IAP driver 0x0800 4000 - 0x0800 9FFF: Application firmware 0x0800 A000 - 0x0800 FFFF - Keeping a backup of current running application firmware

#define USER_FLASH_LAST_PAGE_ADDRESS 0x0800F800
#define USER_FLASH_APP_LAST_PAGE_ADDRESS 0x08009800
#define USER_FLASH_END_ADDRESS 0x0800FFFF /* 64 KBytes */
#define FLASH_PAGE_SIZE 0x800 /* 2 Kbytes */
#define APPLICATION1_ADDRESS (uint32_t)0x08004000
#define APPLICATION2_ADDRESS (uint32_t)0x0800A000
#define APPLICATION_SIZE 0x6000
void
crc_init(
void
)
{
CRC_DeInit();
CRC_ResetDR();
}
uint32_t FLASH_If_Erase(uint32_t StartSector)
{
uint32_t flashaddress = 0;
flashaddress = StartSector;
while
(flashaddress <= (uint32_t) USER_FLASH_LAST_PAGE_ADDRESS)
{
if
(FLASH_ErasePage(flashaddress) == FLASH_COMPLETE)
{
flashaddress += FLASH_PAGE_SIZE;
}
else
{
/* Error occurred while page erase */
return
(1);
}
}
return
(0);
}
uint32_t FLASH_If_EraseAppArea(uint32_t StartSector)
{
uint32_t flashaddress = 0;
flashaddress = StartSector;
FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR);
while
(flashaddress <= (uint32_t) USER_FLASH_APP_LAST_PAGE_ADDRESS)
{
if
(FLASH_ErasePage(flashaddress) == FLASH_COMPLETE)
{
flashaddress += FLASH_PAGE_SIZE;
}
else
{
/* Error occurred while page erase */
return
(1);
}
}
return
(0);
}
uint32_t CRC_CalcBlockCRC(uint32_t pBuffer[], uint32_t BufferLength)
{
uint32_t index = 0;
for
(index = 0; index < BufferLength; index++)
{
CRC->DR = pBuffer[index];
}
return
(CRC->DR);
}
int
copy_image(
void
)
{
__IO uint32_t dst = APPLICATION2_ADDRESS;
__IO uint32_t src = APPLICATION1_ADDRESS;
uint32_t crc[2];
__IO 
int
i;
/*
* Calculate CRC, The size should be in multiples of 32 bit data 
* TODO: Replace size value with a macro
*/
crc[0] = CRC_CalcBlockCRC((uint32_t *)APPLICATION1_ADDRESS,(APPLICATION_SIZE/4));
if
(FLASH_If_Erase(APPLICATION2_ADDRESS)) 
{
SerialPutString(
''

 Flash erase error 


''
);
return
ERROR;
}
/* start copying */
for
(i = 0; i < (APPLICATION_SIZE/4); ++i)
{
while
(FLASH_ProgramWord(dst, *(uint32_t *)src) != FLASH_COMPLETE) {} 
if
((*(uint32_t *)dst) != (*(uint32_t *)src)) 
{
SerialPutString(
''

Error writing image

''
);
return
ERROR;
}
src +=4;
dst +=4;
}
/* verify the data */
CRC_ResetDR();
crc[1] = CRC_CalcBlockCRC((uint32_t *)(APPLICATION2_ADDRESS), (APPLICATION_SIZE/4));
if
(crc[0] != crc[1]) 
{
SerialPutString(
''

 error in backing up firmware 


''
);
return
ERROR;
}
sprintf(dbg, 
''

copy_image: CRC[0]: 0x%x \tCRC[1]: 0x%x

''
, crc[0], crc[1]);
SerialPutString(dbg);
return
SUCCESS;
}
int
rollback(
void
)
{
__IO uint32_t dst = APPLICATION1_ADDRESS;
__IO uint32_t src = APPLICATION2_ADDRESS;
uint32_t crc[2];
__IO 
int
i;
/*
* Calculate CRC, The size should be in multiples of 32 bit data 
* TODO: Replace size value with a macro
*/
crc[0] = CRC_CalcBlockCRC((uint32_t *)APPLICATION2_ADDRESS, (APPLICATION_SIZE/4));
if
(FLASH_If_EraseAppArea(APPLICATION1_ADDRESS)) 
{
SerialPutString(
''

 Flash erase error 


''
);
return
ERROR;
}
/* start copying */
for
(i = 0; i < (APPLICATION_SIZE/4); ++i)
{
while
(FLASH_ProgramWord(dst, *(uint32_t *)src) != FLASH_COMPLETE) {} 
if
((*(uint32_t *)dst) != (*(uint32_t *)src)) 
{
SerialPutString(
''

Error writing image

''
);
return
ERROR;
}
src +=4;
dst +=4;
}
/* verify the data */
CRC_ResetDR();
crc[1] = CRC_CalcBlockCRC((uint32_t *)(APPLICATION1_ADDRESS), (APPLICATION_SIZE/4));
if
(crc[0] != crc[1]) 
{
SerialPutString(
''

 error in rolling back old firmware 


''
);
sprintf(dbg, 
''

rollback: CRC[0]: 0x%x \tCRC[1]: 0x%x

''
, crc[0], crc[1]);
SerialPutString(dbg);
return
ERROR;
}
sprintf(dbg, 
''

rollback: CRC[0]: 0x%x \tCRC[1]: 0x%x

''
, crc[0], crc[1]);
SerialPutString(dbg);
return
SUCCESS;
}
main(
void
)
{
// init relevant clocks and peripherals
// ...
// ...
crc_init();
copy_image()
rollback(); 
// crc value mismatch here
while
(1)
{
// do something
}
}

----------------------------snip from serial console logs------------------------------ copy_image: CRC[0]: 0x3c0d7fa CRC[1]: 0x3c0d7fa <--crc calculation after copying the current image at a different region in memory (refer copy_image above) Updating Firmware............ <--- upgrading firmware error in rolling back old firmware <--- error rollback: CRC[0]:

0x8d09986c

CRC[1]: 0x931a25c5 In the rollback routine, the CRC value for app area 2 is

0x8d09986c

which is already different than the value reported for app area 2 in copy_image (

0x3c0d7fa

) !!!
Posted on January 25, 2016 at 17:50

uint32_t CRC_CalcBlockCRC(uint32_t pBuffer[], uint32_t BufferLength)
{
uint32_t index;
CRC_ResetDR();
for(index = 0; index < 
BufferLength
; index++)
{
CRC->DR = pBuffer[index];
}
return (CRC->DR);
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
gmate1
Associate II
Posted on January 29, 2016 at 10:52

Thank you.

Removed the CRC calculation part and found that I was calling a routine, prep_iap (forgot to post it before) and in prep_iap(), the current application firmware is copied to a separatearea in memory (by calling copy_image) and later, while trying to erase the application area,entire flash memory, except the bootloader area was getting erased,thus rendering the backup useless and later an attempt to do a rollbackend up, copying 0xFF...FF from the backup area to the application area. Solution was NOT to erase the back-up area once the image has beencopied and is done by replacing, FLASH_If_Erase() withFLASH_If_EraseAppArea()

/* erase user application area */
- FLASH_If_Erase(APPLICATION1_ADDRESS);
+ FLASH_If_EraseAppArea(APPLICATION1_ADDRESS);