Modified version of the Watchdog library with improved support for STM32
Dependents: LightSaber iot_water_monitor_v2
Fork of Watchdog by
Watchdog.cpp@7:8912bb017956, 2015-10-27 (annotated)
- 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?
User | Revision | Line number | New 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 |