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