Harvard Microcontrollers
Many small microcontrollers (Microchip PIC, Atmel AVR, Intel 8051, Cypress PSoC, etc.) have Harvard architecture. They can only execute code from program memory (flash or ROM). You can copy any byte from the program memory to RAM. However, (2) copying executable instructions from ROM to RAM is not the answer - with these small microcontrollers, the program counter always refers to some address in the program memory. Unable to execute code in RAM.
Copying data from ROM to RAM is quite common. When you turn on the power for the first time, a typical firmware application redirects all RAM and then copies the initial values ​​of non-constant global and static variables from ROM to RAM immediately before the start of main (). Whenever an application needs to pop a fixed line from a serial port, it reads that line from the ROM.
With earlier versions of these microcontrollers, an external “device programmer” connected to the microcontroller is the only way to change the program. During normal operation, the device was not near the "device-programmer." If the software running on the microcontroller needs to be written to the program memory ROM - sorry, too bad - that was impossible. Many embedded systems had a non-volatile EEPROM that the code could write, but this was only for storing data values. The microcontroller could only execute code in software ROM, and not in EEPROM or RAM. People could do great things with these microcontrollers, including BASIC translators and Forth bytecode interpreters. Thus, it is obvious that code (1) should never be written to program memory.
With several recent "self-programming" microcontrollers (from Atmel, Microchip, Cypress, etc.), the chip has special equipment that allows software running on the microcontroller to erase and reprogram its own program memory blocks. Some applications use this “self-programming” function to read and write data to “extra” flash blocks — data that is never executed, so it is not considered self-modifying code, but it doesn’t do anything with a large EEPROM. So far, I have seen only two kinds of software running on Harvard architecture microcontrollers that write new executable software to their own Flash program: Forth downloaders and compilers.
When the Arduino bootloader (bootloader) starts up and detects that firmware for a new application is available, it downloads the new application firmware (in RAM) and writes it to Flash. The next time you turn on the system, it now launches the shiny new firmware version 16.98, rather than the awkward old version 16.97. (Flash blocks containing the loader itself remain unchanged). This would not have been possible without the self-programming function for writing to the program memory.
Some Forth implementations run on a small microcontroller, compile new executable code and use the "self-programming" function to save the program in Flash - a process somewhat similar to compiling the JVM "just in time". (It seems that all other languages ​​require a too large and complicated compiler to work on a small microcontroller and, therefore, have an edit-compile-load cycle, which requires much more wall clock time).