LPC1768 and LPC11U24 watchdog timer
Dependents: GSwifi_tsutenkaku barometer-m0 BMAGThrRev
WDT.cpp@3:b1efde09d8a7, 2016-05-25 (annotated)
- Committer:
- okini3939
- Date:
- Wed May 25 08:52:32 2016 +0000
- Revision:
- 3:b1efde09d8a7
- Parent:
- 2:f6f05e2eafd0
supported LPC8XX
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
okini3939 | 1:f7baa89f84bc | 1 | #include "mbed.h" |
okini3939 | 1:f7baa89f84bc | 2 | #include "WDT.h" |
okini3939 | 1:f7baa89f84bc | 3 | |
okini3939 | 2:f6f05e2eafd0 | 4 | FunctionPointer Watchdog::_fptr; |
okini3939 | 2:f6f05e2eafd0 | 5 | |
okini3939 | 2:f6f05e2eafd0 | 6 | // Simon's Watchdog |
okini3939 | 2:f6f05e2eafd0 | 7 | // see: http://mbed.org/forum/mbed/topic/508/ |
okini3939 | 1:f7baa89f84bc | 8 | void Watchdog::init(float s) { |
okini3939 | 1:f7baa89f84bc | 9 | #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) |
okini3939 | 1:f7baa89f84bc | 10 | LPC_WDT->WDCLKSEL = 0x01; // Set CLK src to PCLK |
okini3939 | 1:f7baa89f84bc | 11 | uint32_t clk = SystemCoreClock / 16; // WD has a fixed /4 prescaler, PCLK default is /4 |
okini3939 | 1:f7baa89f84bc | 12 | LPC_WDT->WDTC = s * (float)clk; |
okini3939 | 1:f7baa89f84bc | 13 | LPC_WDT->WDMOD = 0x03; // Enabled and Reset |
okini3939 | 2:f6f05e2eafd0 | 14 | #elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11UXX) |
okini3939 | 3:b1efde09d8a7 | 15 | LPC_WWDT->CLKSEL = 0x01; // Set CLK src to WDOSC |
okini3939 | 3:b1efde09d8a7 | 16 | uint32_t clk = 500000 / 64 / 4; // WD has a fixed /4 prescaler, WDOSC default is /4 |
okini3939 | 1:f7baa89f84bc | 17 | LPC_WWDT->TC = s * (float)clk; |
okini3939 | 1:f7baa89f84bc | 18 | LPC_WWDT->MOD = 0x03; // Enabled and Reset |
okini3939 | 3:b1efde09d8a7 | 19 | #elif defined(TARGET_LPC81X) || defined(TARGET_LPC82X) |
okini3939 | 3:b1efde09d8a7 | 20 | LPC_SYSCON->WDTOSCCTRL = (0xA << 5); // wdt_osc_clk = Fclkana/2, Fclkana = 3.5MHz |
okini3939 | 3:b1efde09d8a7 | 21 | LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 17); // Enable Clock WWDT |
okini3939 | 3:b1efde09d8a7 | 22 | LPC_SYSCON->PDRUNCFG &= ~(1 << 6); // Enable Power WDTOSC_PD |
okini3939 | 3:b1efde09d8a7 | 23 | uint32_t clk = ((3500000 / 2) / 4); // COUNT = wdt_osc_clk/4 |
okini3939 | 3:b1efde09d8a7 | 24 | LPC_WWDT->TC = s * (float)clk; |
okini3939 | 3:b1efde09d8a7 | 25 | LPC_WWDT->MOD = 0x3; // Enabled and Reset |
okini3939 | 1:f7baa89f84bc | 26 | #endif |
okini3939 | 1:f7baa89f84bc | 27 | kick(); |
okini3939 | 1:f7baa89f84bc | 28 | } |
okini3939 | 1:f7baa89f84bc | 29 | // "kick" or "feed" the dog - reset the watchdog timer |
okini3939 | 1:f7baa89f84bc | 30 | // by writing this required bit pattern |
okini3939 | 1:f7baa89f84bc | 31 | void Watchdog::kick() { |
okini3939 | 1:f7baa89f84bc | 32 | __disable_irq(); |
okini3939 | 1:f7baa89f84bc | 33 | #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) |
okini3939 | 1:f7baa89f84bc | 34 | LPC_WDT->WDFEED = 0xAA; |
okini3939 | 1:f7baa89f84bc | 35 | LPC_WDT->WDFEED = 0x55; |
okini3939 | 2:f6f05e2eafd0 | 36 | #elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11UXX) |
okini3939 | 1:f7baa89f84bc | 37 | LPC_WWDT->FEED = 0xAA; |
okini3939 | 1:f7baa89f84bc | 38 | LPC_WWDT->FEED = 0x55; |
okini3939 | 3:b1efde09d8a7 | 39 | #elif defined(TARGET_LPC81X) || defined(TARGET_LPC82X) |
okini3939 | 3:b1efde09d8a7 | 40 | LPC_WWDT->FEED = 0xAA; |
okini3939 | 3:b1efde09d8a7 | 41 | LPC_WWDT->FEED = 0x55; |
okini3939 | 1:f7baa89f84bc | 42 | #endif |
okini3939 | 1:f7baa89f84bc | 43 | __enable_irq(); |
okini3939 | 1:f7baa89f84bc | 44 | } |
okini3939 | 1:f7baa89f84bc | 45 | |
okini3939 | 1:f7baa89f84bc | 46 | int Watchdog::getFlg () { |
okini3939 | 1:f7baa89f84bc | 47 | #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) |
okini3939 | 1:f7baa89f84bc | 48 | return LPC_WDT->WDMOD & (1<<2) ? 1 : 0; |
okini3939 | 2:f6f05e2eafd0 | 49 | #elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11UXX) |
okini3939 | 1:f7baa89f84bc | 50 | return LPC_WWDT->MOD & (1<<2) ? 1 : 0; |
okini3939 | 3:b1efde09d8a7 | 51 | #elif defined(TARGET_LPC81X) || defined(TARGET_LPC82X) |
okini3939 | 3:b1efde09d8a7 | 52 | return LPC_WWDT->MOD & (1<<2) ? 1 : 0; |
okini3939 | 1:f7baa89f84bc | 53 | #endif |
okini3939 | 1:f7baa89f84bc | 54 | } |
okini3939 | 2:f6f05e2eafd0 | 55 | |
okini3939 | 2:f6f05e2eafd0 | 56 | void Watchdog::attach (void (*fptr)(void), float s) { |
okini3939 | 2:f6f05e2eafd0 | 57 | if (fptr) { |
okini3939 | 2:f6f05e2eafd0 | 58 | _fptr.attach(fptr); |
okini3939 | 2:f6f05e2eafd0 | 59 | } |
okini3939 | 2:f6f05e2eafd0 | 60 | #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) |
okini3939 | 2:f6f05e2eafd0 | 61 | LPC_WDT->WDCLKSEL = 0x02; // Set CLK src to RTC |
okini3939 | 2:f6f05e2eafd0 | 62 | uint32_t clk = 32768 / 4; // WD has a fixed /4 prescaler |
okini3939 | 2:f6f05e2eafd0 | 63 | LPC_WDT->WDTC = s * (float)clk; |
okini3939 | 2:f6f05e2eafd0 | 64 | LPC_WDT->WDMOD = 0x01; // Enabled but Reset disable |
okini3939 | 2:f6f05e2eafd0 | 65 | #elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11UXX) |
okini3939 | 2:f6f05e2eafd0 | 66 | LPC_SYSCON->SYSAHBCLKCTRL |= (1<<15); |
okini3939 | 2:f6f05e2eafd0 | 67 | LPC_SYSCON->PDRUNCFG &= ~(1<<6); // WDT on |
okini3939 | 2:f6f05e2eafd0 | 68 | LPC_SYSCON->WDTOSCCTRL = (1<<5)|(0x1f<<0); // 500kHz / 64 |
okini3939 | 2:f6f05e2eafd0 | 69 | |
okini3939 | 3:b1efde09d8a7 | 70 | LPC_WWDT->CLKSEL = (1<<0); // Set CLK src to WDOSC |
okini3939 | 3:b1efde09d8a7 | 71 | uint32_t clk = 500000 / 64 / 4; // WD has a fixed /4 prescaler, WDOSC default is /4 |
okini3939 | 2:f6f05e2eafd0 | 72 | LPC_WWDT->TC = s * (float)clk; |
okini3939 | 2:f6f05e2eafd0 | 73 | LPC_WWDT->WARNINT = 0; |
okini3939 | 2:f6f05e2eafd0 | 74 | LPC_WWDT->MOD = 0x01; // Enabled but Reset disable |
okini3939 | 2:f6f05e2eafd0 | 75 | kick(); |
okini3939 | 2:f6f05e2eafd0 | 76 | LPC_SYSCON->STARTERP1 |= (1<<12); |
okini3939 | 3:b1efde09d8a7 | 77 | #elif defined(TARGET_LPC81X) || defined(TARGET_LPC82X) |
okini3939 | 3:b1efde09d8a7 | 78 | LPC_SYSCON->WDTOSCCTRL = (0xA << 5); // wdt_osc_clk = Fclkana/2, Fclkana = 3.5MHz |
okini3939 | 3:b1efde09d8a7 | 79 | LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 17); // Enable Clock WWDT |
okini3939 | 3:b1efde09d8a7 | 80 | LPC_SYSCON->PDRUNCFG &= ~(1 << 6); // Enable Power WDTOSC_PD |
okini3939 | 3:b1efde09d8a7 | 81 | uint32_t clk = ((3500000 / 2) / 4); // COUNT = wdt_osc_clk/4 |
okini3939 | 3:b1efde09d8a7 | 82 | LPC_WWDT->TC = s * (float)clk; |
okini3939 | 3:b1efde09d8a7 | 83 | LPC_WWDT->WARNINT = 0; |
okini3939 | 3:b1efde09d8a7 | 84 | LPC_WWDT->MOD = 0x1; // Enabled and Reset |
okini3939 | 3:b1efde09d8a7 | 85 | kick(); |
okini3939 | 3:b1efde09d8a7 | 86 | LPC_SYSCON->STARTERP1 |= (1<<12); |
okini3939 | 2:f6f05e2eafd0 | 87 | #endif |
okini3939 | 2:f6f05e2eafd0 | 88 | NVIC_SetVector(WDT_IRQn, (uint32_t)&Watchdog::isr_wdt); |
okini3939 | 2:f6f05e2eafd0 | 89 | NVIC_ClearPendingIRQ(WDT_IRQn); |
okini3939 | 2:f6f05e2eafd0 | 90 | NVIC_EnableIRQ(WDT_IRQn); |
okini3939 | 2:f6f05e2eafd0 | 91 | } |
okini3939 | 2:f6f05e2eafd0 | 92 | |
okini3939 | 2:f6f05e2eafd0 | 93 | template<typename T> |
okini3939 | 2:f6f05e2eafd0 | 94 | void Watchdog::attach (T *object, void (*fptr)(void), float s) { |
okini3939 | 2:f6f05e2eafd0 | 95 | if (fptr) { |
okini3939 | 2:f6f05e2eafd0 | 96 | _fptr.attach(object, fptr); |
okini3939 | 2:f6f05e2eafd0 | 97 | } |
okini3939 | 2:f6f05e2eafd0 | 98 | attach(NULL, s); |
okini3939 | 2:f6f05e2eafd0 | 99 | } |
okini3939 | 2:f6f05e2eafd0 | 100 | |
okini3939 | 2:f6f05e2eafd0 | 101 | void Watchdog::isr_wdt(void) { |
okini3939 | 2:f6f05e2eafd0 | 102 | #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) |
okini3939 | 2:f6f05e2eafd0 | 103 | LPC_WDT->WDMOD |= (1<<3); |
okini3939 | 2:f6f05e2eafd0 | 104 | LPC_WDT->WDMOD &= ~(1<<2); |
okini3939 | 2:f6f05e2eafd0 | 105 | #elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11UXX) |
okini3939 | 2:f6f05e2eafd0 | 106 | LPC_WWDT->MOD |= (1<<3); |
okini3939 | 2:f6f05e2eafd0 | 107 | LPC_WWDT->MOD &= ~(1<<2); |
okini3939 | 3:b1efde09d8a7 | 108 | #elif defined(TARGET_LPC81X) || defined(TARGET_LPC82X) |
okini3939 | 3:b1efde09d8a7 | 109 | LPC_WWDT->MOD |= (1<<3); |
okini3939 | 3:b1efde09d8a7 | 110 | LPC_WWDT->MOD &= ~(1<<2); |
okini3939 | 2:f6f05e2eafd0 | 111 | #endif |
okini3939 | 2:f6f05e2eafd0 | 112 | _fptr.call(); |
okini3939 | 2:f6f05e2eafd0 | 113 | } |
okini3939 | 2:f6f05e2eafd0 | 114 | |
okini3939 | 2:f6f05e2eafd0 | 115 | void Watchdog::sleep () { |
okini3939 | 2:f6f05e2eafd0 | 116 | #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) |
okini3939 | 2:f6f05e2eafd0 | 117 | LPC_SC->PCON = 0; |
okini3939 | 2:f6f05e2eafd0 | 118 | #elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11UXX) |
okini3939 | 2:f6f05e2eafd0 | 119 | LPC_PMU->PCON = 0; |
okini3939 | 3:b1efde09d8a7 | 120 | #elif defined(TARGET_LPC81X) || defined(TARGET_LPC82X) |
okini3939 | 3:b1efde09d8a7 | 121 | LPC_PMU->PCON = 0; |
okini3939 | 2:f6f05e2eafd0 | 122 | #endif |
okini3939 | 2:f6f05e2eafd0 | 123 | SCB->SCR &= ~(1<<2); |
okini3939 | 2:f6f05e2eafd0 | 124 | __WFI(); |
okini3939 | 2:f6f05e2eafd0 | 125 | } |
okini3939 | 2:f6f05e2eafd0 | 126 | |
okini3939 | 2:f6f05e2eafd0 | 127 | void Watchdog::deepSleep () { |
okini3939 | 2:f6f05e2eafd0 | 128 | #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) |
okini3939 | 2:f6f05e2eafd0 | 129 | LPC_SC->PCON &= ~(7<<0); |
okini3939 | 2:f6f05e2eafd0 | 130 | LPC_SC->PCON |= (1<<0); |
okini3939 | 2:f6f05e2eafd0 | 131 | #elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11UXX) |
okini3939 | 2:f6f05e2eafd0 | 132 | LPC_SYSCON->PDSLEEPCFG &= ~(1<<6); // WDT on |
okini3939 | 2:f6f05e2eafd0 | 133 | LPC_SYSCON->PDAWAKECFG = LPC_SYSCON->PDRUNCFG; |
okini3939 | 2:f6f05e2eafd0 | 134 | LPC_PMU->PCON &= ~(7<<0); |
okini3939 | 2:f6f05e2eafd0 | 135 | LPC_PMU->PCON |= (1<<0); |
okini3939 | 3:b1efde09d8a7 | 136 | #elif defined(TARGET_LPC81X) || defined(TARGET_LPC82X) |
okini3939 | 3:b1efde09d8a7 | 137 | LPC_SYSCON->PDSLEEPCFG &= ~(1<<6); // WDT on |
okini3939 | 3:b1efde09d8a7 | 138 | LPC_SYSCON->PDAWAKECFG = LPC_SYSCON->PDRUNCFG; |
okini3939 | 3:b1efde09d8a7 | 139 | LPC_PMU->PCON &= ~(7<<0); |
okini3939 | 3:b1efde09d8a7 | 140 | LPC_PMU->PCON |= (1<<0); |
okini3939 | 2:f6f05e2eafd0 | 141 | #endif |
okini3939 | 2:f6f05e2eafd0 | 142 | SCB->SCR |= (1<<2); |
okini3939 | 2:f6f05e2eafd0 | 143 | __WFI(); |
okini3939 | 2:f6f05e2eafd0 | 144 | } |
okini3939 | 3:b1efde09d8a7 | 145 | |
okini3939 | 3:b1efde09d8a7 | 146 | void Watchdog::powerDown () { |
okini3939 | 3:b1efde09d8a7 | 147 | #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) |
okini3939 | 3:b1efde09d8a7 | 148 | LPC_SC->PCON &= ~(7<<0); |
okini3939 | 3:b1efde09d8a7 | 149 | LPC_SC->PCON |= (2<<0); |
okini3939 | 3:b1efde09d8a7 | 150 | #elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11UXX) |
okini3939 | 3:b1efde09d8a7 | 151 | LPC_SYSCON->PDSLEEPCFG &= ~(1<<6); // WDT on |
okini3939 | 3:b1efde09d8a7 | 152 | LPC_SYSCON->PDAWAKECFG = LPC_SYSCON->PDRUNCFG; |
okini3939 | 3:b1efde09d8a7 | 153 | LPC_PMU->PCON &= ~(7<<0); |
okini3939 | 3:b1efde09d8a7 | 154 | LPC_PMU->PCON = (2<<0); |
okini3939 | 3:b1efde09d8a7 | 155 | #elif defined(TARGET_LPC81X) || defined(TARGET_LPC82X) |
okini3939 | 3:b1efde09d8a7 | 156 | LPC_SYSCON->PDSLEEPCFG &= ~(1<<6); // WDT on |
okini3939 | 3:b1efde09d8a7 | 157 | LPC_SYSCON->PDAWAKECFG = LPC_SYSCON->PDRUNCFG; |
okini3939 | 3:b1efde09d8a7 | 158 | LPC_PMU->PCON &= ~(7<<0); |
okini3939 | 3:b1efde09d8a7 | 159 | LPC_PMU->PCON = (2<<0); |
okini3939 | 3:b1efde09d8a7 | 160 | #endif |
okini3939 | 3:b1efde09d8a7 | 161 | SCB->SCR |= (1<<2); |
okini3939 | 3:b1efde09d8a7 | 162 | __WFI(); |
okini3939 | 3:b1efde09d8a7 | 163 | } |