add the implementation of LP1768 wakeup based on the old WakeUp library
Dependencies: LPC1114_WakeInterruptIn
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 #define EXTI_RTC_LINE (1 << 17) 00008 00009 //Most things are pretty similar between the different STM targets. 00010 //Only the IRQ number the alarm is connected to differs. Any errors 00011 //with RTC_IRQn/RTC_Alarm_IRQn in them are related to this 00012 #if defined(TARGET_M4) 00013 #define RTC_IRQ RTC_Alarm_IRQn 00014 #else 00015 #define RTC_IRQ RTC_IRQn 00016 #endif 00017 00018 FunctionPointer WakeUp::callback; 00019 00020 void WakeUp::set_ms(uint32_t ms) 00021 { 00022 if (!rtc_isenabled()) { //Make sure RTC is running 00023 rtc_init(); 00024 wait_us(250); //The f401 seems to want a delay after init 00025 } 00026 00027 PWR->CR |= PWR_CR_DBP; //Enable power domain 00028 RTC->WPR = 0xCA; //Disable RTC write protection 00029 RTC->WPR = 0x53; 00030 00031 //Alarm must be disabled to change anything 00032 RTC->CR &= ~RTC_CR_ALRAE; 00033 while(!(RTC->ISR & RTC_ISR_ALRAWF)); 00034 00035 if (ms == 0) { //Just disable alarm 00036 PWR->CR &= ~PWR_CR_DBP; //Disable power domain 00037 RTC->WPR = 0xFF; //Enable RTC write protection 00038 return; 00039 } 00040 00041 //RTC prescaler + calculate how many sub-seconds should be added 00042 uint32_t prescaler = (RTC->PRER & 0x7FFF) + 1; 00043 uint32_t subsecsadd = ((ms % 1000) * prescaler) / 1000; 00044 00045 if ((ms < 1000) && (subsecsadd < 2)) 00046 subsecsadd = 2; //At least 2 subsecs delay to be sure interrupt is called 00047 00048 __disable_irq(); //At this point we don't want IRQs anymore 00049 00050 //Get current time 00051 uint32_t subsecs = RTC->SSR; 00052 time_t secs = rtc_read(); 00053 00054 //Calculate alarm values 00055 //Subseconds is countdown, so substract the 'added' sub-seconds and prevent underflow 00056 if (subsecs < subsecsadd) { 00057 subsecs += prescaler; 00058 secs++; 00059 } 00060 subsecs -= subsecsadd; 00061 00062 //Set seconds correctly 00063 secs += ms / 1000; 00064 struct tm *timeinfo = localtime(&secs); 00065 00066 //Enable rising edge EXTI interrupt of the RTC 00067 EXTI->IMR |= EXTI_RTC_LINE; 00068 EXTI->EMR &= ~EXTI_RTC_LINE; 00069 EXTI->RTSR |= EXTI_RTC_LINE; 00070 EXTI->FTSR &= ~EXTI_RTC_LINE; 00071 00072 //Calculate alarm register values 00073 uint32_t alarmreg = 0; 00074 alarmreg |= BYTE2BCD(timeinfo->tm_sec) << 0; 00075 alarmreg |= BYTE2BCD(timeinfo->tm_min) << 8; 00076 alarmreg |= BYTE2BCD(timeinfo->tm_hour) << 16; 00077 alarmreg |= BYTE2BCD(timeinfo->tm_mday) << 24; 00078 00079 //Enable RTC interrupt 00080 RTC->ALRMAR = alarmreg; 00081 RTC->ALRMASSR = subsecs | RTC_ALRMASSR_MASKSS; //Mask no subseconds 00082 RTC->CR |= RTC_CR_ALRAE | RTC_CR_ALRAIE; //Enable Alarm 00083 00084 RTC->WPR = 0xFF; //Enable RTC write protection 00085 PWR->CR &= ~PWR_CR_DBP; //Disable power domain 00086 00087 __enable_irq(); //Alarm is set, so irqs can be enabled again 00088 00089 //Enable everything else 00090 NVIC_SetVector(RTC_IRQ, (uint32_t)WakeUp::irq_handler); 00091 NVIC_EnableIRQ(RTC_IRQ); 00092 } 00093 00094 00095 void WakeUp::irq_handler(void) 00096 { 00097 //Clear RTC + EXTI interrupt flags 00098 PWR->CR |= PWR_CR_DBP; //Enable power domain 00099 RTC->ISR &= ~RTC_ISR_ALRAF; 00100 EXTI->PR = EXTI_RTC_LINE; 00101 PWR->CR &= ~PWR_CR_DBP; //Disable power domain 00102 callback.call(); 00103 } 00104 00105 void WakeUp::calibrate(void) 00106 { 00107 //RTC, we assume it is accurate enough without calibration 00108 } 00109 00110 00111 #endif
Generated on Wed Jul 13 2022 02:11:11 by 1.7.2