Skip to content

Commit a0dcaf7

Browse files
committed
[STM32L4xx] LowPowerTicker implementation
LowPowerTicker for STM32L4xx family is implemented using the RTC periodic unit functionality. For more informations please follow this document: * www.st.com/resource/en/application_note/dm00025071.pdf Change-Id: I4ab3a33dbdfb4061ce24f4b4db4986cf463b8568
1 parent b395dd5 commit a0dcaf7

File tree

3 files changed

+201
-1
lines changed

3 files changed

+201
-1
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#include "device.h"
2+
3+
#if DEVICE_LOWPOWERTIMER
4+
5+
#include "ticker_api.h"
6+
#include "lp_ticker_api.h"
7+
#include "rtc_api.h"
8+
#include "rtc_api_hal.h"
9+
10+
static uint8_t lp_ticker_inited = 0;
11+
static uint32_t m_timestamp = 0;
12+
static uint32_t m_offset = 0;
13+
14+
void lp_ticker_init() {
15+
/*
16+
* At this stage we don't have the users requested time.
17+
* This is only to cover the API implementation.
18+
*/
19+
}
20+
21+
uint32_t lp_ticker_read() {
22+
/*
23+
* Becuase our RTC has a periodic wake-up timer we just want to simply
24+
* return the desired timestamp value to configure RTC exactly with the value
25+
* provided by the user and to fulfill the mBed ticker architecture.
26+
*/
27+
return m_timestamp;
28+
}
29+
30+
void lp_ticker_set_interrupt(timestamp_t timestamp) {
31+
m_offset = timestamp;
32+
33+
if (lp_ticker_inited) return;
34+
lp_ticker_inited = 1;
35+
36+
rtc_periodic_ticker_init(timestamp);
37+
rtc_set_irq_handler((uint32_t) lp_ticker_irq_handler);
38+
}
39+
40+
void lp_ticker_disable_interrupt() {
41+
lp_ticker_inited = 0;
42+
rtc_periodic_ticker_disable_irq();
43+
}
44+
45+
void lp_ticker_clear_interrupt() {
46+
m_timestamp = m_offset;
47+
}
48+
49+
#endif

hal/targets/hal/TARGET_STM/TARGET_STM32L4/rtc_api.c

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
*******************************************************************************
2929
*/
3030
#include "rtc_api.h"
31+
#include "rtc_api_hal.h"
32+
#include "stm32l4xx.h"
33+
#include "stm32l4xx_hal_rtc_ex.h"
3134

3235
#if DEVICE_RTC
3336

@@ -38,9 +41,42 @@ static int rtc_inited = 0;
3841
#endif
3942

4043
static RTC_HandleTypeDef RtcHandle;
44+
static uint32_t m_synch_prediv;
4145

42-
void rtc_init(void)
46+
#if DEVICE_LOWPOWERTIMER
47+
static void (*irq_handler)(void);
48+
49+
static void rtc_calc_periodic_vals(float req_time, uint32_t *periodic_cnt)
50+
{
51+
uint16_t synch_div;
52+
float requested_time = (float)(req_time / 1000000);
53+
float ck;
54+
55+
/*
56+
* 38000 is LSI typical value. To be measured precisely using a timer input
57+
* capture for example.
58+
*/
59+
float freq = (DEVICE_RTC_LSI ? 38000 : LSE_VALUE);
60+
61+
for (synch_div = 0; synch_div < (int)freq; synch_div++)
62+
{
63+
ck = freq / ((synch_div + 1.0) * 128.0);
64+
*periodic_cnt = ck * requested_time;
65+
66+
if (*periodic_cnt < 0xFFFF) {
67+
break;
68+
}
69+
}
70+
m_synch_prediv = synch_div;
71+
}
72+
73+
void RTC_WKUP_IRQHandler()
4374
{
75+
HAL_RTCEx_WakeUpTimerIRQHandler(&RtcHandle);
76+
}
77+
#endif
78+
79+
void rtc_init(void) {
4480
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
4581
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
4682
uint32_t rtc_freq = 0;
@@ -104,7 +140,12 @@ void rtc_init(void)
104140

105141
RtcHandle.Init.HourFormat = RTC_HOURFORMAT_24;
106142
RtcHandle.Init.AsynchPrediv = 127;
143+
#if !DEVICE_LOWPOWERTIMER
107144
RtcHandle.Init.SynchPrediv = (rtc_freq / 128) - 1;
145+
#else
146+
RtcHandle.Init.SynchPrediv = m_synch_prediv;
147+
#endif
148+
108149
RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE;
109150
RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
110151
RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
@@ -229,4 +270,61 @@ void rtc_write(time_t t)
229270
HAL_RTC_SetTime(&RtcHandle, &timeStruct, RTC_FORMAT_BIN);
230271
}
231272

