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