Skip to content

Commit da43d65

Browse files
authored
Merge pull request #5459 from jeromecoutant/PR_LPT_RTC
STM32 Low Power Timer feature updates
2 parents ef44e4b + 17a5484 commit da43d65

File tree

5 files changed

+125
-102
lines changed

5 files changed

+125
-102
lines changed

targets/TARGET_STM/lp_ticker.c

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* mbed Microcontroller Library
22
*******************************************************************************
3-
* Copyright (c) 2016, STMicroelectronics
3+
* Copyright (c) 2017, STMicroelectronics
44
* All rights reserved.
55
*
66
* Redistribution and use in source and binary forms, with or without
@@ -31,29 +31,18 @@
3131

3232
#if DEVICE_LOWPOWERTIMER
3333

34-
#include "ticker_api.h"
35-
#include "lp_ticker_api.h"
36-
#include "rtc_api.h"
3734
#include "rtc_api_hal.h"
3835

39-
static uint8_t lp_ticker_inited = 0;
40-
4136
void lp_ticker_init(void)
4237
{
43-
if (lp_ticker_inited) return;
44-
lp_ticker_inited = 1;
45-
4638
rtc_init();
47-
rtc_set_irq_handler((uint32_t) lp_ticker_irq_handler);
4839
}
4940

5041
uint32_t lp_ticker_read(void)
5142
{
5243
uint32_t usecs = 0;
5344
time_t time = 0;
5445

55-
lp_ticker_init();
56-
5746
do {
5847
time = rtc_read();
5948
usecs = rtc_read_subseconds();
@@ -82,7 +71,7 @@ void lp_ticker_disable_interrupt(void)
8271

8372
void lp_ticker_clear_interrupt(void)
8473
{
85-
74+
NVIC_ClearPendingIRQ(RTC_WKUP_IRQn);
8675
}
8776

88-
#endif
77+
#endif /* DEVICE_LOWPOWERTIMER */

targets/TARGET_STM/rtc_api.c

Lines changed: 77 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* mbed Microcontroller Library
22
*******************************************************************************
3-
* Copyright (c) 2016, STMicroelectronics
3+
* Copyright (c) 2017, STMicroelectronics
44
* All rights reserved.
55
*
66
* Redistribution and use in source and binary forms, with or without
@@ -27,29 +27,15 @@
2727
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2828
*******************************************************************************
2929
*/
30+
3031
#if DEVICE_RTC
3132

32-
#include "rtc_api.h"
3333
#include "rtc_api_hal.h"
3434
#include "mbed_error.h"
3535
#include "mbed_mktime.h"
3636

3737
static RTC_HandleTypeDef RtcHandle;
3838

39-
#if RTC_LSI
40-
#define RTC_CLOCK LSI_VALUE
41-
#else
42-
#define RTC_CLOCK LSE_VALUE
43-
#endif
44-
45-
#if DEVICE_LOWPOWERTIMER
46-
#define RTC_ASYNCH_PREDIV ((RTC_CLOCK - 1) / 0x8000)
47-
#define RTC_SYNCH_PREDIV (RTC_CLOCK / (RTC_ASYNCH_PREDIV + 1) - 1)
48-
#else
49-
#define RTC_ASYNCH_PREDIV (0x007F)
50-
#define RTC_SYNCH_PREDIV (RTC_CLOCK / (RTC_ASYNCH_PREDIV + 1) - 1)
51-
#endif
52-
5339
#if DEVICE_LOWPOWERTIMER
5440
static void (*irq_handler)(void);
5541
static void RTC_IRQHandler(void);
@@ -61,38 +47,38 @@ void rtc_init(void)
6147
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
6248

6349
// Enable access to Backup domain
50+
__HAL_RCC_PWR_CLK_ENABLE();
6451
HAL_PWR_EnableBkUpAccess();
6552

66-
RtcHandle.Instance = RTC;
67-
RtcHandle.State = HAL_RTC_STATE_RESET;
53+
if (rtc_isenabled()) {
54+
return;
55+
}
6856

69-
#if !RTC_LSI
70-
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
57+
#if MBED_CONF_TARGET_LSE_AVAILABLE
58+
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_LSE;
7159
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; // Mandatory, otherwise the PLL is reconfigured!
7260
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
7361
RCC_OscInitStruct.LSIState = RCC_LSI_OFF;
7462

75-
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) == HAL_OK) {
76-
__HAL_RCC_RTC_CLKPRESCALER(RCC_RTCCLKSOURCE_LSE);
77-
__HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE);
78-
} else {
63+
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
7964
error("Cannot initialize RTC with LSE\n");
8065
}
8166

