Go Down

Topic: Arduino Due - Over-The-Air Update (Read 1 time) previous topic - next topic


Hi All,
We are currently using the Arduino Due with a GSM module.
We would like to add OTA support to the product.

Given that we already handled the downloading of the 'bin' file and its storage on the SAM3X's flash, what should be the best attitude towards the switching of the running code?
Should we use IAP feature? (It's not clear whether we can use IAP when using Arduino IDE)
Should we try altering the Bootloader and replace the code in 'bank0'? (Also it's not clear here whether the Bootloader can be updated for the SAM3X microcontrollers)
Is it something that can be done with Arduino IDE at all? Or should we switch to Atmel's IDE instead?

We will appreciate your tips here.




You can use IAP functions in your code to read/set/clear  GPNVM bits (see Sam3x datasheet page 1442).


Jan 08, 2020, 02:41 pm Last Edit: Jan 09, 2020, 04:16 pm by shachar_o
Can anyone give a minimum working example code that writes a blinking led bin file to FLASH1 from FLASH0 and then resets to run FLASH1? I have been trying to do this for a while but it seems the Arduino just hangs after I programmatically reset it, without running the binary data I copied over to FLASH1.

Here are the steps I have taken:
1) Compile a simple blinking led program.
2) Export the bin file.
3) Send the exported bin file over UART to the Arduino.
4) Save the bytes as they arrive to FLASH1, using this library:
5) Use the method provided in the above post above to set GPNVM bits and perform a reset.

Result: Arduino hangs. I have tried various combinations of code to perform this and it does not seem to matter. I will be grateful for any assistance you can provide.



Yes, getting it all to work without lock ups can be frustrating. As mentioned in the linked thread, I had this all working many years ago. Of course, my mind has leaked since then. Still, there are a couple of things to keep in mind with this whole scheme of switching between FLASH0 and FLASH1. Perhaps one of the biggest things is that you SHOULD NOT issue any calls that change GPNVM bits inside of a normal function. For best stability only change the bits from within a RAM resident function. As you know, the Due is not exactly overflowing with RAM but it does have 100k of RAM so store your OTA functions in RAM and call them from there. You use this before your RAM functions:

Code: [Select]

__attribute__ ((long_call, section (".ramfunc")))

Also, disable interrupts while you are working.

Both tips are based on the same reasoning here: I'm pretty sure the chip literally remaps RAM instantly when you change the GPNVM bits. It's covered in the manual but the processor remaps the proper FLASH page to address 0 when you set the GPNVM bits. Then code and interrupts can be based on address 0 and not care whether they were in FLASH0 or FLASH1. The code compiled by the IDE actually uses the non-remapped addresses for function calls but interrupts still kind of have to happen at the lower remapped address. So, if you've got interrupts enabled then subsequent interrupts will find the new interrupt table but you're running code based from the old one and it dies. If you're running in a FLASH function then it probably isn't really where it should be anymore. Also, boom, dead freeze. This is why you want to change the bits in a RAM function then immediately force a reboot. That way you come back running code that agrees with the hardware (hopefully)

So, it is irritating and that's why you want to do it all once and then copy the code. Which is exactly what I did. I've even used my FirmwareReceiver library (https://github.com/collin80/FirmwareReceiver) in a motor controller. So, I know it works. Even over CANbus I can successfully update a device and have it reboot and be OK. So, look at the FirmwareReceiver stuff at my github and it should lead you in the right direction.

Go Up