1. Background
There is no perfect software; due to design flaws and business requirement updates, software is constantly being upgraded and improved. This article focuses on how to replace the currently running old software with new software, especially for electronic products where Over-the-Air (OTA) upgrades are constrained by hardware resources, necessitating different solutions for software upgrades.
2. OTA Upgrade Process
Depending on hardware resources and the overall system framework, different upgrade solutions need to be selected. The choice of solution should be based on practical considerations, with technical aspects being secondary.
3. OTA Upgrade Solutions
3.1 Full Package Upgrade
To incorporate the online upgrade function, the main application program needs to be split, similar to having two sets of programs running within the device. The standard terminology is bootload + app, where the bootload remains unchanged and is responsible for receiving the new software package and overwriting the app area.
Hardware Limitations | Solutions |
---|---|
The microcontroller itself does not have network connectivity and can only download new software packages from a remote server using an external network module, then transfer it to the microcontroller via serial port. | The external host downloads the new software package and notifies the microcontroller to enter upgrade mode. |
The internal RAM of the microcontroller is small, unable to perform copy operations or cache large amounts of data; the internal EEPROM is small, unable to store the entire new software package. | New software can only be received in segments during the Bootload period and immediately written to flash. |
Challenges and Risks:
4) Generally, PC software does not need to consider memory and storage space and also uses full package upgrades, saving two files simultaneously. For example, when app.exe is running, it downloads a new app_new.exe. After verifying the download, app.exe self-destructs and deletes itself, then renames app_new.exe to app.exe and starts it.
Challenges and Risks:
1) The creation and restoration algorithm verification for the differential package must consider RAM when restoring the new software package in bootload. The differential package is generated in blocks, and restoration is also performed in blocks. Before writing each new software block, the old block must be backed up to prevent failure to restore due to unexpected power loss.
If an exception occurs, rebooting still enters bootload, checking which block has been restored last, and continuing with the subsequent operations. Some may also compress files to further reduce the size of the differential package, decompressing before restoration.
2) During the upgrade, it is essential to ensure that the generated differential package is based on the current version running on the device. For example, if the device is running V01, but the provided differential package is based on V02 to V03, it will cause exceptions. Alternatively, special version characters can be preset in the file, allowing differential restoration upgrades only when versions match. Full packages do not have this drawback, as long as bootload is normal, any app software version can be upgraded to another.
Dynamic loading occurs at the linking stage, where upper-layer code objects are compiled into dynamically loadable AXF files instead of directly merging with other object files into executable files. This is mainly achieved by using armlink to configure -entry to specify the initial entry point of the image file or using the #pragma arm section code keyword in the code to ensure that the dynamic upper layer has a fixed entry address. All lower-level interface function pointers called by the upper layer are assigned empty instructions during the compilation stage to ensure compilation, and later point to the actual addresses of the lower layer.
This action takes place during system startup, loading from flash to memory, where the relative addresses of all interfaces within the file remain unchanged, maintaining an overall offset. This way, the software can still calculate and obtain the entry address of the dynamic image file. When loaded into the memory area, it must be ensured that this area is not occupied; otherwise, memory overwrite will definitely lead to exceptions.
After the lower layer starts, only the entry function of the dynamic loading file can be found, but the actual interaction interfaces between the lower and upper layers are certainly more than one, and the upper layer will inevitably call lower-level interfaces. This requires implementing address mapping between the upper and lower layers within the first function body with a clear address. There are two solutions: one is to assign function pointers, and the other is to search for pointers based on strings. The lower layer needs to provide the upper layer with the interface function pointer table for the interfaces called by the lower layer, assigning values to the upper layer function pointers in a fixed order; or the lower layer only provides the upper layer with one function, but within that function body, it retrieves function pointers based on strings. This way, the upper layer can call the fixed lower layer interfaces in advance.
The interfaces provided by the upper layer to the lower layer are also fixed function pointers, connected using the above methods. The core of interface mapping is that there is a function address in the dynamic loading block specified during linking, where the mapping between upper and lower layer functions is implemented. In addition to functions, global variables are also passed using pointers in the same manner.
Challenges and Risks:
4. Conclusion

END