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:
Tue Oct 27 16:02:33 2015 +0000
Revision:
7:8912bb017956
Parent:
5:2dad2a78ffbd
Child:
8:3c7d083f26b5
Updated the STM version so that it will accept the value of timer in seconds, just like how it is for the other architectures.

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 7:8912bb017956 79 int 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 7:8912bb017956 94 s = s * 40000; // The average frequency of STM32 watchdog timer is 40 kHz but it can vary between 30 and 60 kHz
salarian 7:8912bb017956 95 int scale = 1 + log2(s / 4096); // The RLR register is 12 bits and beyond that a prescaler should be used
salarian 7:8912bb017956 96 int residual = s / (1 << scale); // The value for the RLR register
salarian 7:8912bb017956 97
WiredHome 5:2dad2a78ffbd 98 IWDG->KR = 0x5555; // enable write to PR, RLR
salarian 7:8912bb017956 99 IWDG->PR = scale - 2; // Prescaler has values of multiples of 4 (i.e. 2 ^2), page 486 Reference Manual
salarian 7:8912bb017956 100 IWDG->RLR = residual; // Init RLR
WiredHome 5:2dad2a78ffbd 101 IWDG->KR = 0xAAAA; // Reload the watchdog
WiredHome 5:2dad2a78ffbd 102 IWDG->KR = 0xCCCC; // Starts the WD
WiredHome 5:2dad2a78ffbd 103 }
WiredHome 0:7a316f14da9c 104
WiredHome 5:2dad2a78ffbd 105 /// "Service", "kick" or "feed" the dog - reset the watchdog timer
WiredHome 5:2dad2a78ffbd 106 void Watchdog::Service() {
WiredHome 5:2dad2a78ffbd 107 IWDG->KR = 0xAAAA;
WiredHome 5:2dad2a78ffbd 108 }
WiredHome 5:2dad2a78ffbd 109
WiredHome 5:2dad2a78ffbd 110 /// get the flag to indicate if the watchdog causes the reset
WiredHome 5:2dad2a78ffbd 111 bool Watchdog::WatchdogCausedReset() {
WiredHome 5:2dad2a78ffbd 112 if (wdreset) {
WiredHome 5:2dad2a78ffbd 113 RCC->CSR |= (1<<24); // clear reset flag
WiredHome 5:2dad2a78ffbd 114 }
WiredHome 5:2dad2a78ffbd 115 return wdreset;
WiredHome 5:2dad2a78ffbd 116 }
WiredHome 5:2dad2a78ffbd 117 #endif