Added Restart(by RESET) function from Standby mode only for some Nucleo boards (STM32 series)
Dependencies: LPC1114_WakeInterruptIn
Fork of WakeUp by
WakeUp_LPC11XX.cpp
00001 /** 00002 See homepage of this lib for LPC11xx special treatment 00003 **/ 00004 00005 #ifdef TARGET_LPC11XX_11CXX 00006 00007 #include "WakeUp.h" 00008 #include "WakeInterruptIn.h" 00009 #include "pinmap.h" 00010 #include "toolchain.h" 00011 00012 //Pin used, allowed pins = P0_1 (dp24, default), P0_8 (dp1) and P0_9 (dp2) 00013 //By defining WakeUpPin in for example your main.cpp this can be overridden 00014 WEAK PinName WakeUpPin = dp24; 00015 extern PinName WakeUpPin; 00016 00017 WakeInterruptIn IRQ_in(WakeUpPin); 00018 PwmOut pulse_out(WakeUpPin); 00019 00020 Callback<void()> WakeUp::callback; 00021 float WakeUp::cycles_per_ms = 20.0; 00022 00023 static uint32_t old_clk_sel = ~0; 00024 static uint32_t SYSAHBCLKCTRL; 00025 static uint32_t TCR, PR, MR3; 00026 static LPC_TMR_TypeDef *WakeUpTimer; 00027 static uint32_t SYSAHBCLKCTRL_Sleep; 00028 static uint8_t WakeUpTimer_Match; 00029 00030 static inline void restore(void); 00031 00032 00033 void WakeUp::set_ms(uint32_t ms) 00034 { 00035 if (old_clk_sel == ~0) { //Only during first run 00036 old_clk_sel = LPC_SYSCON->MAINCLKSEL; 00037 SYSAHBCLKCTRL = LPC_SYSCON->SYSAHBCLKCTRL; 00038 00039 switch(WakeUpPin) { 00040 case dp24: 00041 WakeUpTimer = LPC_TMR32B0; 00042 SYSAHBCLKCTRL_Sleep = 0x15 | (1<<9); 00043 WakeUpTimer_Match = 2; 00044 break; 00045 case dp1: 00046 WakeUpTimer = LPC_TMR16B0; 00047 SYSAHBCLKCTRL_Sleep = 0x15 | (1<<7); 00048 WakeUpTimer_Match = 0; 00049 break; 00050 case dp2: 00051 WakeUpTimer = LPC_TMR16B0; 00052 SYSAHBCLKCTRL_Sleep = 0x15 | (1<<7); 00053 WakeUpTimer_Match = 1; 00054 break; 00055 default: 00056 error("Invalid WakeUp pin, choose dp1, dp2 or dp24"); 00057 } 00058 } 00059 00060 if (ms != 0) { 00061 if (LPC_SYSCON->SYSAHBCLKCTRL != SYSAHBCLKCTRL_Sleep) //Always when it is different from sleep settings 00062 SYSAHBCLKCTRL = LPC_SYSCON->SYSAHBCLKCTRL; 00063 00064 LPC_SYSCON->PDRUNCFG &= ~PDRUNCFG_WDTOSC_PD; 00065 LPC_SYSCON->PDSLEEPCFG = 0x000018B7 | (LPC_SYSCON->PDRUNCFG & (PDRUNCFG_WDTOSC_PD | PDRUNCFG_BOD_PD)); 00066 00067 //Set oscillator for 20kHz 00068 LPC_SYSCON->WDTOSCCTRL = 14 | (1<<5); 00069 00070 //Store old PWM 00071 TCR = WakeUpTimer->TCR; 00072 PR = WakeUpTimer->PR; 00073 MR3 = WakeUpTimer->MR3; 00074 00075 //Setup PWM 00076 WakeUpTimer->TCR = TMR16B0TCR_CRST; 00077 uint32_t ticks = (float)ms * cycles_per_ms; 00078 00079 //whatever timer it is, we treat it as 16-bit (with PR that is 32-bit still, do the math, it is enough for this) 00080 WakeUpTimer->PR = ticks >> 16; 00081 WakeUpTimer->MR[WakeUpTimer_Match] = ticks / ((ticks >> 16) + 1); 00082 WakeUpTimer->MR3 = 0xFFFF; 00083 00084 IRQ_in.rise(irq_handler); 00085 00086 //Disable most peripherals 00087 LPC_SYSCON->SYSAHBCLKCTRL = SYSAHBCLKCTRL_Sleep; 00088 00089 //Switch clock to WD OSC 00090 LPC_SYSCON->MAINCLKSEL = 0x2; 00091 LPC_SYSCON->MAINCLKUEN = 0; 00092 LPC_SYSCON->MAINCLKUEN = MAINCLKUEN_ENA; 00093 00094 //Enable PWM: 00095 WakeUpTimer->TCR = TMR16B0TCR_CEN; 00096 } else { 00097 //Else restore normal settings 00098 restore(); 00099 } 00100 00101 } 00102 00103 void WakeUp::irq_handler(void) 00104 { 00105 restore(); 00106 callback.call(); 00107 } 00108 00109 void WakeUp::calibrate(void) 00110 { 00111 //Save current pin function 00112 __IO uint32_t *reg = (__IO uint32_t*)(LPC_IOCON_BASE + (dp24 & 0xFF)); 00113 uint32_t old_pinfun = *reg; 00114 00115 //Set oscillator for 20kHz 00116 LPC_SYSCON->PDRUNCFG &= ~PDRUNCFG_WDTOSC_PD; 00117 LPC_SYSCON->WDTOSCCTRL = 14 | (1<<5); 00118 00119 //Direct WDT to the CLKOUT pin (dp24), sample it back 00120 DigitalIn din(dp24); 00121 Timer timer; 00122 00123 LPC_SYSCON->CLKOUTDIV = 1; 00124 LPC_SYSCON->CLKOUTCLKSEL = 0x2; 00125 LPC_SYSCON->CLKOUTUEN = 0; 00126 LPC_SYSCON->CLKOUTUEN = CLKOUTUEN_ENA; 00127 pin_function(dp24, 1); 00128 00129 int count = 0; 00130 timer.start(); 00131 while (timer.read_ms() < 100) { 00132 while (din.read() == 0); 00133 while (din.read() == 1); 00134 count++; 00135 } 00136 cycles_per_ms = (float)count / 100.0f; 00137 00138 //Set old pin function back, disable CLKOUT 00139 *reg = old_pinfun; 00140 LPC_SYSCON->CLKOUTDIV = 0; 00141 } 00142 00143 static inline void restore(void) { 00144 00145 WakeUpTimer->MR[WakeUpTimer_Match] = 0xFFFFFFFF; 00146 00147 if (old_clk_sel == 3) //Was running on PLL 00148 while(LPC_SYSCON->SYSPLLSTAT != SYSPLLSTAT_LOCK); 00149 00150 if (old_clk_sel < 4) { //If valid setting 00151 LPC_SYSCON->MAINCLKSEL = old_clk_sel; 00152 LPC_SYSCON->MAINCLKUEN = 0; 00153 LPC_SYSCON->MAINCLKUEN = MAINCLKUEN_ENA; 00154 } 00155 00156 IRQ_in.rise(NULL); 00157 00158 LPC_SYSCON->SYSAHBCLKCTRL = SYSAHBCLKCTRL; 00159 00160 WakeUpTimer->MR3 = MR3; 00161 WakeUpTimer->PR = PR; 00162 WakeUpTimer->TCR = TCR; 00163 } 00164 00165 #endif
Generated on Tue Jul 12 2022 20:08:52 by 1.7.2