Basic implementation of watchdog

Dependencies:   STM_ResetSupervisor USBDevice

Committer:
JesiMiranda
Date:
Tue Jun 25 23:31:34 2019 +0000
Revision:
0:975e02a70882
Basic watchdog implementation for ST Nucleo boards;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
JesiMiranda 0:975e02a70882 1 /// @file Watchdog.cpp provides the interface to the Watchdog module
JesiMiranda 0:975e02a70882 2 ///
JesiMiranda 0:975e02a70882 3 /// This provides basic Watchdog service for the mbed. You can configure
JesiMiranda 0:975e02a70882 4 /// various timeout intervals that meet your system needs. Additionally,
JesiMiranda 0:975e02a70882 5 /// it is possible to identify if the Watchdog was the cause of any
JesiMiranda 0:975e02a70882 6 /// system restart.
JesiMiranda 0:975e02a70882 7 ///
JesiMiranda 0:975e02a70882 8 /// Adapted from Simon's Watchdog code from http://mbed.org/forum/mbed/topic/508/
JesiMiranda 0:975e02a70882 9 ///
JesiMiranda 0:975e02a70882 10 /// @note Copyright © 2011 by Smartware Computing, all rights reserved.
JesiMiranda 0:975e02a70882 11 /// This software may be used to derive new software, as long as
JesiMiranda 0:975e02a70882 12 /// this copyright statement remains in the source file.
JesiMiranda 0:975e02a70882 13 /// @author David Smart
JesiMiranda 0:975e02a70882 14 ///
JesiMiranda 0:975e02a70882 15 /// @note Copyright © 2015 by NBRemond, all rights reserved.
JesiMiranda 0:975e02a70882 16 /// This software may be used to derive new software, as long as
JesiMiranda 0:975e02a70882 17 /// this copyright statement remains in the source file.
JesiMiranda 0:975e02a70882 18 ///
JesiMiranda 0:975e02a70882 19 /// Added support for STM32 Nucleo platforms
JesiMiranda 0:975e02a70882 20 ///
JesiMiranda 0:975e02a70882 21 /// @author Bernaérd Remond
JesiMiranda 0:975e02a70882 22 ///
JesiMiranda 0:975e02a70882 23
JesiMiranda 0:975e02a70882 24 //#define LPC
JesiMiranda 0:975e02a70882 25 #define ST_NUCLEO
JesiMiranda 0:975e02a70882 26
JesiMiranda 0:975e02a70882 27
JesiMiranda 0:975e02a70882 28 #include "mbed.h"
JesiMiranda 0:975e02a70882 29 #include "Watchdog.h"
JesiMiranda 0:975e02a70882 30
JesiMiranda 0:975e02a70882 31
JesiMiranda 0:975e02a70882 32 /// Watchdog gets instantiated at the module level
JesiMiranda 0:975e02a70882 33 Watchdog::Watchdog() {
JesiMiranda 0:975e02a70882 34 #ifdef LPC
JesiMiranda 0:975e02a70882 35 wdreset = (LPC_WDT->WDMOD >> 2) & 1; // capture the cause of the previous reset
JesiMiranda 0:975e02a70882 36 #endif
JesiMiranda 0:975e02a70882 37 #ifdef ST_NUCLEO
JesiMiranda 0:975e02a70882 38 // capture the cause of the previous reset
JesiMiranda 0:975e02a70882 39 /* Check if the system has resumed from IWDG reset */
JesiMiranda 0:975e02a70882 40 /*
JesiMiranda 0:975e02a70882 41 if (__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST)) {
JesiMiranda 0:975e02a70882 42 wdreset = true;
JesiMiranda 0:975e02a70882 43 }
JesiMiranda 0:975e02a70882 44 else {
JesiMiranda 0:975e02a70882 45 wdreset = false;
JesiMiranda 0:975e02a70882 46 }
JesiMiranda 0:975e02a70882 47 */
JesiMiranda 0:975e02a70882 48 printf("in constructor\r\n");
JesiMiranda 0:975e02a70882 49 wdreset = false;
JesiMiranda 0:975e02a70882 50 #endif
JesiMiranda 0:975e02a70882 51
JesiMiranda 0:975e02a70882 52 }
JesiMiranda 0:975e02a70882 53
JesiMiranda 0:975e02a70882 54 /// Load timeout value in watchdog timer and enable
JesiMiranda 0:975e02a70882 55 void Watchdog::Configure(float timeout) {
JesiMiranda 0:975e02a70882 56 #ifdef LPC
JesiMiranda 0:975e02a70882 57 LPC_WDT->WDCLKSEL = 0x1; // Set CLK src to PCLK
JesiMiranda 0:975e02a70882 58 uint32_t clk = SystemCoreClock / 16; // WD has a fixed /4 prescaler, PCLK default is /4
JesiMiranda 0:975e02a70882 59 LPC_WDT->WDTC = (uint32_t)(timeout * (float)clk);
JesiMiranda 0:975e02a70882 60 LPC_WDT->WDMOD = 0x3; // Enabled and Reset
JesiMiranda 0:975e02a70882 61 #endif
JesiMiranda 0:975e02a70882 62
JesiMiranda 0:975e02a70882 63 #ifdef ST_NUCLEO
JesiMiranda 0:975e02a70882 64 // see http://embedded-lab.com/blog/?p=9662
JesiMiranda 0:975e02a70882 65 #define LsiFreq (45000)
JesiMiranda 0:975e02a70882 66 uint16_t PrescalerCode;
JesiMiranda 0:975e02a70882 67 uint16_t Prescaler;
JesiMiranda 0:975e02a70882 68 uint16_t ReloadValue;
JesiMiranda 0:975e02a70882 69 float Calculated_timeout;
JesiMiranda 0:975e02a70882 70
JesiMiranda 0:975e02a70882 71 if ((timeout * (LsiFreq/4)) < 0x7FF) {
JesiMiranda 0:975e02a70882 72 PrescalerCode = IWDG_PRESCALER_4;
JesiMiranda 0:975e02a70882 73 Prescaler = 4;
JesiMiranda 0:975e02a70882 74 }
JesiMiranda 0:975e02a70882 75 else if ((timeout * (LsiFreq/8)) < 0xFF0) {
JesiMiranda 0:975e02a70882 76 PrescalerCode = IWDG_PRESCALER_8;
JesiMiranda 0:975e02a70882 77 Prescaler = 8;
JesiMiranda 0:975e02a70882 78 }
JesiMiranda 0:975e02a70882 79 else if ((timeout * (LsiFreq/16)) < 0xFF0) {
JesiMiranda 0:975e02a70882 80 PrescalerCode = IWDG_PRESCALER_16;
JesiMiranda 0:975e02a70882 81 Prescaler = 16;
JesiMiranda 0:975e02a70882 82 }
JesiMiranda 0:975e02a70882 83 else if ((timeout * (LsiFreq/32)) < 0xFF0) {
JesiMiranda 0:975e02a70882 84 PrescalerCode = IWDG_PRESCALER_32;
JesiMiranda 0:975e02a70882 85 Prescaler = 32;
JesiMiranda 0:975e02a70882 86 }
JesiMiranda 0:975e02a70882 87 else if ((timeout * (LsiFreq/64)) < 0xFF0) {
JesiMiranda 0:975e02a70882 88 PrescalerCode = IWDG_PRESCALER_64;
JesiMiranda 0:975e02a70882 89 Prescaler = 64;
JesiMiranda 0:975e02a70882 90 }
JesiMiranda 0:975e02a70882 91 else if ((timeout * (LsiFreq/128)) < 0xFF0) {
JesiMiranda 0:975e02a70882 92 PrescalerCode = IWDG_PRESCALER_128;
JesiMiranda 0:975e02a70882 93 Prescaler = 128;
JesiMiranda 0:975e02a70882 94 }
JesiMiranda 0:975e02a70882 95 else {
JesiMiranda 0:975e02a70882 96 PrescalerCode = IWDG_PRESCALER_256;
JesiMiranda 0:975e02a70882 97 Prescaler = 256;
JesiMiranda 0:975e02a70882 98 }
JesiMiranda 0:975e02a70882 99
JesiMiranda 0:975e02a70882 100 // specifies the IWDG Reload value. This parameter must be a number between 0 and 0x0FFF.
JesiMiranda 0:975e02a70882 101 ReloadValue = (uint32_t)(timeout * (LsiFreq/Prescaler));
JesiMiranda 0:975e02a70882 102
JesiMiranda 0:975e02a70882 103 Calculated_timeout = ((float)(Prescaler * ReloadValue)) / LsiFreq;
JesiMiranda 0:975e02a70882 104 printf("WATCHDOG set with prescaler:%d reload value: 0x%X - timeout:%f\n",Prescaler, ReloadValue, Calculated_timeout);
JesiMiranda 0:975e02a70882 105
JesiMiranda 0:975e02a70882 106 IWDG->KR = 0x5555; //Disable write protection of IWDG registers
JesiMiranda 0:975e02a70882 107 IWDG->PR = PrescalerCode; //Set PR value
JesiMiranda 0:975e02a70882 108 IWDG->RLR = ReloadValue; //Set RLR value
JesiMiranda 0:975e02a70882 109 IWDG->KR = 0xAAAA; //Reload IWDG
JesiMiranda 0:975e02a70882 110 IWDG->KR = 0xCCCC; //Start IWDG - See more at: http://embedded-lab.com/blog/?p=9662#sthash.6VNxVSn0.dpuf
JesiMiranda 0:975e02a70882 111 #endif
JesiMiranda 0:975e02a70882 112
JesiMiranda 0:975e02a70882 113 Service();
JesiMiranda 0:975e02a70882 114 }
JesiMiranda 0:975e02a70882 115
JesiMiranda 0:975e02a70882 116 /// "Service", "kick" or "feed" the dog - reset the watchdog timer
JesiMiranda 0:975e02a70882 117 /// by writing this required bit pattern
JesiMiranda 0:975e02a70882 118 void Watchdog::Service() {
JesiMiranda 0:975e02a70882 119 #ifdef LPC
JesiMiranda 0:975e02a70882 120 LPC_WDT->WDFEED = 0xAA;
JesiMiranda 0:975e02a70882 121 LPC_WDT->WDFEED = 0x55;
JesiMiranda 0:975e02a70882 122 #endif
JesiMiranda 0:975e02a70882 123 #ifdef ST_NUCLEO
JesiMiranda 0:975e02a70882 124 IWDG->KR = 0xAAAA; //Reload IWDG - See more at: http://embedded-lab.com/blog/?p=9662#sthash.6VNxVSn0.dpuf
JesiMiranda 0:975e02a70882 125 #endif
JesiMiranda 0:975e02a70882 126 }
JesiMiranda 0:975e02a70882 127
JesiMiranda 0:975e02a70882 128 /// get the flag to indicate if the watchdog causes the reset
JesiMiranda 0:975e02a70882 129 bool Watchdog::WatchdogCausedReset() {
JesiMiranda 0:975e02a70882 130 return wdreset;
JesiMiranda 0:975e02a70882 131 }