28
28
*******************************************************************************
29
29
*/
30
30
#include "rtc_api.h"
31
+ #include "rtc_api_hal.h"
32
+ #include "stm32l0xx.h"
33
+ #include "stm32l0xx_hal_rtc_ex.h"
31
34
32
35
#if DEVICE_RTC
33
36
@@ -38,9 +41,42 @@ static int rtc_inited = 0;
38
41
#endif
39
42
40
43
static RTC_HandleTypeDef RtcHandle ;
44
+ static uint32_t m_synch_prediv ;
41
45
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 ()
43
74
{
75
+ HAL_RTCEx_WakeUpTimerIRQHandler (& RtcHandle );
76
+ }
77
+ #endif
78
+
79
+ void rtc_init (void ) {
44
80
RCC_OscInitTypeDef RCC_OscInitStruct ;
45
81
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct ;
46
82
uint32_t rtc_freq = 0 ;
@@ -103,7 +139,12 @@ void rtc_init(void)
103
139
104
140
RtcHandle .Init .HourFormat = RTC_HOURFORMAT_24 ;
105
141
RtcHandle .Init .AsynchPrediv = 127 ;
142
+ #if !DEVICE_LOWPOWERTIMER
106
143
RtcHandle .Init .SynchPrediv = (rtc_freq / 128 ) - 1 ;
144
+ #else
145
+ RtcHandle .Init .SynchPrediv = m_synch_prediv ;
146
+ #endif
147
+
107
148
RtcHandle .Init .OutPut = RTC_OUTPUT_DISABLE ;
108
149
RtcHandle .Init .OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH ;
109
150
RtcHandle .Init .OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN ;
@@ -230,4 +271,61 @@ void rtc_write(time_t t)
230
271
HAL_RTC_SetTime (& RtcHandle , & timeStruct , FORMAT_BIN );
231
272
}
232
273
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
+
233
331
#endif
0 commit comments