Modified version of the Watchdog library with improved support for STM32

Dependents:   LightSaber iot_water_monitor_v2

Fork of Watchdog by David Smart

Committer:
salarian
Date:
Wed Nov 11 16:05:42 2015 +0000
Revision:
9:84f7c088c261
Parent:
8:3c7d083f26b5
Refactored the STM32 bit variant of the functions and set the default clock to 32.768 kHz (crystal oscillator)

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 ///
WiredHome 0:7a316f14da9c 15 #include "mbed.h"
WiredHome 0:7a316f14da9c 16 #include "Watchdog.h"
WiredHome 0:7a316f14da9c 17
WiredHome 5:2dad2a78ffbd 18 #if defined( TARGET_LPC1768 )
WiredHome 0:7a316f14da9c 19 /// Watchdog gets instantiated at the module level
WiredHome 0:7a316f14da9c 20 Watchdog::Watchdog() {
WiredHome 2:2873f068f325 21 wdreset = (LPC_WDT->WDMOD >> 2) & 1; // capture the cause of the previous reset
WiredHome 0:7a316f14da9c 22 }
WiredHome 0:7a316f14da9c 23
WiredHome 0:7a316f14da9c 24 /// Load timeout value in watchdog timer and enable
WiredHome 0:7a316f14da9c 25 void Watchdog::Configure(float s) {
WiredHome 0:7a316f14da9c 26 LPC_WDT->WDCLKSEL = 0x1; // Set CLK src to PCLK
WiredHome 0:7a316f14da9c 27 uint32_t clk = SystemCoreClock / 16; // WD has a fixed /4 prescaler, PCLK default is /4
WiredHome 2:2873f068f325 28 LPC_WDT->WDTC = (uint32_t)(s * (float)clk);
WiredHome 0:7a316f14da9c 29 LPC_WDT->WDMOD = 0x3; // Enabled and Reset
WiredHome 0:7a316f14da9c 30 Service();
WiredHome 0:7a316f14da9c 31 }
WiredHome 0:7a316f14da9c 32
WiredHome 0:7a316f14da9c 33 /// "Service", "kick" or "feed" the dog - reset the watchdog timer
WiredHome 0:7a316f14da9c 34 /// by writing this required bit pattern
WiredHome 0:7a316f14da9c 35 void Watchdog::Service() {
WiredHome 0:7a316f14da9c 36 LPC_WDT->WDFEED = 0xAA;
WiredHome 0:7a316f14da9c 37 LPC_WDT->WDFEED = 0x55;
WiredHome 0:7a316f14da9c 38 }
WiredHome 0:7a316f14da9c 39
WiredHome 0:7a316f14da9c 40 /// get the flag to indicate if the watchdog causes the reset
WiredHome 0:7a316f14da9c 41 bool Watchdog::WatchdogCausedReset() {
WiredHome 0:7a316f14da9c 42 return wdreset;
WiredHome 0:7a316f14da9c 43 }
WiredHome 5:2dad2a78ffbd 44 #elif defined( TARGET_LPC4088 )
WiredHome 5:2dad2a78ffbd 45 // from Gesotec Gesotec
WiredHome 5:2dad2a78ffbd 46 /// Watchdog gets instantiated at the module level
WiredHome 5:2dad2a78ffbd 47 Watchdog::Watchdog() {
WiredHome 5:2dad2a78ffbd 48 wdreset = (LPC_WDT->MOD >> 2) & 1; // capture the cause of the previous reset
WiredHome 5:2dad2a78ffbd 49 }
WiredHome 5:2dad2a78ffbd 50
WiredHome 5:2dad2a78ffbd 51 /// Load timeout value in watchdog timer and enable
WiredHome 5:2dad2a78ffbd 52 void Watchdog::Configure(float s) {
WiredHome 5:2dad2a78ffbd 53 //LPC_WDT->CLKSEL = 0x1; // Set CLK src to PCLK
WiredHome 5:2dad2a78ffbd 54 uint32_t clk = 500000 / 4; // WD has a fixed /4 prescaler, and a 500khz oscillator
WiredHome 5:2dad2a78ffbd 55 LPC_WDT->TC = (uint32_t)(s * (float)clk);
WiredHome 5:2dad2a78ffbd 56 LPC_WDT->MOD = 0x3; // Enabled and Reset
WiredHome 5:2dad2a78ffbd 57 Service();
WiredHome 5:2dad2a78ffbd 58 }
WiredHome 5:2dad2a78ffbd 59
WiredHome 5:2dad2a78ffbd 60 /// "Service", "kick" or "feed" the dog - reset the watchdog timer
WiredHome 5:2dad2a78ffbd 61 /// by writing this required bit pattern
WiredHome 5:2dad2a78ffbd 62 void Watchdog::Service() {
WiredHome 5:2dad2a78ffbd 63 LPC_WDT->FEED = 0xAA;
WiredHome 5:2dad2a78ffbd 64 LPC_WDT->FEED = 0x55;
WiredHome 5:2dad2a78ffbd 65 }
WiredHome 5:2dad2a78ffbd 66
WiredHome 5:2dad2a78ffbd 67 /// get the flag to indicate if the watchdog causes the reset
WiredHome 5:2dad2a78ffbd 68 bool Watchdog::WatchdogCausedReset() {
WiredHome 5:2dad2a78ffbd 69 return wdreset;
WiredHome 5:2dad2a78ffbd 70 }
WiredHome 5:2dad2a78ffbd 71 #elif defined( TARGET_STM )
WiredHome 5:2dad2a78ffbd 72 // Derived from Chau Vo
WiredHome 5:2dad2a78ffbd 73 /// Watchdog gets instantiated at the module level
WiredHome 5:2dad2a78ffbd 74 Watchdog::Watchdog() {
WiredHome 5:2dad2a78ffbd 75 wdreset = (RCC->CSR & (1<<29)) ? true : false; // read the IWDGRSTF (Independent WD, not the windows WD)
WiredHome 5:2dad2a78ffbd 76 }
WiredHome 0:7a316f14da9c 77
salarian 7:8912bb017956 78 // Compute the log2 of an integer. This is the simplest algorithm but probably is a bit slow.
salarian 9:84f7c088c261 79 int Watchdog::log2(unsigned v)
salarian 7:8912bb017956 80 {
salarian 7:8912bb017956 81 unsigned r = 0;
salarian 7:8912bb017956 82
salarian 7:8912bb017956 83 while (v >>= 1)
salarian 7:8912bb017956 84 r++;
salarian 7:8912bb017956 85
salarian 7:8912bb017956 86 return r;
salarian 7:8912bb017956 87 }
salarian 7:8912bb017956 88
salarian 7:8912bb017956 89
WiredHome 5:2dad2a78ffbd 90 /// Load timeout value in watchdog timer and enable
salarian 7:8912bb017956 91 void Watchdog::Configure(float s) {
WiredHome 5:2dad2a78ffbd 92 // http://www.st.com/web/en/resource/technical/document/reference_manual/CD00171190.pdf
salarian 7:8912bb017956 93
salarian 9:84f7c088c261 94 s = s * 32768; // Newer Nucleo boards have 32.768 kHz crystal. Without it, the internal
salarian 9:84f7c088c261 95 // RC clock would have an average frequency of 40 kHz (variable between 30 and 60 kHz)
salarian 9:84f7c088c261 96
salarian 7:8912bb017956 97 int scale = 1 + log2(s / 4096); // The RLR register is 12 bits and beyond that a prescaler should be used
salarian 7:8912bb017956 98 int residual = s / (1 << scale); // The value for the RLR register
salarian 7:8912bb017956 99
salarian 8:3c7d083f26b5 100 if (scale > 8) { //STM32 allows a maximum time of around 26.2 seconds for the Watchdog timer
salarian 8:3c7d083f26b5 101 scale = 8;
salarian 8:3c7d083f26b5 102 residual = 0xFFF;
salarian 8:3c7d083f26b5 103 }
salarian 9:84f7c088c261 104
WiredHome 5:2dad2a78ffbd 105 IWDG->KR = 0x5555; // enable write to PR, RLR
salarian 7:8912bb017956 106 IWDG->PR = scale - 2; // Prescaler has values of multiples of 4 (i.e. 2 ^2), page 486 Reference Manual
salarian 7:8912bb017956 107 IWDG->RLR = residual; // Init RLR
WiredHome 5:2dad2a78ffbd 108 IWDG->KR = 0xAAAA; // Reload the watchdog
WiredHome 5:2dad2a78ffbd 109 IWDG->KR = 0xCCCC; // Starts the WD
WiredHome 5:2dad2a78ffbd 110 }
WiredHome 0:7a316f14da9c 111
WiredHome 5:2dad2a78ffbd 112 /// "Service", "kick" or "feed" the dog - reset the watchdog timer
WiredHome 5:2dad2a78ffbd 113 void Watchdog::Service() {
WiredHome 5:2dad2a78ffbd 114 IWDG->KR = 0xAAAA;
WiredHome 5:2dad2a78ffbd 115 }
WiredHome 5:2dad2a78ffbd 116
WiredHome 5:2dad2a78ffbd 117 /// get the flag to indicate if the watchdog causes the reset
WiredHome 5:2dad2a78ffbd 118 bool Watchdog::WatchdogCausedReset() {
WiredHome 5:2dad2a78ffbd 119 if (wdreset) {
WiredHome 5:2dad2a78ffbd 120 RCC->CSR |= (1<<24); // clear reset flag
WiredHome 5:2dad2a78ffbd 121 }
WiredHome 5:2dad2a78ffbd 122 return wdreset;
WiredHome 5:2dad2a78ffbd 123 }
WiredHome 5:2dad2a78ffbd 124 #endif