Hello @�?lvaro Alejandro de Rada Alonso ,
As @Community member stated, it is a standard internal flash programming sequence. You can check the example for your specific MCU: STM32CubeF4/Projects/STM32F429ZI-Nucleo/Examples/FLASH/FLASH_EraseProgram at master · STMicroelectronics/STM32CubeF4 · GitHub
Otherwise, what you're intending to do (dynamic loading) has its own caveats, the most important of them is security. Uploading arbitrary code to be executed is unsafe, and can be devastating especially for industrial automation. I'll give you some pointer on about how it can be done, but beware, it is not recommended unless you know what you're doing:
Code placement:
STM32F4 has no MMU, so code placement should be static or the code to be placed should be position independent.
The code to be loaded is always placed in the same region (flash or RAM). The region's size would define the maximum binary size. If the the code would require static variables or global variables, a RAM region should also be allocated. This can be achieved through the linker file.
- Position independent code:
It is possible to generate position indipendentt code (--rwpi option under MDK-ARM, -fPIC for gcc, --ropi for IAR). The generated code will run from anywhere (alignement should be respected), but the generated code will be relatively large and slow.
Memory protection:
When running external libraries, it is always a good idea to "sandbox" it. In this contexts it means using the MPU to disallow memory access to critical regions (OS memory, etc...). This can be done using FreeRTOS with MPU support and running the task in unprivileged mode: FreeRTOS-MPU - ARM Cortex-M3 and ARM Cortex-M4 Memory Protection Unit support in FreeRTOS.
LIBC and exported functions:
The loaded code won't have any idea on where to locate standard library functions and OS interaction functions (vTaskDelay() for example). Either the symbols need to be exported before hand from the main binary and used during the linking process (SYMDEFs for MDK-ARM and IAR). it the main binary is recompiled, these symbols would move. So you'd need to implement a branch table or use software interrupts (SVC calls) to resolve the issue.
From the other side, the loaded binary should have a format that indicates precisely the offset of the entry function and, perhaps, how much stack is needed if you intend to scale the stack dynamically.
Execution:
Once the code is loaded, it needs to be executed by the OS. For FreeRTOS, task creation requires a function pointer to create the task. The function pointer would be the entry point that we've talked before. If your binary contains more than one task, then the binary format should be able to express that.
Security:
Unless you're working on a personal project that will never be deployed or used in any capacity except as a curiosity, security is mandatory. Transferring the binary securely encrypting it and signing is necessary. You can check how SBSFU does it for example: X-CUBE-SBSFU - Secure boot & secure firmware update software expansion for STM32Cube - STMicroelectronics.
Finally, I remember (but am not sure), that the pebble smart watch is able to dynamically load code, and some of its code is available: GitHub - jwise/FreeRTOS-Pebble: basic FreeRTOS implementation for Pebble Time.
There's also the following github repo with an implementation of dynamic loading for ZephyrRTOS GitHub - rgujju/Dynamic_App_Loading: Dynamically load apps to zephyr RTOS.
Best regards,
@SBEN .2