The Low Power Trap of STM32! 5-Year Battery Life Turns into 5 Weeks, Nearly Causing a Total Failure in a Million IoT Deployments, and the Culprit is the Debugger That Wasn’t ‘Frozen’

A few years ago, we worked on an IoT project using the STM32 solution, where the client insisted that the coin cell battery must last for five years.

We were familiar with this task. We entered the <span>Standby</span> mode, turned off everything that could be turned off, and measured the current with a multimeter in the lab, achieving a sleep current of 2uA, which was very stable. Calculating it out, five years was more than sufficient, and at that time, we thought this project was a piece of cake.

However, after the first batch was shipped, within a month, the backend was flooded with alerts, and devices were going offline in large numbers. The client was almost shouting on the phone. Upon recalling the boards for inspection, we found that the batteries were completely drained.

This situation was perplexing.

The most critical issue was that as soon as the board was brought back to the lab and connected to the J-Link, the power consumption curve looked textbook-perfect; the sleep current was indeed 2uA, and no problems were visible. But once the debugger was unplugged and the board was left to run on its own, although we couldn’t see the current, it would inevitably die after a month or so.

During that time, the hardware engineers were more anxious than the boards themselves, repeatedly checking the schematics, suspecting whether some capacitor was leaking or if there was a problem with a batch of chips. The software team was also going crazy, combing through the code, fearing that some interrupt hadn’t been properly disabled.

Everyone was at their wits’ end, even starting to question life itself, wondering if they had encountered some quantum mechanics issue, where the act of ‘observation’ itself changed the outcome.

Eventually, a recent graduate, who had been quietly measuring for two days, asked, ‘Have we ever run a complete power consumption test in the lab without unplugging the debugger?’

That question was a wake-up call.

We immediately set up the simplest test: one board, only connected to the power supply, with all other lines, including the debug and serial lines, unplugged. Then we connected a high-precision power analyzer in series with the power supply.

The true culprit was revealed instantly.

The power analyzer clearly showed that after the board entered <span>Standby</span>, the current was not 2uA at all, but was steadily sitting at 150uA. Not too much, but enough to drain a coin cell battery within a few weeks.

Since the problem could be consistently reproduced, it was no longer a mystery. The direction was clear: the issue lay in the state of ‘whether the debugger is connected or not.’

The first suspect was the <span>SWDIO</span> and <span>SWCLK</span> debug pins. When the debugger is unplugged, these two pins are left floating, with uncertain pull-up and pull-down states, and the input buffers are bound to leak current. This is basic knowledge. So, before entering <span>Standby</span>, we first forced these two pins to be set as Analog State.

After measuring again, the current dropped from 150uA to 30uA.

It was effective! But it didn’t completely solve the problem. Where was the remaining 30uA coming from?

There was no choice but to dig into the manual. We went through the thick STM32 reference manual, looking at every register with ‘Debug’ in its name. Finally, in the <span>DBGMCU</span> module, we found a control register called <span>DBGMCU_CR</span>.

It contained several bits, including <span>DBG_STOP</span> and <span>DBG_STANDBY</span>, which, as the names suggest, determine whether the internal debug circuitry sleeps along with the chip when it enters Stop or Standby mode, or continues to ‘stand guard.’

By default, in order to allow you to connect to the debugger even in low power mode, this internal debug circuitry is not completely turned off.

It was a moment of realization. We had always thought that once we unplugged the external J-Link, debugging was no longer our concern. But in fact, the internal ‘connector’ of the chip was still consuming power, waiting to re-establish a handshake with the debugger at any time.

The solution was simple: before entering <span>Standby</span>, we just needed to send a command to <span>DBGMCU</span> to tell it to sleep as well, no need to wait. It was just a line of code:

<span>HAL_DBGMCU_DisableDBGStandbyMode();</span>

After adding this line and setting the GPIO to analog state, the final measurement showed the current stably dropped to 1.8uA.

Since then, our team has established a strict rule, written into the development process:

Any final power consumption test for a product must be conducted in a ‘bare’ state, with all lines unplugged and only the power supply connected, using a power analyzer for at least 24 hours; only then can the data be considered valid. Any power consumption values claimed to be measured in a debug state are self-deception.

Tools are convenient, but sometimes, the most convenient things are the deepest pits.

Leave a Comment