I have a requirement to use both Sleep and Standby modes on a BluePill. I am using the STM32Sleep.h library for the Standby and it works as expected however the goToSleep() function in the library does not work correctly – it instead puts the processor in standby. I want to put the processor into deep sleep for x minutes and when out of deepsleep, put it into sleep when it is waiting external tasks. The processor exits deep sleep either as a result of an external wakeup on the WKUP pin or as a result of an RTC alarm. For sleep mode, I am using the RTC’s one second interrupt to wake the processor from sleep every second. My code does not use any other interrupt functions.
I have looked at lots of code on this forum for the sleep and found that they don’t work on my hardware and in all cases simply continue to execute immediately after the wfi statement. In all cases where the software appears to be correctly coded, the processor wakes immediately after executing the wfi command. I have observed this behavioour using a logic analyser and setting test pins before the wfi instruction and clearing it afterwards.
My Bluepill has the USB bootloader installed however the USB is only used for this function, it is not used for the application. I suspect the processor is being woken up from a core interrupt or from the bootloader. But I cannot find anything in other posted examples that try to address interrupts outside of the application itself. Am I missing something?
#include <RTClock.h>
#include <STM32Sleep.h>
RTClock rt (RTCSEL_LSE); // Initialise RTC with LSE
// Defined for power and sleep functions pwr.h and scb.h
#include <libmaple/pwr.h>
#include <libmaple/scb.h>
#include <libmaple/iwdg.h>
#define TestPin1 PB6 // SCL1
#define TestPin2 PB7 // SDA1
volatile uint32_t globSecCnt = 0;
uint32_t lastGlobSecCnt = 0;
// RTC Seconds Interrupt Handler
void rtc_sec_intr(){
if(rtc_is_second()){
globSecCnt++;
// clear the sesonds interrupt flag
RTC_BASE->CRL &= ~(1<<RTC_CRL_SECF_BIT);
}
}
setup(){
// .. other typical setup - no interrupt logic
rt.attachSecondsInterrupt(rtc_sec_intr);
}
void Snooze(void){
Clear the RTC Seconds Interrupt Flag
if (RTC_BASE->CRL & (1<<RTC_CRL_SECF_BIT))
RTC_BASE->CRL &= ~(1<<RTC_CRL_SECF_BIT);
digitalWrite(TestPin2, HIGH);
// Clear PDDS and LPDS bits
PWR_BASE->CR &= ~(PWR_CR_PDDS | PWR_CR_LPDS);
// clear sleepdeep in the system control register
SCB_BASE->SCR &= ~SCB_SCR_SLEEPDEEP;
// Clear previous wakeup register by setting the CWUF bit
PWR_BASE->CR |= PWR_CR_CWUF;
// set Low-power sleep.
PWR_BASE->CR |= PWR_CR_LPDS;
// Now go into stop mode, wake up on interrupt
asm(" wfi");
// Clear SLEEPDEEP bit so we can use SLEEP mode
SCB_BASE->SCR &= ~SCB_SCR_SLEEPDEEP;
digitalWrite(TestPin2, LOW);
}
If you don’t need USB serial, then you should remove the compiler directive “-DSERIAL_USB” from the boards.txt line corresponding to the plue pill.
I will try the directive for the board.txt file.
Thanks, Andrew
Best, E.
incidentally found an app note about the low power modes as well
http://www.st.com/content/ccc/resource/ … 171691.pdf
i didn’t need sleep, so i just keep rtc running on vbat from a coin cell, disconnecting power if it isn’t needed ![]()
There were two primary sources of interrupts that were waking the processor up outside of my application. The first was the USB from the bootloader. I did not want to create a custom boards file. I have seen this approach is just too hard to manage over time. Instead the very first instruction in my setup was:
// disable USB interrupts
Serial.end();
At the moment Serial.end () does not power down the USB Serial . This is a known “feature” and there is a PR pending to fix this.
[RogerClark – Wed Dec 13, 2017 8:37 am] –
FYIAt the moment Serial.end () does not power down the USB Serial . This is a known “feature” and there is a PR pending to fix this.
… of course, such a “fix” will kill serial enumeration over USB … might as well unplug the USB cable. the fun part of this is that re-enumeration may not take on the same port number. Oh, joy …
Ray
The core secretly calls Serial.begin() as part of the core init, to enable this feature.
I have not tested the PR to turn off USB power, when Serial.end() is called, but it seems a logical extension of what Serial.end() already does.
[edogaldo – Wed Dec 13, 2017 4:48 pm] –
Wouldn’t it be enough to re-execute a Serial.begin() at wakeup?!
Perhaps. https://support.microsoft.com/en-us/hel … usb-device
In Linux Mint 17.3/64, I have witnessed an upload to Maple, reset, and a different port being enumerated. I then have to select the new serial port in the ArduinoIDE. I really have not lookin into the specifics but do remember it has happened with an ESP8266 Node board, too.
Ray
I’ve seen it happen quite a lot (I’m using Ubuntu, so it probably affects most Debian based distros). Incidentally a similar issue exists in some versions of Windows, which can lead to loads of phantom com ports cluttering up the place, as I found out while trying to put new ROM images on some old Android phones using a Windows VM.

