armbootloaderatmelatsam3x

Atmel SAM3X8E Loses VTOR After Hard Reset


I seem to be reiterating this question from here and here. When I reboot my system after flashing firmware onto an opposing flash bank, the VTOR is 0 (meaning it does not boot from flash) and I cannot run the new firmware.

I use the EFC controller to program the firmware binary into the second flash bank. For example, the active firmware is at Flash0, located at 0x0008_0000. The implementation guide says that Flash1 is located at 0x000C_0000. I can see the complete firmware to be flashed is contained, without errors, at 0x000C_0000. Once the firmware is loaded and verified, I switch the GPNVM boot bank:

efc_perform_command(EFC0, EFC_FCMD_SGPB, 1); //set GPNVM bit 1
efc_perform_command(EFC0, EFC_FCMD_SGPB, 2); //set GPNVM bit 2
/* Now check to make sure the bit has flipped) */
efc_perform_command(EFC0, EFC_FCMD_GGPB, 0);
status = efc_get_result(EFC0);
printf("GPNVM is now %d\n", status);

/* Now set the VTOR to the flash1 start address) */
__DSB();
__ISB();
SCB->VTOR = ((uint32_t)FLASH1_ADDRESS & SCB_VTOR_TBLOFF_Msk);
/* Checking the VTOR value here shows a result of 0x000C_0000 */
__DSB();
__ISB();

/* Now reset the device by pulling NRSTB pin low */
reset_pull_NRSTB_low();
while(1); 

After executing this code, I again check the VTOR register at 0xE000_ED08 and the value is now 0x0000_0000. The firmware does not appear to load as the chip looks to address 0x0000_0000 to start the firmware.

Could it be that I have improperly set the GPNVM bits and it is looking for ROM vectors? If that is the case, what are the proper GPNVM bits to set? According to the table on page 33 of the bootloader document, the GPNVM bits should be "0b110" so that GPNVM[1] is 1 and GPNVM[2] is 1 - meaning that the firmware will start from Flash Bank 1. Is this a correct interpretation?


Solution

  • Ok, of course I knew that finding the solution would make me feel stupid. But here you go... I ultimately changed the linker script in the Device_Startup folder as provided by Atmel and compiled it twice; each with the FLASH0 and FLASH1 addresses respectively in place, with no other changes to the firmware. And...the firmware binaries were identical! But that shouldn't be the case according to Atmel.

    I had been confused because it says that the memories are mirrored, which led me to believe that setting the GPNVM only pointed to the start of the flash bank at the same address and remapped the latter half based on GPNVM2. Instead, it seems as if it actually loads the vector table from the second word of the firmware binary (SP and then PC).

    So it does need to be told where to jump inside the contiguous flash bank. I went into the ASF solution properties to find the ARM/GNU Linker preferences and found the real linker file in the tag section. It is not the one that seems to be referenced in my project. I changed it based on the guidelines I mentioned above and it switched over successfully to run the firmware on the opposite bank.

    Easy solution to a seemingly obscure hardware problem. Thanks for your help!