|
STM32 Bootloader
Customizable Bootloader for STM32 microcontrollers
|
Customizable Bootloader for STM32 microcontrollers. This project includes a demonstration for the STM32L496-Discovery board how to perform in-application-programming of a firmware located on external SD card with FAT32 file system.
Update: After almost 10 years, I've decided to give a proper refactor for this project. With the v2.0.0 release the project adopted a modern, modular and scalable project structure based on the stm32-project-template. The build system is CMake-based, while the legacy Make & SCons-based build systems are still available with limited functionality. The bootloader demonstration is refactored: the source code is fully MISRA-conform and passes clang-tidy and cppcheck static code analysis checks. Check out the CHANGELOG.md for the complete list of changes!
The source code of the entire bootloader project is documented and commented thoroughly. The generated documentation page is published here: https://akospasztor.github.io/stm32-bootloader
This demo is implemented on the 32L496GDISCOVERY board from ST [1], equipped with a STM32L496AG microcontroller [2]. Please refer to the user manual of the discovery board for the complete schematics and board description [3].
The microSD card is connected to the MCU over SDIO interface. The implementation uses the official HAL library of ST [4] and can be compiled with the GNU Arm Embedded Toolchain. Programming and debugging are performed over the on-board ST-LINK debugger.
There are two LEDs located on the discovery board, which are easily accessible, and they don't require the use of the IO expander. These LEDs are used for signaling various status to the user and they are labeled as LD2 and LD3.
The middle (center) button of the blue joystick (B2) located on the discovery board is used for user interaction. This center button is simply referred as "button" in the following sections.
The UART2 interface of the MCU is connected directly to the ST-LINK on the board. When the ST-LINK is connected to the computer via USB, an additional virtual com port (USB VCP) is initialized by the debugger. The assigned COM port number can be checked in the Device Manager on Windows. This example project uses this virtual com port to output various debug messages.
A compiled application image named app-demo.bin in the test folder is provided with this example project. This file can be copied directly to the SD card of the discovery board and it can be used for testing the functionality of the bootloader.
The microcontroller flash is organized as follows: by default, the first 64 kBytes (32 pages) of the flash is reserved for the bootloader and the rest of the flash is the application space.
\ Figure 1: Flash organization
The bootloader can be easily customized and tailored to the required hardware and environment, i.e. to perform firmware updates over various interfaces or even to implement over-the-air (OTA) updates if the hardware incorporates wireless communication modules.
The application image has to be in binary format. The CRC verification requires a file (named app-demo.crc by default) to be present on the SD card alongside of the application binary, containing the CRC value of the application.
If the checksum verification is enabled, the binary must include the checksum value at the end of the image. When creating the application image, the checksum has to be calculated over the entire image (except the checksum area) with the following parameters:
The CRC can be calculated with the following parameters:
Tip: Use the following website to quickly calculate the CRC of a binary file, with the settings specified below: https://emn178.github.io/online-tools/crc/
| Setting | Value |
|---|---|
| Input type | File |
| Model | Custom |
| Width | 32 bit |
| Polynomial | 04C11DB7 |
| Initial value | FFFFFFFF |
| XOR out | FFFFFFFF |
| Refin | Disable (Unchecked) |
| Refout | Disable (Unchecked) |
Note: Alternatively, CRC-32/MPEG-2 preset model can be selected as this CRC model corresponds to the required CRC settings.
Follow these steps to carry out a firmware update provided by this project:
app-demo.bin located in the test folder onto the SD card.app-demo.crc containing the CRC value (in hex format, without the 0x prefix) of the application image. Note: Alternatively, the app-demo.crc file located in the test folder can also be simply copied over to the SD card as it already contains the CRC value of the app-demo.bin file.CN5 port (located on the shorter side of the board), perform a mass erase and flash the bootloader firmware to the STM32L496-Discovery board.B2), then reset the board by pressing the B1 button. Keep holding the joystick button until the following log is displayed: Release button now to update the firmware...Important notes:
system_stm32l4xx.c file by default. This has to be either disabled (the bootloader can be configured to perform the vector table relocation before the jump) or manually set the vector table offset register (VTOR) to the appropriate offset value which is the start address of the application space. For more information, please refer to [5].The project can be built with the GNU Arm Embedded Toolchain. CMake is used as the main build system, however the legacy build options with Make and SCons are still available with limited functionality.
Note: As of the v2.0.0 release, this project is based on the modern stm32-project-template project. Check out its README.md for detailed description of available features, commands, devcontainer & VSCode integration details, and more.
10-2020-q4.requirements.txt file contains packages that are used for style checks. It is highly recommended to install and run the python packages in a python virtual environment (virtualenv).Note: In case the GCC for ARM or the clang-tools are not available in your PATH (e.g. you have multiple, different versions installed), you can specify the toolchain paths in the respective toolchain .cmake file.
| Command | Description |
|---|---|
cmake --list-presets | List all CMake presets |
cmake --preset Debug | Configure the project for Debug build |
cmake --build build/Debug | Build the firmware with Debug build type |
cmake --build build/Debug --target clean | Clean the Debug target |
cmake --build build/Debug --target check-format | Check source code formatting with clang-format |
cmake --build build/Debug --target run-format | Run source code formatting with clang-format |
cmake --build build/Debug --target cppcheck | Perform analysis and MISRA conformity check with cppcheck |
cmake --build build/Debug --target tidy | Perform analysis and style check with clang-tidy |
cmake --build build/Debug --target doxygen | Generate documentation with Doxygen |
Supported CMake configurations and presets:
| Preset | Description |
|---|---|
Debug | Debug preset for debugging, without any optimization enabled |
Release | Release preset with O3 optimization |
MinSizeRel | Release preset with Os optimization for size with link time optimization enabled |
RelWithDebInfo | Release preset with O2 optimization with debug information |
Steps to compile and build with GNU Make:
GCC_PATH environmental variable containing the path to the bin folder of the installed GNU Arm Embedded Toolchain. The Makefile checks for the GCC_PATH environmental variable before checking PATH.GCC subfolder where the makefile is located.make and hit enter.build subfolder should contain the binary, ELF and HEX output files, named stm32-bootloader.bin, stm32-bootloader.elf and stm32-bootloader.hex respectively.This project currently supports two build configurations: debug (default) and release. Follow these steps to compile and build the project with SCons. Please note that the recommended usage is within a virtualenv.
pip install -r requirements.txt. This contains SCons (among other helper tools).bin folder of the GNU Arm Embedded Toolchain does not exist in the PATH, it can be specified in the SConstruct file.scons -j8scons --all -j8scons --helpbuild subfolder should contain the generated outputs, organized in subfolders with the names of the build configurations.By default, the debug configuration is set up with a SEGGER J-Link debug probe. SEGGER offers a tool to convert the onboard ST-Link debugger on Discovery and Nucleo boards into a SEGGER J-Link debugger. The onboard ST-Link debugger on the STM32L496-Discovery board used in this project was converted to a J-Link debugger with this tool.
This project provides debug configurations for VSCode via the Cortex-Debug extension (see .vscode/launch.json) and for SEGGER Ozone (see the Ozone project file in the project/ozone folder).
After power-up, the bootloader starts. The bootloader checks for user-interaction:
\ Figure 2: Bootloader sequence
The bootloader can be configured in the bootloader.h file. The file includes detailed comments and descriptions related to the configurable parameters and definitions.
The .devcontainer folder contains the devcontainer file which enables development inside a container.
The .github folder contains the GitHub Actions workflow file which describes the CI pipeline that runs automatically on every git push operation.
The application-level source code of the bootloader is located in the bootloader folder; organized into source and include subfolders.
The bsp folder stands for Board Support Package. This folder contains the board- and microcontroller-specific files and drivers. These drivers are interfaced by the application-level source code and they function as tiny wrappers around the low-level (STM32 HAL) drivers. This allows the application to interface these thin wrappers instead of the manufacturer-specific low-level code, thus providing easy portability across different chips and microcontrollers.
Upon building the project, a build folder is created. All build-related files and output binaries are located in the build folder, organized into subfolders. Each build target and their respective output files have their own subfolder. The generated Doxygen documentation output files are also located in the build folder.
The cmake folder contains the files related to the CMake-based build system, including the toolchain and microcontroller-specific files.
Thedocs folder contains the doxygen configuration file (Doxyfile) and other documentation-related static files.
The lib folder contains all third-party code, including the CMSIS (Cortex Microcontroller Software Interface Standard) as well as the HAL (Hardware Abstraction Layer) drivers from ST. Additionally, the lib folder contains the FatFs library as well.
The lint folder contains the helper files for the static code analysis tools.
The project folder contains SDK- and debugger-specific files organized into subfolders.
The script folder contains helper scripts related to the project and the build system.
The test folder contains test and verification files and helpers, including the compiled application image named app-demo.bin. This file can be copied directly to the SD card of the discovery board and it can be used for testing the functionality of the bootloader.
[1] 32L496GDISCOVERY, https://www.st.com/en/evaluation-tools/32l496gdiscovery.html
[2] STM32L496AG, http://www.st.com/en/microcontrollers/stm32l496ag.html
[3] UM2160, "User manual, Discovery kit with STM32L496AG MCU", https://www.st.com/resource/en/user_manual/dm00353127.pdf
[4] UM1884, "Description of STM32L4 HAL and Low Layer drivers", http://www.st.com/resource/en/user_manual/dm00173145.pdf
[5] PM0214, "STM32F3 Series, STM32F4 Series, STM32L4 Series and STM32L4+ Series Cortex®-M4 Programming Manual", http://www.st.com/resource/en/programming_manual/dm00046982.pdf
[6] AN2606, "STM32 microcontroller system memory boot mode", http://www.st.com/resource/en/application_note/cd00167594.pdf
[7] AN3156, "USB DFU protocol used in the STM32 bootloader", http://www.st.com/resource/en/application_note/cd00264379.pdf
[8] UM0412, "Getting started with DfuSe USB device firmware upgrade", http://www.st.com/resource/en/user_manual/cd00155676.pdf