on 2020-08-12 6:32 AM - edited on 2025-08-13 9:15 AM by pepfof
STM32 MCUs feature the system memory boot mode, which enables programming the device through the integrated peripheral interfaces, as outlined in AN2606 - Introduction to system memory boot mode on STM32 MCUs
To select system memory boot mode at device startup, a pattern as outlined in AN2606 must be applied. This typically involves configuration of the option bytes or applying voltages to certain MCU pins.
On some STM32 devices, their respective bootloader activation pattern contains a specific provision for entering the system memory boot mode: the empty check mechanism. On power-on reset, the MCU checks the value at the first address of the flash memory, and enters system memory boot mode if this value is unprogrammed (equal to 0xFFFFFFFF). These are devices to which bootloader activation patterns 6, 11, 13 and 16 from AN2606 apply.
The following MCUs feature bootloader activation patterns 6, 11, 13, 16 as per AN2606:
STM32 Series | STM32 MCU |
F0 |
|
C0 |
|
G0 |
|
L0 |
|
L4 |
|
U0 |
|
WL |
|
WB |
|
The empty check only being present on select devices may result in unexpected behavior for users. On previously unprogrammed MCUs featuring the empty check mechanism, system memory boot mode is entered automatically upon power-on reset until they are programmed. The following issues may arise from this:
To prevent a previously unprogrammed MCU from entering system memory boot mode upon startup:
STM32 MCUs do not automatically clear the "flash empty" bit after the flash has been programmed through system memory boot mode. This means that subsequent resets will result in the MCU again entering the integrated bootloader, as the flash is still considered "empty". In order to rectify this:
In this specific case, on the MCUs requiring Pattern 11 for bootloader activation, as per AN2606, the factory default setting of option bits provides no mechanism to enter the bootloader by applying voltages to MCU pins. This means that after the initial programming of flash, the bootloader cannot be entered unless explicitly done so in user code by either jumping to the bootloader code or modifying the option bytes and performing a reset.
If the application has no other provision for entering the integrated bootloader, and it is required to be used in place of a debugger, it will be necessary to program the nBOOT0_SEL bit of a fresh MCU to "0" in order for the MCU to select between user code and the integrated bootloader based on the voltage applied to the BOOT0 pin.
Due to the empty check bit not being cleared automatically when flash is programmed (see Clearing the empty check bit), the user may erroneously assume that their option byte configuration allows them to enter system memory boot mode upon reset, whereas this may not be the case, and the MCU has simply re-entered the integrated bootloader due to the empty check bit still being set. Afterwards, when a power-cycle is performed and the empty check bit is cleared, the integrated bootloader can not be accessed anymore. Care must be taken to ensure the correct configuration of option bytes for these MCUs if re-entering system memory boot mode is necessary during development (double-check the option byte configuration when programming the MCU).
See also: “STM32 boot and startup tips" MOOC
(edit: thanks for fixing typo)
Let's try invoke the author, maybe he will fix it @Martin HUBIK
@Martin HUBIK Any chance this could be updated for the recent additions? In particular the U5, H5 and C0 series, but I think there are others.
There's an additional mechanism in STM32 which are not in the list above and which indeed don't primarily check FLASH to be empty, but have dual-bank FLASH, e.g. 'G4 - if the BLB2 option bit is set (i.e. boot from bank 2 selected, and this is NOT the default setting) and all other bits and pins are set to boot from user FLASH, the bootloader is still entered if neither FLASH contains valid code.
In the 'G4 RM0440, this fact is not contained in the Boot modes table, but is somewhat hidden in the following narrative, so it's relatively easy to miss.
Hello everyone,
We recently discovered the "Empty Check Mechanism" on the STM32U0 series of MCUs - specifically the STM32U083CC - and wanted to share our experience in case it helps others encountering similar issues in the future.
Our device is designed to be battery-powered and deployed in remote (often unattended) locations. As such, implementing a power-on cycle reset feature was essential, in addition to managing various sensors and actuators. This reset is triggered by either a GPIO signal or an external monitoring circuit that cuts power and restores it after a short delay.
We chose the STM32U0 series for its low power consumption, which made it a suitable candidate for our application.
During the design phase, we reviewed all available documentation for the STM32U0 family, but skipped AN2606, assuming it was only relevant to the internal bootloader - which we didn’t plan to use. Unfortunately, we were unaware of the Empty Check Mechanism, and we had connected the GPIO used for triggering the external power-on cycle to one of the bootloader-related GPIOs.
We acknowledge that this issue could have been avoided had we thoroughly reviewed all documentation. However, we relied on our experience from previous projects using other STM32 families, where this mechanism did not exist, and we were accustomed to the traditional handling of the BOOT0 pin.
As we’re using a debug setup via SWDIO/SWDCLK (J-Link/ST-Link), this led to an unexpected issue: we were unable to program the device initially as we normally would.
Thankfully, we caught this during the first prototype stage and will be reassigning the affected pins in the production version. However, we struggle to see the reasoning behind this behavior. The traditional BOOT0 pin, together with option bytes like nBOOT_SEL, nBOOT1, and nBOOT0, had served their purpose well for years.
This new mechanism not only complicates things, but also reduces the number of usable GPIOs - especially on smaller packages - by forcing them OUT off a high-impedance state on the first power-up.
> This new mechanism not only complicates things, but also reduces the number of usable GPIOs - especially on smaller packages - by forcing them OUT off a high-impedance state on the first power-up.
The intention with the empty-check bootloader empty presumably was to increase number of usable pins, by omitting BOOT0. I agree that this may create a less clean situation, if the users are not aware of all the consequences. One way how to tackle this is to perform initial programming under hardware NRST pin is held low. This of course may have its implications on the hardware design (at least that pin has to be brought out to programming header, but also the programming environment has to be capable of programming under reset), too.
The real problem is in the fact that the bootloader pulls some of the pins up/down using the nominally 40kOhm pull, but, even more disturbingly, that it pulls some if the pins *hard* (due to what I consider to be a flawed SPI-bootloader implementation). AN2606 does not make a very good job in warning to this, this being decribed only in a footnote to the "resources" table, and also in a rather cryptic formulation involving reference to the internal actions of the bootloader ("...as soon as the bit DMATx enable on SPI CR2 register is set to 0x1") where in fact DMAT is enabled in the SPI bootloader unconditionally (as can be checked by single-stepping or disassembling the bootloader).
I agree that this issue is grave enough so that users are clearly notified of it in the datasheet, at around the pinout table; and/or in the GPIO chapter of RM. A simple reference to AN2606 would suffice, would AN2606 clearly and unambiguously list which pins are used - pulled, hard or weak - and how.
JW