Skip to content

Commit 22c8dc5

Browse files
committed
Merge pull request stm32duino#183 from fprwi6labs/add_lowPower_driver into quakesense
Add LowPower driver and fix some conflicts in cores/arduino/stm32/uart.c
2 parents 2415879 + f418e3c commit 22c8dc5

File tree

7 files changed

+450
-16
lines changed

7 files changed

+450
-16
lines changed

cores/arduino/HardwareSerial.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -380,5 +380,6 @@ void HardwareSerial::setRx(PinName _rx) {
380380
void HardwareSerial::setTx(PinName _tx){
381381
_serial.pin_tx = _tx;
382382
}
383+
383384
#endif // HAVE_HWSERIALx
384385
#endif // !NO_HWSERIAL

cores/arduino/HardwareSerial.h

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ class HardwareSerial : public Stream
125125
void setRx(PinName _rx);
126126
void setTx(PinName _tx);
127127

128+
friend class STM32LowPower;
129+
128130
// Interrupt handlers
129131
static void _rx_complete_irq(serial_t* obj);
130132
static int _tx_complete_irq(serial_t* obj);

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 "LowPower.h"
1718
#include "spi_com.h"
1819
#include "stm32_eeprom.h"
1920
#include "timer.h"

cores/arduino/stm32/LowPower.c

+327
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,327 @@
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 "LowPower.h"
41+
42+
#ifdef HAL_PWR_MODULE_ENABLED
43+
44+
#ifdef __cplusplus
45+
extern "C" {
46+
#endif
47+
48+
// NOTE: is these pins are common to a MCU family?
49+
/* Wakeup pins list. Allow to know which pins can be used as wake up pin in
50+
standby or shutdown mode */
51+
#if defined(STM32L053xx)
52+
const PinMap PinMap_WKUP[] = {
53+
{PA_0, NP, 1}, //WKUP1
54+
{PC_13, NP, 2}, //WKUP2
55+
{NC, NP, 0}
56+
};
57+
#elif defined(STM32L476xx)
58+
const PinMap PinMap_WKUP[] = {
59+
{PA_0, NP, 1}, //WKUP1
60+
{PC_13, NP, 2}, //WKUP2
61+
{PE_6, NP, 3}, //WKUP3
62+
{PA_2, NP, 4}, //WKUP4
63+
{PC_5, NP, 5}, //WKUP5
64+
{NC, NP, 0}
65+
};
66+
#endif
67+
68+
// Save UART handler for callback
69+
static UART_HandleTypeDef* WakeUpUart = NULL;
70+
// Save callback pointer
71+
static void (*WakeUpUartCb)( void ) = NULL;
72+
73+
/**
74+
* @brief Initialize low power mode
75+
* @param None
76+
* @retval None
77+
*/
78+
void LowPower_init(){
79+
/* Enable Power Clock */
80+
__HAL_RCC_PWR_CLK_ENABLE();
81+
82+
/* Ensure that HSI is wake-up system clock */
83+
__HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI);
84+
85+
/* Check if the system was resumed from StandBy mode */
86+
if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB) != RESET)
87+
{
88+
/* Clear Standby flag */
89+
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
90+
}
91+
92+
/* Clear all related wakeup flags */
93+
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
94+
}
95+
96+
/**
97+
* @brief Configure a pin as wakeup source if compatible.
98+
* @param pin: pin to configure
99+
* @param mode: pin mode (edge or state). The configuration have to be compatible.
100+
* @retval None
101+
*/
102+
void LowPower_EnableWakeUpPin(uint32_t pin, uint32_t mode) {
103+
#ifndef STM32L4xx
104+
UNUSED(mode);
105+
#endif
106+
PinName p = digitalPinToPinName(pin);
107+
uint32_t wupPin = pinmap_find_function(p, PinMap_WKUP);
108+
switch (wupPin) {
109+
#ifdef PWR_WAKEUP_PIN1
110+
case 1 :
111+
#ifdef STM32L4xx
112+
if (mode == RISING) {
113+
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1_HIGH);
114+
}
115+
else {
116+
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1_LOW);
117+
}
118+
#else
119+
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
120+
#endif
121+
break;
122+
#endif //PWR_WAKEUP_PIN1
123+
#ifdef PWR_WAKEUP_PIN2
124+
case 2 :
125+
#ifdef STM32L4xx
126+
if (mode == RISING) {
127+
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN2_HIGH);
128+
}
129+
else {
130+
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN2_LOW);
131+
}
132+
#else
133+
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN2);
134+
#endif
135+
break;
136+
#endif //PWR_WAKEUP_PIN2
137+
#ifdef PWR_WAKEUP_PIN3
138+
case 3 :
139+
#ifdef STM32L4xx
140+
if (mode == RISING) {
141+
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN3_HIGH);
142+
}
143+
else {
144+
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN3_LOW);
145+
}
146+
#else
147+
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN3);
148+
#endif
149+
break;
150+
#endif //PWR_WAKEUP_PIN3
151+
#ifdef PWR_WAKEUP_PIN4
152+
case 4 :
153+
#ifdef STM32L4xx
154+
if (mode == RISING) {
155+
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN4_HIGH);
156+
}
157+
else {
158+
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN4_LOW);
159+
}
160+
#else
161+
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN4);
162+
#endif
163+
break;
164+
#endif //PWR_WAKEUP_PIN4
165+
#ifdef PWR_WAKEUP_PIN5
166+
case 5 :
167+
#ifdef STM32L4xx
168+
if (mode == RISING) {
169+
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN5_HIGH);
170+
}
171+
else {
172+
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN5_LOW);
173+
}
174+
#else
175+
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN5);
176+
#endif
177+
break;
178+
#endif //PWR_WAKEUP_PIN5
179+
default :
180+
break;
181+
}
182+
}
183+
184+
/**
185+
* @brief Enable the sleep mode.
186+
* @param None
187+
* @retval None
188+
*/
189+
void LowPower_sleep(uint32_t regulator){
190+
__disable_irq();
191+
/*Suspend Tick increment to prevent wakeup by Systick interrupt.
192+
Otherwise the Systick interrupt will wake up the device within 1ms (HAL time base)*/
193+
HAL_SuspendTick();
194+
195+
/* Enter Sleep Mode , wake up is done once User push-button is pressed */
196+
HAL_PWR_EnterSLEEPMode(regulator, PWR_SLEEPENTRY_WFI);
197+
198+
/* Resume Tick interrupt if disabled prior to SLEEP mode entry */
199+
HAL_ResumeTick();
200+
__enable_irq();
201+
202+
if (WakeUpUartCb != NULL) {
203+
WakeUpUartCb();
204+
}
205+
}
206+
207+
/**
208+
* @brief Enable the stop mode.
209+
* @param None
210+
* @retval None
211+
*/
212+
void LowPower_stop(){
213+
__disable_irq();
214+
215+
#if STM32L4xx
216+
if (WakeUpUart != NULL) {
217+
HAL_UARTEx_EnableStopMode(WakeUpUart);
218+
}
219+
#endif
220+
221+
#ifdef STM32L0xx
222+
/* Enable Ultra low power mode */
223+
HAL_PWREx_EnableUltraLowPower();
224+
225+
/* Enable the fast wake up from Ultra low power mode */
226+
HAL_PWREx_EnableFastWakeUp();
227+
228+
/* Select HSI as system clock source after Wake Up from Stop mode */
229+
__HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI);
230+
#endif
231+
232+
// Enter Stop mode
233+
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
234+
235+
// Exit Stop mode reset clocks
236+
SystemClock_Config();
237+
__enable_irq();
238+
239+
#if STM32L4xx
240+
if (WakeUpUart != NULL) {
241+
HAL_UARTEx_DisableStopMode(WakeUpUart);
242+
243+
if (WakeUpUartCb != NULL) {
244+
WakeUpUartCb();
245+
}
246+
}
247+
#endif
248+
}
249+
250+
/**
251+
* @brief Enable the standby mode. The board reset when leaves this mode.
252+
* @param None
253+
* @retval None
254+
*/
255+
void LowPower_standby(){
256+
__disable_irq();
257+
258+
#ifdef STM32L0xx
259+
/* Enable Ultra low power mode */
260+
HAL_PWREx_EnableUltraLowPower();
261+
262+
/* Enable the fast wake up from Ultra low power mode */
263+
HAL_PWREx_EnableFastWakeUp();
264+
#endif
265+
266+
HAL_PWR_EnterSTANDBYMode();
267+
}
268+
269+
/**
270+
* @brief Enable the shutdown mode.The board reset when leaves this mode.
271+
* If shutdown mode not available, use standby mode instead.
272+
* @param None
273+
* @retval None
274+
*/
275+
void LowPower_shutdown(){
276+
__disable_irq();
277+
#ifdef STM32L4xx
278+
// LSE must be on to use shutdown mode
279+
if(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == SET) {
280+
HAL_PWREx_EnterSHUTDOWNMode();
281+
} else {
282+
LowPower_standby();
283+
}
284+
#else
285+
LowPower_standby();
286+
#endif
287+
}
288+
289+
/**
290+
* @brief Configure the UART as a wakeup source. A callback can be called when
291+
* the chip leaves the low power mode. See board datasheet to check
292+
* with which low power mode the UART is compatible.
293+
* @param serial: pointer to serial
294+
* @param FuncPtr: pointer to callback
295+
* @retval None
296+
*/
297+
void LowPower_EnableWakeUpUart(serial_t* serial, void (*FuncPtr)( void ) ) {
298+
UART_WakeUpTypeDef WakeUpSelection;
299+
300+
// Save Uart handler
301+
WakeUpUart = &(serial->handle);
302+
303+
// Save callback
304+
WakeUpUartCb = FuncPtr;
305+
306+
/* make sure that no UART transfer is on-going */
307+
while(__HAL_UART_GET_FLAG(WakeUpUart, USART_ISR_BUSY) == SET);
308+
/* make sure that UART is ready to receive
309+
* (test carried out again later in HAL_UARTEx_StopModeWakeUpSourceConfig) */
310+
while(__HAL_UART_GET_FLAG(WakeUpUart, USART_ISR_REACK) == RESET);
311+
312+
/* set the wake-up event:
313+
* specify wake-up on RXNE flag */
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+
}
320+
321+
#ifdef __cplusplus
322+
}
323+
#endif
324+
325+
#endif // HAL_PWR_MODULE_ENABLED
326+
327+
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

0 commit comments

Comments
 (0)