Added Restart(by RESET) function from Standby mode only for some Nucleo boards (STM32 series)
Dependencies: LPC1114_WakeInterruptIn
Fork of WakeUp by
Example program using "Standby function" for Nucleo series is here.
/users/kenjiArai/code/Check_StandBy/
Device/WakeUp_STM32_others.cpp@26:df9d01556394, 2017-10-03 (annotated)
- 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?
User | Revision | Line number | New 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 |