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:
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?

UserRevisionLine numberNew 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