diff --git a/README.md b/README.md index 9eba8f8..16e0c75 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,64 @@ # STM32LowPower Arduino library to support Low Power + +## API + +* **`void begin()`**: configure the Low Power + +* **`void idle(uint32_t millis)`**: enter in idle mode +**param** millis (optional): number of milliseconds before to exit the mode. At least 1000 ms. The RTC is used in alarm mode to wakeup the chip in millis milliseconds. + +* **`void sleep(uint32_t millis)`**: enter in sleep mode +**param** millis (optional): number of milliseconds before to exit the mode. At least 1000 ms. The RTC is used in alarm mode to wakeup the chip in millis milliseconds. + +* **`void deepSleep(uint32_t millis)`**: enter in deepSleep mode +**param** millis (optional): number of milliseconds before to exit the mode. At least 1000 ms. The RTC is used in alarm mode to wakeup the chip in millis milliseconds. + +* **`void shutdown(uint32_t millis)`**: enter in shutdown mode +**param** millis (optional): number of milliseconds before to exit the mode. At least 1000 ms. The RTC is used in alarm mode to wakeup the board in millis milliseconds. + +* **`void attachInterruptWakeup(uint32_t pin, voidFuncPtrVoid callback, uint32_t mode)`**: Enable GPIO pin in interrupt mode. If the pin is a wakeup pin, it is configured as wakeup source (see board documentation). +**param** pin: pin number +**param** callback: pointer to callback +**param** mode: interrupt mode (HIGH, LOW, RISING, FALLING or CHANGE) + +* **`void enableWakeupFrom(HardwareSerial *serial, voidFuncPtrVoid callback)`**: enable a UART peripheral in low power mode. See board documentation for low power mode compatibility. +**param** serial: pointer to a UART +**param** callback: pointer to a callback to call when the board is waked up. + +* **`void enableWakeupFrom(TwoWire *wire, voidFuncPtrVoid callback)`**: +enable an I2C peripheral in low power mode. See board documentation for low power mode compatibility. +**param** wire: pointer to I2C +**param** callback: pointer to a callback to call when the board is waked up. + +* **`void enableWakeupFrom(STM32RTC *rtc, voidFuncPtr callback)`** +attach a callback to the RTC peripheral. +**param** rtc: pointer to RTC +**param** callback: pointer to a callback to call when the board is waked up. + +`Begin()` function must be called at least once before `idle()`, `sleep()`, `deepSleep()` or `shutdown()` functions. + +`attachInterruptWakeup()` or `enableWakeupFrom()` functions should be called before `idle()`, `sleep()`, `deepSleep()` or `shutdown()` functions. + +The board will restart when exit the deepSleep or shutdown mode. + +## Hardware state + +* **Idle mode**: low wake-up latency (µs range) (e.g. ARM WFI). Memories and +voltage supplies are retained. Minimal power saving mainly on the core itself. + +* **sleep mode**: low wake-up latency (µs range) (e.g. ARM WFI), Memories and +voltage supplies are retained. Minimal power saving mainly on the core itself but +higher than idle mode. + +* **deep sleep mode**: medium latency (ms range), clocks are gated to reduced. Memories +and voltage supplies are retained. If supported, Peripherals wake-up is possible (UART, I2C ...). + +* **shutdown mode**: high wake-up latency (posible hundereds of ms or second +timeframe), voltage supplies are cut except always-on domain, memory content +are lost and system basically reboots. + +## Source + +You can find the source files at +https://github.com/stm32duino/STM32LowPower diff --git a/examples/ExternalWakeup/ExternalWakeup.ino b/examples/ExternalWakeup/ExternalWakeup.ino new file mode 100644 index 0000000..9a80ed8 --- /dev/null +++ b/examples/ExternalWakeup/ExternalWakeup.ino @@ -0,0 +1,49 @@ +/* + ExternalWakeup + + This sketch demonstrates the usage of External Interrupts (on pins) to wakeup a chip in sleep mode. + Sleep modes allow a significant drop in the power usage of a board while it does nothing waiting for an event to happen. Battery powered application can take advantage of these modes to enhance battery life significantly. + + In this sketch, shorting pin 8 to a GND will wake up the board. + + This example code is in the public domain. +*/ + +#include "STM32LowPower.h" + +// Blink sequence number +// Declare it volatile since it's incremented inside an interrupt +volatile int repetitions = 1; + +// Pin used to trigger a wakeup +const int pin = USER_BTN; + +void setup() { + pinMode(LED_BUILTIN, OUTPUT); + // Set pin as INPUT_PULLUP to avoid spurious wakeup + pinMode(pin, INPUT_PULLUP); + + // Configure low power + LowPower.begin(); + // Attach a wakeup interrupt on pin, calling repetitionsIncrease when the device is woken up + LowPower.attachInterruptWakeup(pin, repetitionsIncrease, CHANGE); +} + +void loop() { + for (int i = 0; i < repetitions; i++) { + digitalWrite(LED_BUILTIN, HIGH); + delay(500); + digitalWrite(LED_BUILTIN, LOW); + delay(500); + } + // Triggers an infinite sleep (the device will be woken up only by the registered wakeup sources) + // The power consumption of the chip will drop consistently + LowPower.sleep(); +} + +void repetitionsIncrease() { + // This function will be called once on device wakeup + // You can do some little operations here (like changing variables which will be used in the loop) + // Remember to avoid calling delay() and long running functions since this functions executes in interrupt context + repetitions ++; +} diff --git a/examples/SerialSleep/SerialSleep.ino b/examples/SerialSleep/SerialSleep.ino new file mode 100644 index 0000000..b2a4bc6 --- /dev/null +++ b/examples/SerialSleep/SerialSleep.ino @@ -0,0 +1,41 @@ +/* + SerialDeepSleep + + This sketch demonstrates the usage of Serial Interrupts to wakeup a chip in sleep mode. + + This sketch is compatible only with board supporting uart peripheral in stop mode. + + This example code is in the public domain. +*/ + +#include "STM32LowPower.h" + +void setup() { + Serial.begin(9600); + // Configure low power + LowPower.begin(); + // Enable UART in Low Power mode wakeup source + LowPower.enableWakeupFrom(&Serial, SerialWakeup); +} + +void loop() { + digitalWrite(LED_BUILTIN, HIGH); + delay(500); + digitalWrite(LED_BUILTIN, LOW); + delay(500); + // Triggers an infinite sleep (the device will be woken up only by the registered wakeup sources) + // The power consumption of the chip will drop consistently + LowPower.sleep(); +} + +void SerialWakeup() { + // This function will be called once on device wakeup + // You can do some little operations here (like changing variables which will be used in the loop) + // Remember to avoid calling delay() and long running functions since this functions executes in interrupt context + delay(100); + while(Serial.available()) { + char c = Serial.read(); + Serial.print(c); + } + Serial.println(); +} diff --git a/examples/TimedWakeup/TimedWakeup.ino b/examples/TimedWakeup/TimedWakeup.ino new file mode 100644 index 0000000..395b406 --- /dev/null +++ b/examples/TimedWakeup/TimedWakeup.ino @@ -0,0 +1,24 @@ +/* + TimedWakeup + + This sketch demonstrates the usage of Internal Interrupts to wakeup a chip in deep sleep mode. + + In this sketch, the internal RTC will wake up the processor every 2 seconds. + + This example code is in the public domain. +*/ + +#include "STM32LowPower.h" + +void setup() { + pinMode(LED_BUILTIN, OUTPUT); + // Configure low power + LowPower.begin(); +} + +void loop() { + digitalWrite(LED_BUILTIN, HIGH); + LowPower.deepSleep(500); + digitalWrite(LED_BUILTIN, LOW); + LowPower.deepSleep(500); +} diff --git a/keywords.txt b/keywords.txt new file mode 100644 index 0000000..80d9c07 --- /dev/null +++ b/keywords.txt @@ -0,0 +1,26 @@ +####################################### +# Syntax Coloring Map For Energy Saving +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +ArduinoLowPower KEYWORD1 +LowPower KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +idle KEYWORD2 +sleep KEYWORD2 +deepSleep KEYWORD2 +shutdown KEYWORD2 +attachInterruptWakeup KEYWORD2 +enableWakeupFrom KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/library.properties b/library.properties new file mode 100644 index 0000000..708170f --- /dev/null +++ b/library.properties @@ -0,0 +1,9 @@ +name=STM32duino Low Power +version=1.0.0 +author=Wi6Labs +maintainer=stm32duino +sentence=Power save primitives features for STM32 boards +paragraph=With this library you can manage the low power states of STM32 boards +category=Device Control +url=https://github.com/stm32duino/STM32LowPower +architectures=stm32 diff --git a/src/STM32LowPower.cpp b/src/STM32LowPower.cpp new file mode 100644 index 0000000..e35ddfa --- /dev/null +++ b/src/STM32LowPower.cpp @@ -0,0 +1,221 @@ +/** +****************************************************************************** +* @file STM32LowPower.cpp +* @author WI6LABS +* @version V1.0.0 +* @date 11-December-2017 +* @brief Provides a STM32 Low Power interface with Arduino +* +****************************************************************************** +* @attention +* +*

