28
28
*******************************************************************************
29
29
*/
30
30
#include "rtc_api.h"
31
+ #include "rtc_api_hal.h"
32
+ #include "stm32l4xx.h"
33
+ #include "stm32l4xx_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_WKUP_IRQHandler ()
43
74
{
75
+ HAL_RTCEx_WakeUpTimerIRQHandler (& RtcHandle );
76
+ }
77
+ #endif
78
+
79
+ void rtc_init (void ) {
44
80
RCC_OscInitTypeDef RCC_OscInitStruct = {0 };
45
81
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0 };
46
82
uint32_t rtc_freq = 0 ;
@@ -104,7 +140,12 @@ void rtc_init(void)
104
140
105
141
RtcHandle .Init .HourFormat = RTC_HOURFORMAT_24 ;
106
142
RtcHandle .Init .AsynchPrediv = 127 ;
143
+ #if !DEVICE_LOWPOWERTIMER
107
144
RtcHandle .Init .SynchPrediv = (rtc_freq / 128 ) - 1 ;
145
+ #else
146
+ RtcHandle .Init .SynchPrediv = m_synch_prediv ;
147
+ #endif
148
+
108
149
RtcHandle .Init .OutPut = RTC_OUTPUT_DISABLE ;
109
150
RtcHandle .Init .OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH ;
110
151
RtcHandle .Init .OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN ;
@@ -229,4 +270,61 @@ void rtc_write(time_t t)
229
270
HAL_RTC_SetTime (& RtcHandle , & timeStruct , RTC_FORMAT_BIN );
230
271
}
231
272
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
+
232
330
#endif
0 commit comments