Skip to content

Commit 0eba6c9

Browse files
committed
STM32 LPTICKER update for targets supporting RTC
1 parent 9b8dd34 commit 0eba6c9

File tree

3 files changed

+104
-81
lines changed

3 files changed

+104
-81
lines changed

targets/TARGET_STM/lp_ticker.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,8 @@ static void LPTIM1_IRQHandler(void)
173173
/* Clear Compare match flag */
174174
__HAL_LPTIM_CLEAR_FLAG(&LptimHandle, LPTIM_FLAG_CMPM);
175175

176-
if (irq_handler) {
177-
irq_handler();
176+
if (irq_handler) {
177+
irq_handler();
178178
}
179179
}
180180
}
@@ -240,28 +240,35 @@ void lp_ticker_clear_interrupt(void)
240240
#else /* MBED_CONF_TARGET_LPTICKER_LPTIM */
241241

242242
#include "rtc_api_hal.h"
243+
244+
const ticker_info_t* lp_ticker_get_info()
245+
{
246+
static const ticker_info_t info = {
247+
RTC_CLOCK/4, // RTC_WAKEUPCLOCK_RTCCLK_DIV4
248+
32
249+
};
250+
return &info;
251+
}
252+
243253
void lp_ticker_init(void)
244254
{
245255
rtc_init();
256+
lp_ticker_disable_interrupt();
246257
}
247258

248259
uint32_t lp_ticker_read(void)
249260
{
250-
uint32_t usecs = rtc_read_us();
251-
return usecs;
261+
return rtc_read_lp();
252262
}
253263

254264
void lp_ticker_set_interrupt(timestamp_t timestamp)
255265
{
256-
uint32_t delta;
257-
258-
delta = timestamp - lp_ticker_read();
259-
rtc_set_wake_up_timer(delta);
266+
rtc_set_wake_up_timer(timestamp);
260267
}
261268

262269
void lp_ticker_fire_interrupt(void)
263270
{
264-
NVIC_SetPendingIRQ(RTC_WKUP_IRQn);
271+
rtc_fire_interrupt();
265272
}
266273

267274
void lp_ticker_disable_interrupt(void)
@@ -271,7 +278,7 @@ void lp_ticker_disable_interrupt(void)
271278

272279
void lp_ticker_clear_interrupt(void)
273280
{
274-
NVIC_ClearPendingIRQ(RTC_WKUP_IRQn);
281+
NVIC_DisableIRQ(RTC_WKUP_IRQn);
275282
}
276283

277284
#endif /* MBED_CONF_TARGET_LPTICKER_LPTIM */

targets/TARGET_STM/rtc_api.c

Lines changed: 62 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,6 @@
3636

3737
static RTC_HandleTypeDef RtcHandle;
3838

