28
28
*******************************************************************************
29
29
*/
30
30
#include "rtc_api.h"
31
+ #include "rtc_api_hal.h"
32
+ #include "stm32l1xx.h"
33
+ #include "stm32l1xx_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
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
uint32_t rtc_freq = 0 ;
46
82
@@ -101,8 +137,13 @@ void rtc_init(void)
101
137
RtcHandle .Init .SynchPrediv = (rtc_freq / 2 ) - 1 ;
102
138
#else
103
139
RtcHandle .Init .AsynchPrediv = 127 ;
140
+ #if !DEVICE_LOWPOWERTIMER
104
141
RtcHandle .Init .SynchPrediv = (rtc_freq / 128 ) - 1 ;
142
+ #else
143
+ RtcHandle .Init .SynchPrediv = m_synch_prediv ;
105
144
#endif
145
+ #endif // TARGET_MOTE_L152RC
146
+
106
147
RtcHandle .Init .OutPut = RTC_OUTPUT_DISABLE ;
107
148
RtcHandle .Init .OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH ;
108
149
RtcHandle .Init .OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN ;
@@ -227,4 +268,61 @@ void rtc_write(time_t t)
227
268
HAL_RTC_SetTime (& RtcHandle , & timeStruct , FORMAT_BIN );
228
269
}
229
270
271
+ #if DEVICE_LOWPOWERTIMER
272
+ void rtc_set_irq_handler (uint32_t handler )
273
+ {
274
+ irq_handler = (void (* )(void )) handler ;
275
+ }
276
+
277
+ void rtc_periodic_ticker_init (uint32_t timestamp )
278
+ {
279
+ uint32_t periodic_counter ;
280
+ uint32_t rtcclk ;
281
+ HAL_StatusTypeDef ret ;
282
+
283
+ /*
284
+ * For more informations how WakeUp unit values were calculated please follow
285
+ * this document: www.st.com/resource/en/application_note/dm00025071.pdf
286
+ */
287
+ if (timestamp <= 4000000 ) {
288
+ periodic_counter = timestamp / 61.035 ;
289
+ rtcclk = RTC_WAKEUPCLOCK_RTCCLK_DIV2 ;
290
+ m_synch_prediv = 0 ;
291
+ } else {
292
+ rtc_calc_periodic_vals ((float )(timestamp ), & periodic_counter );
293
+ rtcclk = RTC_WAKEUPCLOCK_CK_SPRE_16BITS ;
294
+ }
295
+
296
+ rtc_init ();
297
+
298
+ /*
299
+ * For some reason we need to clear the wakeup time flag to able to start
300
+ * the RTC periodic unit.
301
+ */
302
+ __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG (& RtcHandle , RTC_FLAG_WUTF );
303
+ ret = HAL_RTCEx_SetWakeUpTimer_IT (& RtcHandle , periodic_counter - 1 , rtcclk );
304
+
305
+ if (ret != HAL_OK ) {
306
+ error ("SetWakeUpTimer_IT failed!\n" );
307
+ }
308
+
309
+ NVIC_SetVector (RTC_WKUP_IRQn , (uint32_t ) & RTC_IRQHandler );
310
+ HAL_NVIC_EnableIRQ (RTC_WKUP_IRQn );
311
+ }
312
+
313
+ void rtc_periodic_ticker_disable_irq ()
314
+ {
315
+ HAL_RTCEx_DeactivateWakeUpTimer (& RtcHandle );
316
+ }
317
+
318
+ void HAL_RTCEx_WakeUpTimerEventCallback (RTC_HandleTypeDef * hrtc )
319
+ {
320
+ if (irq_handler )
321
+ {
322
+ // Fire the user callback
323
+ irq_handler ();
324
+ }
325
+ }
326
+ #endif // DEVICE_LOWPOWERTIMER
327
+
230
328
#endif
0 commit comments