67+
__HAL_RCC_RTC_CLKPRESCALER(RCC_RTCCLKSOURCE_LSE);
68+
__HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE);
69+
8270
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
8371
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
8472
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
8573
error("PeriphClkInitStruct RTC failed with LSE\n");
8674
}
87-
#else /* !RTC_LSI */
88-
__HAL_RCC_PWR_CLK_ENABLE();
89-
75+
#else /* MBED_CONF_TARGET_LSE_AVAILABLE */
9076
// Reset Backup domain
9177
__HAL_RCC_BACKUPRESET_FORCE();
9278
__HAL_RCC_BACKUPRESET_RELEASE();
9379

9480
// Enable LSI clock
95-
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI;
81+
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_LSE;
9682
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; // Mandatory, otherwise the PLL is reconfigured!
9783
RCC_OscInitStruct.LSEState = RCC_LSE_OFF;
9884
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
@@ -108,46 +94,50 @@ void rtc_init(void)
10894
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
10995
error("PeriphClkInitStruct RTC failed with LSI\n");
11096
}
111-
#endif /* !RTC_LSI */
97+
#endif /* MBED_CONF_TARGET_LSE_AVAILABLE */
11298

11399
// Enable RTC
114100
__HAL_RCC_RTC_ENABLE();
115101

102+
RtcHandle.Instance = RTC;
103+
RtcHandle.State = HAL_RTC_STATE_RESET;
104+
116105
#if TARGET_STM32F1
117106
RtcHandle.Init.AsynchPrediv = RTC_AUTO_1_SECOND;
118107
#else /* TARGET_STM32F1 */
119108
RtcHandle.Init.HourFormat = RTC_HOURFORMAT_24;
120-
RtcHandle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV;
121-
RtcHandle.Init.SynchPrediv = RTC_SYNCH_PREDIV;
109+
110+
/* PREDIV_A : 7-bit asynchronous prescaler */
111+
#if DEVICE_LOWPOWERTIMER
112+
/* PREDIV_A is set to a small value to improve the SubSeconds resolution */
113+
/* with a 32768Hz clock, PREDIV_A=7 gives a precision of 244us */
114+
RtcHandle.Init.AsynchPrediv = 7;
115+
#else
116+
/* PREDIV_A is set to the maximum value to improve the consumption */
117+
RtcHandle.Init.AsynchPrediv = 0x007F;
118+
#endif
119+
/* PREDIV_S : 15-bit synchronous prescaler */
120+
/* PREDIV_S is set in order to get a 1 Hz clock */
121+
RtcHandle.Init.SynchPrediv = RTC_CLOCK / (RtcHandle.Init.AsynchPrediv + 1) - 1;
122122
RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE;
123123
RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
124124
RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
125125
#endif /* TARGET_STM32F1 */
126126

127127
if (HAL_RTC_Init(&RtcHandle) != HAL_OK) {
128-
error("RTC error: RTC initialization failed.");
128+
error("RTC initialization failed");
129129
}
130130

131-
#if DEVICE_LOWPOWERTIMER
131+
rtc_synchronize(); // Wait for RSF
132132

133-
#if !RTC_LSI
134-
if (!rtc_isenabled())
135-
#endif /* !RTC_LSI */
136-
{
133+
if (!rtc_isenabled()) {
137134
rtc_write(0);
138135
}
139-
140-
NVIC_ClearPendingIRQ(RTC_WKUP_IRQn);
141-
NVIC_DisableIRQ(RTC_WKUP_IRQn);
142-
NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler);
143-
NVIC_EnableIRQ(RTC_WKUP_IRQn);
144-
145-
#endif /* DEVICE_LOWPOWERTIMER */
146136
}
147137