39-
#if DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM
40-
41-
#define GET_TICK_PERIOD(VALUE) (2048 * 1000000 / VALUE) /* 1s / SynchPrediv value * 2^11 (value to get the maximum precision value with no u32 overflow) */
42-
43-
static void (*irq_handler)(void);
44-
static void RTC_IRQHandler(void);
45-
static uint32_t lp_TickPeriod_us = GET_TICK_PERIOD(4095); /* default SynchPrediv value = 4095 */
46-
#endif /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */
47-
4839
void rtc_init(void)
4940
{
5041
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
@@ -119,10 +110,6 @@ void rtc_init(void)
119110
RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
120111
#endif /* TARGET_STM32F1 */
121112

122-
#if DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM
123-
lp_TickPeriod_us = GET_TICK_PERIOD(RtcHandle.Init.SynchPrediv);
124-
#endif
125-
126113
if (HAL_RTC_Init(&RtcHandle) != HAL_OK) {
127114
error("RTC initialization failed");
128115
}
@@ -288,18 +275,41 @@ void rtc_synchronize(void)
288275

289276
#if DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM
290277

278+
static void RTC_IRQHandler(void);
279+
static void (*irq_handler)(void);
280+
281+
volatile uint8_t lp_Fired = 0;
282+
volatile uint32_t LP_continuous_time = 0;
283+
volatile uint32_t LP_last_RTC_time = 0;
284+
291285
static void RTC_IRQHandler(void)
292286
{
293287
/* Update HAL state */
294288
RtcHandle.Instance = RTC;
295-
HAL_RTCEx_WakeUpTimerIRQHandler(&RtcHandle);
296-
/* In case of registered handler, call it. */
297-
if (irq_handler) {
298-
irq_handler();
289+
if(__HAL_RTC_WAKEUPTIMER_GET_IT(&RtcHandle, RTC_IT_WUT)) {
290+
/* Get the status of the Interrupt */
291+
if((uint32_t)(RTC->CR & RTC_IT_WUT) != (uint32_t)RESET) {
292+
/* Clear the WAKEUPTIMER interrupt pending bit */
293+
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&RtcHandle, RTC_FLAG_WUTF);
294+
295+
lp_Fired = 0;
296+
if (irq_handler) {
297+
irq_handler();
298+
}
299+
}
299300
}
301+
302+
if (lp_Fired) {
303+
lp_Fired = 0;
304+
if (irq_handler) {
305+
irq_handler();
306+
}
307+
}
308+
309+
__HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG();
300310
}
301311

302-
uint32_t rtc_read_us(void)
312+
uint32_t rtc_read_lp(void)
303313
{
304314
RTC_TimeTypeDef timeStruct = {0};
305315
RTC_DateTypeDef dateStruct = {0};
@@ -316,52 +326,52 @@ uint32_t rtc_read_us(void)
316326
time/date is one second less than as indicated by RTC_TR/RTC_DR. */
317327
timeStruct.Seconds -= 1;
318328
}
319-
uint32_t RTCTime = timeStruct.Seconds + timeStruct.Minutes * 60 + timeStruct.Hours * 60 * 60;
320-
uint32_t Time_us = ((timeStruct.SecondFraction - timeStruct.SubSeconds) * lp_TickPeriod_us) >> 11;
329+
uint32_t RTC_time_s = timeStruct.Seconds + timeStruct.Minutes * 60 + timeStruct.Hours * 60 * 60; // Max 0x0001-517F => * 8191 + 8191 = 0x2A2E-AE80
321330

322-
return (RTCTime * 1000000) + Time_us ;
331+
if (LP_last_RTC_time <= RTC_time_s) {
332+
LP_continuous_time += (RTC_time_s - LP_last_RTC_time);
333+
} else {
334+
LP_continuous_time += (24 * 60 * 60 + RTC_time_s - LP_last_RTC_time);
335+
}
336+
LP_last_RTC_time = RTC_time_s;
337+
338+
return LP_continuous_time * PREDIV_S_VALUE + timeStruct.SecondFraction - timeStruct.SubSeconds;
323339
}
324340

325-
void rtc_set_wake_up_timer(uint32_t delta)
341+
void rtc_set_wake_up_timer(timestamp_t timestamp)
326342
{
327-
#define RTC_CLOCK_US (((uint64_t)RTC_CLOCK << 32 ) / 1000000)
328-
329343
uint32_t WakeUpCounter;
330-
uint32_t WakeUpClock;
331-
332-
/* Ex for Wakeup period resolution with RTCCLK=32768 Hz :
333-
* RTCCLK_DIV2: ~122us < wakeup period < ~4s
334-
* RTCCLK_DIV4: ~244us < wakeup period < ~8s
335-
* RTCCLK_DIV8: ~488us < wakeup period < ~16s
336-
* RTCCLK_DIV16: ~976us < wakeup period < ~32s
337-
* CK_SPRE_16BITS: 1s < wakeup period < (0xFFFF+ 1) x 1 s = 65536 s (18 hours)
338-
* CK_SPRE_17BITS: 18h+1s < wakeup period < (0x1FFFF+ 1) x 1 s = 131072 s (36 hours)
339-
*/
340-
if (delta < (0x10000 * 2 / RTC_CLOCK * 1000000) ) { // (0xFFFF + 1) * RTCCLK_DIV2 / RTC_CLOCK * 1s
341-
WakeUpCounter = (((uint64_t)delta * RTC_CLOCK_US) >> 32) >> 1 ;
342-
WakeUpClock = RTC_WAKEUPCLOCK_RTCCLK_DIV2;
343-
} else if (delta < (0x10000 * 4 / RTC_CLOCK * 1000000) ) {
344-
WakeUpCounter = (((uint64_t)delta * RTC_CLOCK_US) >> 32) >> 2 ;
345-
WakeUpClock = RTC_WAKEUPCLOCK_RTCCLK_DIV4;
346-
} else if (delta < (0x10000 * 8 / RTC_CLOCK * 1000000) ) {
347-
WakeUpCounter = (((uint64_t)delta * RTC_CLOCK_US) >> 32) >> 3 ;
348-
WakeUpClock = RTC_WAKEUPCLOCK_RTCCLK_DIV8;
349-
} else if (delta < (0x10000 * 16 / RTC_CLOCK * 1000000) ) {
350-
WakeUpCounter = (((uint64_t)delta * RTC_CLOCK_US) >> 32) >> 4 ;
351-
WakeUpClock = RTC_WAKEUPCLOCK_RTCCLK_DIV16;
344+
uint32_t current_lp_time;
345+
346+
current_lp_time = rtc_read_lp();
347+
348+
if (timestamp < current_lp_time) {
349+
WakeUpCounter = 0xFFFFFFFF - current_lp_time + timestamp;
352350
} else {
353-
WakeUpCounter = (delta / 1000000) ;
354-
WakeUpClock = RTC_WAKEUPCLOCK_CK_SPRE_16BITS;
351+
WakeUpCounter = timestamp - current_lp_time;
355352
}
356353

357-
irq_handler = (void (*)(void))lp_ticker_irq_handler;
358-
NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler);
359-
NVIC_EnableIRQ(RTC_WKUP_IRQn);
354+
if (WakeUpCounter > 0xFFFF) {
355+
WakeUpCounter = 0xFFFF;
356+
}
360357

361358
RtcHandle.Instance = RTC;
362-
if (HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, (uint32_t)WakeUpCounter, WakeUpClock) != HAL_OK) {
359+
if (HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, WakeUpCounter, RTC_WAKEUPCLOCK_RTCCLK_DIV4) != HAL_OK) {
363360
error("rtc_set_wake_up_timer init error\n");
364361
}
362+
363+
NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler);
364+
irq_handler = (void (*)(void))lp_ticker_irq_handler;
365+
NVIC_EnableIRQ(RTC_WKUP_IRQn);
366+
}
367+
368+
void rtc_fire_interrupt(void)
369+
{
370+
lp_Fired = 1;
371+
NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler);
372+
irq_handler = (void (*)(void))lp_ticker_irq_handler;
373+
NVIC_SetPendingIRQ(RTC_WKUP_IRQn);
374+
NVIC_EnableIRQ(RTC_WKUP_IRQn);
365375
}
366376

