Modified WakeUp program to run on STM32L152RE
Dependencies: mbed LPC1114_WakeInterruptIn
Fork of WakeUp by
Diff: Device/WakeUp_LPC11XX.cpp
- Revision:
- 10:c41bc9154a7c
- Child:
- 11:72db657fc572
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Device/WakeUp_LPC11XX.cpp Mon Jul 28 19:46:03 2014 +0000 @@ -0,0 +1,117 @@ +/** +See homepage of this lib for LPC11xx special treatment +**/ + +#ifdef TARGET_LPC11XX_11CXX + +//dp1 or dp2 can be chosen +#define WAKEUP_PIN dp1 +//#define WAKEUP_PIN dp2 + +#define WAKEUP_MATCH (((WAKEUP_PIN >> PIN_SHIFT) & 0xF) - 8) +#define WAKEUP_CHANNEL ((WAKEUP_PIN >> PIN_SHIFT) & 0xF) + +#define WAKEUP_TIMER LPC_TMR16B0 +#define WAKEUP_TIMER_EN 7 + +#define SYSAHBCLKCTRL_SLEEP (0x15 | (1<<WAKEUP_TIMER_EN)) + +#include "WakeUp.h" +#include "WakeInterruptIn.h" + +WakeInterruptIn IRQ_in(WAKEUP_PIN); +PwmOut pulse_out(WAKEUP_PIN); + +FunctionPointer WakeUp::callback; +float WakeUp::cycles_per_ms = 20.0; + +static uint32_t old_clk_sel = ~0; +static uint32_t SYSAHBCLKCTRL; +static uint32_t TCR, PR, MR3; + +static inline void restore(void); + + +void WakeUp::set_ms(uint32_t ms) +{ + if (ms != 0) { + if (old_clk_sel == ~0) { //Only during first run + old_clk_sel = LPC_SYSCON->MAINCLKSEL; + SYSAHBCLKCTRL = LPC_SYSCON->SYSAHBCLKCTRL; + } + + if (LPC_SYSCON->SYSAHBCLKCTRL != SYSAHBCLKCTRL_SLEEP) //Always when it is different from sleep settings + SYSAHBCLKCTRL = LPC_SYSCON->SYSAHBCLKCTRL; + + LPC_SYSCON->PDRUNCFG &= ~PDRUNCFG_WDTOSC_PD; + LPC_SYSCON->PDSLEEPCFG = 0x000018B7 | (LPC_SYSCON->PDRUNCFG & (PDRUNCFG_WDTOSC_PD | PDRUNCFG_BOD_PD)); + + //Set oscillator for 20kHz + LPC_SYSCON->WDTOSCCTRL = 14 | (1<<5); + + //Store old PWM + TCR = WAKEUP_TIMER->TCR; + PR = WAKEUP_TIMER->PR; + MR3 = WAKEUP_TIMER->MR3; + + //Setup PWM + WAKEUP_TIMER->TCR = TMR16B0TCR_CRST; + uint32_t ticks = (float)ms * cycles_per_ms; + + //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) + WAKEUP_TIMER->PR = ticks >> 16; + WAKEUP_TIMER->MR[WAKEUP_MATCH] = ticks / ((ticks >> 16) + 1); + WAKEUP_TIMER->MR3 = 0xFFFF; + + IRQ_in.rise(irq_handler); + + //Disable most peripherals + LPC_SYSCON->SYSAHBCLKCTRL = SYSAHBCLKCTRL_SLEEP; + + //Switch clock to WD OSC + LPC_SYSCON->MAINCLKSEL = 0x2; + LPC_SYSCON->MAINCLKUEN = 0; + LPC_SYSCON->MAINCLKUEN = MAINCLKUEN_ENA; + + //Enable PWM: + WAKEUP_TIMER->TCR = TMR16B0TCR_CEN; + } else { + //Else restore normal settings + restore(); + } + +} + +void WakeUp::irq_handler(void) +{ + restore(); + callback.call(); +} + +void WakeUp::calibrate(void) +{ +} + +static inline void restore(void) { + + WAKEUP_TIMER->MR[WAKEUP_MATCH] = 0xFFFF; + + if (old_clk_sel == 3) //Was running on PLL + while(LPC_SYSCON->SYSPLLSTAT != SYSPLLSTAT_LOCK); + + if (old_clk_sel < 4) { //If valid setting + LPC_SYSCON->MAINCLKSEL = old_clk_sel; + LPC_SYSCON->MAINCLKUEN = 0; + LPC_SYSCON->MAINCLKUEN = MAINCLKUEN_ENA; + } + + IRQ_in.rise(NULL); + + LPC_SYSCON->SYSAHBCLKCTRL = SYSAHBCLKCTRL; + + WAKEUP_TIMER->MR3 = MR3; + WAKEUP_TIMER->PR = PR; + WAKEUP_TIMER->TCR = TCR; +} + +#endif