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 Jun 14 08:56:55 2017 +0000
Revision:
23:69a0c843e4bd
Parent:
19:9d355da2770e
Switched WakeUp to use the new callback system, to remove warnings during compilation.; ; Attached normal functions should still work the same. Attaching member functions is now:; WakeUp::attach(callback(&object, &Class::function));

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 23:69a0c843e4bd 6 Callback<void()> 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 19:9d355da2770e 52 #ifdef OSC0
Sissors 18:13aed323e040 53 OSC0->CR |= OSC_CR_EREFSTEN_MASK;
Sissors 19:9d355da2770e 54 #else
Sissors 19:9d355da2770e 55 OSC->CR |= OSC_CR_EREFSTEN_MASK;
Sissors 19:9d355da2770e 56 #endif
Sissors 18:13aed323e040 57 LPTMR0->PSR = LPTMR_PSR_PCS(2);
Sissors 18:13aed323e040 58 counts = (uint32_t)((float)ms * 32.768f);
Sissors 18:13aed323e040 59 } else {
Sissors 18:13aed323e040 60 //Clock from the 1kHz LPO
Sissors 18:13aed323e040 61 LPTMR0->PSR = LPTMR_PSR_PCS(1);
Sissors 18:13aed323e040 62 counts = (uint32_t)((float)ms * cycles_per_ms);
Sissors 18:13aed323e040 63 }
Sissors 18:13aed323e040 64
Sissors 7:bb411115f814 65 //If no prescaler is needed
Sissors 7:bb411115f814 66 if (counts <= 0xFFFF)
Sissors 7:bb411115f814 67 LPTMR0->PSR |= LPTMR_PSR_PBYP_MASK;
Sissors 7:bb411115f814 68 else { //Otherwise increase prescaler until it fits
Sissors 7:bb411115f814 69 counts >>= 1;
Sissors 7:bb411115f814 70 uint32_t prescaler = 0;
Sissors 7:bb411115f814 71 while (counts > 0xFFFF) {
Sissors 7:bb411115f814 72 counts >>= 1;
Sissors 7:bb411115f814 73 prescaler++;
Sissors 7:bb411115f814 74 }
Sissors 7:bb411115f814 75 LPTMR0->PSR |= LPTMR_PSR_PRESCALE(prescaler);
Sissors 7:bb411115f814 76 }
Sissors 7:bb411115f814 77 LPTMR0->CMR = counts;
Sissors 7:bb411115f814 78
Sissors 7:bb411115f814 79 LPTMR0->CSR = LPTMR_CSR_TIE_MASK;
Sissors 7:bb411115f814 80 LPTMR0->CSR |= LPTMR_CSR_TEN_MASK;
Sissors 7:bb411115f814 81 } else {
Sissors 7:bb411115f814 82 restore();
Sissors 7:bb411115f814 83 }
Sissors 7:bb411115f814 84
Sissors 7:bb411115f814 85 }
Sissors 7:bb411115f814 86
Sissors 7:bb411115f814 87
Sissors 7:bb411115f814 88 void WakeUp::irq_handler(void)
Sissors 7:bb411115f814 89 {
Sissors 7:bb411115f814 90 // write 1 to TCF to clear the LPT timer compare flag
Sissors 7:bb411115f814 91 LPTMR0->CSR |= LPTMR_CSR_TCF_MASK;
Sissors 7:bb411115f814 92 restore();
Sissors 7:bb411115f814 93 callback.call();
Sissors 7:bb411115f814 94 }
Sissors 7:bb411115f814 95
Sissors 7:bb411115f814 96 void WakeUp::calibrate(void)
Sissors 7:bb411115f814 97 {
Sissors 18:13aed323e040 98 if (!is32kXtal()) {
Sissors 18:13aed323e040 99 wait_us(1); //Otherwise next wait might overwrite our settings
Sissors 18:13aed323e040 100 cycles_per_ms = 1.0;
Sissors 18:13aed323e040 101 set_ms(1100);
Sissors 18:13aed323e040 102 wait_ms(100);
Sissors 18:13aed323e040 103
Sissors 18:13aed323e040 104 //Write first to sync value
Sissors 18:13aed323e040 105 LPTMR0->CNR = 0;
Sissors 18:13aed323e040 106 uint32_t ticks = LPTMR0->CNR;
Sissors 18:13aed323e040 107 cycles_per_ms = ticks / 100.0;
Sissors 18:13aed323e040 108 set_ms(0);
Sissors 18:13aed323e040 109 }
Sissors 7:bb411115f814 110 }
Sissors 7:bb411115f814 111
Sissors 7:bb411115f814 112 void restore(void){
Sissors 7:bb411115f814 113 /* Reset */
Sissors 7:bb411115f814 114 LPTMR0->CSR = 0;
Sissors 7:bb411115f814 115
Sissors 7:bb411115f814 116 /* Set interrupt handler */
Sissors 7:bb411115f814 117 NVIC_SetVector(LPTimer_IRQn, oldvector);
Sissors 7:bb411115f814 118 NVIC_EnableIRQ(LPTimer_IRQn);
Sissors 7:bb411115f814 119
Sissors 7:bb411115f814 120 /* Clock at (1)MHz -> (1)tick/us */
Sissors 7:bb411115f814 121 LPTMR0->PSR = oldPSR;
Sissors 7:bb411115f814 122
Sissors 7:bb411115f814 123 if (remainder_count) {
Sissors 7:bb411115f814 124 /* Set the compare register */
Sissors 7:bb411115f814 125 LPTMR0->CMR = remainder_count;
Sissors 7:bb411115f814 126
Sissors 7:bb411115f814 127 /* Enable interrupt */
Sissors 7:bb411115f814 128 LPTMR0->CSR |= LPTMR_CSR_TIE_MASK;
Sissors 7:bb411115f814 129
Sissors 7:bb411115f814 130 /* Start the timer */
Sissors 7:bb411115f814 131 LPTMR0->CSR |= LPTMR_CSR_TEN_MASK;
Sissors 7:bb411115f814 132 }
Sissors 7:bb411115f814 133 }
Sissors 7:bb411115f814 134
Sissors 7:bb411115f814 135 #endif