I'm trying to add in-field firmware update to a product running on an S70. Firmware is in the Flash and normally executes from the Flash. It downloads new image via a custom USB link into SRAM, calls a "RAMFUNC" which needs to do the diry work of erasing the flash and writing the new image to Flash before resetting.

This application does have the complication of also running FreeRTOS. When the new firmware is ready, the RAMFUNC-function will 'enter critical' and disable interrupts before proceeding.

I have found that the processor stalls during the flash erase though. Code snippets follow:

The firmware first does a dummy decode of the image (including CRC checks etc) to make sure it is able to use it. Then it disables the USB link (which now stops my easy debug ), followed by enterring a critical section (which I believe stops FreeRTOS from trying to do context switches) and disabling interrupts.

Next the firmware clears two test points (drive them low). This works.

Then it erases the flash (which works because the flash is perfectly erased) and toggles an LED in a loop until the erase operation is complete. The LED does toggle, but then stops.

After the loop one of the test points is driven high again. This does NOT happen.

So clearly the micro has jumped from here. It's not watchdog because the watchdog is disabled in the init code and is never serviced by the firmware. So it must be either an interrupt or an exception.

But I expect interrupts to be disabled. And what would cause an exception inside of that loop?

Please, what am I missing here?

portable_delay_cycles() is the ASF Cycle Counter function which is defined as "OPTIMIZE_HIGH" and "RAMFUNC".

cpu_irq_disable() is a #define which calls "__disable_irq()" and "__DMB()":
__disable_irq() is an inline function that executes cpsid

You may be starting the ready poll so soon that the EFC has not turned the ready bit off yet. I have a EFC flash writing function on SAM4S and SAM4E. The code inserts one dsb instuction between the command register write and the poll loop.

If I were you, I'd check that the generated machine code is compiled and linked/located for running in the RAM.

If you're using the GNU compiler toolkit (gcc and derivatives), the assembly listing of the module containing your function is available adding '-Wa,-ahlms=update.lst' to the gcc command line. The linked/located ELF file can be dissected by:
arm-none-eabi-objdump -D myrunfile.elf >myrunfile.dis