Writing to PROGMEM (!)
Surprise! You can write to AVR flash memory (PROGMEM) from your own program code, in a controlled, purposeful way.
*WARNING: SUPERDUPEREXPERTS ONLY *
As in: even though I have all kinds of ideas here, I’m extremely skeptical of my own ability to bend this technique to my will without ‘bricking’ my Arduino… repeatedly. And I deal with these quasi-ROP tricks for a living.
The technique presented here is brilliant, and the developer has “made the theoretical practical”… clearly a kindred spirit. The genie he’s summoned is very very powerful and cares nothing for your project or your time. That said, I had to share this.
Background is: the SPM instruction (which is the only way to write to PROGMEM flash on AVR) cannot execute outside of the bootloader. It can only execute when it’s inside the bootloader code itself – not your application code. So… you just find an SPM in the bootloader code, and use it where it sits!
-
Find SPM opcode in bootloader. You’re going to jump to it, but not yet. You’d just keep executing more bootloader code, which would be Bad.
-
Load the registers as you wish, to write the right thing to the right place, in preparation for executing SPM.
-
Set an interrupt timer to go off in just a couple of exactly timed clock cycles – just after the SPM instruction you’ve found completes but before the next instruction in the bootloader executes.
-
Jump to the SPM you found in the bootloader. It executes as you wish, writing into PROGMEM flash. Then, just before the next bootloader instruction can execute, the interrupt fires, and control returns to your code.
p0w! You just wrote to PROGMEM flash from your own code!
On the one hand, this rocks and is sort of absolutely fantastic. One could, in theory, write code to load a new HEX file from SD, or use PROGMEM as storage, or persistent data, or you could write a JIT for an LED language,… or, you know- anything.
On the other hand,when I think about what it would take to get there, I see a huge, sad pile of twitching, half-mangled, half-dead AVR chips, mauled in the process of debugging this monstrosity. I mean: they’re not dead DEAD dead; you just need to use an external programmer to revive them. And I suspect you’d be doing that a lot during the development process. Which seems like a giant pain in the bootloader.
And yet…