367377
void rtc_deactivate_wake_up_timer(void)

targets/TARGET_STM/rtc_api_hal.h

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -44,45 +44,51 @@ extern "C" {
4444
#define RTC_CLOCK LSI_VALUE
4545
#endif
4646

47-
/* PREDIV_A : 7-bit asynchronous prescaler */
48-
/* PREDIV_S : 15-bit synchronous prescaler */
49-
/* PREDIV_S is set in order to get a 1 Hz clock */
5047
#if DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM
51-
/* PREDIV_A is set to a small value to improve the SubSeconds resolution */
52-
/* with a 32768Hz clock, PREDIV_A=7 gives a precision of 244us */
53-
#define PREDIV_A_VALUE 7
54-
#else /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */
55-
/* PREDIV_A is set to the maximum value to improve the consumption */
56-
#define PREDIV_A_VALUE 127
57-
#endif /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */
58-
59-
#define PREDIV_S_VALUE RTC_CLOCK / (PREDIV_A_VALUE + 1) - 1
48+
/* PREDIV_A : 7-bit asynchronous prescaler */
49+
/* PREDIV_A is set to set LPTICKER frequency to RTC_CLOCK/4 */
50+
#define PREDIV_A_VALUE 3
6051

61-
/** Read RTC time with subsecond precision.
52+
/** Read RTC counter with sub second precision
6253
*
63-
* @return Time is microsecond
54+
* @return LP ticker counter
6455
*/
65-
uint32_t rtc_read_us(void);
56+
uint32_t rtc_read_lp(void);
6657

67-
/** Program a wake up timer event in delta microseconds.
58+
/** Program a wake up timer event
6859
*
69-
* @param delta The time to wait
60+
* @param timestamp: counter to set
7061
*/
71-
void rtc_set_wake_up_timer(uint32_t delta);
62+
void rtc_set_wake_up_timer(timestamp_t timestamp);
63+
64+
/** Call RTC Wake Up IT
65+
*/
66+
void rtc_fire_interrupt(void);
7267

7368
/** Disable the wake up timer event.
7469
*
7570
* The wake up timer use auto reload, you have to deactivate it manually.
7671
*/
7772
void rtc_deactivate_wake_up_timer(void);
7873

74+
#else /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */
75+
76+
/* PREDIV_A : 7-bit asynchronous prescaler */
77+
/* PREDIV_A is set to the maximum value to improve the consumption */
78+
#define PREDIV_A_VALUE 127
79+
80+
#endif /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */
81+
82+
/* PREDIV_S : 15-bit synchronous prescaler */
83+
/* PREDIV_S is set in order to get a 1 Hz clock */
84+
#define PREDIV_S_VALUE RTC_CLOCK / (PREDIV_A_VALUE + 1) - 1
85+
7986
/** Synchronise the RTC shadow registers.
8087
*
8188
* Must be called after a deepsleep.
8289
*/
8390
void rtc_synchronize(void);
8491

85-
8692
#ifdef __cplusplus
8793
}
8894
#endif

0 commit comments

Comments
 (0)