© COPYRIGHT(c) 2017 STMicroelectronics

+* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* 3. Neither the name of STMicroelectronics nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +*/ + +#include "STM32LowPower.h" + +STM32LowPower LowPower; + + +STM32LowPower::STM32LowPower() +{ + _configured = false; +} + +/** + * @brief Initializes the low power mode + * @param None + * @retval None + */ +void STM32LowPower::begin(void) +{ + LowPower_init(); + _configured = true; +} + +/** + * @brief Enable the idle low power mode (STM32 sleep). Exit this mode on interrupt. + * @param None + * @retval None + */ +void STM32LowPower::idle(void) +{ + LowPower_sleep(PWR_MAINREGULATOR_ON); +} + +/** + * @brief Enable the idle low power mode (STM32 sleep). Exit this mode on + * interrupt or in n milliseconds. + * @param millis: delay before leave the idle mode. + * @retval None + */ +void STM32LowPower::idle(uint32_t millis) +{ + programRtcWakeUp(millis); + LowPower_sleep(PWR_MAINREGULATOR_ON); +} + +/** + * @brief Enable the sleep low power mode (STM32 sleep). Exit this mode on + * interrupt. + * @param none + * @retval None + */ +void STM32LowPower::sleep(void) +{ + LowPower_sleep(PWR_LOWPOWERREGULATOR_ON); +} + +/** + * @brief Enable the sleep low power mode (STM32 sleep). Exit this mode on + * interrupt or in n milliseconds. + * @param millis: delay before leave the idle mode. + * @retval None + */ +void STM32LowPower::sleep(uint32_t millis) +{ + programRtcWakeUp(millis); + LowPower_sleep(PWR_LOWPOWERREGULATOR_ON); +} + +/** + * @brief Enable the deepsleep low power mode (STM32 stop). Exit this mode on + * interrupt. + * @param none + * @retval None + */ +void STM32LowPower::deepSleep(void) +{ + LowPower_stop(); +} + +/** + * @brief Enable the deepsleep low power mode (STM32 stop). Exit this mode on + * interrupt or in n milliseconds. + * @param millis: delay before leave the idle mode. + * @retval None + */ +void STM32LowPower::deepSleep(uint32_t millis) +{ + programRtcWakeUp(millis); + LowPower_stop(); +} + +/** + * @brief Enable the shutdown low power mode (STM32 shutdown or standby mode). + * Exit this mode on interrupt. + * @param none + * @retval None + */ +void STM32LowPower::shutdown(void) +{ + LowPower_shutdown(); +} + +/** + * @brief Enable the shutdown low power mode (STM32 shutdown or standby mode). + * Exit this mode on interrupt or in n milliseconds. + * @param millis: delay before leave the idle mode. + * @retval None + */ +void STM32LowPower::shutdown(uint32_t millis) +{ + programRtcWakeUp(millis); + LowPower_shutdown(); +} + +/** + * @brief Enable GPIO pin in interrupt mode. If the pin is a wakeup pin, it is + * configured as wakeup source. + * @param pin: pin number + * @param callback: pointer to callback function. + * @param mode: pin interrupt mode (HIGH, LOW, RISING, FALLING or CHANGE) + * @retval None + */ +void STM32LowPower::attachInterruptWakeup(uint32_t pin, voidFuncPtrVoid callback, uint32_t mode) +{ + // all GPIO for idle (smt32 sleep) and sleep (stm32 stop) + attachInterrupt(pin, callback, mode); + + // If Gpio is a Wake up pin activate it for deepSleep (standby stm32) and shutdown + LowPower_EnableWakeUpPin(pin, mode); +} + +/** + * @brief Enable a serial interface as a wakeup source. + * @param serial: pointer to a HardwareSerial + * @param callback: pointer to callback function called when leave the low power + * mode. + * @retval None + */ +void STM32LowPower::enableWakeupFrom(HardwareSerial *serial, voidFuncPtrVoid callback) +{ + LowPower_EnableWakeUpUart(&(serial->_serial), callback); +} + +/** + * @brief Attach a callback to a RTC alarm. + * @param rtc: pointer to a STM32RTC + * @param callback: pointer to callback function called when leave the low power + * mode. + * @retval None + */ +void STM32LowPower::enableWakeupFrom(STM32RTC *rtc, voidFuncPtr callback) +{ + rtc->attachInterrupt(callback); +} + +/** + * @brief Configure the RTC alarm + * @param millis: time of the alarm in milliseconds. At least 1000ms. + * @retval None + */ +void STM32LowPower::programRtcWakeUp(uint32_t millis) +{ + int epoc; + uint32_t sec; + + if(millis > 0) { + if (!rtcLowPower.isConfigured()){ + // LSE must be selected as clock source to wakeup the device from shutdown mode + rtcLowPower.setClockSource(RTC_LSE_CLOCK); + //Enable RTC + rtcLowPower.begin(HOUR_24); + } + + // convert millisecond to second + sec = millis / 1000; + // Minimum is 1 second + if (sec == 0){ + sec = 1; + } + + epoc = rtcLowPower.getEpoch(); + rtcLowPower.setAlarmEpoch( epoc + sec ); + } + +} diff --git a/src/STM32LowPower.h b/src/STM32LowPower.h new file mode 100644 index 0000000..f2e7ba2 --- /dev/null +++ b/src/STM32LowPower.h @@ -0,0 +1,92 @@ +/** +****************************************************************************** +* @file STM32LowPower.h +* @author WI6LABS +* @version V1.0.0 +* @date 11-December-2017 +* @brief Provides a STM32 Low Power interface with Arduino +* +****************************************************************************** +* @attention +* +*

