Low power mode with and without USB

Generic boards that are not Maple or Maple mini clones, and don't contain the additional USB reset hardware
Post Reply
peekay123
Posts: 27
Joined: Tue Nov 08, 2016 8:39 pm

Low power mode with and without USB

Post by peekay123 » Mon Dec 31, 2018 8:29 pm

I have a blue pill board that I am using for measuring STOP and STANDBY mode current to the MCU. I removed the power LED resistor and I am powering the board (external programmable PSU) via the 3.3 pin to bypass the regulator. All measurement were done with a Siglent SDM3045X multimeter.

A little background - I have a custom board with an STM32F103RCT6 running without an external HSE crystal. The board does have 32KHz LSE crystal for the RTC. I am running the STM32 with the HSI at 8MHz and without the PLL. I am finding that I cannot get to the sub-1mA currents in STOP or STANDBY sleep modes and I do not understand why. Thus, I am using the "bare" blue pill board to do current testing with a similar MCU.

I used code I found in this forum for setting the MCU for STOP and STANDBY modes:

Code: Select all

#include 
#include 
// the setup function runs once when you press reset or power the board
void setup() {
	uint32_t btime = millis();
	pinMode(LED_BUILTIN, OUTPUT);
	while(millis() - btime < 5000) {
		digitalWrite(LED_BUILTIN, LOW);
		delay(500);
		digitalWrite(LED_BUILTIN, HIGH);
		delay(500);
	}
	sleepMode(true);
}
// the loop function runs over and over again forever
void loop() {
}
void sleepMode(bool deepSleepFlag)
{
  // Clear PDDS and LPDS bits
  PWR_BASE->CR &= PWR_CR_LPDS | PWR_CR_PDDS | PWR_CR_CWUF;
  // Set PDDS and LPDS bits for standby mode, and set Clear WUF flag (required per datasheet):
  PWR_BASE->CR |= PWR_CR_CWUF;
  PWR_BASE->CR |= PWR_CR_PDDS;
  // Enable wakeup pin bit.
  PWR_BASE->CR |=  PWR_CSR_EWUP;
  // Low-power deepsleep bit.
  // PWR_BASE->CR |= PWR_CR_LPDS;
  // System Control Register Bits. See...
  // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0497a/Cihhjgdh.html
  if (deepSleepFlag)
  { // Experimental
    // Set Power down deepsleep bit.
    PWR_BASE->CR |= PWR_CR_PDDS;
    // Unset Low-power deepsleep.
    PWR_BASE->CR &= ~PWR_CR_LPDS;
    // Set sleepdeep in the system control register - if set, we deepsleep and coldstart from RTC or pin interrupts.
    SCB_BASE->SCR |= SCB_SCR_SLEEPDEEP;
  } else {
    //  Unset Power down deepsleep bit.
    PWR_BASE->CR &= ~PWR_CR_PDDS;
    // set Low-power deepsleep.
    PWR_BASE->CR |= PWR_CR_LPDS;
    // Unset sleepdeep in the system control register - if not set then we only sleep and can wake from RTC or pin interrupts.
    SCB_BASE->SCR |= SCB_SCR_SLEEPDEEP;
    // Low-power deepsleep bit.
  }
  // Set end Event on Pending bit: - enabled events and all interrupts, including disabled interrupts, can wakeup the processor.
  // SCB_BASE->SCR |= SCB_SCR_SEVONPEND;
  // Set SLEEPONEXIT -Indicates sleep-on-exit when returning from Handler mode to Thread mode -
  // if enabled, we will effectively sleep from the end of  one interrupt till the start of the next.
  // SCB_BASE->SCR |= SCB_SCR_SLEEPONEXIT;
  // Now go into stop mode, wake up on interrupt
  asm("    wfi");
}
For initial testing, I flashed the generic bootloader to the bluepill. I then selected the generic STM32F103C series in the Arduino IDE (v1.86) and chose the "Upload method: STM32Duino bootloader" and a 72MHz(Normal) clock. Everything flashed over fine and once in STANDBY sleep, I measured 35uA on the 3.3V supply. Selecting a 48MHz clock produced the same results.

I then changed the upload method to "Serial" and connected the same USB-to-Serial FTDI I had used to flash the bootloader. Again, I flashed the exact same code except this time via serial. Now in sleep mode I measured a current of 1.5mA. Thinking it might be related to the FTDI connection, I removed the RX/TX connections but it made no difference.

I am at a loss as to why these would behave differently except for the fact that one uses the bootloader and the other doesn't. Perhaps the bootloader leaves the MCU registers in a different state before passing control to the user code that the non-bootloader version does not.

Does anyone have any insight here? Nothing I have found from ST Micro has been helpful.

Thanks!

Paul

edogaldo
Posts: 432
Joined: Fri Jun 03, 2016 8:19 am

Re: Low power mode with and without USB

Post by edogaldo » Tue Jan 01, 2019 12:28 am

It seems to me you didn’t disable the systick which is a wakeup trigger.

peekay123
Posts: 27
Joined: Tue Nov 08, 2016 8:39 pm

Re: Low power mode with and without USB

Post by peekay123 » Tue Jan 01, 2019 8:08 pm

I added

Code: Select all

systick_disable()
before calling

Code: Select all

wfi
and it made no different. Besides, all clocks are disabled in STANDBY sleep.

I tried with both the bootloader and Serial flash with the same results. The current with the Serial load is actually 1.8 - 2.0mA while that of the USB bootloader flash is 38uA.

peekay123
Posts: 27
Joined: Tue Nov 08, 2016 8:39 pm

Re: Low power mode with and without USB

Post by peekay123 » Thu Jan 17, 2019 4:32 pm

UPDATE: I wrote a new set of sleep functions based on the STM32 Core libraries. With these I was able to flash my test code via the STM32 built-in serial bootloader and was able to achieve 38uA STANDBY sleep current consistently. Oddly, if I drop Vdd to 2.8V (from 3.3v), the current rises to 77uA and I'm not sure why.

In STOP mode and with light tweaking (all pins to ANALOG INPUT mode, disabled peripheral clocks, set HCLK to 125KHz), I could only get down to 1.7mA STOP sleep current. There is obviously more to do to get the current down to below 1ma.

Post Reply