Skip to content

Commit 8618610

Browse files
committed
Add low power driver
Signed-off-by: fpr <fabien.perroquin@wi6labs.com>
1 parent 47f9d92 commit 8618610

File tree

4 files changed

+407
-0
lines changed

4 files changed

+407
-0
lines changed

cores/arduino/board.h

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ extern "C"{
1414
#include "digital_io.h"
1515
#include "hal_uart_emul.h"
1616
#include "hw_config.h"
17+
#include "low_power.h"
1718
#include "rtc.h"
1819
#include "spi_com.h"
1920
#include "stm32_eeprom.h"

cores/arduino/stm32/low_power.c

+332
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,332 @@
1+
/**
2+
******************************************************************************
3+
* @file LowPower.c
4+
* @author WI6LABS
5+
* @version V1.0.0
6+
* @date 17 - November -2017
7+
* @brief Provides a Low Power interface
8+
*
9+
******************************************************************************
10+
* @attention
11+
*
12+
* <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
13+
*
14+
* Redistribution and use in source and binary forms, with or without modification,
15+
* are permitted provided that the following conditions are met:
16+
* 1. Redistributions of source code must retain the above copyright notice,
17+
* this list of conditions and the following disclaimer.
18+
* 2. Redistributions in binary form must reproduce the above copyright notice,
19+
* this list of conditions and the following disclaimer in the documentation
20+
* and/or other materials provided with the distribution.
21+
* 3. Neither the name of STMicroelectronics nor the names of its contributors
22+
* may be used to endorse or promote products derived from this software
23+
* without specific prior written permission.
24+
*
25+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
29+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35+
*
36+
******************************************************************************
37+
*/
38+
39+
#include "Arduino.h"
40+
#include "low_power.h"
41+
42+
#ifdef HAL_PWR_MODULE_ENABLED
43+
44+
#ifdef __cplusplus
45+
extern "C" {
46+
#endif
47+
48+
#ifdef UART_IT_WUF
49+
/* Save UART handler for callback */
50+
static UART_HandleTypeDef* WakeUpUart = NULL;
51+
#endif
52+
/* Save callback pointer */
53+
static void (*WakeUpUartCb)( void ) = NULL;
54+
55+
/**
56+
* @brief Initialize low power mode
57+
* @param None
58+
* @retval None
59+
*/
60+
void LowPower_init(){
61+
/* Enable Power Clock */
62+
__HAL_RCC_PWR_CLK_ENABLE();
63+
64+
/* Allow access to Backup domain */
65+
HAL_PWR_EnableBkUpAccess();
66+
67+
/* Reset RTC Domain */
68+
__HAL_RCC_BACKUPRESET_FORCE();
69+
__HAL_RCC_BACKUPRESET_RELEASE();
70+
71+
#ifdef __HAL_RCC_WAKEUPSTOP_CLK_CONFIG
72+
/* Ensure that HSI is wake-up system clock */
73+
__HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI);
74+
#endif
75+
/* Check if the system was resumed from StandBy mode */
76+
if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB) != RESET)
77+
{
78+
/* Clear Standby flag */
79+
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
80+
}
81+
82+
/* Clear all related wakeup flags */
83+
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
84+
}
85+
86+
/**
87+
* @brief Configure a pin as wakeup source if compatible.
88+
* @param pin: pin to configure
89+
* @param mode: pin mode (edge or state). The configuration have to be compatible.
90+
* @retval None
91+
*/
92+
void LowPower_EnableWakeUpPin(uint32_t pin, uint32_t mode) {
93+
#if !defined(PWR_WAKEUP_PIN1_HIGH)
94+
UNUSED(mode);
95+
#endif
96+
uint32_t wkup_pin;
97+
PinName p = digitalPinToPinName(pin);
98+
if (p != NC) {
99+
switch (p) {
100+
default :
101+
#ifdef PWR_WAKEUP_PIN1
102+
case SYS_WKUP1 :
103+
wkup_pin = PWR_WAKEUP_PIN1;
104+
#ifdef PWR_WAKEUP_PIN1_HIGH
105+
if (mode != RISING) {
106+
wkup_pin = PWR_WAKEUP_PIN1_LOW;
107+
}
108+
#endif
109+
break;
110+
#endif /* PWR_WAKEUP_PIN1 */
111+
#ifdef PWR_WAKEUP_PIN2
112+
case SYS_WKUP2 :
113+
wkup_pin = PWR_WAKEUP_PIN2;
114+
#ifdef PWR_WAKEUP_PIN2_HIGH
115+
if (mode != RISING) {
116+
wkup_pin = PWR_WAKEUP_PIN2_LOW;
117+
}
118+
#endif
119+
break;
120+
#endif /* PWR_WAKEUP_PIN2 */
121+
#ifdef PWR_WAKEUP_PIN3
122+
case SYS_WKUP3 :
123+
wkup_pin = PWR_WAKEUP_PIN3;
124+
#ifdef PWR_WAKEUP_PIN3_HIGH
125+
if (mode != RISING) {
126+
wkup_pin = PWR_WAKEUP_PIN3_LOW;
127+
}
128+
#endif
129+
break;
130+
#endif /* PWR_WAKEUP_PIN3 */
131+
#ifdef PWR_WAKEUP_PIN4
132+
case SYS_WKUP4 :
133+
wkup_pin = PWR_WAKEUP_PIN4;
134+
#ifdef PWR_WAKEUP_PIN4_HIGH
135+
if (mode != RISING) {
136+
wkup_pin = PWR_WAKEUP_PIN4_LOW;
137+
}
138+
#endif
139+
break;
140+
#endif /* PWR_WAKEUP_PIN4 */
141+
#ifdef PWR_WAKEUP_PIN5
142+
case SYS_WKUP5 :
143+
wkup_pin = PWR_WAKEUP_PIN5;
144+
#ifdef PWR_WAKEUP_PIN5_HIGH
145+
if (mode != RISING) {
146+
wkup_pin = PWR_WAKEUP_PIN5_LOW;
147+
}
148+
#endif
149+
break;
150+
#endif /* PWR_WAKEUP_PIN5 */
151+
#ifdef PWR_WAKEUP_PIN6
152+
case SYS_WKUP6 :
153+
wkup_pin = PWR_WAKEUP_PIN6;
154+
#ifdef PWR_WAKEUP_PIN6_HIGH
155+
if (mode != RISING) {
156+
wkup_pin = PWR_WAKEUP_PIN6_LOW;
157+
}
158+
#endif
159+
break;
160+
#endif /* PWR_WAKEUP_PIN6 */
161+
#ifdef PWR_WAKEUP_PIN7
162+
case SYS_WKUP7 :
163+
wkup_pin = PWR_WAKEUP_PIN7;
164+
break;
165+
#endif /* PWR_WAKEUP_PIN7 */
166+
#ifdef PWR_WAKEUP_PIN8
167+
case SYS_WKUP8 :
168+
wkup_pin = PWR_WAKEUP_PIN8;
169+
break;
170+
#endif /* PWR_WAKEUP_PIN8 */
171+
}
172+
HAL_PWR_EnableWakeUpPin(wkup_pin);
173+
}
174+
}
175+
176+
/**
177+
* @brief Enable the sleep mode.
178+
* @param None
179+
* @retval None
180+
*/
181+
void LowPower_sleep(uint32_t regulator){
182+
/*
183+
* Suspend Tick increment to prevent wakeup by Systick interrupt.
184+
* Otherwise the Systick interrupt will wake up the device within
185+
* 1ms (HAL time base)
186+
*/
187+
HAL_SuspendTick();
188+
189+
/* Enter Sleep Mode , wake up is done once User push-button is pressed */
190+
HAL_PWR_EnterSLEEPMode(regulator, PWR_SLEEPENTRY_WFI);
191+
192+
/* Resume Tick interrupt if disabled prior to SLEEP mode entry */
193+
HAL_ResumeTick();
194+
195+
if (WakeUpUartCb != NULL) {
196+
WakeUpUartCb();
197+
}
198+
}
199+
200+
/**
201+
* @brief Enable the stop mode.
202+
* @param obj : pointer to serial_t structure
203+
* @retval None
204+
*/
205+
void LowPower_stop(serial_t *obj){
206+
__disable_irq();
207+
208+
#ifdef UART_IT_WUF
209+
if (WakeUpUart != NULL) {
210+
HAL_UARTEx_EnableStopMode(WakeUpUart);
211+
}
212+
#endif
213+
214+
#if defined(STM32L0xx) || defined(STM32L1xx)
215+
/* Enable Ultra low power mode */
216+
HAL_PWREx_EnableUltraLowPower();
217+
218+
/* Enable the fast wake up from Ultra low power mode */
219+
HAL_PWREx_EnableFastWakeUp();
220+
#endif
221+
#ifdef __HAL_RCC_WAKEUPSTOP_CLK_CONFIG
222+
/* Select HSI as system clock source after Wake Up from Stop mode */
223+
__HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI);
224+
#endif
225+
226+
/* Enter Stop mode */
227+
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
228+
229+
/* Exit Stop mode reset clocks */
230+
SystemClock_Config();
231+
#ifdef UART_IT_WUF
232+
if (WakeUpUart != NULL) {
233+
/* In case of WakeUp from UART, reset its clock source to HSI */
234+
uart_config_lowpower(obj);
235+
HAL_UARTEx_DisableStopMode(WakeUpUart);
236+
}
237+
#else
238+
UNUSED(obj);
239+
#endif
240+
__enable_irq();
241+
242+
HAL_Delay(10);
243+
244+
if (WakeUpUartCb != NULL) {
245+
WakeUpUartCb();
246+
}
247+
}
248+
249+
/**
250+
* @brief Enable the standby mode. The board reset when leaves this mode.
251+
* @param None
252+
* @retval None
253+
*/
254+
void LowPower_standby(){
255+
__disable_irq();
256+
257+
#if defined(STM32L0xx) || defined(STM32L1xx)
258+
/* Enable Ultra low power mode */
259+
HAL_PWREx_EnableUltraLowPower();
260+
261+
/* Enable the fast wake up from Ultra low power mode */
262+
HAL_PWREx_EnableFastWakeUp();
263+
#endif
264+
265+
HAL_PWR_EnterSTANDBYMode();
266+
}
267+
268+
/**
269+
* @brief Enable the shutdown mode.The board reset when leaves this mode.
270+
* If shutdown mode not available, use standby mode instead.
271+
* @param None
272+
* @retval None
273+
*/
274+
void LowPower_shutdown(){
275+
__disable_irq();
276+
#ifdef STM32L4xx
277+
/* LSE must be on to use shutdown mode */
278+
if(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == SET) {
279+
HAL_PWREx_EnterSHUTDOWNMode();
280+
} else
281+
#endif
282+
{
283+
LowPower_standby();
284+
}
285+
}
286+
287+
/**
288+
* @brief Configure the UART as a wakeup source. A callback can be called when
289+
* the chip leaves the low power mode. See board datasheet to check
290+
* with which low power mode the UART is compatible.
291+
* Warning This function will change UART clock source to HSI
292+
* @param serial: pointer to serial
293+
* @param FuncPtr: pointer to callback
294+
* @retval None
295+
*/
296+
void LowPower_EnableWakeUpUart(serial_t* serial, void (*FuncPtr)( void ) ) {
297+
#ifdef UART_IT_WUF
298+
UART_WakeUpTypeDef WakeUpSelection;
299+
if(serial == NULL) {
300+
return;
301+
}
302+
/* Save Uart handler and Serial object */
303+
WakeUpUart = &(serial->handle);
304+
305+
/* make sure that no UART transfer is on-going */
306+
while(__HAL_UART_GET_FLAG(WakeUpUart, USART_ISR_BUSY) == SET);
307+
/* make sure that UART is ready to receive
308+
* (test carried out again later in HAL_UARTEx_StopModeWakeUpSourceConfig) */
309+
while(__HAL_UART_GET_FLAG(WakeUpUart, USART_ISR_REACK) == RESET);
310+
311+
/* set the wake-up event:
312+
* specify wake-up on RXNE flag
313+
*/
314+
WakeUpSelection.WakeUpEvent = UART_WAKEUP_ON_READDATA_NONEMPTY;
315+
HAL_UARTEx_StopModeWakeUpSourceConfig(WakeUpUart, WakeUpSelection);
316+
317+
/* Enable the UART Wake UP from STOP1 mode Interrupt */
318+
__HAL_UART_ENABLE_IT(WakeUpUart, UART_IT_WUF);
319+
#else
320+
UNUSED(serial);
321+
#endif
322+
/* Save callback */
323+
WakeUpUartCb = FuncPtr;
324+
}
325+
326+
#ifdef __cplusplus
327+
}
328+
#endif
329+
330+
#endif /* HAL_PWR_MODULE_ENABLED */
331+
332+
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

0 commit comments

Comments
 (0)