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
kenjiArai 25:2bd9df8c3ac8 1 // Created new file only for STM32/Nucleo boards which I have own it
kenjiArai 25:2bd9df8c3ac8 2 // by JH1PJL 2017-9-21
kenjiArai 25:2bd9df8c3ac8 3
kenjiArai 25:2bd9df8c3ac8 4 #if defined(TARGET_NUCLEO_F446RE) || defined(TARGET_NUCLEO_F411RE)\
kenjiArai 25:2bd9df8c3ac8 5 || defined(TARGET_NUCLEO_F401RE)\
kenjiArai 25:2bd9df8c3ac8 6 || defined(TARGET_NUCLEO_L152RE) || defined(TARGET_NUCLEO_L073RZ)\
kenjiArai 25:2bd9df8c3ac8 7 || defined(TARGET_NUCLEO_L053R8)
kenjiArai 25:2bd9df8c3ac8 8
kenjiArai 25:2bd9df8c3ac8 9 #include "WakeUp.h"
kenjiArai 25:2bd9df8c3ac8 10 #include "rtc_api.h"
kenjiArai 25:2bd9df8c3ac8 11
kenjiArai 26:df9d01556394 12 //#define DEBUG
kenjiArai 25:2bd9df8c3ac8 13
kenjiArai 25:2bd9df8c3ac8 14 extern Serial pc;
kenjiArai 25:2bd9df8c3ac8 15
kenjiArai 26:df9d01556394 16 #if 0
kenjiArai 25:2bd9df8c3ac8 17 #define DBG(...) pc.printf(__VA_ARGS__)
kenjiArai 25:2bd9df8c3ac8 18 #else
kenjiArai 25:2bd9df8c3ac8 19 #define DBG(...) {;}
kenjiArai 25:2bd9df8c3ac8 20 #endif
kenjiArai 25:2bd9df8c3ac8 21
kenjiArai 26:df9d01556394 22 #if 0
kenjiArai 25:2bd9df8c3ac8 23 #define DBGP(...) pc.printf(__VA_ARGS__)
kenjiArai 25:2bd9df8c3ac8 24 #else
kenjiArai 25:2bd9df8c3ac8 25 #define DBGP(...) {;}
kenjiArai 25:2bd9df8c3ac8 26 #endif
kenjiArai 25:2bd9df8c3ac8 27
kenjiArai 25:2bd9df8c3ac8 28 #define BYTE2BCD(byte) ((byte % 10) | ((byte / 10) << 4))
kenjiArai 25:2bd9df8c3ac8 29
kenjiArai 25:2bd9df8c3ac8 30 //Most things are pretty similar between the different STM targets.
kenjiArai 25:2bd9df8c3ac8 31 //Only the IRQ number the alarm is connected to differs. Any errors
kenjiArai 25:2bd9df8c3ac8 32 //with RTC_IRQn/RTC_Alarm_IRQn in them are related to this
kenjiArai 25:2bd9df8c3ac8 33 #if defined(TARGET_M4) || defined(TARGET_M3)
kenjiArai 25:2bd9df8c3ac8 34 #define RTC_IRQ RTC_Alarm_IRQn
kenjiArai 25:2bd9df8c3ac8 35 #else
kenjiArai 25:2bd9df8c3ac8 36 #define RTC_IRQ RTC_IRQn
kenjiArai 25:2bd9df8c3ac8 37 #endif
kenjiArai 25:2bd9df8c3ac8 38
kenjiArai 25:2bd9df8c3ac8 39 // Some things to handle Disco L476VG (and similar ones)
kenjiArai 25:2bd9df8c3ac8 40 #if defined(TARGET_STM32L4)
kenjiArai 25:2bd9df8c3ac8 41 #define IMR IMR1
kenjiArai 25:2bd9df8c3ac8 42 #define EMR EMR1
kenjiArai 25:2bd9df8c3ac8 43 #define RTSR RTSR1
kenjiArai 25:2bd9df8c3ac8 44 #define FTSR FTSR2
kenjiArai 25:2bd9df8c3ac8 45 #define PR PR1
kenjiArai 25:2bd9df8c3ac8 46 #endif
kenjiArai 25:2bd9df8c3ac8 47
kenjiArai 25:2bd9df8c3ac8 48 Callback<void()> WakeUp::callback;
kenjiArai 25:2bd9df8c3ac8 49 bool WakeUp::use_reset = false;
kenjiArai 25:2bd9df8c3ac8 50
kenjiArai 25:2bd9df8c3ac8 51
kenjiArai 25:2bd9df8c3ac8 52 void WakeUp::set_ms(uint32_t ms)
kenjiArai 25:2bd9df8c3ac8 53 {
kenjiArai 25:2bd9df8c3ac8 54 if (ms == 0) { //Just disable alarm
kenjiArai 25:2bd9df8c3ac8 55 return;
kenjiArai 25:2bd9df8c3ac8 56 }
kenjiArai 25:2bd9df8c3ac8 57
kenjiArai 25:2bd9df8c3ac8 58 if (!rtc_isenabled()) { //Make sure RTC is running
kenjiArai 25:2bd9df8c3ac8 59 rtc_init();
kenjiArai 25:2bd9df8c3ac8 60 wait_us(250); //The f401 seems to want a delay after init
kenjiArai 25:2bd9df8c3ac8 61 }
kenjiArai 25:2bd9df8c3ac8 62
kenjiArai 25:2bd9df8c3ac8 63 PWR->CR |= PWR_CR_DBP; //Enable power domain
kenjiArai 25:2bd9df8c3ac8 64 RTC->WPR = 0xCA; //Disable RTC write protection
kenjiArai 25:2bd9df8c3ac8 65 RTC->WPR = 0x53;
kenjiArai 25:2bd9df8c3ac8 66
kenjiArai 25:2bd9df8c3ac8 67 //Alarm must be disabled to change anything
kenjiArai 25:2bd9df8c3ac8 68 RTC->CR &= ~RTC_CR_ALRAE;
kenjiArai 25:2bd9df8c3ac8 69 RTC->CR &= 0x00ff00ff;
kenjiArai 25:2bd9df8c3ac8 70 while(!(RTC->ISR & RTC_ISR_ALRAWF));
kenjiArai 25:2bd9df8c3ac8 71
kenjiArai 25:2bd9df8c3ac8 72 DBG("Step(%u)\r\n", __LINE__);
kenjiArai 25:2bd9df8c3ac8 73
kenjiArai 25:2bd9df8c3ac8 74 //RTC prescaler + calculate how many sub-seconds should be added
kenjiArai 25:2bd9df8c3ac8 75 uint32_t prescaler = (RTC->PRER & 0x7FFF) + 1;
kenjiArai 25:2bd9df8c3ac8 76 uint32_t subsecsadd = ((ms % 1000) * prescaler) / 1000;
kenjiArai 25:2bd9df8c3ac8 77
kenjiArai 25:2bd9df8c3ac8 78 if ((ms < 1000) && (subsecsadd < 2))
kenjiArai 25:2bd9df8c3ac8 79 subsecsadd = 2;//At least 5 subsecs delay to be sure interrupt is called
kenjiArai 25:2bd9df8c3ac8 80
kenjiArai 25:2bd9df8c3ac8 81 __disable_irq(); //At this point we don't want IRQs anymore
kenjiArai 25:2bd9df8c3ac8 82
kenjiArai 25:2bd9df8c3ac8 83 //Get current time
kenjiArai 25:2bd9df8c3ac8 84 uint32_t subsecs = RTC->SSR;
kenjiArai 25:2bd9df8c3ac8 85 time_t secs = rtc_read();
kenjiArai 25:2bd9df8c3ac8 86 DBG("Step(%u),secs:%d,subsecs:%d\r\n", __LINE__, secs, subsecs);
kenjiArai 25:2bd9df8c3ac8 87
kenjiArai 25:2bd9df8c3ac8 88 //Calculate alarm values
kenjiArai 25:2bd9df8c3ac8 89 //Subseconds is countdown,
kenjiArai 25:2bd9df8c3ac8 90 // so substract the 'added' sub-seconds and prevent underflow
kenjiArai 25:2bd9df8c3ac8 91 if (subsecs < subsecsadd) {
kenjiArai 25:2bd9df8c3ac8 92 subsecs += prescaler;
kenjiArai 25:2bd9df8c3ac8 93 secs++;
kenjiArai 25:2bd9df8c3ac8 94 }
kenjiArai 25:2bd9df8c3ac8 95 subsecs -= subsecsadd;
kenjiArai 25:2bd9df8c3ac8 96
kenjiArai 25:2bd9df8c3ac8 97 //Set seconds correctly
kenjiArai 25:2bd9df8c3ac8 98 secs += ms / 1000;
kenjiArai 25:2bd9df8c3ac8 99 struct tm *timeinfo = localtime(&secs);
kenjiArai 25:2bd9df8c3ac8 100 DBG("Step(%u),secs:%d\r\n", __LINE__, secs);
kenjiArai 25:2bd9df8c3ac8 101
kenjiArai 25:2bd9df8c3ac8 102 //Enable rising edge EXTI interrupt of the RTC
kenjiArai 25:2bd9df8c3ac8 103 EXTI->IMR |= RTC_EXTI_LINE_ALARM_EVENT; // enable it
kenjiArai 25:2bd9df8c3ac8 104 EXTI->EMR &= ~RTC_EXTI_LINE_ALARM_EVENT; // disable event
kenjiArai 25:2bd9df8c3ac8 105 EXTI->RTSR |= RTC_EXTI_LINE_ALARM_EVENT; // enable rising edge
kenjiArai 25:2bd9df8c3ac8 106 EXTI->FTSR &= ~RTC_EXTI_LINE_ALARM_EVENT; // disable falling edge
kenjiArai 25:2bd9df8c3ac8 107
kenjiArai 25:2bd9df8c3ac8 108 //Calculate alarm register values
kenjiArai 25:2bd9df8c3ac8 109 uint32_t alarmreg = 0;
kenjiArai 25:2bd9df8c3ac8 110 alarmreg |= BYTE2BCD(timeinfo->tm_sec) << 0;
kenjiArai 25:2bd9df8c3ac8 111 alarmreg |= BYTE2BCD(timeinfo->tm_min) << 8;
kenjiArai 25:2bd9df8c3ac8 112 alarmreg |= BYTE2BCD(timeinfo->tm_hour) << 16;
kenjiArai 25:2bd9df8c3ac8 113 alarmreg |= BYTE2BCD(timeinfo->tm_mday) << 24;
kenjiArai 25:2bd9df8c3ac8 114 alarmreg &= 0x3f3f7f7f; // All MSKx & WDSEL = 0
kenjiArai 25:2bd9df8c3ac8 115
kenjiArai 25:2bd9df8c3ac8 116 //Enable RTC interrupt (use Alarm-A)
kenjiArai 25:2bd9df8c3ac8 117 DBG("Step(%u),alarmreg:0x%08x\r\n", __LINE__, alarmreg);
kenjiArai 25:2bd9df8c3ac8 118 DBG("Step(%u),RTC->ISR:0x%08x\r\n", __LINE__, RTC->ISR);
kenjiArai 25:2bd9df8c3ac8 119 RTC->ALRMAR = alarmreg;
kenjiArai 25:2bd9df8c3ac8 120 RTC->ALRMASSR = subsecs | RTC_ALRMASSR_MASKSS; //Mask no subseconds
kenjiArai 25:2bd9df8c3ac8 121 DBG("Step(%u),alarmreg(reg):0x%08x\r\n", __LINE__, RTC->ALRMAR);
kenjiArai 25:2bd9df8c3ac8 122 RTC->CR |= RTC_CR_ALRAE | RTC_CR_ALRAIE; //Enable Alarm-A
kenjiArai 25:2bd9df8c3ac8 123 DBG("Step(%u),RTC->CR:0x%08x\r\n", __LINE__, RTC->CR);
kenjiArai 25:2bd9df8c3ac8 124
kenjiArai 25:2bd9df8c3ac8 125 RTC->WPR = 0xFF; //Enable RTC write protection
kenjiArai 25:2bd9df8c3ac8 126 PWR->CR &= ~PWR_CR_DBP; //Disable power domain
kenjiArai 25:2bd9df8c3ac8 127
kenjiArai 25:2bd9df8c3ac8 128 __enable_irq(); //Alarm is set, so irqs can be enabled again
kenjiArai 25:2bd9df8c3ac8 129
kenjiArai 25:2bd9df8c3ac8 130 //Enable everything else
kenjiArai 25:2bd9df8c3ac8 131 NVIC_SetVector(RTC_IRQ, (uint32_t)WakeUp::irq_handler);
kenjiArai 25:2bd9df8c3ac8 132 NVIC_EnableIRQ(RTC_IRQ);
kenjiArai 25:2bd9df8c3ac8 133 use_reset = false;
kenjiArai 25:2bd9df8c3ac8 134 //---- Only for Debug purpose
kenjiArai 25:2bd9df8c3ac8 135 DBGP("PWR->CR 0x%08x:0x%08x\r\n",&PWR->CR, PWR->CR);
kenjiArai 25:2bd9df8c3ac8 136 DBGP("PWR->CSR 0x%08x:0x%08x\r\n",&PWR->CSR, PWR->CSR);
kenjiArai 25:2bd9df8c3ac8 137 DBGP("SCB->SCR 0x%08x:0x%08x\r\n",&SCB->SCR, SCB->SCR);
kenjiArai 25:2bd9df8c3ac8 138 DBGP("SCB->AIRCR 0x%08x:0x%08x\r\n",&SCB->AIRCR, SCB->AIRCR);
kenjiArai 25:2bd9df8c3ac8 139 DBGP("EXTI->IMR 0x%08x:0x%08x\r\n",&EXTI->IMR, EXTI->IMR);
kenjiArai 25:2bd9df8c3ac8 140 DBGP("EXTI->EMR 0x%08x:0x%08x\r\n",&EXTI->EMR, EXTI->EMR);
kenjiArai 25:2bd9df8c3ac8 141 DBGP("EXTI->RTSR 0x%08x:0x%08x\r\n",&EXTI->RTSR, EXTI->RTSR);
kenjiArai 25:2bd9df8c3ac8 142 DBGP("EXTI->FTSR 0x%08x:0x%08x\r\n",&EXTI->FTSR, EXTI->FTSR);
kenjiArai 25:2bd9df8c3ac8 143 DBGP("RTC->TR 0x%08x:0x%08x\r\n",&RTC->TR,RTC->TR);
kenjiArai 25:2bd9df8c3ac8 144 DBGP("RTC->DR 0x%08x:0x%08x\r\n",&RTC->DR,RTC->DR);
kenjiArai 25:2bd9df8c3ac8 145 DBGP("RTC->CR 0x%08x:0x%08x\r\n",&RTC->CR,RTC->CR);
kenjiArai 25:2bd9df8c3ac8 146 DBGP("RTC->ISR 0x%08x:0x%08x\r\n",&RTC->ISR,RTC->ISR);
kenjiArai 25:2bd9df8c3ac8 147 DBGP("RTC->ALRMAR 0x%08x:0x%08x\r\n",&RTC->ALRMAR,RTC->ALRMAR);
kenjiArai 25:2bd9df8c3ac8 148 }
kenjiArai 25:2bd9df8c3ac8 149
kenjiArai 25:2bd9df8c3ac8 150 void WakeUp::standby_then_reset(uint32_t ms)
kenjiArai 25:2bd9df8c3ac8 151 {
kenjiArai 25:2bd9df8c3ac8 152 DBG("Step(%u),ms:%d\r\n", __LINE__, ms);
kenjiArai 25:2bd9df8c3ac8 153 if (ms == 0){ // just go to Reset
kenjiArai 25:2bd9df8c3ac8 154 __NVIC_SystemReset();
kenjiArai 25:2bd9df8c3ac8 155 }
kenjiArai 25:2bd9df8c3ac8 156 set_ms(ms);
kenjiArai 25:2bd9df8c3ac8 157 use_reset = true;
kenjiArai 25:2bd9df8c3ac8 158 PWR->CR |= PWR_CR_CWUF;
kenjiArai 25:2bd9df8c3ac8 159 HAL_PWR_EnterSTANDBYMode();
kenjiArai 25:2bd9df8c3ac8 160 }
kenjiArai 25:2bd9df8c3ac8 161
kenjiArai 25:2bd9df8c3ac8 162 void WakeUp::irq_handler(void)
kenjiArai 25:2bd9df8c3ac8 163 {
kenjiArai 25:2bd9df8c3ac8 164 //Clear RTC + EXTI interrupt flags
kenjiArai 25:2bd9df8c3ac8 165 PWR->CR |= PWR_CR_DBP; // Enable power domain
kenjiArai 25:2bd9df8c3ac8 166 RTC->ISR &= ~RTC_ISR_ALRAF;
kenjiArai 25:2bd9df8c3ac8 167 RTC->CR &= 0x00ff00ff; // just in case
kenjiArai 25:2bd9df8c3ac8 168 RTC->WPR = 0xCA; // Disable RTC write protection
kenjiArai 25:2bd9df8c3ac8 169 RTC->WPR = 0x53;
kenjiArai 25:2bd9df8c3ac8 170 RTC->CR &= ~(RTC_CR_ALRAE | RTC_CR_ALRAIE); //DisEnable Alarm-A
kenjiArai 25:2bd9df8c3ac8 171 RTC->WPR = 0xFF; // Enable RTC write protection
kenjiArai 25:2bd9df8c3ac8 172 EXTI->PR = RTC_EXTI_LINE_ALARM_EVENT;
kenjiArai 25:2bd9df8c3ac8 173 PWR->CR &= ~PWR_CR_DBP; // Disable power domain
kenjiArai 25:2bd9df8c3ac8 174 if (use_reset == true){
kenjiArai 25:2bd9df8c3ac8 175 NVIC_SystemReset();
kenjiArai 25:2bd9df8c3ac8 176 } else {
kenjiArai 25:2bd9df8c3ac8 177 if (callback){
kenjiArai 25:2bd9df8c3ac8 178 callback.call();
kenjiArai 25:2bd9df8c3ac8 179 }
kenjiArai 25:2bd9df8c3ac8 180 }
kenjiArai 25:2bd9df8c3ac8 181 }
kenjiArai 25:2bd9df8c3ac8 182
kenjiArai 25:2bd9df8c3ac8 183 void WakeUp::calibrate(void)
kenjiArai 25:2bd9df8c3ac8 184 {
kenjiArai 25:2bd9df8c3ac8 185 //RTC, we assume it is accurate enough without calibration
kenjiArai 25:2bd9df8c3ac8 186 }
kenjiArai 25:2bd9df8c3ac8 187
kenjiArai 25:2bd9df8c3ac8 188 #endif