Tomonori Kuroki / MuWatchdog

Fork of Watchdog by David Smart

Committer:
mutech
Date:
Tue Sep 13 17:01:18 2016 +0000
Revision:
7:3814d72b8166
Parent:
5:2dad2a78ffbd
Child:
8:ea82a76ca81f
This provides a basic Watchdog service, and includes a startup detection to determine if the reset was caused by the WD.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 2:2873f068f325 1 /// @file Watchdog.cpp provides the interface to the Watchdog module
WiredHome 2:2873f068f325 2 ///
WiredHome 2:2873f068f325 3 /// This provides basic Watchdog service for the mbed. You can configure
WiredHome 2:2873f068f325 4 /// various timeout intervals that meet your system needs. Additionally,
WiredHome 2:2873f068f325 5 /// it is possible to identify if the Watchdog was the cause of any
WiredHome 2:2873f068f325 6 /// system restart.
WiredHome 2:2873f068f325 7 ///
WiredHome 2:2873f068f325 8 /// Adapted from Simon's Watchdog code from http://mbed.org/forum/mbed/topic/508/
WiredHome 2:2873f068f325 9 ///
WiredHome 2:2873f068f325 10 /// @note Copyright © 2011 by Smartware Computing, all rights reserved.
WiredHome 2:2873f068f325 11 /// This software may be used to derive new software, as long as
WiredHome 2:2873f068f325 12 /// this copyright statement remains in the source file.
WiredHome 2:2873f068f325 13 /// @author David Smart
WiredHome 2:2873f068f325 14 ///
mutech 7:3814d72b8166 15 /// \li v2.10 - 20160914: Changed TARGET_STM by mutech, t.kuroki
mutech 7:3814d72b8166 16
WiredHome 0:7a316f14da9c 17 #include "Watchdog.h"
WiredHome 0:7a316f14da9c 18
WiredHome 5:2dad2a78ffbd 19 #if defined( TARGET_LPC1768 )
WiredHome 0:7a316f14da9c 20 /// Watchdog gets instantiated at the module level
WiredHome 0:7a316f14da9c 21 Watchdog::Watchdog() {
WiredHome 2:2873f068f325 22 wdreset = (LPC_WDT->WDMOD >> 2) & 1; // capture the cause of the previous reset
WiredHome 0:7a316f14da9c 23 }
WiredHome 0:7a316f14da9c 24
WiredHome 0:7a316f14da9c 25 /// Load timeout value in watchdog timer and enable
WiredHome 0:7a316f14da9c 26 void Watchdog::Configure(float s) {
WiredHome 0:7a316f14da9c 27 LPC_WDT->WDCLKSEL = 0x1; // Set CLK src to PCLK
WiredHome 0:7a316f14da9c 28 uint32_t clk = SystemCoreClock / 16; // WD has a fixed /4 prescaler, PCLK default is /4
WiredHome 2:2873f068f325 29 LPC_WDT->WDTC = (uint32_t)(s * (float)clk);
WiredHome 0:7a316f14da9c 30 LPC_WDT->WDMOD = 0x3; // Enabled and Reset
WiredHome 0:7a316f14da9c 31 Service();
WiredHome 0:7a316f14da9c 32 }
WiredHome 0:7a316f14da9c 33
mutech 7:3814d72b8166 34 void Watchdog::Configure(int ms) {
mutech 7:3814d72b8166 35 LPC_WDT->WDCLKSEL = 0x1; // Set CLK src to PCLK
mutech 7:3814d72b8166 36 uint32_t clk = SystemCoreClock / 1000; //
mutech 7:3814d72b8166 37 LPC_WDT->WDTC = (ms * clk) / 16; // WD has a fixed /4 prescaler, PCLK default is /4
mutech 7:3814d72b8166 38 LPC_WDT->WDMOD = 0x3; // Enabled and Reset
mutech 7:3814d72b8166 39 Service();
mutech 7:3814d72b8166 40 }
mutech 7:3814d72b8166 41
WiredHome 0:7a316f14da9c 42 /// "Service", "kick" or "feed" the dog - reset the watchdog timer
WiredHome 0:7a316f14da9c 43 /// by writing this required bit pattern
WiredHome 0:7a316f14da9c 44 void Watchdog::Service() {
WiredHome 0:7a316f14da9c 45 LPC_WDT->WDFEED = 0xAA;
WiredHome 0:7a316f14da9c 46 LPC_WDT->WDFEED = 0x55;
WiredHome 0:7a316f14da9c 47 }
WiredHome 0:7a316f14da9c 48
WiredHome 0:7a316f14da9c 49 /// get the flag to indicate if the watchdog causes the reset
WiredHome 0:7a316f14da9c 50 bool Watchdog::WatchdogCausedReset() {
WiredHome 0:7a316f14da9c 51 return wdreset;
WiredHome 0:7a316f14da9c 52 }
WiredHome 5:2dad2a78ffbd 53 #elif defined( TARGET_LPC4088 )
WiredHome 5:2dad2a78ffbd 54 // from Gesotec Gesotec
WiredHome 5:2dad2a78ffbd 55 /// Watchdog gets instantiated at the module level
WiredHome 5:2dad2a78ffbd 56 Watchdog::Watchdog() {
WiredHome 5:2dad2a78ffbd 57 wdreset = (LPC_WDT->MOD >> 2) & 1; // capture the cause of the previous reset
WiredHome 5:2dad2a78ffbd 58 }
WiredHome 5:2dad2a78ffbd 59
WiredHome 5:2dad2a78ffbd 60 /// Load timeout value in watchdog timer and enable
WiredHome 5:2dad2a78ffbd 61 void Watchdog::Configure(float s) {
WiredHome 5:2dad2a78ffbd 62 //LPC_WDT->CLKSEL = 0x1; // Set CLK src to PCLK
WiredHome 5:2dad2a78ffbd 63 uint32_t clk = 500000 / 4; // WD has a fixed /4 prescaler, and a 500khz oscillator
WiredHome 5:2dad2a78ffbd 64 LPC_WDT->TC = (uint32_t)(s * (float)clk);
WiredHome 5:2dad2a78ffbd 65 LPC_WDT->MOD = 0x3; // Enabled and Reset
WiredHome 5:2dad2a78ffbd 66 Service();
WiredHome 5:2dad2a78ffbd 67 }
mutech 7:3814d72b8166 68
mutech 7:3814d72b8166 69 void Watchdog::Configure(int ms) {
mutech 7:3814d72b8166 70 //LPC_WDT->CLKSEL = 0x1; // Set CLK src to PCLK
mutech 7:3814d72b8166 71 uint32_t clk = 500000 / 4; // WD has a fixed /4 prescaler, and a 500khz oscillator
mutech 7:3814d72b8166 72 LPC_WDT->TC = (ms * clk) / 1000;
mutech 7:3814d72b8166 73 LPC_WDT->MOD = 0x3; // Enabled and Reset
mutech 7:3814d72b8166 74 Service();
mutech 7:3814d72b8166 75 }
mutech 7:3814d72b8166 76
WiredHome 5:2dad2a78ffbd 77 /// "Service", "kick" or "feed" the dog - reset the watchdog timer
WiredHome 5:2dad2a78ffbd 78 /// by writing this required bit pattern
WiredHome 5:2dad2a78ffbd 79 void Watchdog::Service() {
WiredHome 5:2dad2a78ffbd 80 LPC_WDT->FEED = 0xAA;
WiredHome 5:2dad2a78ffbd 81 LPC_WDT->FEED = 0x55;
WiredHome 5:2dad2a78ffbd 82 }
WiredHome 5:2dad2a78ffbd 83
WiredHome 5:2dad2a78ffbd 84 /// get the flag to indicate if the watchdog causes the reset
WiredHome 5:2dad2a78ffbd 85 bool Watchdog::WatchdogCausedReset() {
WiredHome 5:2dad2a78ffbd 86 return wdreset;
WiredHome 5:2dad2a78ffbd 87 }
mutech 7:3814d72b8166 88 #elif defined(TARGET_STM)
mutech 7:3814d72b8166 89 Watchdog::Watchdog()
mutech 7:3814d72b8166 90 {
WiredHome 5:2dad2a78ffbd 91 wdreset = (RCC->CSR & (1<<29)) ? true : false; // read the IWDGRSTF (Independent WD, not the windows WD)
WiredHome 5:2dad2a78ffbd 92 }
WiredHome 0:7a316f14da9c 93
mutech 7:3814d72b8166 94 // 最大有効ビット数(MSB:Most Significant Bit)
mutech 7:3814d72b8166 95 int Watchdog::MSB16bit(uint16_t v)
mutech 7:3814d72b8166 96 {
mutech 7:3814d72b8166 97 v |= (v >> 1);
mutech 7:3814d72b8166 98 v |= (v >> 2);
mutech 7:3814d72b8166 99 v |= (v >> 4);
mutech 7:3814d72b8166 100 v |= (v >> 8);
mutech 7:3814d72b8166 101 // return count16bit(v) - 1;
mutech 7:3814d72b8166 102 // 立っているビットの数を数える
mutech 7:3814d72b8166 103 v = (v & 0x5555) + ((v >> 1) & 0x5555);
mutech 7:3814d72b8166 104 v = (v & 0x3333) + ((v >> 2) & 0x3333);
mutech 7:3814d72b8166 105 v = (v & 0x0f0f) + ((v >> 4) & 0x0f0f);
mutech 7:3814d72b8166 106 return (v & 0x00ff) + ((v >> 8) & 0x00ff) - 1;
mutech 7:3814d72b8166 107 }
mutech 7:3814d72b8166 108
mutech 7:3814d72b8166 109 // 整数Xを含む最小のべき乗指数
mutech 7:3814d72b8166 110 int Watchdog::calcExponent16bit(uint16_t v)
mutech 7:3814d72b8166 111 {
mutech 7:3814d72b8166 112 return (v == 0) ? 0 : MSB16bit(v - 1) + 1;
mutech 7:3814d72b8166 113 }
mutech 7:3814d72b8166 114
mutech 7:3814d72b8166 115 //#define WDT_CLOCK 32768 // 32.768 kHz
mutech 7:3814d72b8166 116 #define WDT_CLOCK 40000 // 40 kHz
mutech 7:3814d72b8166 117
WiredHome 5:2dad2a78ffbd 118 /// Load timeout value in watchdog timer and enable
mutech 7:3814d72b8166 119 void Watchdog::Configure(float s)
mutech 7:3814d72b8166 120 {
WiredHome 5:2dad2a78ffbd 121 // http://www.st.com/web/en/resource/technical/document/reference_manual/CD00171190.pdf
mutech 7:3814d72b8166 122
mutech 7:3814d72b8166 123 s = s * WDT_CLOCK; // Newer Nucleo boards have 32.768 kHz crystal. Without it, the internal
mutech 7:3814d72b8166 124 // RC clock would have an average frequency of 40 kHz (variable between 30 and 60 kHz)
mutech 7:3814d72b8166 125 int scale = calcExponent16bit(((int)s + 4095) / 4096);
mutech 7:3814d72b8166 126 if (scale < 2)
mutech 7:3814d72b8166 127 scale = 2;
mutech 7:3814d72b8166 128 int residual = s / (1 << scale); // The value for the RLR register
mutech 7:3814d72b8166 129 if (residual < 1)
mutech 7:3814d72b8166 130 residual = 1;
mutech 7:3814d72b8166 131
mutech 7:3814d72b8166 132 if (scale > 8) //STM32 allows a maximum time of around 26.2 seconds for the Watchdog timer
mutech 7:3814d72b8166 133 {
mutech 7:3814d72b8166 134 scale = 8;
mutech 7:3814d72b8166 135 residual = 4096;
mutech 7:3814d72b8166 136 }
mutech 7:3814d72b8166 137
WiredHome 5:2dad2a78ffbd 138 IWDG->KR = 0x5555; // enable write to PR, RLR
mutech 7:3814d72b8166 139 IWDG->PR = scale - 2; // Prescaler has values of multiples of 4 (i.e. 2 ^2), page 486 Reference Manual
mutech 7:3814d72b8166 140 IWDG->RLR = residual - 1; // Init RLR
mutech 7:3814d72b8166 141 IWDG->KR = 0xAAAA; // Reload the watchdog
mutech 7:3814d72b8166 142 IWDG->KR = 0xCCCC; // Starts the WD
mutech 7:3814d72b8166 143 }
mutech 7:3814d72b8166 144
mutech 7:3814d72b8166 145 void Watchdog::Configure(int ms)
mutech 7:3814d72b8166 146 {
mutech 7:3814d72b8166 147 // http://www.st.com/web/en/resource/technical/document/reference_manual/CD00171190.pdf
mutech 7:3814d72b8166 148 ms = (ms * WDT_CLOCK) / 1000; // Newer Nucleo boards have 32.768 kHz crystal. Without it, the internal
mutech 7:3814d72b8166 149 // RC clock would have an average frequency of 40 kHz (variable between 30 and 60 kHz)
mutech 7:3814d72b8166 150
mutech 7:3814d72b8166 151 int scale = calcExponent16bit((ms + 4095) >> 12);
mutech 7:3814d72b8166 152 if (scale < 2)
mutech 7:3814d72b8166 153 scale = 2;
mutech 7:3814d72b8166 154 int residual = ms / (1 << scale); // The value for the RLR register
mutech 7:3814d72b8166 155 if (residual < 1)
mutech 7:3814d72b8166 156 residual = 1;
mutech 7:3814d72b8166 157
mutech 7:3814d72b8166 158 if (scale > 8) // STM32 allows a maximum time of around 26.2 seconds for the Watchdog timer
mutech 7:3814d72b8166 159 {
mutech 7:3814d72b8166 160 scale = 8;
mutech 7:3814d72b8166 161 residual = 4096;
mutech 7:3814d72b8166 162 }
mutech 7:3814d72b8166 163
mutech 7:3814d72b8166 164 IWDG->KR = 0x5555; // enable write to PR, RLR
mutech 7:3814d72b8166 165 IWDG->PR = scale - 2; // Prescaler has values of multiples of 4 (i.e. 2 ^2), page 486 Reference Manual
mutech 7:3814d72b8166 166 IWDG->RLR = residual - 1; // Init RLR
WiredHome 5:2dad2a78ffbd 167 IWDG->KR = 0xAAAA; // Reload the watchdog
WiredHome 5:2dad2a78ffbd 168 IWDG->KR = 0xCCCC; // Starts the WD
WiredHome 5:2dad2a78ffbd 169 }
WiredHome 0:7a316f14da9c 170
WiredHome 5:2dad2a78ffbd 171 /// "Service", "kick" or "feed" the dog - reset the watchdog timer
mutech 7:3814d72b8166 172 void Watchdog::Service()
mutech 7:3814d72b8166 173 {
WiredHome 5:2dad2a78ffbd 174 IWDG->KR = 0xAAAA;
WiredHome 5:2dad2a78ffbd 175 }
WiredHome 5:2dad2a78ffbd 176
WiredHome 5:2dad2a78ffbd 177 /// get the flag to indicate if the watchdog causes the reset
mutech 7:3814d72b8166 178 bool Watchdog::WatchdogCausedReset()
mutech 7:3814d72b8166 179 {
mutech 7:3814d72b8166 180 if (wdreset)
mutech 7:3814d72b8166 181 {
WiredHome 5:2dad2a78ffbd 182 RCC->CSR |= (1<<24); // clear reset flag
WiredHome 5:2dad2a78ffbd 183 }
WiredHome 5:2dad2a78ffbd 184 return wdreset;
WiredHome 5:2dad2a78ffbd 185 }
WiredHome 5:2dad2a78ffbd 186 #endif