Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of WakeUp by
WakeUp_STM_RTC.cpp
00001 #ifdef TARGET_STM 00002 00003 #include "WakeUp.h" 00004 #include "rtc_api.h" 00005 00006 #define BYTE2BCD(byte) ((byte % 10) | ((byte / 10) << 4)) 00007 00008 //Most things are pretty similar between the different STM targets. 00009 //Only the IRQ number the alarm is connected to differs. Any errors 00010 //with RTC_IRQn/RTC_Alarm_IRQn in them are related to this 00011 #if defined(TARGET_M4) || defined(TARGET_M3) 00012 #define RTC_IRQ RTC_Alarm_IRQn 00013 #else 00014 #define RTC_IRQ RTC_IRQn 00015 #endif 00016 00017 // Some things to handle Disco L476VG (and similar ones) 00018 #if defined(TARGET_STM32L4) 00019 #define IMR IMR1 00020 #define EMR EMR1 00021 #define RTSR RTSR1 00022 #define FTSR FTSR2 00023 #define PR PR1 00024 #endif 00025 00026 //Disabling the Backup Powerdomain does not seem to work nicely anymore if you want to use other RTC functions afterwards. 00027 //For now I have disabled it in code, if you find WakeUp increases your powerconsumption, try enabling it again (code is still there, just commented) 00028 00029 FunctionPointer WakeUp::callback; 00030 00031 void WakeUp::set_ms(uint32_t s) 00032 { 00033 if (!rtc_isenabled()) { //Make sure RTC is running 00034 rtc_init(); 00035 wait_us(250); //The f401 seems to want a delay after init 00036 } 00037 00038 //PWR->CR |= PWR_CR_DBP; //Enable power domain 00039 RTC->WPR = 0xCA; //Disable RTC write protection 00040 RTC->WPR = 0x53; 00041 00042 //Alarm must be disabled to change anything 00043 RTC->CR &= ~RTC_CR_ALRAE; 00044 while(!(RTC->ISR & RTC_ISR_ALRAWF)); 00045 00046 if (s == 0) { //Just disable alarm 00047 //PWR->CR &= ~PWR_CR_DBP; //Disable power domain 00048 RTC->WPR = 0xFF; //Enable RTC write protection 00049 return; 00050 } 00051 00052 //RTC prescaler + calculate how many sub-seconds should be added 00053 uint32_t prescaler = (RTC->PRER & 0x7FFF) + 1; 00054 uint32_t subsecsadd = s* prescaler; 00055 00056 if ((s < 1) && (subsecsadd < 2)) 00057 subsecsadd = 2; //At least 2 subsecs delay to be sure interrupt is called 00058 00059 __disable_irq(); //At this point we don't want IRQs anymore 00060 00061 //Get current time 00062 uint32_t subsecs = RTC->SSR; 00063 time_t secs = rtc_read(); 00064 00065 //Calculate alarm values 00066 //Subseconds is countdown, so substract the 'added' sub-seconds and prevent underflow 00067 if (subsecs < subsecsadd) { 00068 subsecs += prescaler; 00069 secs++; 00070 } 00071 subsecs -= subsecsadd; 00072 00073 //Set seconds correctly 00074 secs += s; 00075 struct tm *timeinfo = localtime(&secs); 00076 00077 //Enable rising edge EXTI interrupt of the RTC 00078 EXTI->IMR |= RTC_EXTI_LINE_ALARM_EVENT; 00079 EXTI->EMR &= ~RTC_EXTI_LINE_ALARM_EVENT; 00080 EXTI->RTSR |= RTC_EXTI_LINE_ALARM_EVENT; 00081 EXTI->FTSR &= ~RTC_EXTI_LINE_ALARM_EVENT; 00082 00083 //Calculate alarm register values 00084 uint32_t alarmreg = 0; 00085 alarmreg |= BYTE2BCD(timeinfo->tm_sec) << 0; 00086 alarmreg |= BYTE2BCD(timeinfo->tm_min) << 8; 00087 alarmreg |= BYTE2BCD(timeinfo->tm_hour) << 16; 00088 alarmreg |= BYTE2BCD(timeinfo->tm_mday) << 24; 00089 00090 //Enable RTC interrupt 00091 RTC->ALRMAR = alarmreg; 00092 RTC->ALRMASSR = subsecs | RTC_ALRMASSR_MASKSS; //Mask no subseconds 00093 RTC->CR |= RTC_CR_ALRAE | RTC_CR_ALRAIE; //Enable Alarm 00094 00095 RTC->WPR = 0xFF; //Enable RTC write protection 00096 //PWR->CR &= ~PWR_CR_DBP; //Disable power domain 00097 00098 __enable_irq(); //Alarm is set, so irqs can be enabled again 00099 00100 //Enable everything else 00101 NVIC_SetVector(RTC_IRQ, (uint32_t)WakeUp::irq_handler); 00102 NVIC_EnableIRQ(RTC_IRQ); 00103 } 00104 00105 00106 void WakeUp::irq_handler(void) 00107 { 00108 //Clear RTC + EXTI interrupt flags 00109 //PWR->CR |= PWR_CR_DBP; //Enable power domain 00110 RTC->ISR &= ~RTC_ISR_ALRAF; 00111 RTC->WPR = 0xCA; //Disable RTC write protection 00112 RTC->WPR = 0x53; 00113 RTC->CR &= ~RTC_CR_ALRAE; 00114 RTC->WPR = 0xFF; //Enable RTC write protection 00115 EXTI->PR = RTC_EXTI_LINE_ALARM_EVENT; 00116 //PWR->CR &= ~PWR_CR_DBP; //Disable power domain 00117 callback.call(); 00118 } 00119 00120 void WakeUp::calibrate(void) 00121 { 00122 //RTC, we assume it is accurate enough without calibration 00123 } 00124 00125 00126 #endif
Generated on Sun Jul 17 2022 01:34:26 by
1.7.2