148138
void rtc_free(void)
149139
{
150-
#if RTC_LSI
140+
#if !MBED_CONF_TARGET_LSE_AVAILABLE
151141
// Enable Power clock
152142
__HAL_RCC_PWR_CLK_ENABLE();
153143

@@ -279,8 +269,12 @@ void rtc_write(time_t t)
279269
#endif /* TARGET_STM32F1 */
280270

281271
// Change the RTC current date/time
282-
HAL_RTC_SetDate(&RtcHandle, &dateStruct, RTC_FORMAT_BIN);
283-
HAL_RTC_SetTime(&RtcHandle, &timeStruct, RTC_FORMAT_BIN);
272+
if (HAL_RTC_SetDate(&RtcHandle, &dateStruct, RTC_FORMAT_BIN) != HAL_OK) {
273+
error("HAL_RTC_SetDate error\n");
274+
}
275+
if (HAL_RTC_SetTime(&RtcHandle, &timeStruct, RTC_FORMAT_BIN) != HAL_OK) {
276+
error("HAL_RTC_SetTime error\n");
277+
}
284278
}
285279

286280
int rtc_isenabled(void)
@@ -292,6 +286,13 @@ int rtc_isenabled(void)
292286
#endif /* TARGET_STM32F1 */
293287
}
294288

289+
void rtc_synchronize(void)
290+
{
291+
if (HAL_RTC_WaitForSynchro(&RtcHandle) != HAL_OK) {
292+
error("rtc_synchronize error\n");
293+
}
294+
}
295+
295296
#if DEVICE_LOWPOWERTIMER
296297

297298
static void RTC_IRQHandler(void)
@@ -304,23 +305,42 @@ static void RTC_IRQHandler(void)
304305
}
305306
}
306307

307-
void rtc_set_irq_handler(uint32_t handler)
308-
{
309-
irq_handler = (void (*)(void))handler;
310-
}
311-
312308
uint32_t rtc_read_subseconds(void)
313309
{
314-
return 1000000.f * ((double)(RTC_SYNCH_PREDIV - RTC->SSR) / (RTC_SYNCH_PREDIV + 1));
310+
return 1000000.f * ((double)((RTC->PRER & RTC_PRER_PREDIV_S) - RTC->SSR) / ((RTC->PRER & RTC_PRER_PREDIV_S) + 1));
315311
}
316312

317313
void rtc_set_wake_up_timer(uint32_t delta)
318314
{
319-
uint32_t wake_up_counter = delta / (2000000 / RTC_CLOCK);
315+
/* Ex for Wakeup period resolution with RTCCLK=32768 Hz :
316+
* RTCCLK_DIV2: ~122us < wakeup period < ~4s
317+
* RTCCLK_DIV4: ~244us < wakeup period < ~8s
318+
* RTCCLK_DIV8: ~488us < wakeup period < ~16s
319+
* RTCCLK_DIV16: ~976us < wakeup period < ~32s
320+
* CK_SPRE_16BITS: 1s < wakeup period < (0xFFFF+ 1) x 1 s = 65536 s (18 hours)
321+
* CK_SPRE_17BITS: 18h+1s < wakeup period < (0x1FFFF+ 1) x 1 s = 131072 s (36 hours)
322+
*/
323+
uint32_t WakeUpClock[6] = {RTC_WAKEUPCLOCK_RTCCLK_DIV2, RTC_WAKEUPCLOCK_RTCCLK_DIV4, RTC_WAKEUPCLOCK_RTCCLK_DIV8, RTC_WAKEUPCLOCK_RTCCLK_DIV16, RTC_WAKEUPCLOCK_CK_SPRE_16BITS, RTC_WAKEUPCLOCK_CK_SPRE_17BITS};
324+
uint8_t ClockDiv[4] = {2, 4, 8, 16};
325+
uint32_t WakeUpCounter;
326+
uint8_t DivIndex = 0;
327+
328+
do {
329+
WakeUpCounter = delta / (ClockDiv[DivIndex] * 1000000 / RTC_CLOCK);
330+
DivIndex++;
331+
} while ( (WakeUpCounter > 0xFFFF) && (DivIndex < 4) );
332+
333+
if (WakeUpCounter > 0xFFFF) {
334+
WakeUpCounter = delta / 1000000;
335+
DivIndex++;
336+
}
320337

321-
if (HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, wake_up_counter,
322-
RTC_WAKEUPCLOCK_RTCCLK_DIV2) != HAL_OK) {
323-
error("Set wake up timer failed\n");
338+
irq_handler = (void (*)(void))lp_ticker_irq_handler;
339+
NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler);
340+
NVIC_EnableIRQ(RTC_WKUP_IRQn);
341+
342+
if (HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, 0xFFFF & WakeUpCounter, WakeUpClock[DivIndex-1]) != HAL_OK) {
343+
error("rtc_set_wake_up_timer init error (%d)\n", DivIndex);
324344
}
325345
}
326346

