Wake-up timer library to wake from deepsleep/power-down

Dependencies:   LPC1114_WakeInterruptIn

Fork of WakeUp by Erik -

Committer:
Sissors
Date:
Wed Jul 30 20:39:57 2014 +0000
Revision:
14:6bf547e1e62d
Parent:
13:fd24cec76d5a
Calibrate on LPC1114 now restores pin function settings afterwards (previously this broke wakeups were dp24 was used).
;
; Moved WakeInterruptIn to Device folder.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sissors 10:c41bc9154a7c 1 /**
Sissors 10:c41bc9154a7c 2 See homepage of this lib for LPC11xx special treatment
Sissors 10:c41bc9154a7c 3 **/
Sissors 10:c41bc9154a7c 4
Sissors 10:c41bc9154a7c 5 #ifdef TARGET_LPC11XX_11CXX
Sissors 10:c41bc9154a7c 6
Sissors 10:c41bc9154a7c 7 #include "WakeUp.h"
Sissors 10:c41bc9154a7c 8 #include "WakeInterruptIn.h"
Sissors 12:779d866b8a2d 9 #include "pinmap.h"
Sissors 13:fd24cec76d5a 10 #include "toolchain.h"
Sissors 10:c41bc9154a7c 11
Sissors 11:72db657fc572 12 //Pin used, allowed pins = P0_1 (dp24, default), P0_8 (dp1) and P0_9 (dp2)
Sissors 11:72db657fc572 13 //By defining WakeUpPin in for example your main.cpp this can be overridden
Sissors 11:72db657fc572 14 WEAK PinName WakeUpPin = dp24;
Sissors 11:72db657fc572 15 extern PinName WakeUpPin;
Sissors 11:72db657fc572 16
Sissors 11:72db657fc572 17 WakeInterruptIn IRQ_in(WakeUpPin);
Sissors 11:72db657fc572 18 PwmOut pulse_out(WakeUpPin);
Sissors 10:c41bc9154a7c 19
Sissors 10:c41bc9154a7c 20 FunctionPointer WakeUp::callback;
Sissors 10:c41bc9154a7c 21 float WakeUp::cycles_per_ms = 20.0;
Sissors 10:c41bc9154a7c 22
Sissors 10:c41bc9154a7c 23 static uint32_t old_clk_sel = ~0;
Sissors 10:c41bc9154a7c 24 static uint32_t SYSAHBCLKCTRL;
Sissors 10:c41bc9154a7c 25 static uint32_t TCR, PR, MR3;
Sissors 11:72db657fc572 26 static LPC_TMR_TypeDef *WakeUpTimer;
Sissors 11:72db657fc572 27 static uint32_t SYSAHBCLKCTRL_Sleep;
Sissors 11:72db657fc572 28 static uint8_t WakeUpTimer_Match;
Sissors 10:c41bc9154a7c 29
Sissors 10:c41bc9154a7c 30 static inline void restore(void);
Sissors 10:c41bc9154a7c 31
Sissors 10:c41bc9154a7c 32
Sissors 10:c41bc9154a7c 33 void WakeUp::set_ms(uint32_t ms)
Sissors 10:c41bc9154a7c 34 {
Sissors 11:72db657fc572 35 if (old_clk_sel == ~0) { //Only during first run
Sissors 11:72db657fc572 36 old_clk_sel = LPC_SYSCON->MAINCLKSEL;
Sissors 11:72db657fc572 37 SYSAHBCLKCTRL = LPC_SYSCON->SYSAHBCLKCTRL;
Sissors 10:c41bc9154a7c 38
Sissors 11:72db657fc572 39 switch(WakeUpPin) {
Sissors 11:72db657fc572 40 case dp24:
Sissors 11:72db657fc572 41 WakeUpTimer = LPC_TMR32B0;
Sissors 11:72db657fc572 42 SYSAHBCLKCTRL_Sleep = 0x15 | (1<<9);
Sissors 11:72db657fc572 43 WakeUpTimer_Match = 2;
Sissors 11:72db657fc572 44 break;
Sissors 11:72db657fc572 45 case dp1:
Sissors 11:72db657fc572 46 WakeUpTimer = LPC_TMR16B0;
Sissors 11:72db657fc572 47 SYSAHBCLKCTRL_Sleep = 0x15 | (1<<7);
Sissors 11:72db657fc572 48 WakeUpTimer_Match = 0;
Sissors 11:72db657fc572 49 break;
Sissors 11:72db657fc572 50 case dp2:
Sissors 11:72db657fc572 51 WakeUpTimer = LPC_TMR16B0;
Sissors 11:72db657fc572 52 SYSAHBCLKCTRL_Sleep = 0x15 | (1<<7);
Sissors 11:72db657fc572 53 WakeUpTimer_Match = 1;
Sissors 11:72db657fc572 54 break;
Sissors 11:72db657fc572 55 default:
Sissors 11:72db657fc572 56 error("Invalid WakeUp pin, choose dp1, dp2 or dp24");
Sissors 11:72db657fc572 57 }
Sissors 11:72db657fc572 58 }
Sissors 11:72db657fc572 59
Sissors 11:72db657fc572 60 if (ms != 0) {
Sissors 11:72db657fc572 61 if (LPC_SYSCON->SYSAHBCLKCTRL != SYSAHBCLKCTRL_Sleep) //Always when it is different from sleep settings
Sissors 10:c41bc9154a7c 62 SYSAHBCLKCTRL = LPC_SYSCON->SYSAHBCLKCTRL;
Sissors 10:c41bc9154a7c 63
Sissors 10:c41bc9154a7c 64 LPC_SYSCON->PDRUNCFG &= ~PDRUNCFG_WDTOSC_PD;
Sissors 10:c41bc9154a7c 65 LPC_SYSCON->PDSLEEPCFG = 0x000018B7 | (LPC_SYSCON->PDRUNCFG & (PDRUNCFG_WDTOSC_PD | PDRUNCFG_BOD_PD));
Sissors 10:c41bc9154a7c 66
Sissors 10:c41bc9154a7c 67 //Set oscillator for 20kHz
Sissors 10:c41bc9154a7c 68 LPC_SYSCON->WDTOSCCTRL = 14 | (1<<5);
Sissors 10:c41bc9154a7c 69
Sissors 10:c41bc9154a7c 70 //Store old PWM
Sissors 11:72db657fc572 71 TCR = WakeUpTimer->TCR;
Sissors 11:72db657fc572 72 PR = WakeUpTimer->PR;
Sissors 11:72db657fc572 73 MR3 = WakeUpTimer->MR3;
Sissors 10:c41bc9154a7c 74
Sissors 10:c41bc9154a7c 75 //Setup PWM
Sissors 11:72db657fc572 76 WakeUpTimer->TCR = TMR16B0TCR_CRST;
Sissors 10:c41bc9154a7c 77 uint32_t ticks = (float)ms * cycles_per_ms;
Sissors 10:c41bc9154a7c 78
Sissors 10:c41bc9154a7c 79 //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)
Sissors 11:72db657fc572 80 WakeUpTimer->PR = ticks >> 16;
Sissors 11:72db657fc572 81 WakeUpTimer->MR[WakeUpTimer_Match] = ticks / ((ticks >> 16) + 1);
Sissors 11:72db657fc572 82 WakeUpTimer->MR3 = 0xFFFF;
Sissors 10:c41bc9154a7c 83
Sissors 10:c41bc9154a7c 84 IRQ_in.rise(irq_handler);
Sissors 10:c41bc9154a7c 85
Sissors 10:c41bc9154a7c 86 //Disable most peripherals
Sissors 11:72db657fc572 87 LPC_SYSCON->SYSAHBCLKCTRL = SYSAHBCLKCTRL_Sleep;
Sissors 10:c41bc9154a7c 88
Sissors 10:c41bc9154a7c 89 //Switch clock to WD OSC
Sissors 10:c41bc9154a7c 90 LPC_SYSCON->MAINCLKSEL = 0x2;
Sissors 10:c41bc9154a7c 91 LPC_SYSCON->MAINCLKUEN = 0;
Sissors 10:c41bc9154a7c 92 LPC_SYSCON->MAINCLKUEN = MAINCLKUEN_ENA;
Sissors 10:c41bc9154a7c 93
Sissors 10:c41bc9154a7c 94 //Enable PWM:
Sissors 11:72db657fc572 95 WakeUpTimer->TCR = TMR16B0TCR_CEN;
Sissors 10:c41bc9154a7c 96 } else {
Sissors 10:c41bc9154a7c 97 //Else restore normal settings
Sissors 10:c41bc9154a7c 98 restore();
Sissors 10:c41bc9154a7c 99 }
Sissors 10:c41bc9154a7c 100
Sissors 10:c41bc9154a7c 101 }
Sissors 10:c41bc9154a7c 102
Sissors 10:c41bc9154a7c 103 void WakeUp::irq_handler(void)
Sissors 10:c41bc9154a7c 104 {
Sissors 10:c41bc9154a7c 105 restore();
Sissors 10:c41bc9154a7c 106 callback.call();
Sissors 10:c41bc9154a7c 107 }
Sissors 10:c41bc9154a7c 108
Sissors 10:c41bc9154a7c 109 void WakeUp::calibrate(void)
Sissors 10:c41bc9154a7c 110 {
Sissors 14:6bf547e1e62d 111 //Save current pin function
Sissors 14:6bf547e1e62d 112 __IO uint32_t *reg = (__IO uint32_t*)(LPC_IOCON_BASE + (dp24 & 0xFF));
Sissors 14:6bf547e1e62d 113 uint32_t old_pinfun = *reg;
Sissors 14:6bf547e1e62d 114
Sissors 12:779d866b8a2d 115 //Set oscillator for 20kHz
Sissors 12:779d866b8a2d 116 LPC_SYSCON->PDRUNCFG &= ~PDRUNCFG_WDTOSC_PD;
Sissors 12:779d866b8a2d 117 LPC_SYSCON->WDTOSCCTRL = 14 | (1<<5);
Sissors 12:779d866b8a2d 118
Sissors 12:779d866b8a2d 119 //Direct WDT to the CLKOUT pin (dp24), sample it back
Sissors 12:779d866b8a2d 120 DigitalIn din(dp24);
Sissors 12:779d866b8a2d 121 Timer timer;
Sissors 12:779d866b8a2d 122
Sissors 12:779d866b8a2d 123 LPC_SYSCON->CLKOUTDIV = 1;
Sissors 12:779d866b8a2d 124 LPC_SYSCON->CLKOUTCLKSEL = 0x2;
Sissors 12:779d866b8a2d 125 LPC_SYSCON->CLKOUTUEN = 0;
Sissors 12:779d866b8a2d 126 LPC_SYSCON->CLKOUTUEN = CLKOUTUEN_ENA;
Sissors 12:779d866b8a2d 127 pin_function(dp24, 1);
Sissors 12:779d866b8a2d 128
Sissors 12:779d866b8a2d 129 int count = 0;
Sissors 12:779d866b8a2d 130 timer.start();
Sissors 12:779d866b8a2d 131 while (timer.read_ms() < 100) {
Sissors 12:779d866b8a2d 132 while (din.read() == 0);
Sissors 12:779d866b8a2d 133 while (din.read() == 1);
Sissors 12:779d866b8a2d 134 count++;
Sissors 12:779d866b8a2d 135 }
Sissors 12:779d866b8a2d 136 cycles_per_ms = (float)count / 100.0f;
Sissors 14:6bf547e1e62d 137
Sissors 14:6bf547e1e62d 138 //Set old pin function back, disable CLKOUT
Sissors 14:6bf547e1e62d 139 *reg = old_pinfun;
Sissors 14:6bf547e1e62d 140 LPC_SYSCON->CLKOUTDIV = 0;
Sissors 10:c41bc9154a7c 141 }
Sissors 10:c41bc9154a7c 142
Sissors 10:c41bc9154a7c 143 static inline void restore(void) {
Sissors 10:c41bc9154a7c 144
Sissors 11:72db657fc572 145 WakeUpTimer->MR[WakeUpTimer_Match] = 0xFFFFFFFF;
Sissors 10:c41bc9154a7c 146
Sissors 10:c41bc9154a7c 147 if (old_clk_sel == 3) //Was running on PLL
Sissors 10:c41bc9154a7c 148 while(LPC_SYSCON->SYSPLLSTAT != SYSPLLSTAT_LOCK);
Sissors 10:c41bc9154a7c 149
Sissors 10:c41bc9154a7c 150 if (old_clk_sel < 4) { //If valid setting
Sissors 10:c41bc9154a7c 151 LPC_SYSCON->MAINCLKSEL = old_clk_sel;
Sissors 10:c41bc9154a7c 152 LPC_SYSCON->MAINCLKUEN = 0;
Sissors 10:c41bc9154a7c 153 LPC_SYSCON->MAINCLKUEN = MAINCLKUEN_ENA;
Sissors 10:c41bc9154a7c 154 }
Sissors 10:c41bc9154a7c 155
Sissors 10:c41bc9154a7c 156 IRQ_in.rise(NULL);
Sissors 10:c41bc9154a7c 157
Sissors 10:c41bc9154a7c 158 LPC_SYSCON->SYSAHBCLKCTRL = SYSAHBCLKCTRL;
Sissors 10:c41bc9154a7c 159
Sissors 11:72db657fc572 160 WakeUpTimer->MR3 = MR3;
Sissors 11:72db657fc572 161 WakeUpTimer->PR = PR;
Sissors 11:72db657fc572 162 WakeUpTimer->TCR = TCR;
Sissors 10:c41bc9154a7c 163 }
Sissors 10:c41bc9154a7c 164
Sissors 10:c41bc9154a7c 165 #endif