Skip to content

Commit 94bada0

Browse files
committed
[STM32L0xx] LowPowerTicker implementation
LowPowerTicker for STM32L0xx 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: Ia4b784a9842971ff4225eccab2938ecba54097be
1 parent b395dd5 commit 94bada0

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_STM32L0/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 "stm32l0xx.h"
33+
#include "stm32l0xx_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_IRQHandler()
4374
{
75+
HAL_RTCEx_WakeUpTimerIRQHandler(&RtcHandle);
76+
}
77+
#endif
78+
79+
void rtc_init(void) {
4480
RCC_OscInitTypeDef RCC_OscInitStruct;
4581
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
4682
uint32_t rtc_freq = 0;
@@ -103,7 +139,12 @@ void rtc_init(void)
103139

104140
RtcHandle.Init.HourFormat = RTC_HOURFORMAT_24;
105141
RtcHandle.Init.AsynchPrediv = 127;
142+
#if !DEVICE_LOWPOWERTIMER
106143
RtcHandle.Init.SynchPrediv = (rtc_freq / 128) - 1;
144+
#else
145+
RtcHandle.Init.SynchPrediv = m_synch_prediv;
146+
#endif
147+
107148
RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE;
108149
RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
109150
RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
@@ -230,4 +271,61 @@ void rtc_write(time_t t)
230271
HAL_RTC_SetTime(&RtcHandle, &timeStruct, FORMAT_BIN);
231272
}
232273

274+
#if DEVICE_LOWPOWERTIMER
275+
void rtc_set_irq_handler(uint32_t handler)
276+
{
277+
irq_handler = (void (*)(void)) handler;
278+
}
279+
280+
void rtc_periodic_ticker_init(uint32_t timestamp)
281+
{
282+
uint32_t periodic_counter;
283+
uint32_t rtcclk;
284+
HAL_StatusTypeDef ret;
285+
286+
/*
287+
* For more informations how WakeUp unit values were calculated please follow
288+
* this document: www.st.com/resource/en/application_note/dm00025071.pdf
289+
*/
290+
if (timestamp <= 4000000) {
291+
periodic_counter = timestamp / 61.035;
292+
rtcclk = RTC_WAKEUPCLOCK_RTCCLK_DIV2;
293+
m_synch_prediv = 0;
294+
} else {
295+
rtc_calc_periodic_vals((float)(timestamp), &periodic_counter);
296+
rtcclk = RTC_WAKEUPCLOCK_CK_SPRE_16BITS;
297+
}
298+
299+
rtc_init();
300+
301+
/*
302+
* For some reason we need to clear the wakeup time flag to able to start
303+
* the RTC periodic unit.
304+
*/
305+
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&RtcHandle, RTC_FLAG_WUTF);
306+
ret = HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, periodic_counter - 1, rtcclk);
307+
308+
if (ret != HAL_OK) {
309+
error("SetWakeUpTimer_IT failed!\n");
310+
}
311+
312+
NVIC_SetVector(RTC_IRQn, (uint32_t) &RTC_IRQHandler);
313+
HAL_NVIC_EnableIRQ(RTC_IRQn);
314+
}
315+
316+
void rtc_periodic_ticker_disable_irq()
317+
{
318+
HAL_RTCEx_DeactivateWakeUpTimer(&RtcHandle);
319+
}
320+
321+
void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
322+
{
323+
if (irq_handler)
324+
{
325+
// Fire the user callback
326+
irq_handler();
327+
}
328+
}
329+
#endif // DEVICE_LOWPOWERTIMER
330+
233331
#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)