© COPYRIGHT(c) 2017 STMicroelectronics

+* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* 3. Neither the name of STMicroelectronics nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +*/ + +#ifndef _STM32_LOW_POWER_H_ +#define _STM32_LOW_POWER_H_ + +#include +#include "STM32RTC.h" +#include "Wire.h" + +typedef void (*voidFuncPtrVoid)( void ) ; + +class STM32LowPower { +public: + STM32LowPower(); + + void begin(void); + + void idle(void); + void idle(uint32_t millis); + void idle(int millis) { + idle((uint32_t)millis); + } + + void sleep(void); + void sleep(uint32_t millis); + void sleep(int millis) { + sleep((uint32_t)millis); + } + + void deepSleep(void); + void deepSleep(uint32_t millis); + void deepSleep(int millis) { + deepSleep((uint32_t)millis); + } + + void shutdown(void); + void shutdown(uint32_t millis); + void shutdown(int millis) { + shutdown((uint32_t)millis); + } + + void attachInterruptWakeup(uint32_t pin, voidFuncPtrVoid callback, uint32_t mode); + + void enableWakeupFrom(HardwareSerial *serial, voidFuncPtrVoid callback); + void enableWakeupFrom(STM32RTC *rtc, voidFuncPtr callback); + +private: + bool _configured; /* Low Power mode initialization status */ + STM32RTC rtcLowPower; /* RTC pointer */ + + void programRtcWakeUp(uint32_t millis); +}; + +extern STM32LowPower LowPower; + +#endif // _STM32_LOW_POWER_H_