ms2s,STM32 Private
Fork of WakeUp by
Embed:
(wiki syntax)
Show/hide line numbers
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