@@ -38,6 +38,10 @@ static rtc_dev rtc = {
3838
3939rtc_dev *RTC = &rtc;
4040
41+ voidFuncPtr handlerAlarmA = NULL ;
42+ voidFuncPtr handlerAlarmB = NULL ;
43+ voidFuncPtr handlerPeriodicWakeup = NULL ;
44+
4145
4246RTClock::RTClock () {
4347 RTClock (RTCSEL_HSE, 7999 , 124 );
@@ -50,54 +54,54 @@ RTClock::RTClock(rtc_clk_src src) {
5054RTClock::RTClock (rtc_clk_src src, uint16 sync_prescaler, uint16 async_prescaler) {
5155 uint32 t = 0 ;
5256 RCC_BASE->APB1ENR |= RCC_APB1RSTR_PWRRST;
53- dbg_printf (" RCC_BASE->APB1ENR = %08X\r\n " , RCC_BASE->APB1ENR );
54- dbg_printf (" before bkp_init\r\n " );
57+ rtc_debug_printf (" RCC_BASE->APB1ENR = %08X\r\n " , RCC_BASE->APB1ENR );
58+ rtc_debug_printf (" before bkp_init\r\n " );
5559 bkp_init (); // turn on peripheral clocks to PWR and BKP and reset the backup domain via RCC registers.
5660 // (we reset the backup domain here because we must in order to change the rtc clock source).
57- dbg_printf (" before bkp_disable_writes\r\n " );
61+ rtc_debug_printf (" before bkp_disable_writes\r\n " );
5862 bkp_disable_writes ();
59- dbg_printf (" before bkp_enable_writes\r\n " );
63+ rtc_debug_printf (" before bkp_enable_writes\r\n " );
6064 bkp_enable_writes (); // enable writes to the backup registers and the RTC registers via the DBP bit in the PWR control register
61- dbg_printf (" RCC_BASE->CFGR = %08X\r\n " , RCC_BASE->CFGR );
65+ rtc_debug_printf (" RCC_BASE->CFGR = %08X\r\n " , RCC_BASE->CFGR );
6266 RCC_BASE->CFGR |= (0x08 << 16 ); // Set the RTCPRE to HSE / 8.
63- dbg_printf (" RCC_BASE->CFGR = %08X\r\n " , RCC_BASE->CFGR );
67+ rtc_debug_printf (" RCC_BASE->CFGR = %08X\r\n " , RCC_BASE->CFGR );
6468
6569 switch (src) {
6670 case RTCSEL_LSE :
67- dbg_printf (" Preparing RTC for LSE mode\r\n " );
71+ rtc_debug_printf (" Preparing RTC for LSE mode\r\n " );
6872 if ((RCC_BASE->BDCR & 0x00000300 ) != 0x0100 )
6973 RCC_BASE->BDCR = 0x00010000 ; // Reset the entire Backup domain
7074 RCC_BASE->BDCR = 0x00008101 ;
71- dbg_printf (" RCC_BASE->BDCR = %08X\r\n " , RCC_BASE->BDCR );
75+ rtc_debug_printf (" RCC_BASE->BDCR = %08X\r\n " , RCC_BASE->BDCR );
7276 while (!(RCC_BASE->BDCR & 0x00000002 )) {
7377 if (++t > 1000000 ) {
74- dbg_printf (" RCC_BASE->BDCR.LSERDY Timeout !\r\n " );
75- dbg_printf (" RCC_BASE->BDCR = %08X\r\n " , RCC_BASE->BDCR );
78+ rtc_debug_printf (" RCC_BASE->BDCR.LSERDY Timeout !\r\n " );
79+ rtc_debug_printf (" RCC_BASE->BDCR = %08X\r\n " , RCC_BASE->BDCR );
7680 return ;
7781 }
7882 }
79- dbg_printf (" RCC_BASE->BDCR = %08X\r\n " , RCC_BASE->BDCR );
83+ rtc_debug_printf (" RCC_BASE->BDCR = %08X\r\n " , RCC_BASE->BDCR );
8084 rtc_enter_config_mode ();
8185 if (sync_prescaler == 0 && async_prescaler == 0 )
8286 RTC_BASE->PRER = 255 | (127 << 16 );
8387 else
8488 RTC_BASE->PRER = sync_prescaler | (async_prescaler << 16 );
8589 break ;
8690 case RTCSEL_LSI :
87- dbg_printf (" Preparing RTC for LSI mode\r\n " );
91+ rtc_debug_printf (" Preparing RTC for LSI mode\r\n " );
8892 if ((RCC_BASE->BDCR & 0x00000300 ) != 0x0200 )
8993 RCC_BASE->BDCR = 0x00010000 ; // Reset the entire Backup domain
9094 RCC_BASE->BDCR = 0x00008204 ;
9195 RCC_BASE->CSR |= 0x00000001 ;
92- dbg_printf (" RCC_BASE->BDCR = %08X\r\n " , RCC_BASE->BDCR );
96+ rtc_debug_printf (" RCC_BASE->BDCR = %08X\r\n " , RCC_BASE->BDCR );
9397 while (!(RCC_BASE->CSR & 0x00000002 )) {
9498 if (++t > 1000000 ) {
95- dbg_printf (" RCC_BASE->CSR.LSIRDY Timeout !\r\n " );
96- dbg_printf (" RCC_BASE->CSR = %08X\r\n " , RCC_BASE->CSR );
99+ rtc_debug_printf (" RCC_BASE->CSR.LSIRDY Timeout !\r\n " );
100+ rtc_debug_printf (" RCC_BASE->CSR = %08X\r\n " , RCC_BASE->CSR );
97101 return ;
98102 }
99103 }
100- dbg_printf (" RCC_BASE->BDCR = %08X\r\n " , RCC_BASE->BDCR );
104+ rtc_debug_printf (" RCC_BASE->BDCR = %08X\r\n " , RCC_BASE->BDCR );
101105 rtc_enter_config_mode ();
102106 if (sync_prescaler == 0 && async_prescaler == 0 )
103107 RTC_BASE->PRER = 249 | (127 << 16 );
@@ -106,32 +110,32 @@ RTClock::RTClock(rtc_clk_src src, uint16 sync_prescaler, uint16 async_prescaler)
106110 break ;
107111 case RTCSEL_DEFAULT:
108112 case RTCSEL_HSE :
109- dbg_printf (" Preparing RTC for HSE mode\r\n " );
113+ rtc_debug_printf (" Preparing RTC for HSE mode\r\n " );
110114 if ((RCC_BASE->BDCR & 0x00000300 ) != 0x0300 )
111115 RCC_BASE->BDCR = 0x00010000 ; // Reset the entire Backup domain
112116 RCC_BASE->BDCR = 0x00008304 ;
113- dbg_printf (" RCC_BASE->BDCR = %08X\r\n " , RCC_BASE->BDCR );
117+ rtc_debug_printf (" RCC_BASE->BDCR = %08X\r\n " , RCC_BASE->BDCR );
114118 rtc_enter_config_mode ();
115119 if (sync_prescaler == 0 && async_prescaler == 0 )
116120 RTC_BASE->PRER = 7999 | (124 << 16 );
117121 else
118122 RTC_BASE->PRER = sync_prescaler | (async_prescaler << 16 );
119123 break ;
120124 case RTCSEL_NONE:
121- dbg_printf (" Preparing RTC for NONE mode\r\n " );
125+ rtc_debug_printf (" Preparing RTC for NONE mode\r\n " );
122126 if ((RCC_BASE->BDCR & 0x00000300 ) != 0x0000 )
123127 RCC_BASE->BDCR = 0x00010000 ; // Reset the entire Backup domain
124128 RCC_BASE->BDCR = RCC_BDCR_RTCSEL_NONE;
125129 // do nothing. Have a look at the clocks to see the diff between NONE and DEFAULT
126130 break ;
127131 }
128132 RCC_BASE->CR |= 0x00000040 ; // Turn to 24hrs mode
129- // dbg_printf ("before rtc_clear_sync\r\n");
133+ // rtc_debug_printf ("before rtc_clear_sync\r\n");
130134// rtc_clear_sync();
131- // dbg_printf ("before rtc_wait_sync\r\n");
135+ // rtc_debug_printf ("before rtc_wait_sync\r\n");
132136// rtc_wait_sync();
133137 rtc_exit_config_mode ();
134- dbg_printf (" end of rtc_init\r\n " );
138+ rtc_debug_printf (" end of rtc_init\r\n " );
135139}
136140
137141/*
@@ -237,25 +241,8 @@ struct tm* RTClock::getTime(struct tm* tm_ptr) {
237241 return tm_ptr;
238242}
239243
240- void RTClock::createAlarm (voidFuncPtr function, time_t alarm_time_t ) {
241- // rtc_set_alarm(alarm_time_t); //must be int... for standardization sake.
242- // rtc_attach_interrupt(RTC_ALARM_SPECIFIC_INTERRUPT, function);
243- }
244-
245- void RTClock::createAlarm (voidFuncPtr function, tm* alarm_tm) {
246- // time_t alarm = mktime(alarm_tm);//convert to time_t
247- // createAlarm(function, alarm);
248- }
249-
250- void RTClock::attachSecondsInterrupt (voidFuncPtr function) {
251- // rtc_attach_interrupt(RTC_SECONDS_INTERRUPT, function);
252- }
253-
254- void RTClock::detachSecondsInterrupt () {
255- // rtc_detach_interrupt(RTC_SECONDS_INTERRUPT);
256- }
257-
258244void RTClock::setAlarmATime (tm * tm_ptr, bool hours_match, bool mins_match, bool secs_match, bool date_match) {
245+ uint32 t = 0 ;
259246 rtc_enter_config_mode ();
260247 unsigned int bits = ((tm_ptr->tm_mday / 10 ) << 28 ) | ((tm_ptr->tm_mday % 10 ) << 24 ) |
261248 ((tm_ptr->tm_hour / 10 ) << 20 ) | ((tm_ptr->tm_hour % 10 ) << 16 ) |
@@ -265,9 +252,21 @@ void RTClock::setAlarmATime (tm * tm_ptr, bool hours_match, bool mins_match, boo
265252 if (!hours_match) bits |= (1 << 23 );
266253 if (!mins_match) bits |= (1 << 15 );
267254 if (!secs_match) bits |= (1 << 7 );
255+ RTC_BASE->CR &= ~(1 << RTC_CR_ALRAE_BIT);
256+ while (!(RTC_BASE->ISR & (1 << RTC_ISR_ALRAWF_BIT))) {
257+ if (++t > 1000000 ) {
258+ rtc_debug_printf (" RTC_BASE->ISR.ALRAWF Timeout !\r\n " );
259+ rtc_debug_printf (" RTC_BASE->ISR = %08X\r\n " , RTC_BASE->ISR );
260+ return ;
261+ }
262+ }
268263 RTC_BASE->ALRMAR = bits;
264+ RTC_BASE->CR |= (1 << RTC_CR_ALRAE_BIT);
269265 RTC_BASE->CR |= (1 << RTC_CR_ALRAIE_BIT); // turn on ALRAIE
270266 rtc_exit_config_mode ();
267+ nvic_irq_enable (NVIC_RTCALARM);
268+ nvic_irq_enable (NVIC_RTC);
269+ rtc_enable_alarm_event ();
271270}
272271
273272
@@ -285,6 +284,7 @@ void RTClock::turnOffAlarmA() {
285284
286285
287286void RTClock::setAlarmBTime (tm * tm_ptr, bool hours_match, bool mins_match, bool secs_match, bool date_match) {
287+ uint32 t = 0 ;
288288 rtc_enter_config_mode ();
289289 unsigned int bits = ((tm_ptr->tm_mday / 10 ) << 28 ) | ((tm_ptr->tm_mday % 10 ) << 24 ) |
290290 ((tm_ptr->tm_hour / 10 ) << 20 ) | ((tm_ptr->tm_hour % 10 ) << 16 ) |
@@ -294,9 +294,21 @@ void RTClock::setAlarmBTime (tm * tm_ptr, bool hours_match, bool mins_match, boo
294294 if (!hours_match) bits |= (1 << 23 );
295295 if (!mins_match) bits |= (1 << 15 );
296296 if (!secs_match) bits |= (1 << 7 );
297+ RTC_BASE->CR &= ~(1 << RTC_CR_ALRBE_BIT);
298+ while (!(RTC_BASE->ISR & (1 << RTC_ISR_ALRBWF_BIT))) {
299+ if (++t > 1000000 ) {
300+ rtc_debug_printf (" RTC_BASE->ISR.ALRBWF Timeout !\r\n " );
301+ rtc_debug_printf (" RTC_BASE->ISR = %08X\r\n " , RTC_BASE->ISR );
302+ return ;
303+ }
304+ }
297305 RTC_BASE->ALRMBR = bits;
306+ RTC_BASE->CR |= (1 << RTC_CR_ALRBE_BIT);
298307 RTC_BASE->CR |= (1 << RTC_CR_ALRBIE_BIT); // turn on ALRBIE
299308 rtc_exit_config_mode ();
309+ nvic_irq_enable (NVIC_RTCALARM);
310+ nvic_irq_enable (NVIC_RTC);
311+ rtc_enable_alarm_event ();
300312}
301313
302314
@@ -314,32 +326,98 @@ void RTClock::turnOffAlarmB() {
314326
315327
316328void RTClock::setPeriodicWakeup (uint16 period) {
329+ uint32 t = 0 ;
317330 rtc_enter_config_mode ();
318- dbg_printf (" before setting RTC_BASE->WUTR\r\n " );
331+ RTC_BASE->CR &= ~(1 << RTC_CR_WUTE_BIT);
332+ while (!(RTC_BASE->ISR & (1 << RTC_ISR_WUTWF_BIT))) {
333+ if (++t > 1000000 ) {
334+ rtc_debug_printf (" RTC_BASE->ISR.WUTWF Timeout !\r\n " );
335+ rtc_debug_printf (" RTC_BASE->ISR = %08X\r\n " , RTC_BASE->ISR );
336+ return ;
337+ }
338+ }
339+ rtc_debug_printf (" before setting RTC_BASE->WUTR\r\n " );
319340 RTC_BASE->WUTR = period; // set the period
320- dbg_printf (" before setting RTC_BASE->CR.WUCKSEL\r\n " );
341+ rtc_debug_printf (" RTC_BASE->WUTR = %08X\r\n " , RTC_BASE->WUTR );
342+ rtc_debug_printf (" before setting RTC_BASE->CR.WUCKSEL\r\n " );
321343 RTC_BASE->CR &= ~(3 ); RTC_BASE->CR |= 4 ; // Set the WUCKSEL to 1Hz (0x00000004)
344+ RTC_BASE->ISR &= ~(1 << RTC_ISR_WUTF_BIT);
345+ RTC_BASE->CR |= (1 << RTC_CR_WUTE_BIT);
322346 if (period == 0 )
323347 RTC_BASE->CR &= ~(1 << RTC_CR_WUTIE_BIT); // if period is 0, turn off periodic wakeup interrupt.
324348 else {
325- dbg_printf (" before turn ON RTC_BASE->CR.WUTIE\r\n " );
349+ rtc_debug_printf (" before turn ON RTC_BASE->CR.WUTIE\r\n " );
326350 RTC_BASE->CR |= (1 << RTC_CR_WUTIE_BIT); // turn on WUTIE
327351 }
328- dbg_printf (" RCC_BASE->CR = %08X\r\n " , RCC_BASE->CR );
352+ rtc_debug_printf (" RCC_BASE->CR = %08X\r\n " , RCC_BASE->CR );
329353 rtc_exit_config_mode ();
330354 rtc_enable_wakeup_event ();
331355 nvic_irq_enable (NVIC_RTC);
332- nvic_irq_enable (NVIC_RTCALARM);
333- dbg_printf (" setPeriodicWakeup() done !\r\n " );
356+ rtc_debug_printf (" setPeriodicWakeup() done !\r\n " );
334357}
335358
336- extern " C" {
337- void __irq_rtc (void ) {
338- dbg_printf (" __irq_rtc() called !\r\n " );
339- *bb_perip (&EXTI_BASE->PR , EXTI_RTC_WAKEUP_BIT) = 1 ;
359+
360+ void RTClock::attachAlarmAInterrupt (voidFuncPtr function) {
361+ handlerAlarmA = function;
340362}
341- void __irq_rtcalarm (void ) {
342- dbg_printf (" __irq_rtcalarm() called !\r\n " );
343- *bb_perip (&EXTI_BASE->PR , EXTI_RTC_ALARM_BIT) = 1 ;
363+
364+ void RTClock::detachAlarmAInterrupt () {
365+ handlerAlarmA = NULL ;
366+ }
367+
368+ void RTClock::attachAlarmBInterrupt (voidFuncPtr function) {
369+ handlerAlarmB = function;
344370}
371+
372+ void RTClock::detachAlarmBInterrupt () {
373+ handlerAlarmB = NULL ;
374+ }
375+
376+ void RTClock::attachPeriodicWakeupInterrupt (voidFuncPtr function) {
377+ handlerPeriodicWakeup = function;
378+ }
379+
380+ void RTClock::detachPeriodicWakeupInterrupt () {
381+ handlerPeriodicWakeup = NULL ;
382+ }
383+
384+
385+
386+ extern " C" {
387+ void __irq_rtc (void ) {
388+ rtc_debug_printf (" __irq_rtc() called !\r\n " );
389+ rtc_enter_config_mode ();
390+ RTC_BASE->ISR &= ~(1 << RTC_ISR_WUTF_BIT);
391+ rtc_exit_config_mode ();
392+ *bb_perip (&EXTI_BASE->PR , EXTI_RTC_WAKEUP_BIT) = 1 ;
393+ if (handlerPeriodicWakeup != NULL ) {
394+ handlerPeriodicWakeup ();
395+ }
396+ }
397+
398+ void __irq_rtcalarm (void ) {
399+ bool isAlarmA = false ;
400+ bool isAlarmB = false ;
401+ rtc_debug_printf (" __irq_rtcalarm() called !\r\n " );
402+ rtc_enter_config_mode ();
403+ if (RTC_BASE->ISR & (1 << RTC_ISR_ALRAF_BIT)) {
404+ isAlarmA = true ;
405+ rtc_debug_printf (" AlarmA !\r\n " );
406+ RTC_BASE->ISR &= ~(1 << RTC_ISR_ALRAF_BIT);
407+ }
408+ if (RTC_BASE->ISR & (1 << RTC_ISR_ALRBF_BIT)) {
409+ isAlarmB = true ;
410+ rtc_debug_printf (" AlarmB !\r\n " );
411+ RTC_BASE->ISR &= ~(1 << RTC_ISR_ALRBF_BIT);
412+ }
413+ rtc_exit_config_mode ();
414+ *bb_perip (&EXTI_BASE->PR , EXTI_RTC_ALARM_BIT) = 1 ;
415+ if (isAlarmA && handlerAlarmA != NULL ) {
416+ handlerAlarmA ();
417+ }
418+ if (isAlarmB && handlerAlarmB != NULL ) {
419+ handlerAlarmB ();
420+ }
421+ }
345422}
423+
0 commit comments