Not for any practical purpose but just out of curiosity, I want to abuse the flash memory and write it dynamically at run-time. This is, in a sense, what the bootloader does. If I understand it, the only way to modify flash is to do so from instructions written to the boot sector. Is it possible to stick a simple function in there that writes to flash memory, and call it from running code? If so, how do I put it there? I have no issue with calling functions from function pointers, so I don't think I'll have an issue actually calling the function once I get there, but I need to know how to stick into flash in the first place.
The Optiboot version 8 has a
do_spm function which can be called from application. The Optiboot repository contains an example for the use of this function.
SPM is the AVR CPU instruction to write to flash memory. The Optiboot wraps this in a function. A pointer to this function is put in a 'vector table' at the beginning of the bootloader. The first pointer jumps to
main, the second pointer jumps to
do_spm. The optiboot.h then has the function as (version for small Optiboot)
typedef void (*do_spm_t)(uint16_t address, uint8_t command, uint16_t data); const do_spm_t do_spm = (do_spm_t)((FLASHEND-511+2)>>1)
I made an enhancement of this, a copy_flash_pages function with reset option to bootload an AVR from its own flash. It is added as third entry in the 'vectors table' of Optiboot. It is used in my ArduinoOTA library for AVR MCUs.
typedef void (*copy_flash_pages_t)(uint32_t dest, uint32_t src, uint16_t page_count, uint8_t reset); const copy_flash_pages_t copy_flash_pages = (copy_flash_pages_t)((FLASHEND-1023+4)>>1);