28
28
*******************************************************************************
29
29
*/
30
30
#include "rtc_api.h"
31
+ #include "rtc_api_hal.h"
32
+ #include "stm32f7xx.h"
33
+ #include "stm32f7xx_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 ;
45
81
uint32_t rtc_freq = 0 ;
46
82
@@ -91,7 +127,12 @@ void rtc_init(void)
91
127
92
128
RtcHandle .Init .HourFormat = RTC_HOURFORMAT_24 ;
93
129
RtcHandle .Init .AsynchPrediv = 127 ;
130
+ #if !DEVICE_LOWPOWERTIMER
94
131
RtcHandle .Init .SynchPrediv = (rtc_freq / 128 ) - 1 ;
132
+ #else
133
+ RtcHandle .Init .SynchPrediv = m_synch_prediv ;
134
+ #endif
135
+
95
136
RtcHandle .Init .OutPut = RTC_OUTPUT_DISABLE ;
96
137
RtcHandle .Init .OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH ;
97
138
RtcHandle .Init .OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN ;
@@ -219,4 +260,64 @@ void rtc_write(time_t t)
219
260
HAL_RTC_SetTime (& RtcHandle , & timeStruct , FORMAT_BIN );
220
261
}
221
262
263
+ #if DEVICE_LOWPOWERTIMER
264
+ void rtc_set_irq_handler (uint32_t handler )
265
+ {
266
+ irq_handler = (void (* )(void )) handler ;
267
+ }
268
+
269
+ void rtc_periodic_ticker_init (uint32_t timestamp )
270
+ {
271
+ uint32_t periodic_counter ;
272
+ uint32_t rtcclk ;
273
+ HAL_StatusTypeDef ret ;
274
+
275
+ /*
276
+ * For more informations how WakeUp unit values were calculated please follow
277
+ * this document: www.st.com/resource/en/application_note/dm00025071.pdf
278
+ */
279
+ if (timestamp <= 4000000 ) {
280
+ // The minimum time resolution
281
+ float min_res = 61.035 ;
282
+
283
+ periodic_counter = timestamp / min_res ;
284
+ rtcclk = RTC_WAKEUPCLOCK_RTCCLK_DIV2 ;
285
+ m_synch_prediv = 0 ;
286
+ } else {
287
+ rtc_calc_periodic_vals ((float )(timestamp ), & periodic_counter );
288
+ rtcclk = RTC_WAKEUPCLOCK_CK_SPRE_16BITS ;
289
+ }
290
+
291
+ rtc_init ();
292
+
293
+ /*
294
+ * For some reason we need to clear the wakeup time flag to able to start
295
+ * the RTC periodic unit.
296
+ */
297
+ __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG (& RtcHandle , RTC_FLAG_WUTF );
298
+ ret = HAL_RTCEx_SetWakeUpTimer_IT (& RtcHandle , periodic_counter - 1 , rtcclk );
299
+
300
+ if (ret != HAL_OK ) {
301
+ error ("SetWakeUpTimer_IT failed!\n" );
302
+ }
303
+
304
+ NVIC_SetVector (RTC_WKUP_IRQn , (uint32_t ) & RTC_WKUP_IRQHandler );
305
+ HAL_NVIC_EnableIRQ (RTC_WKUP_IRQn );
306
+ }
307
+
308
+ void rtc_periodic_ticker_disable_irq ()
309
+ {
310
+ HAL_RTCEx_DeactivateWakeUpTimer (& RtcHandle );
311
+ }
312
+
313
+ void HAL_RTCEx_WakeUpTimerEventCallback (RTC_HandleTypeDef * hrtc )
314
+ {
315
+ if (irq_handler )
316
+ {
317
+ // Fire the user callback
318
+ irq_handler ();
319
+ }
320
+ }
321
+ #endif // DEVICE_LOWPOWERTIMER
322
+
222
323
#endif
0 commit comments