We are having limited success with the Due on a project and have run into a situation where we are trying to boot from either flash and be able to update to the opposite one. We'd like to set it up such that we can download the update and flash it to the non-active bank and then switch to it.
We initially followed the instructions for creating a flash 1 bootloader, and we were successful in doing that, but wondered if we were to flash using the bin, are there address specific relocations that have been linked in, or is everything relative in the program space? Will a bin work in either bank without modification?
No, you can't flash the same sketch to either FLASH bank. I wish one could.
The binary has static addresses that will be based either in FLASH0 or FLASH1 and so there's really no way to flash the same sketch to either bank. If you flash a normal Arduino sketch to FLASH1 it'll try to call functions in FLASH0 which will likely then crash. If you try to flash a FLASH1 sketch to FLASH0 the inverse will happen and crashing is once again nearly certain. I thought about doing an address fix up on sketches to automatically re-write them to work in FLASH0 or FLASH1 but that's a lot of work. You'd have to essentially disassemble the sketch to know what is data and code and where the call addresses are, etc. You could also use a map file for that which then doesn't require disassembling but then you have to parse a very nasty file format to get the symbols to relocate. In the end it just seems like more work than it's worth.
Maybe a workaround would be to compile 2 versions of each file, one compiled for Flash bank 0 and the other one for Flash bank 1. Say your sketch is named Prog, you will name ProgV0 the version for lower Flash bank and ProgV1 for upper Flash bank, i.e.:
You get the .bin of ProgV0 with these parameters in linker script:
MEMORY
{
rom (rx) : ORIGIN = 0x00080000, LENGTH = 0x00040000 /* Flash, 256K /
sram0 (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00010000 / sram0, 64K /
sram1 (rwx) : ORIGIN = 0x20080000, LENGTH = 0x00008000 / sram1, 32K /
ram (rwx) : ORIGIN = 0x20070000, LENGTH = 0x00018000 / sram, 96K */
}
And you get the .bin of ProgV1 with these parameters in linker script:
MEMORY
{
rom (rx) : ORIGIN = 0x000C0000, LENGTH = 0x00040000 /* Flash, 256K /
sram0 (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00010000 / sram0, 64K /
sram1 (rwx) : ORIGIN = 0x20080000, LENGTH = 0x00008000 / sram1, 32K /
ram (rwx) : ORIGIN = 0x20070000, LENGTH = 0x00018000 / sram, 96K */
}
You store these 2 .bin on an SD card and you add a sub-routine at the beginning of each sketch to trigger the upload of a .bin from the SD card: ProgV1.bin if you run from Flash bank 0, ProgV0.bin if you run from Flash bank 1. After reset, the correct bin will be executed.
In either case, you can check with the .lss that your Reset_Handler() begins at rom + 0x148.