Tomonori Kuroki / MuWatchdog

Fork of Watchdog by David Smart

Revision:
7:3814d72b8166
Parent:
5:2dad2a78ffbd
Child:
8:ea82a76ca81f
diff -r e0f547e22dd5 -r 3814d72b8166 Watchdog.cpp
--- a/Watchdog.cpp	Mon Mar 16 01:04:32 2015 +0000
+++ b/Watchdog.cpp	Tue Sep 13 17:01:18 2016 +0000
@@ -12,7 +12,8 @@
 ///     this copyright statement remains in the source file.
 /// @author David Smart
 ///
-#include "mbed.h"
+/// \li v2.10 - 20160914: Changed TARGET_STM by mutech, t.kuroki
+
 #include "Watchdog.h"
 
 #if defined( TARGET_LPC1768 )
@@ -30,6 +31,14 @@
     Service();
 }
 
+void Watchdog::Configure(int ms) {
+    LPC_WDT->WDCLKSEL = 0x1;                // Set CLK src to PCLK
+    uint32_t clk = SystemCoreClock / 1000;  // 
+    LPC_WDT->WDTC = (ms * clk) / 16;        // WD has a fixed /4 prescaler, PCLK default is /4
+    LPC_WDT->WDMOD = 0x3;                   // Enabled and Reset
+    Service();
+}
+
 /// "Service", "kick" or "feed" the dog - reset the watchdog timer
 /// by writing this required bit pattern
 void Watchdog::Service() {
@@ -56,7 +65,15 @@
     LPC_WDT->MOD = 0x3;                   // Enabled and Reset
     Service();
 }
- 
+
+void Watchdog::Configure(int ms) {
+    //LPC_WDT->CLKSEL = 0x1;                // Set CLK src to PCLK
+    uint32_t clk = 500000 / 4;    // WD has a fixed /4 prescaler, and a 500khz oscillator
+    LPC_WDT->TC = (ms * clk) / 1000;
+    LPC_WDT->MOD = 0x3;                   // Enabled and Reset
+    Service();
+}
+
 /// "Service", "kick" or "feed" the dog - reset the watchdog timer
 /// by writing this required bit pattern
 void Watchdog::Service() {
@@ -68,31 +85,100 @@
 bool Watchdog::WatchdogCausedReset() {
     return wdreset;
 }
-#elif defined( TARGET_STM )
-// Derived from Chau Vo
-/// Watchdog gets instantiated at the module level
-Watchdog::Watchdog() {
+#elif defined(TARGET_STM)
+Watchdog::Watchdog()
+{
     wdreset = (RCC->CSR & (1<<29)) ? true : false;  // read the IWDGRSTF (Independent WD, not the windows WD)
 }
 
+// 最大有効ビット数(MSB:Most Significant Bit)
+int Watchdog::MSB16bit(uint16_t v)
+{
+    v |= (v >> 1);
+    v |= (v >> 2);
+    v |= (v >> 4);
+    v |= (v >> 8);
+//  return count16bit(v) - 1;
+// 立っているビットの数を数える
+    v = (v & 0x5555) + ((v >> 1) & 0x5555);
+    v = (v & 0x3333) + ((v >> 2) & 0x3333);
+    v = (v & 0x0f0f) + ((v >> 4) & 0x0f0f);
+    return  (v & 0x00ff) + ((v >> 8) & 0x00ff) - 1;
+}
+
+// 整数Xを含む最小のべき乗指数
+int Watchdog::calcExponent16bit(uint16_t v)
+{
+    return (v == 0) ? 0 : MSB16bit(v - 1) + 1;
+}
+
+//#define WDT_CLOCK     32768       // 32.768 kHz
+#define WDT_CLOCK       40000       // 40 kHz
+
 /// Load timeout value in watchdog timer and enable
-void Watchdog::Configure(int pr) {
+void Watchdog::Configure(float s)
+{
     // http://www.st.com/web/en/resource/technical/document/reference_manual/CD00171190.pdf
+
+    s = s * WDT_CLOCK;          // Newer Nucleo boards have 32.768 kHz crystal. Without it, the internal 
+                                // RC clock would have an average frequency of 40 kHz (variable between 30 and 60 kHz)
+    int scale = calcExponent16bit(((int)s + 4095) / 4096);
+    if (scale < 2)
+        scale = 2;
+    int residual = s / (1 << scale);    // The value for the RLR register
+    if (residual < 1)
+        residual = 1;
+
+    if (scale > 8)              //STM32 allows a maximum time of around 26.2 seconds for the Watchdog timer
+    {
+        scale = 8;
+        residual = 4096;
+    }
+
     IWDG->KR  = 0x5555;         // enable write to PR, RLR
-    IWDG->PR  = pr;             // Init prescaler, page 486 Reference Manual
-    IWDG->RLR = 0xFFF;          // Init RLR
+    IWDG->PR  = scale - 2;      // Prescaler has values of multiples of 4 (i.e. 2 ^2), page 486 Reference Manual
+    IWDG->RLR = residual - 1;   // Init RLR
+    IWDG->KR  = 0xAAAA;         // Reload the watchdog
+    IWDG->KR  = 0xCCCC;         // Starts the WD
+}
+
+void Watchdog::Configure(int ms)
+{
+    // http://www.st.com/web/en/resource/technical/document/reference_manual/CD00171190.pdf
+    ms = (ms * WDT_CLOCK) / 1000;   // Newer Nucleo boards have 32.768 kHz crystal. Without it, the internal 
+                                // RC clock would have an average frequency of 40 kHz (variable between 30 and 60 kHz)
+
+    int scale = calcExponent16bit((ms + 4095) >> 12);
+    if (scale < 2)
+        scale = 2;
+    int residual = ms / (1 << scale);   // The value for the RLR register
+    if (residual < 1)
+        residual = 1;
+
+    if (scale > 8)              // STM32 allows a maximum time of around 26.2 seconds for the Watchdog timer
+    {
+        scale = 8;
+        residual = 4096;
+    }
+
+    IWDG->KR  = 0x5555;         // enable write to PR, RLR
+    IWDG->PR  = scale - 2;      // Prescaler has values of multiples of 4 (i.e. 2 ^2), page 486 Reference Manual
+    IWDG->RLR = residual - 1;   // Init RLR
     IWDG->KR  = 0xAAAA;         // Reload the watchdog
     IWDG->KR  = 0xCCCC;         // Starts the WD
 }
 
 /// "Service", "kick" or "feed" the dog - reset the watchdog timer
-void Watchdog::Service() {
+void Watchdog::Service()
+{
     IWDG->KR  = 0xAAAA;
 }
 
 /// get the flag to indicate if the watchdog causes the reset
-bool Watchdog::WatchdogCausedReset() {
-    if (wdreset) {
+bool Watchdog::WatchdogCausedReset()
+{
+    if (wdreset)
+    {
         RCC->CSR |= (1<<24); // clear reset flag
     }
     return wdreset;