LPC1768 and LPC11U24 watchdog timer
Dependents: GSwifi_tsutenkaku barometer-m0 BMAGThrRev
Diff: WDT.cpp
- Revision:
- 2:f6f05e2eafd0
- Parent:
- 1:f7baa89f84bc
- Child:
- 3:b1efde09d8a7
--- a/WDT.cpp Sat Aug 04 11:36:51 2012 +0000 +++ b/WDT.cpp Fri Jul 11 00:53:14 2014 +0000 @@ -1,15 +1,17 @@ #include "mbed.h" #include "WDT.h" -// Simon's Watchdog code from -// http://mbed.org/forum/mbed/topic/508/ +FunctionPointer Watchdog::_fptr; + +// Simon's Watchdog +// see: http://mbed.org/forum/mbed/topic/508/ void Watchdog::init(float s) { #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) LPC_WDT->WDCLKSEL = 0x01; // Set CLK src to PCLK uint32_t clk = SystemCoreClock / 16; // WD has a fixed /4 prescaler, PCLK default is /4 LPC_WDT->WDTC = s * (float)clk; LPC_WDT->WDMOD = 0x03; // Enabled and Reset -#elif defined(TARGET_LPC11U24) +#elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11UXX) LPC_WWDT->CLKSEL = 0x01; // Set CLK src to PCLK uint32_t clk = SystemCoreClock / 16; // WD has a fixed /4 prescaler, PCLK default is /4 LPC_WWDT->TC = s * (float)clk; @@ -24,7 +26,7 @@ #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) LPC_WDT->WDFEED = 0xAA; LPC_WDT->WDFEED = 0x55; -#elif defined(TARGET_LPC11U24) +#elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11UXX) LPC_WWDT->FEED = 0xAA; LPC_WWDT->FEED = 0x55; #endif @@ -34,7 +36,77 @@ int Watchdog::getFlg () { #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) return LPC_WDT->WDMOD & (1<<2) ? 1 : 0; -#elif defined(TARGET_LPC11U24) +#elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11UXX) return LPC_WWDT->MOD & (1<<2) ? 1 : 0; #endif } + +void Watchdog::attach (void (*fptr)(void), float s) { + if (fptr) { + _fptr.attach(fptr); + } +#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) + LPC_WDT->WDCLKSEL = 0x02; // Set CLK src to RTC + uint32_t clk = 32768 / 4; // WD has a fixed /4 prescaler + LPC_WDT->WDTC = s * (float)clk; + LPC_WDT->WDMOD = 0x01; // Enabled but Reset disable +#elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11UXX) + LPC_SYSCON->SYSAHBCLKCTRL |= (1<<15); + LPC_SYSCON->PDRUNCFG &= ~(1<<6); // WDT on + LPC_SYSCON->WDTOSCCTRL = (1<<5)|(0x1f<<0); // 500kHz / 64 + + LPC_WWDT->CLKSEL = (1<<0); // Set CLK src to PCLK + uint32_t clk = 500000 / 64 / 4; // WD has a fixed /4 prescaler, PCLK default is /4 + LPC_WWDT->TC = s * (float)clk; + LPC_WWDT->WARNINT = 0; + LPC_WWDT->MOD = 0x01; // Enabled but Reset disable + kick(); + LPC_SYSCON->STARTERP1 |= (1<<12); +#endif + NVIC_SetVector(WDT_IRQn, (uint32_t)&Watchdog::isr_wdt); + NVIC_ClearPendingIRQ(WDT_IRQn); + NVIC_EnableIRQ(WDT_IRQn); +} + +template<typename T> +void Watchdog::attach (T *object, void (*fptr)(void), float s) { + if (fptr) { + _fptr.attach(object, fptr); + } + attach(NULL, s); +} + +void Watchdog::isr_wdt(void) { +#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) + LPC_WDT->WDMOD |= (1<<3); + LPC_WDT->WDMOD &= ~(1<<2); +#elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11UXX) + LPC_WWDT->MOD |= (1<<3); + LPC_WWDT->MOD &= ~(1<<2); +#endif + _fptr.call(); +} + +void Watchdog::sleep () { +#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) + LPC_SC->PCON = 0; +#elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11UXX) + LPC_PMU->PCON = 0; +#endif + SCB->SCR &= ~(1<<2); + __WFI(); +} + +void Watchdog::deepSleep () { +#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) + LPC_SC->PCON &= ~(7<<0); + LPC_SC->PCON |= (1<<0); +#elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11UXX) + LPC_SYSCON->PDSLEEPCFG &= ~(1<<6); // WDT on + LPC_SYSCON->PDAWAKECFG = LPC_SYSCON->PDRUNCFG; + LPC_PMU->PCON &= ~(7<<0); + LPC_PMU->PCON |= (1<<0); +#endif + SCB->SCR |= (1<<2); + __WFI(); +}