273+
#if DEVICE_LOWPOWERTIMER
274+
void rtc_set_irq_handler(uint32_t handler)
275+
{
276+
irq_handler = (void (*)(void)) handler;
277+
}
278+
279+
void rtc_periodic_ticker_init(uint32_t timestamp)
280+
{
281+
uint32_t periodic_counter;
282+
uint32_t rtcclk;
283+
HAL_StatusTypeDef ret;
284+
285+
/*
286+
* For more informations how WakeUp unit values were calculated please follow
287+
* this document: www.st.com/resource/en/application_note/dm00025071.pdf
288+
*/
289+
if (timestamp <= 4000000) {
290+
periodic_counter = timestamp / 61.035;
291+
rtcclk = RTC_WAKEUPCLOCK_RTCCLK_DIV2;
292+
m_synch_prediv = 0;
293+
} else {
294+
rtc_calc_periodic_vals((float)(timestamp), &periodic_counter);
295+
rtcclk = RTC_WAKEUPCLOCK_CK_SPRE_16BITS;
296+
}
297+
298+
rtc_init();
299+
300+
/*
301+
* For some reason we need to clear the wakeup time flag to able to start
302+
* the RTC periodic unit.
303+
*/
304+
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&RtcHandle, RTC_FLAG_WUTF);
305+
ret = HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, periodic_counter - 1, rtcclk);
306+
307+
if (ret != HAL_OK) {
308+
error("SetWakeUpTimer_IT failed!\n");
309+
}
310+
311+
NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t) &RTC_WKUP_IRQHandler);
312+
HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn);
313+
}
314+
315+
void rtc_periodic_ticker_disable_irq()
316+
{
317+
HAL_RTCEx_DeactivateWakeUpTimer(&RtcHandle);
318+
}
319+
320+
void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
321+
{
322+
if (irq_handler)
323+
{
324+
// Fire the user callback
325+
irq_handler();
326+
}
327+
}
328+
#endif // DEVICE_LOWPOWERTIMER
329+
232330
#endif
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/* mbed Microcontroller Library
2+
*******************************************************************************
3+
* Copyright (c) 2016, STMicroelectronics
4+
* All rights reserved.
5+
*
6+
* Redistribution and use in source and binary forms, with or without
7+
* modification, are permitted provided that the following conditions are met:
8+
*
9+
* 1. Redistributions of source code must retain the above copyright notice,
10+
* this list of conditions and the following disclaimer.
11+
* 2. Redistributions in binary form must reproduce the above copyright notice,
12+
* this list of conditions and the following disclaimer in the documentation
13+
* and/or other materials provided with the distribution.
14+
* 3. Neither the name of STMicroelectronics nor the names of its contributors
15+
* may be used to endorse or promote products derived from this software
16+
* without specific prior written permission.
17+
*
18+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28+
*******************************************************************************
29+
*/
30+
31+
#ifndef MBED_RTC_API_HAL_H
32+
#define MBED_RTC_API_HAL_H
33+
34+
#include <stdint.h>
35+
#include "rtc_api.h"
36+
37+
#ifdef __cplusplus
38+
extern "C" {
39+
#endif
40+
41+
/*
42+
* Extend rtc_api.h
43+
*/
44+
void rtc_set_irq_handler(uint32_t handler);
45+
46+
void rtc_periodic_ticker_init(uint32_t timestamp);
47+
void rtc_periodic_ticker_disable_irq();
48+
49+
#ifdef __cplusplus
50+
}
51+
#endif
52+
53+
#endif

0 commit comments

Comments
 (0)