An invitation to brainstorm, implement ... - or if you have already an implementation...
Goal
I want to run my FW. It should be possible to load code, during runtime and let it be executed, without to touch the running system.
Load different code files, without to flash, without to reset MCU - like an EXE file or a "plug-in".
Use Case
I have a GPIO interrupt. The actions to do (e.g. a SPI transfer, check the data, do some stuff), should be "programmable".
I do not want to modify the entire project, instead: I want to load a piece of code, generated (separately) and loaded when my MCU runs my FW already.
The system code is extended during runtime (without to recompile, flash, restart ... the entire MCU and FW, extend with this "plug-in").
It like to "load and run an EXE file".
Usage
My users run the board with my FW. They can write and generate a "plug in" (exe FILE), load it to the running system (e.g. via network, from SD card).
It extends the functionality without to flash, without to reset the running MCU. And they can change the "plug-in" on the fly, load another one...
Ideas
Most obvious: I reserve space in ITCM (or on FlashROM) where I can load code later (or flash the reserved FlashROM sectors).
Q: how to reserve a fix, known region (it should have fix, constant start and end address) in ITCM (or FlashROM, ITCM is preferred due to speed).
My users should use Arduino IDE with my FW LIB files (to resolve and use existing functions, e.g. UART print, SPI transaction).
They just create a "sketch" for "their user code" on "my sketch".
This user code can call existing functions in my MCU FW.
(OK, just provide a linker reference file to resolve externals).
There is this "SVC n" assembly function (Software Vector Call, Supervisor Call).
If I would use this - the generated code is "location independent" (relocatible) - cool: I do not need to tell where all the functions are. The reloaded code would do
SVC 3, e.g. for "UART_print()" and all fine.
Q: but as I understand: SVC is like an Interrupt: how can I call other functions which need also INTs, but not "blocked" due to SVC call?
SVC would be like an interrupt, other interrupts blocked.
And biggest problem: how to return from SVC to caller like a "synchronous function call" (with a return value)?
OK, I could implement a "BIOS vector table":
A linker file provides which address "to call" for a specific function (like a vector table). Just tell the user code where "the BIOS vector table" is and call
now the "BIOS vectors" (easier, just a bit more space and not really "relocatible", e.g. I move the vector table around).
So, my users can now use Arduino IDE, with my "FW LIB file" (resolving external calls), edit code, compile and create an EXEcutable.
(and just this user code, no insights to my MCU code, much shorter code and faster compile time).
The MCU FW running can load such EXE-file, activate and let it be executed (e.g. it replaces my GPIO INT handler code).
The main questions:
OK, it needs to modify the linker script (to reserve the space).
Assume, I want to "load this code" on ITCM (and space is reserved) - can I read as data from a file (SD card) and load/write to ITCM?
Can I do a data write on ITCM code memory?
As I understand: all the code sits in an (external) flash memory. It is loaded during boot time into internal ITCM RAM (with attributes from compile time).
When I flash a sector in (external) flash memory - I assume it would be executed from there (slow). How to force to copy this code
into internal ITCM RAM, for faster execution - without to reboot?
Is there a helper function to load code from external ROM Flash to ITCM during runtime?
(actually nonsense: space must be available in ITCM for it, load directly, e.g. from SD card to ITCM)
Let's see.
Just to share idea, invite you for this project, brainstorm with you... It should be possible (I am sure), just to cope with the "devils details and traps". ;-)
Goal
I want to run my FW. It should be possible to load code, during runtime and let it be executed, without to touch the running system.
Load different code files, without to flash, without to reset MCU - like an EXE file or a "plug-in".
Use Case
I have a GPIO interrupt. The actions to do (e.g. a SPI transfer, check the data, do some stuff), should be "programmable".
I do not want to modify the entire project, instead: I want to load a piece of code, generated (separately) and loaded when my MCU runs my FW already.
The system code is extended during runtime (without to recompile, flash, restart ... the entire MCU and FW, extend with this "plug-in").
It like to "load and run an EXE file".
Usage
My users run the board with my FW. They can write and generate a "plug in" (exe FILE), load it to the running system (e.g. via network, from SD card).
It extends the functionality without to flash, without to reset the running MCU. And they can change the "plug-in" on the fly, load another one...
Ideas
Most obvious: I reserve space in ITCM (or on FlashROM) where I can load code later (or flash the reserved FlashROM sectors).
Q: how to reserve a fix, known region (it should have fix, constant start and end address) in ITCM (or FlashROM, ITCM is preferred due to speed).
My users should use Arduino IDE with my FW LIB files (to resolve and use existing functions, e.g. UART print, SPI transaction).
They just create a "sketch" for "their user code" on "my sketch".
This user code can call existing functions in my MCU FW.
(OK, just provide a linker reference file to resolve externals).
There is this "SVC n" assembly function (Software Vector Call, Supervisor Call).
If I would use this - the generated code is "location independent" (relocatible) - cool: I do not need to tell where all the functions are. The reloaded code would do
SVC 3, e.g. for "UART_print()" and all fine.
Q: but as I understand: SVC is like an Interrupt: how can I call other functions which need also INTs, but not "blocked" due to SVC call?
SVC would be like an interrupt, other interrupts blocked.
And biggest problem: how to return from SVC to caller like a "synchronous function call" (with a return value)?
OK, I could implement a "BIOS vector table":
A linker file provides which address "to call" for a specific function (like a vector table). Just tell the user code where "the BIOS vector table" is and call
now the "BIOS vectors" (easier, just a bit more space and not really "relocatible", e.g. I move the vector table around).
So, my users can now use Arduino IDE, with my "FW LIB file" (resolving external calls), edit code, compile and create an EXEcutable.
(and just this user code, no insights to my MCU code, much shorter code and faster compile time).
The MCU FW running can load such EXE-file, activate and let it be executed (e.g. it replaces my GPIO INT handler code).
The main questions:
- how to reserve well known, fix space on ITCM?
- How to reserve fix, well known, space in FlashROM?
- Would you use SVC or a "BIOS Vector Table"?
OK, it needs to modify the linker script (to reserve the space).
Assume, I want to "load this code" on ITCM (and space is reserved) - can I read as data from a file (SD card) and load/write to ITCM?
Can I do a data write on ITCM code memory?
As I understand: all the code sits in an (external) flash memory. It is loaded during boot time into internal ITCM RAM (with attributes from compile time).
When I flash a sector in (external) flash memory - I assume it would be executed from there (slow). How to force to copy this code
into internal ITCM RAM, for faster execution - without to reboot?
Is there a helper function to load code from external ROM Flash to ITCM during runtime?
(actually nonsense: space must be available in ITCM for it, load directly, e.g. from SD card to ITCM)
Let's see.
Just to share idea, invite you for this project, brainstorm with you... It should be possible (I am sure), just to cope with the "devils details and traps". ;-)