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_Freescale.cpp@18:13aed323e040, 2015-07-01 (annotated)
- Committer:
- Sissors
- Date:
- Wed Jul 01 19:28:55 2015 +0000
- Revision:
- 18:13aed323e040
- Parent:
- 16:f3adba7cf7c4
- Child:
- 19:9d355da2770e
Use for Freescale devices 32k system oscillator if available. In this mode no calibration is available: It is assumed you are using a 32kHz crystal with sufficient performance.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Sissors | 16:f3adba7cf7c4 | 1 | #if defined(TARGET_Freescale) |
Sissors | 7:bb411115f814 | 2 | |
Sissors | 7:bb411115f814 | 3 | #include "WakeUp.h" |
Sissors | 7:bb411115f814 | 4 | #include "us_ticker_api.h" |
Sissors | 7:bb411115f814 | 5 | |
Sissors | 7:bb411115f814 | 6 | FunctionPointer WakeUp::callback; |
Sissors | 7:bb411115f814 | 7 | float WakeUp::cycles_per_ms = 1.0; |
Sissors | 7:bb411115f814 | 8 | |
Sissors | 7:bb411115f814 | 9 | static uint16_t remainder_count; |
Sissors | 7:bb411115f814 | 10 | static uint32_t oldvector; |
Sissors | 7:bb411115f814 | 11 | static uint8_t oldPSR; |
Sissors | 7:bb411115f814 | 12 | |
Sissors | 18:13aed323e040 | 13 | //See if we have a 32kHz crystal on the clock input |
Sissors | 18:13aed323e040 | 14 | //Check if the DMX32 bit is set, not perfect, but most cases will work |
Sissors | 18:13aed323e040 | 15 | static inline bool is32kXtal(void) { |
Sissors | 18:13aed323e040 | 16 | return (MCG->C4 & MCG_C4_DMX32_MASK); |
Sissors | 18:13aed323e040 | 17 | } |
Sissors | 18:13aed323e040 | 18 | |
Sissors | 7:bb411115f814 | 19 | void restore(void); |
Sissors | 7:bb411115f814 | 20 | |
Sissors | 7:bb411115f814 | 21 | void WakeUp::set_ms(uint32_t ms) |
Sissors | 7:bb411115f814 | 22 | { |
Sissors | 7:bb411115f814 | 23 | /* Clock the timer */ |
Sissors | 7:bb411115f814 | 24 | SIM->SCGC5 |= 0x1u; |
Sissors | 7:bb411115f814 | 25 | |
Sissors | 7:bb411115f814 | 26 | //Check if it is running, in that case, store current values |
Sissors | 7:bb411115f814 | 27 | remainder_count = 0; |
Sissors | 7:bb411115f814 | 28 | if (NVIC_GetVector(LPTimer_IRQn) != (uint32_t)WakeUp::irq_handler) { |
Sissors | 7:bb411115f814 | 29 | oldvector = NVIC_GetVector(LPTimer_IRQn); |
Sissors | 7:bb411115f814 | 30 | oldPSR = LPTMR0->PSR; |
Sissors | 7:bb411115f814 | 31 | |
Sissors | 7:bb411115f814 | 32 | if (LPTMR0->CSR & LPTMR_CSR_TIE_MASK) { |
Sissors | 7:bb411115f814 | 33 | //Write first to sync value |
Sissors | 7:bb411115f814 | 34 | LPTMR0->CNR = 0; |
Sissors | 7:bb411115f814 | 35 | uint16_t countval = LPTMR0->CNR; |
Sissors | 7:bb411115f814 | 36 | if (countval < LPTMR0->CMR) |
Sissors | 7:bb411115f814 | 37 | remainder_count = countval - LPTMR0->CMR; |
Sissors | 7:bb411115f814 | 38 | } |
Sissors | 7:bb411115f814 | 39 | } |
Sissors | 7:bb411115f814 | 40 | |
Sissors | 7:bb411115f814 | 41 | LPTMR0->CSR = 0; |
Sissors | 7:bb411115f814 | 42 | |
Sissors | 7:bb411115f814 | 43 | if (ms != 0) { |
Sissors | 7:bb411115f814 | 44 | /* Set interrupt handler */ |
Sissors | 7:bb411115f814 | 45 | NVIC_SetVector(LPTimer_IRQn, (uint32_t)WakeUp::irq_handler); |
Sissors | 7:bb411115f814 | 46 | NVIC_EnableIRQ(LPTimer_IRQn); |
Sissors | 7:bb411115f814 | 47 | |
Sissors | 18:13aed323e040 | 48 | uint32_t counts; |
Sissors | 18:13aed323e040 | 49 | //Set clock |
Sissors | 18:13aed323e040 | 50 | if (is32kXtal()) { |
Sissors | 18:13aed323e040 | 51 | SIM->SOPT1 &= ~SIM_SOPT1_OSC32KSEL_MASK; //Put RTC/LPTMR on 32kHz external. |
Sissors | 18:13aed323e040 | 52 | OSC0->CR |= OSC_CR_EREFSTEN_MASK; |
Sissors | 18:13aed323e040 | 53 | LPTMR0->PSR = LPTMR_PSR_PCS(2); |
Sissors | 18:13aed323e040 | 54 | counts = (uint32_t)((float)ms * 32.768f); |
Sissors | 18:13aed323e040 | 55 | } else { |
Sissors | 18:13aed323e040 | 56 | //Clock from the 1kHz LPO |
Sissors | 18:13aed323e040 | 57 | LPTMR0->PSR = LPTMR_PSR_PCS(1); |
Sissors | 18:13aed323e040 | 58 | counts = (uint32_t)((float)ms * cycles_per_ms); |
Sissors | 18:13aed323e040 | 59 | } |
Sissors | 18:13aed323e040 | 60 | |
Sissors | 7:bb411115f814 | 61 | //If no prescaler is needed |
Sissors | 7:bb411115f814 | 62 | if (counts <= 0xFFFF) |
Sissors | 7:bb411115f814 | 63 | LPTMR0->PSR |= LPTMR_PSR_PBYP_MASK; |
Sissors | 7:bb411115f814 | 64 | else { //Otherwise increase prescaler until it fits |
Sissors | 7:bb411115f814 | 65 | counts >>= 1; |
Sissors | 7:bb411115f814 | 66 | uint32_t prescaler = 0; |
Sissors | 7:bb411115f814 | 67 | while (counts > 0xFFFF) { |
Sissors | 7:bb411115f814 | 68 | counts >>= 1; |
Sissors | 7:bb411115f814 | 69 | prescaler++; |
Sissors | 7:bb411115f814 | 70 | } |
Sissors | 7:bb411115f814 | 71 | LPTMR0->PSR |= LPTMR_PSR_PRESCALE(prescaler); |
Sissors | 7:bb411115f814 | 72 | } |
Sissors | 7:bb411115f814 | 73 | LPTMR0->CMR = counts; |
Sissors | 7:bb411115f814 | 74 | |
Sissors | 7:bb411115f814 | 75 | LPTMR0->CSR = LPTMR_CSR_TIE_MASK; |
Sissors | 7:bb411115f814 | 76 | LPTMR0->CSR |= LPTMR_CSR_TEN_MASK; |
Sissors | 7:bb411115f814 | 77 | } else { |
Sissors | 7:bb411115f814 | 78 | restore(); |
Sissors | 7:bb411115f814 | 79 | } |
Sissors | 7:bb411115f814 | 80 | |
Sissors | 7:bb411115f814 | 81 | } |
Sissors | 7:bb411115f814 | 82 | |
Sissors | 7:bb411115f814 | 83 | |
Sissors | 7:bb411115f814 | 84 | void WakeUp::irq_handler(void) |
Sissors | 7:bb411115f814 | 85 | { |
Sissors | 7:bb411115f814 | 86 | // write 1 to TCF to clear the LPT timer compare flag |
Sissors | 7:bb411115f814 | 87 | LPTMR0->CSR |= LPTMR_CSR_TCF_MASK; |
Sissors | 7:bb411115f814 | 88 | restore(); |
Sissors | 7:bb411115f814 | 89 | callback.call(); |
Sissors | 7:bb411115f814 | 90 | } |
Sissors | 7:bb411115f814 | 91 | |
Sissors | 7:bb411115f814 | 92 | void WakeUp::calibrate(void) |
Sissors | 7:bb411115f814 | 93 | { |
Sissors | 18:13aed323e040 | 94 | if (!is32kXtal()) { |
Sissors | 18:13aed323e040 | 95 | wait_us(1); //Otherwise next wait might overwrite our settings |
Sissors | 18:13aed323e040 | 96 | cycles_per_ms = 1.0; |
Sissors | 18:13aed323e040 | 97 | set_ms(1100); |
Sissors | 18:13aed323e040 | 98 | wait_ms(100); |
Sissors | 18:13aed323e040 | 99 | |
Sissors | 18:13aed323e040 | 100 | //Write first to sync value |
Sissors | 18:13aed323e040 | 101 | LPTMR0->CNR = 0; |
Sissors | 18:13aed323e040 | 102 | uint32_t ticks = LPTMR0->CNR; |
Sissors | 18:13aed323e040 | 103 | cycles_per_ms = ticks / 100.0; |
Sissors | 18:13aed323e040 | 104 | set_ms(0); |
Sissors | 18:13aed323e040 | 105 | } |
Sissors | 7:bb411115f814 | 106 | } |
Sissors | 7:bb411115f814 | 107 | |
Sissors | 7:bb411115f814 | 108 | void restore(void){ |
Sissors | 7:bb411115f814 | 109 | /* Reset */ |
Sissors | 7:bb411115f814 | 110 | LPTMR0->CSR = 0; |
Sissors | 7:bb411115f814 | 111 | |
Sissors | 7:bb411115f814 | 112 | /* Set interrupt handler */ |
Sissors | 7:bb411115f814 | 113 | NVIC_SetVector(LPTimer_IRQn, oldvector); |
Sissors | 7:bb411115f814 | 114 | NVIC_EnableIRQ(LPTimer_IRQn); |
Sissors | 7:bb411115f814 | 115 | |
Sissors | 7:bb411115f814 | 116 | /* Clock at (1)MHz -> (1)tick/us */ |
Sissors | 7:bb411115f814 | 117 | LPTMR0->PSR = oldPSR; |
Sissors | 7:bb411115f814 | 118 | |
Sissors | 7:bb411115f814 | 119 | if (remainder_count) { |
Sissors | 7:bb411115f814 | 120 | /* Set the compare register */ |
Sissors | 7:bb411115f814 | 121 | LPTMR0->CMR = remainder_count; |
Sissors | 7:bb411115f814 | 122 | |
Sissors | 7:bb411115f814 | 123 | /* Enable interrupt */ |
Sissors | 7:bb411115f814 | 124 | LPTMR0->CSR |= LPTMR_CSR_TIE_MASK; |
Sissors | 7:bb411115f814 | 125 | |
Sissors | 7:bb411115f814 | 126 | /* Start the timer */ |
Sissors | 7:bb411115f814 | 127 | LPTMR0->CSR |= LPTMR_CSR_TEN_MASK; |
Sissors | 7:bb411115f814 | 128 | } |
Sissors | 7:bb411115f814 | 129 | } |
Sissors | 7:bb411115f814 | 130 | |
Sissors | 7:bb411115f814 | 131 | #endif |