Added Restart(by RESET) function from Standby mode only for some Nucleo boards (STM32 series)

Dependencies:   LPC1114_WakeInterruptIn

Dependents:   Check_StandBy

Fork of WakeUp by Erik -

Example program using "Standby function" for Nucleo series is here.
/users/kenjiArai/code/Check_StandBy/

Committer:
kenjiArai
Date:
Tue Oct 03 00:30:47 2017 +0000
Revision:
26:df9d01556394
Parent:
25:2bd9df8c3ac8
disable DEBUG mode

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sissors 9:29bdf5fed21a 1 #ifdef TARGET_STM
kenjiArai 25:2bd9df8c3ac8 2 // added by JH1PJL 2017-9-21
kenjiArai 25:2bd9df8c3ac8 3 #if defined(TARGET_NUCLEO_F446RE) || defined(TARGET_NUCLEO_F411RE)\
kenjiArai 25:2bd9df8c3ac8 4 || defined(TARGET_NUCLEO_F401RE)\
kenjiArai 25:2bd9df8c3ac8 5 || defined(TARGET_NUCLEO_L152RE) || defined(TARGET_NUCLEO_L073RZ)\
kenjiArai 25:2bd9df8c3ac8 6 || defined(TARGET_NUCLEO_L053R8)
kenjiArai 25:2bd9df8c3ac8 7 // use WakeUp_STM32_others.cpp
kenjiArai 25:2bd9df8c3ac8 8 #else
Sissors 9:29bdf5fed21a 9
Sissors 9:29bdf5fed21a 10 #include "WakeUp.h"
Sissors 9:29bdf5fed21a 11 #include "rtc_api.h"
Sissors 9:29bdf5fed21a 12
Sissors 9:29bdf5fed21a 13 #define BYTE2BCD(byte) ((byte % 10) | ((byte / 10) << 4))
Sissors 9:29bdf5fed21a 14
Sissors 9:29bdf5fed21a 15 //Most things are pretty similar between the different STM targets.
Sissors 9:29bdf5fed21a 16 //Only the IRQ number the alarm is connected to differs. Any errors
Sissors 9:29bdf5fed21a 17 //with RTC_IRQn/RTC_Alarm_IRQn in them are related to this
Sissors 15:b2a710aca356 18 #if defined(TARGET_M4) || defined(TARGET_M3)
kenjiArai 25:2bd9df8c3ac8 19 #define RTC_IRQ RTC_Alarm_IRQn
Sissors 9:29bdf5fed21a 20 #else
Sissors 9:29bdf5fed21a 21 #define RTC_IRQ RTC_IRQn
Sissors 9:29bdf5fed21a 22 #endif
Sissors 9:29bdf5fed21a 23
Sissors 20:68f2ee917691 24 // Some things to handle Disco L476VG (and similar ones)
Sissors 20:68f2ee917691 25 #if defined(TARGET_STM32L4)
Sissors 20:68f2ee917691 26 #define IMR IMR1
Sissors 20:68f2ee917691 27 #define EMR EMR1
Sissors 20:68f2ee917691 28 #define RTSR RTSR1
Sissors 20:68f2ee917691 29 #define FTSR FTSR2
Sissors 20:68f2ee917691 30 #define PR PR1
Sissors 20:68f2ee917691 31 #endif
Sissors 20:68f2ee917691 32
Sissors 17:49d9e3a3e904 33 //Disabling the Backup Powerdomain does not seem to work nicely anymore if you want to use other RTC functions afterwards.
Sissors 17:49d9e3a3e904 34 //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)
Sissors 17:49d9e3a3e904 35
Sissors 23:69a0c843e4bd 36 Callback<void()> WakeUp::callback;
Sissors 9:29bdf5fed21a 37
Sissors 9:29bdf5fed21a 38 void WakeUp::set_ms(uint32_t ms)
Sissors 9:29bdf5fed21a 39 {
Sissors 9:29bdf5fed21a 40 if (!rtc_isenabled()) { //Make sure RTC is running
Sissors 9:29bdf5fed21a 41 rtc_init();
Sissors 9:29bdf5fed21a 42 wait_us(250); //The f401 seems to want a delay after init
Sissors 9:29bdf5fed21a 43 }
Sissors 9:29bdf5fed21a 44
Sissors 17:49d9e3a3e904 45 //PWR->CR |= PWR_CR_DBP; //Enable power domain
Sissors 9:29bdf5fed21a 46 RTC->WPR = 0xCA; //Disable RTC write protection
Sissors 9:29bdf5fed21a 47 RTC->WPR = 0x53;
Sissors 9:29bdf5fed21a 48
Sissors 9:29bdf5fed21a 49 //Alarm must be disabled to change anything
Sissors 9:29bdf5fed21a 50 RTC->CR &= ~RTC_CR_ALRAE;
Sissors 9:29bdf5fed21a 51 while(!(RTC->ISR & RTC_ISR_ALRAWF));
Sissors 9:29bdf5fed21a 52
Sissors 9:29bdf5fed21a 53 if (ms == 0) { //Just disable alarm
Sissors 17:49d9e3a3e904 54 //PWR->CR &= ~PWR_CR_DBP; //Disable power domain
Sissors 9:29bdf5fed21a 55 RTC->WPR = 0xFF; //Enable RTC write protection
Sissors 9:29bdf5fed21a 56 return;
Sissors 9:29bdf5fed21a 57 }
Sissors 9:29bdf5fed21a 58
Sissors 9:29bdf5fed21a 59 //RTC prescaler + calculate how many sub-seconds should be added
Sissors 9:29bdf5fed21a 60 uint32_t prescaler = (RTC->PRER & 0x7FFF) + 1;
Sissors 9:29bdf5fed21a 61 uint32_t subsecsadd = ((ms % 1000) * prescaler) / 1000;
Sissors 9:29bdf5fed21a 62
Sissors 9:29bdf5fed21a 63 if ((ms < 1000) && (subsecsadd < 2))
Sissors 9:29bdf5fed21a 64 subsecsadd = 2; //At least 2 subsecs delay to be sure interrupt is called
Sissors 9:29bdf5fed21a 65
Sissors 9:29bdf5fed21a 66 __disable_irq(); //At this point we don't want IRQs anymore
Sissors 9:29bdf5fed21a 67
Sissors 9:29bdf5fed21a 68 //Get current time
Sissors 9:29bdf5fed21a 69 uint32_t subsecs = RTC->SSR;
Sissors 9:29bdf5fed21a 70 time_t secs = rtc_read();
Sissors 9:29bdf5fed21a 71
Sissors 9:29bdf5fed21a 72 //Calculate alarm values
Sissors 9:29bdf5fed21a 73 //Subseconds is countdown, so substract the 'added' sub-seconds and prevent underflow
Sissors 9:29bdf5fed21a 74 if (subsecs < subsecsadd) {
Sissors 9:29bdf5fed21a 75 subsecs += prescaler;
Sissors 9:29bdf5fed21a 76 secs++;
Sissors 9:29bdf5fed21a 77 }
Sissors 9:29bdf5fed21a 78 subsecs -= subsecsadd;
Sissors 9:29bdf5fed21a 79
Sissors 9:29bdf5fed21a 80 //Set seconds correctly
Sissors 9:29bdf5fed21a 81 secs += ms / 1000;
Sissors 9:29bdf5fed21a 82 struct tm *timeinfo = localtime(&secs);
Sissors 9:29bdf5fed21a 83
Sissors 9:29bdf5fed21a 84 //Enable rising edge EXTI interrupt of the RTC
Sissors 20:68f2ee917691 85 EXTI->IMR |= RTC_EXTI_LINE_ALARM_EVENT;
Sissors 20:68f2ee917691 86 EXTI->EMR &= ~RTC_EXTI_LINE_ALARM_EVENT;
Sissors 20:68f2ee917691 87 EXTI->RTSR |= RTC_EXTI_LINE_ALARM_EVENT;
Sissors 20:68f2ee917691 88 EXTI->FTSR &= ~RTC_EXTI_LINE_ALARM_EVENT;
Sissors 9:29bdf5fed21a 89
Sissors 9:29bdf5fed21a 90 //Calculate alarm register values
Sissors 9:29bdf5fed21a 91 uint32_t alarmreg = 0;
Sissors 9:29bdf5fed21a 92 alarmreg |= BYTE2BCD(timeinfo->tm_sec) << 0;
Sissors 9:29bdf5fed21a 93 alarmreg |= BYTE2BCD(timeinfo->tm_min) << 8;
Sissors 9:29bdf5fed21a 94 alarmreg |= BYTE2BCD(timeinfo->tm_hour) << 16;
Sissors 9:29bdf5fed21a 95 alarmreg |= BYTE2BCD(timeinfo->tm_mday) << 24;
Sissors 9:29bdf5fed21a 96
Sissors 9:29bdf5fed21a 97 //Enable RTC interrupt
Sissors 9:29bdf5fed21a 98 RTC->ALRMAR = alarmreg;
Sissors 9:29bdf5fed21a 99 RTC->ALRMASSR = subsecs | RTC_ALRMASSR_MASKSS; //Mask no subseconds
Sissors 9:29bdf5fed21a 100 RTC->CR |= RTC_CR_ALRAE | RTC_CR_ALRAIE; //Enable Alarm
Sissors 9:29bdf5fed21a 101
Sissors 9:29bdf5fed21a 102 RTC->WPR = 0xFF; //Enable RTC write protection
Sissors 17:49d9e3a3e904 103 //PWR->CR &= ~PWR_CR_DBP; //Disable power domain
Sissors 9:29bdf5fed21a 104
Sissors 9:29bdf5fed21a 105 __enable_irq(); //Alarm is set, so irqs can be enabled again
Sissors 9:29bdf5fed21a 106
Sissors 9:29bdf5fed21a 107 //Enable everything else
kenjiArai 25:2bd9df8c3ac8 108 NVIC_SetVector(RTC_IRQ, (uint32_t)WakeUp::irq_handler);
Sissors 9:29bdf5fed21a 109 NVIC_EnableIRQ(RTC_IRQ);
Sissors 9:29bdf5fed21a 110 }
Sissors 9:29bdf5fed21a 111
Sissors 9:29bdf5fed21a 112
Sissors 9:29bdf5fed21a 113 void WakeUp::irq_handler(void)
Sissors 9:29bdf5fed21a 114 {
Sissors 9:29bdf5fed21a 115 //Clear RTC + EXTI interrupt flags
Sissors 17:49d9e3a3e904 116 //PWR->CR |= PWR_CR_DBP; //Enable power domain
Sissors 9:29bdf5fed21a 117 RTC->ISR &= ~RTC_ISR_ALRAF;
Sissors 17:49d9e3a3e904 118 RTC->WPR = 0xCA; //Disable RTC write protection
Sissors 17:49d9e3a3e904 119 RTC->WPR = 0x53;
Sissors 17:49d9e3a3e904 120 RTC->CR &= ~RTC_CR_ALRAE;
Sissors 17:49d9e3a3e904 121 RTC->WPR = 0xFF; //Enable RTC write protection
Sissors 20:68f2ee917691 122 EXTI->PR = RTC_EXTI_LINE_ALARM_EVENT;
Sissors 17:49d9e3a3e904 123 //PWR->CR &= ~PWR_CR_DBP; //Disable power domain
Sissors 9:29bdf5fed21a 124 callback.call();
Sissors 9:29bdf5fed21a 125 }
Sissors 9:29bdf5fed21a 126
Sissors 9:29bdf5fed21a 127 void WakeUp::calibrate(void)
Sissors 9:29bdf5fed21a 128 {
Sissors 9:29bdf5fed21a 129 //RTC, we assume it is accurate enough without calibration
Sissors 9:29bdf5fed21a 130 }
Sissors 9:29bdf5fed21a 131
kenjiArai 25:2bd9df8c3ac8 132 #endif // TARGET_NUCLEO_F446RE (added by JH1PJL 2017-9-21)
Sissors 9:29bdf5fed21a 133 #endif