@@ -329,10 +349,6 @@ void rtc_deactivate_wake_up_timer(void)
329349
HAL_RTCEx_DeactivateWakeUpTimer(&RtcHandle);
330350
}
331351

332-
void rtc_synchronize(void)
333-
{
334-
HAL_RTC_WaitForSynchro(&RtcHandle);
335-
}
336352
#endif /* DEVICE_LOWPOWERTIMER */
337353

338354
#endif /* DEVICE_RTC */

targets/TARGET_STM/rtc_api_hal.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* mbed Microcontroller Library
22
*******************************************************************************
3-
* Copyright (c) 2016, STMicroelectronics
3+
* Copyright (c) 2017, STMicroelectronics
44
* All rights reserved.
55
*
66
* Redistribution and use in source and binary forms, with or without
@@ -33,19 +33,18 @@
3333

3434
#include <stdint.h>
3535
#include "rtc_api.h"
36+
#include "ticker_api.h"
37+
#include "lp_ticker_api.h"
3638

3739
#ifdef __cplusplus
3840
extern "C" {
3941
#endif
40-
/*
41-
* Extend rtc_api.h
42-
*/
4342

44-
/** Set the given function as handler of wakeup timer event.
45-
*
46-
* @param handler The function to set as handler
47-
*/
48-
void rtc_set_irq_handler(uint32_t handler);
43+
#if MBED_CONF_TARGET_LSE_AVAILABLE
44+
#define RTC_CLOCK LSE_VALUE
45+
#else
46+
#define RTC_CLOCK LSI_VALUE
47+
#endif
4948

5049
/** Read the subsecond register.
5150
*

targets/TARGET_STM/sleep.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,16 +68,16 @@ void hal_deepsleep(void)
6868
#if TARGET_STM32L4
6969
int pwrClockEnabled = __HAL_RCC_PWR_IS_CLK_ENABLED();
7070
int lowPowerModeEnabled = PWR->CR1 & PWR_CR1_LPR;
71-
71+
7272
if (!pwrClockEnabled) {
7373
__HAL_RCC_PWR_CLK_ENABLE();
7474
}
7575
if (lowPowerModeEnabled) {
7676
HAL_PWREx_DisableLowPowerRunMode();
7777
}
78-
78+
7979
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
80-
80+
8181
if (lowPowerModeEnabled) {
8282
HAL_PWREx_EnableLowPowerRunMode();
8383
}
@@ -101,8 +101,15 @@ void hal_deepsleep(void)
101101
TimMasterHandle.Instance = TIM_MST;
102102
__HAL_TIM_SET_COUNTER(&TimMasterHandle, EnterTimeUS);
103103

104-
#if DEVICE_LOWPOWERTIMER
105-
rtc_synchronize();
104+
#if DEVICE_RTC
105+
/* Wait for RTC RSF bit synchro if RTC is configured */
106+
#if (TARGET_STM32F2) || (TARGET_STM32F4) || (TARGET_STM32F7)
107+
if (READ_BIT(RCC->BDCR, RCC_BDCR_RTCSEL)) {
108+
#else /* (TARGET_STM32F2) || (TARGET_STM32F4) || (TARGET_STM32F7) */
109+
if (__HAL_RCC_GET_RTC_SOURCE()) {
110+
#endif /* (TARGET_STM32F2) || (TARGET_STM32F4) || (TARGET_STM32F7) */
111+
rtc_synchronize();
112+
}
106113
#endif
107114
}
108115

0 commit comments

Comments
 (0)