Wake-up timer library to wake from deepsleep/power-down
Dependencies: LPC1114_WakeInterruptIn
Dependents: LPC812_Sleep_HelloWorld KL05Z_DCF77_RTC_Clock LPC1114_data_logger mBuinoBlinky ... more
WakeUp_Freescale.cpp
00001 #if defined(TARGET_Freescale) 00002 00003 #include "WakeUp.h" 00004 #include "us_ticker_api.h" 00005 00006 Callback<void()> WakeUp::callback; 00007 float WakeUp::cycles_per_ms = 1.0; 00008 00009 static uint16_t remainder_count; 00010 static uint32_t oldvector; 00011 static uint8_t oldPSR; 00012 00013 //See if we have a 32kHz crystal on the clock input 00014 //Check if the DMX32 bit is set, not perfect, but most cases will work 00015 static inline bool is32kXtal(void) { 00016 return (MCG->C4 & MCG_C4_DMX32_MASK); 00017 } 00018 00019 void restore(void); 00020 00021 void WakeUp::set_ms(uint32_t ms) 00022 { 00023 /* Clock the timer */ 00024 SIM->SCGC5 |= 0x1u; 00025 00026 //Check if it is running, in that case, store current values 00027 remainder_count = 0; 00028 if (NVIC_GetVector(LPTimer_IRQn) != (uint32_t)WakeUp::irq_handler) { 00029 oldvector = NVIC_GetVector(LPTimer_IRQn); 00030 oldPSR = LPTMR0->PSR; 00031 00032 if (LPTMR0->CSR & LPTMR_CSR_TIE_MASK) { 00033 //Write first to sync value 00034 LPTMR0->CNR = 0; 00035 uint16_t countval = LPTMR0->CNR; 00036 if (countval < LPTMR0->CMR) 00037 remainder_count = countval - LPTMR0->CMR; 00038 } 00039 } 00040 00041 LPTMR0->CSR = 0; 00042 00043 if (ms != 0) { 00044 /* Set interrupt handler */ 00045 NVIC_SetVector(LPTimer_IRQn, (uint32_t)WakeUp::irq_handler); 00046 NVIC_EnableIRQ(LPTimer_IRQn); 00047 00048 uint32_t counts; 00049 //Set clock 00050 if (is32kXtal()) { 00051 SIM->SOPT1 &= ~SIM_SOPT1_OSC32KSEL_MASK; //Put RTC/LPTMR on 32kHz external. 00052 #ifdef OSC0 00053 OSC0->CR |= OSC_CR_EREFSTEN_MASK; 00054 #else 00055 OSC->CR |= OSC_CR_EREFSTEN_MASK; 00056 #endif 00057 LPTMR0->PSR = LPTMR_PSR_PCS(2); 00058 counts = (uint32_t)((float)ms * 32.768f); 00059 } else { 00060 //Clock from the 1kHz LPO 00061 LPTMR0->PSR = LPTMR_PSR_PCS(1); 00062 counts = (uint32_t)((float)ms * cycles_per_ms); 00063 } 00064 00065 //If no prescaler is needed 00066 if (counts <= 0xFFFF) 00067 LPTMR0->PSR |= LPTMR_PSR_PBYP_MASK; 00068 else { //Otherwise increase prescaler until it fits 00069 counts >>= 1; 00070 uint32_t prescaler = 0; 00071 while (counts > 0xFFFF) { 00072 counts >>= 1; 00073 prescaler++; 00074 } 00075 LPTMR0->PSR |= LPTMR_PSR_PRESCALE(prescaler); 00076 } 00077 LPTMR0->CMR = counts; 00078 00079 LPTMR0->CSR = LPTMR_CSR_TIE_MASK; 00080 LPTMR0->CSR |= LPTMR_CSR_TEN_MASK; 00081 } else { 00082 restore(); 00083 } 00084 00085 } 00086 00087 00088 void WakeUp::irq_handler(void) 00089 { 00090 // write 1 to TCF to clear the LPT timer compare flag 00091 LPTMR0->CSR |= LPTMR_CSR_TCF_MASK; 00092 restore(); 00093 callback.call(); 00094 } 00095 00096 void WakeUp::calibrate(void) 00097 { 00098 if (!is32kXtal()) { 00099 wait_us(1); //Otherwise next wait might overwrite our settings 00100 cycles_per_ms = 1.0; 00101 set_ms(1100); 00102 wait_ms(100); 00103 00104 //Write first to sync value 00105 LPTMR0->CNR = 0; 00106 uint32_t ticks = LPTMR0->CNR; 00107 cycles_per_ms = ticks / 100.0; 00108 set_ms(0); 00109 } 00110 } 00111 00112 void restore(void){ 00113 /* Reset */ 00114 LPTMR0->CSR = 0; 00115 00116 /* Set interrupt handler */ 00117 NVIC_SetVector(LPTimer_IRQn, oldvector); 00118 NVIC_EnableIRQ(LPTimer_IRQn); 00119 00120 /* Clock at (1)MHz -> (1)tick/us */ 00121 LPTMR0->PSR = oldPSR; 00122 00123 if (remainder_count) { 00124 /* Set the compare register */ 00125 LPTMR0->CMR = remainder_count; 00126 00127 /* Enable interrupt */ 00128 LPTMR0->CSR |= LPTMR_CSR_TIE_MASK; 00129 00130 /* Start the timer */ 00131 LPTMR0->CSR |= LPTMR_CSR_TEN_MASK; 00132 } 00133 } 00134 00135 #endif
Generated on Tue Jul 12 2022 18:10:03 by 1.7.2