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.
Dependents: Lab04_Check_StandBy_os2 Lab04_wakeup_STM32
WakeUp_STM32.cpp
- Committer:
- cspista
- Date:
- 2021-11-11
- Revision:
- 2:502051beeb95
- Parent:
- 0:abaa4fd0c727
File content as of revision 2:502051beeb95:
/* Original idea & program https://os.mbed.com/users/Sissors/code/WakeUp/ by Erik modified version https://os.mbed.com/users/kenjiArai/code/WakeUp/ */ /* * Modified only for STM CPU * by Kenji Arai / JH1PJL * * http://www7b.biglobe.ne.jp/~kenjia/ * http://mbed.org/users/kenjiArai/ * Created: September 21st, 2017 * Revised: March 12th, 2020 */ #if \ defined(TARGET_NUCLEO_F334R8) # error Not support yet #elif \ defined(TARGET_NUCLEO_F401RE)\ || defined(TARGET_NUCLEO_F411RE)\ || defined(TARGET_NUCLEO_F446RE)\ || defined(TARGET_NUCLEO_L053R8)\ || defined(TARGET_NUCLEO_L073RZ)\ || defined(TARGET_NUCLEO_L152RE) #include "WakeUp_STM32.h" #include "rtc_api.h" #define BYTE2BCD(byte) ((byte % 10) | ((byte / 10) << 4)) //Most things are pretty similar between the different STM targets. //Only the IRQ number the alarm is connected to differs. Any errors //with RTC_IRQn/RTC_Alarm_IRQn in them are related to this #if defined(TARGET_M4) || defined(TARGET_M3) #define RTC_IRQ RTC_Alarm_IRQn #else #define RTC_IRQ RTC_IRQn #endif // Some things to handle Disco L476VG (and similar ones) #if defined(TARGET_STM32L4) #define IMR IMR1 #define EMR EMR1 #define RTSR RTSR1 #define FTSR FTSR2 #define PR PR1 #endif void WakeUp::set_ms(uint32_t ms) { if (ms == 0) { //Just disable alarm return; } if (!rtc_isenabled()) { //Make sure RTC is running rtc_init(); wait_us(250); //The f401 seems to want a delay after init } PWR->CR |= PWR_CR_DBP; //Enable power domain RTC->WPR = 0xCA; //Disable RTC write protection RTC->WPR = 0x53; //Alarm must be disabled to change anything RTC->CR &= ~RTC_CR_ALRAE; RTC->CR &= 0x00ff00ff; while(!(RTC->ISR & RTC_ISR_ALRAWF)); //RTC prescaler + calculate how many sub-seconds should be added uint32_t prescaler = (RTC->PRER & 0x7FFF) + 1; uint32_t subsecsadd = ((ms % 1000) * prescaler) / 1000; if ((ms < 1000) && (subsecsadd < 2)) subsecsadd = 2;//At least 5 subsecs delay to be sure interrupt is called __disable_irq(); //At this point we don't want IRQs anymore //Get current time uint32_t subsecs = RTC->SSR; time_t secs = rtc_read(); //Calculate alarm values //Subseconds is countdown, // so substract the 'added' sub-seconds and prevent underflow if (subsecs < subsecsadd) { subsecs += prescaler; secs++; } subsecs -= subsecsadd; //Set seconds correctly secs += ms / 1000; struct tm *timeinfo = localtime(&secs); //Enable rising edge EXTI interrupt of the RTC EXTI->IMR |= RTC_EXTI_LINE_ALARM_EVENT; // enable it EXTI->EMR &= ~RTC_EXTI_LINE_ALARM_EVENT; // disable event EXTI->RTSR |= RTC_EXTI_LINE_ALARM_EVENT; // enable rising edge EXTI->FTSR &= ~RTC_EXTI_LINE_ALARM_EVENT; // disable falling edge //Calculate alarm register values uint32_t alarmreg = 0; alarmreg |= BYTE2BCD(timeinfo->tm_sec) << 0; alarmreg |= BYTE2BCD(timeinfo->tm_min) << 8; alarmreg |= BYTE2BCD(timeinfo->tm_hour) << 16; alarmreg |= BYTE2BCD(timeinfo->tm_mday) << 24; alarmreg &= 0x3f3f7f7f; // All MSKx & WDSEL = 0 //Enable RTC interrupt (use Alarm-A) RTC->ALRMAR = alarmreg; RTC->ALRMASSR = subsecs | RTC_ALRMASSR_MASKSS; //Mask no subseconds RTC->CR |= RTC_CR_ALRAE | RTC_CR_ALRAIE; //Enable Alarm-A RTC->WPR = 0xFF; //Enable RTC write protection PWR->CR &= ~PWR_CR_DBP; //Disable power domain __enable_irq(); //Alarm is set, so irqs can be enabled again //Enable everything else NVIC_SetVector(RTC_IRQ, (uint32_t)WakeUp::irq_handler); NVIC_EnableIRQ(RTC_IRQ); } void WakeUp::standby_then_reset(uint32_t ms) { if (ms == 0){ // just go to Reset system_reset(); } set_ms(ms); PWR->CR |= PWR_CR_CWUF; HAL_PWR_EnterSTANDBYMode(); } void WakeUp::irq_handler(void) { //Clear RTC + EXTI interrupt flags PWR->CR |= PWR_CR_DBP; // Enable power domain RTC->ISR &= ~RTC_ISR_ALRAF; RTC->CR &= 0x00ff00ff; // just in case RTC->WPR = 0xCA; // Disable RTC write protection RTC->WPR = 0x53; RTC->CR &= ~(RTC_CR_ALRAE | RTC_CR_ALRAIE); //DisEnable Alarm-A RTC->WPR = 0xFF; // Enable RTC write protection EXTI->PR = RTC_EXTI_LINE_ALARM_EVENT; PWR->CR &= ~PWR_CR_DBP; // Disable power domain system_reset(); } #endif