@@ -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/*
@@ -192,6 +196,9 @@ void RTClock::setTime (time_t time_stamp) {
192196
193197void RTClock::setTime (struct tm * tm_ptr) {
194198 rtc_enter_config_mode ();
199+ if (tm_ptr->tm_year > 99 )
200+ tm_ptr->tm_year = tm_ptr->tm_year % 100 ;
201+ tm_ptr->tm_wday = tm_ptr->tm_wday & 0x7 ;
195202 RTC_BASE->TR = ((tm_ptr->tm_hour / 10 ) << 20 ) | ((tm_ptr->tm_hour % 10 ) << 16 ) |
196203 ((tm_ptr->tm_min / 10 ) << 12 ) | ((tm_ptr->tm_min % 10 ) << 8 ) |
197204 ((tm_ptr->tm_sec / 10 ) << 4 ) | (tm_ptr->tm_sec % 10 );
@@ -202,12 +209,14 @@ void RTClock::setTime (struct tm* tm_ptr) {
202209}
203210
204211time_t RTClock::getTime () {
205- int years = 10 * ((RTC_BASE->DR & 0x00F00000 ) >> 20 ) + ((RTC_BASE->DR & 0x000F0000 ) >> 16 );
206- int months = 10 * ((RTC_BASE->DR & 0x00001000 ) >> 12 ) + ((RTC_BASE->DR & 0x00000F00 ) >> 8 );
207- int days = 10 * ((RTC_BASE->DR & 0x00000030 ) >> 4 ) + (RTC_BASE->DR & 0x000000F );
208- int hours = 10 * ((RTC_BASE->TR & 0x00300000 ) >> 20 ) + ((RTC_BASE->TR & 0x000F0000 ) >> 16 );
209- int mins = 10 * ((RTC_BASE->TR & 0x00007000 ) >> 12 ) + ((RTC_BASE->TR & 0x0000F00 ) >> 8 );
210- int secs = 10 * ((RTC_BASE->TR & 0x00000070 ) >> 4 ) + (RTC_BASE->TR & 0x0000000F );
212+ uint32 dr_reg = RTC_BASE->DR ;
213+ uint32 tr_reg = RTC_BASE->TR ;
214+ int years = 10 * ((dr_reg & 0x00F00000 ) >> 20 ) + ((dr_reg & 0x000F0000 ) >> 16 );
215+ int months = 10 * ((dr_reg & 0x00001000 ) >> 12 ) + ((dr_reg & 0x00000F00 ) >> 8 );
216+ int days = 10 * ((dr_reg & 0x00000030 ) >> 4 ) + (dr_reg & 0x000000F );
217+ int hours = 10 * ((tr_reg & 0x00300000 ) >> 20 ) + ((tr_reg & 0x000F0000 ) >> 16 );
218+ int mins = 10 * ((tr_reg & 0x00007000 ) >> 12 ) + ((tr_reg & 0x0000F00 ) >> 8 );
219+ int secs = 10 * ((tr_reg & 0x00000070 ) >> 4 ) + (tr_reg & 0x0000000F );
211220 // seconds from 1970 till 1 jan 00:00:00 of the given year
212221 time_t t = (years + 30 ) * SECS_PER_DAY * 365 ;
213222 for (int i = 0 ; i < years; i++) {
@@ -228,34 +237,19 @@ time_t RTClock::getTime() {
228237}
229238
230239struct tm * RTClock::getTime (struct tm * tm_ptr) {
231- tm_ptr->tm_year = 10 * ((RTC_BASE->DR & 0x00F00000 ) >> 20 ) + ((RTC_BASE->DR & 0x000F0000 ) >> 16 );
232- tm_ptr->tm_mon = 10 * ((RTC_BASE->DR & 0x00001000 ) >> 12 ) + ((RTC_BASE->DR & 0x00000F00 ) >> 8 );
233- tm_ptr->tm_mday = 10 * ((RTC_BASE->DR & 0x00000030 ) >> 4 ) + (RTC_BASE->DR & 0x000000F );
234- tm_ptr->tm_hour = 10 * ((RTC_BASE->TR & 0x00300000 ) >> 20 ) + ((RTC_BASE->TR & 0x000F0000 ) >> 16 );
235- tm_ptr->tm_min = 10 * ((RTC_BASE->TR & 0x00007000 ) >> 12 ) + ((RTC_BASE->TR & 0x0000F00 ) >> 8 );
236- tm_ptr->tm_sec = 10 * ((RTC_BASE->TR & 0x00000070 ) >> 4 ) + (RTC_BASE->TR & 0x0000000F );
240+ uint32 dr_reg = RTC_BASE->DR ;
241+ uint32 tr_reg = RTC_BASE->TR ;
242+ tm_ptr->tm_year = 10 * ((dr_reg & 0x00F00000 ) >> 20 ) + ((dr_reg & 0x000F0000 ) >> 16 );
243+ tm_ptr->tm_mon = 10 * ((dr_reg & 0x00001000 ) >> 12 ) + ((dr_reg & 0x00000F00 ) >> 8 );
244+ tm_ptr->tm_mday = 10 * ((dr_reg & 0x00000030 ) >> 4 ) + (dr_reg & 0x000000F );
245+ tm_ptr->tm_hour = 10 * ((tr_reg & 0x00300000 ) >> 20 ) + ((tr_reg & 0x000F0000 ) >> 16 );
246+ tm_ptr->tm_min = 10 * ((tr_reg & 0x00007000 ) >> 12 ) + ((tr_reg & 0x0000F00 ) >> 8 );
247+ tm_ptr->tm_sec = 10 * ((tr_reg & 0x00000070 ) >> 4 ) + (tr_reg & 0x0000000F );
237248 return tm_ptr;
238249}
239250
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-
258251void RTClock::setAlarmATime (tm * tm_ptr, bool hours_match, bool mins_match, bool secs_match, bool date_match) {
252+ uint32 t = 0 ;
259253 rtc_enter_config_mode ();
260254 unsigned int bits = ((tm_ptr->tm_mday / 10 ) << 28 ) | ((tm_ptr->tm_mday % 10 ) << 24 ) |
261255 ((tm_ptr->tm_hour / 10 ) << 20 ) | ((tm_ptr->tm_hour % 10 ) << 16 ) |
@@ -265,9 +259,21 @@ void RTClock::setAlarmATime (tm * tm_ptr, bool hours_match, bool mins_match, boo
265259 if (!hours_match) bits |= (1 << 23 );
266260 if (!mins_match) bits |= (1 << 15 );
267261 if (!secs_match) bits |= (1 << 7 );
262+ RTC_BASE->CR &= ~(1 << RTC_CR_ALRAE_BIT);
263+ while (!(RTC_BASE->ISR & (1 << RTC_ISR_ALRAWF_BIT))) {
264+ if (++t > 1000000 ) {
265+ rtc_debug_printf (" RTC_BASE->ISR.ALRAWF Timeout !\r\n " );
266+ rtc_debug_printf (" RTC_BASE->ISR = %08X\r\n " , RTC_BASE->ISR );
267+ return ;
268+ }
269+ }
268270 RTC_BASE->ALRMAR = bits;
271+ RTC_BASE->CR |= (1 << RTC_CR_ALRAE_BIT);
269272 RTC_BASE->CR |= (1 << RTC_CR_ALRAIE_BIT); // turn on ALRAIE
270273 rtc_exit_config_mode ();
274+ nvic_irq_enable (NVIC_RTCALARM);
275+ nvic_irq_enable (NVIC_RTC);
276+ rtc_enable_alarm_event ();
271277}
272278
273279
@@ -285,6 +291,7 @@ void RTClock::turnOffAlarmA() {
285291
286292
287293void RTClock::setAlarmBTime (tm * tm_ptr, bool hours_match, bool mins_match, bool secs_match, bool date_match) {
294+ uint32 t = 0 ;
288295 rtc_enter_config_mode ();
289296 unsigned int bits = ((tm_ptr->tm_mday / 10 ) << 28 ) | ((tm_ptr->tm_mday % 10 ) << 24 ) |
290297 ((tm_ptr->tm_hour / 10 ) << 20 ) | ((tm_ptr->tm_hour % 10 ) << 16 ) |
@@ -294,9 +301,21 @@ void RTClock::setAlarmBTime (tm * tm_ptr, bool hours_match, bool mins_match, boo
294301 if (!hours_match) bits |= (1 << 23 );
295302 if (!mins_match) bits |= (1 << 15 );
296303 if (!secs_match) bits |= (1 << 7 );
304+ RTC_BASE->CR &= ~(1 << RTC_CR_ALRBE_BIT);
305+ while (!(RTC_BASE->ISR & (1 << RTC_ISR_ALRBWF_BIT))) {
306+ if (++t > 1000000 ) {
307+ rtc_debug_printf (" RTC_BASE->ISR.ALRBWF Timeout !\r\n " );
308+ rtc_debug_printf (" RTC_BASE->ISR = %08X\r\n " , RTC_BASE->ISR );
309+ return ;
310+ }
311+ }
297312 RTC_BASE->ALRMBR = bits;
313+ RTC_BASE->CR |= (1 << RTC_CR_ALRBE_BIT);
298314 RTC_BASE->CR |= (1 << RTC_CR_ALRBIE_BIT); // turn on ALRBIE
299315 rtc_exit_config_mode ();
316+ nvic_irq_enable (NVIC_RTCALARM);
317+ nvic_irq_enable (NVIC_RTC);
318+ rtc_enable_alarm_event ();
300319}
301320
302321
@@ -314,32 +333,98 @@ void RTClock::turnOffAlarmB() {
314333
315334
316335void RTClock::setPeriodicWakeup (uint16 period) {
336+ uint32 t = 0 ;
317337 rtc_enter_config_mode ();
318- dbg_printf (" before setting RTC_BASE->WUTR\r\n " );
338+ RTC_BASE->CR &= ~(1 << RTC_CR_WUTE_BIT);
339+ while (!(RTC_BASE->ISR & (1 << RTC_ISR_WUTWF_BIT))) {
340+ if (++t > 1000000 ) {
341+ rtc_debug_printf (" RTC_BASE->ISR.WUTWF Timeout !\r\n " );
342+ rtc_debug_printf (" RTC_BASE->ISR = %08X\r\n " , RTC_BASE->ISR );
343+ return ;
344+ }
345+ }
346+ rtc_debug_printf (" before setting RTC_BASE->WUTR\r\n " );
319347 RTC_BASE->WUTR = period; // set the period
320- dbg_printf (" before setting RTC_BASE->CR.WUCKSEL\r\n " );
348+ rtc_debug_printf (" RTC_BASE->WUTR = %08X\r\n " , RTC_BASE->WUTR );
349+ rtc_debug_printf (" before setting RTC_BASE->CR.WUCKSEL\r\n " );
321350 RTC_BASE->CR &= ~(3 ); RTC_BASE->CR |= 4 ; // Set the WUCKSEL to 1Hz (0x00000004)
351+ RTC_BASE->ISR &= ~(1 << RTC_ISR_WUTF_BIT);
352+ RTC_BASE->CR |= (1 << RTC_CR_WUTE_BIT);
322353 if (period == 0 )
323354 RTC_BASE->CR &= ~(1 << RTC_CR_WUTIE_BIT); // if period is 0, turn off periodic wakeup interrupt.
324355 else {
325- dbg_printf (" before turn ON RTC_BASE->CR.WUTIE\r\n " );
356+ rtc_debug_printf (" before turn ON RTC_BASE->CR.WUTIE\r\n " );
326357 RTC_BASE->CR |= (1 << RTC_CR_WUTIE_BIT); // turn on WUTIE
327358 }
328- dbg_printf (" RCC_BASE->CR = %08X\r\n " , RCC_BASE->CR );
359+ rtc_debug_printf (" RCC_BASE->CR = %08X\r\n " , RCC_BASE->CR );
329360 rtc_exit_config_mode ();
330361 rtc_enable_wakeup_event ();
331362 nvic_irq_enable (NVIC_RTC);
332- nvic_irq_enable (NVIC_RTCALARM);
333- dbg_printf (" setPeriodicWakeup() done !\r\n " );
363+ rtc_debug_printf (" setPeriodicWakeup() done !\r\n " );
334364}
335365
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 ;
366+
367+ void RTClock::attachAlarmAInterrupt (voidFuncPtr function) {
368+ handlerAlarmA = function;
340369}
341- void __irq_rtcalarm (void ) {
342- dbg_printf (" __irq_rtcalarm() called !\r\n " );
343- *bb_perip (&EXTI_BASE->PR , EXTI_RTC_ALARM_BIT) = 1 ;
370+
371+ void RTClock::detachAlarmAInterrupt () {
372+ handlerAlarmA = NULL ;
373+ }
374+
375+ void RTClock::attachAlarmBInterrupt (voidFuncPtr function) {
376+ handlerAlarmB = function;
344377}
378+
379+ void RTClock::detachAlarmBInterrupt () {
380+ handlerAlarmB = NULL ;
381+ }
382+
383+ void RTClock::attachPeriodicWakeupInterrupt (voidFuncPtr function) {
384+ handlerPeriodicWakeup = function;
385+ }
386+
387+ void RTClock::detachPeriodicWakeupInterrupt () {
388+ handlerPeriodicWakeup = NULL ;
389+ }
390+
391+
392+
393+ extern " C" {
394+ void __irq_rtc (void ) {
395+ rtc_debug_printf (" __irq_rtc() called !\r\n " );
396+ rtc_enter_config_mode ();
397+ RTC_BASE->ISR &= ~(1 << RTC_ISR_WUTF_BIT);
398+ rtc_exit_config_mode ();
399+ *bb_perip (&EXTI_BASE->PR , EXTI_RTC_WAKEUP_BIT) = 1 ;
400+ if (handlerPeriodicWakeup != NULL ) {
401+ handlerPeriodicWakeup ();
402+ }
403+ }
404+
405+ void __irq_rtcalarm (void ) {
406+ bool isAlarmA = false ;
407+ bool isAlarmB = false ;
408+ rtc_debug_printf (" __irq_rtcalarm() called !\r\n " );
409+ rtc_enter_config_mode ();
410+ if (RTC_BASE->ISR & (1 << RTC_ISR_ALRAF_BIT)) {
411+ isAlarmA = true ;
412+ rtc_debug_printf (" AlarmA !\r\n " );
413+ RTC_BASE->ISR &= ~(1 << RTC_ISR_ALRAF_BIT);
414+ }
415+ if (RTC_BASE->ISR & (1 << RTC_ISR_ALRBF_BIT)) {
416+ isAlarmB = true ;
417+ rtc_debug_printf (" AlarmB !\r\n " );
418+ RTC_BASE->ISR &= ~(1 << RTC_ISR_ALRBF_BIT);
419+ }
420+ rtc_exit_config_mode ();
421+ *bb_perip (&EXTI_BASE->PR , EXTI_RTC_ALARM_BIT) = 1 ;
422+ if (isAlarmA && handlerAlarmA != NULL ) {
423+ handlerAlarmA ();
424+ }
425+ if (isAlarmB && handlerAlarmB != NULL ) {
426+ handlerAlarmB ();
427+ }
428+ }
345429}
430+
0 commit comments