LPC1768 and LPC11U24 watchdog timer

Dependents:   GSwifi_tsutenkaku barometer-m0 BMAGThrRev

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();
+}