DeepSleep with STM32F401 and LowPower Lib isn't working as expected

I have a hardware with an STM32F401 and I’m programming it with PlatformIO and the Arduino framework. I want to put it into low-power mode.

Unfortunately, the original example from the LowPower Library, AlarmTimedWakeup, isn’t working as expected for me. The processor never stops and always runs continuously.

If I change ONLY the mode in this example from DeepSleep to Sleep, it works as expected.

This works

  digitalWrite(PA6, HIGH);
  LowPower.sleep();
  digitalWrite(PA6, LOW);
  LowPower.sleep();

This not

  digitalWrite(PA6, HIGH);
  LowPower.deepSleep();
  digitalWrite(PA6, LOW);
  LowPower.deepSleep();

Does anyone have any suggestions?

Regards
Hans-Joachim

So you’re taking the unmodified example (https://github.com/stm32duino/STM32LowPower/blob/1.5.0/examples/AlarmTimedWakeup/AlarmTimedWakeup.ino) and upload it using what exact platformio.ini? And that already doesn’t deepsleep properly, as is visible on the UART or by the LED_BUILTIN?

My goal is to measure the power consumption of my circuit.

Therefore, I made the following modifications to this example:

  • I added a 5-second delay to Startup to allow for a smooth update via STLINK during this time.
  • I configured three GPIOs as outputs and set them to “0” to disable various components on my hardware.
  • Also I increased the sleep times to enable measurements (DLETA is 5 in this case) line 113 in the example
rtc.setAlarmEpoch(epoc + DELTA, STM32RTC::MATCH_SS, epoc_ms);

Using LowPower.sleep()
The blinking LED indicates that the RTC interrupt is working – the LED blinks at the correct rate.
On the serial output yields the following results:

Alarm Match: 2 times.
Alarm Match: 4 times.
Alarm Match: 6 times.
Alarm Match: 8 times.
Alarm Match: 10 times.

When using LowPower.deepSleep(), the LED flickers minimally (almost constantly on), and the serial output shows:

Alarm Match: 0 times.
Alarm Match: 0 times.
Alarm Match: 0 times.
Alarm Match: 0 times.
…. After 5 seconds
Alarm Match: 1 time.
Alarm Match: 1 time.
Alarm Match: 1 time.

This means to me: The interrupt is working, but the processor never enters sleep mode.

The platformio.ini file is:

[env:genericSTM32F401RC]
platform = ststm32
board = genericSTM32F401RC
framework = arduino
board_build.mcu = stm32f401rct6
upload_protocol = stlink
debug_tool = stlink

Regards,
Hans-Joachim

Hi!
I have a few new insights into this behavior:

  • When I load the program with deepSleep, I get the behavior described.
  • If I then reset only my target hardware, the faulty behavior persists.
  • If I then disconnect the ST-LINK cable, the faulty behavior remains.
  • If I then reset my target hardware, it works as expected.

It’s not entirely clear to me, but apparently, I don’t have to understand everything.
Okay, the power consumption isn’t where I wanted it to be, but it’s significantly closer than before.

Thanks for your efforts on your side.

Regards,
Hans-Joachim

I’ve seen this ‘gotcha’ multiple times: When the firmware is flashed via OpenOCD and a reset is done (either software or hardware), low power firmwares will behave differently. This may be due to OpenOCD e.g. enabling debug register bits for “be able to debug during standby, stop and sleep mode”

Or that the reset method done (via software or NRST toggle) is not ‘complete’ enough.

To get reliable results, I always power cycled the device completely to get the power-on-reset behavior (POR). Also make sure to disconnect the debugger completely, so that no leakage current can flow through SWDIO and SWCLK, or be parasitcally powered through the VCC / GND of the probe. Most competent dev boards will have hardware DIP switches to cut the debugger out of the line physically so that you don’t have to pull out wires constantly.