Class to add reset supervision with a watchdog timer functionality

Dependents:   Example_WatchDog_Timer

Committer:
rlanders73
Date:
Fri Oct 04 15:28:36 2019 +0000
Revision:
3:b7a9432fe880
Parent:
2:72d1cb8fc13c
Child:
4:f31b32884780
added software reset capability.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rlanders73 1:4e2e6a9dc079 1 /// @file Supervisor.cpp provides the interface to the Supervisor module
rlanders73 1:4e2e6a9dc079 2 ///
rlanders73 1:4e2e6a9dc079 3 /// This provides basic Supervisor service for the mbed. You can configure
rlanders73 1:4e2e6a9dc079 4 /// various timeout intervals that meet your system needs. Additionally,
rlanders73 1:4e2e6a9dc079 5 /// it is possible to identify if the Supervisor was the cause of any
rlanders73 1:4e2e6a9dc079 6 /// system restart.
rlanders73 1:4e2e6a9dc079 7 ///
rlanders73 1:4e2e6a9dc079 8 /// Adapted from Simon's watchdog code from http://mbed.org/forum/mbed/topic/508/
rlanders73 1:4e2e6a9dc079 9
rlanders73 1:4e2e6a9dc079 10
rlanders73 1:4e2e6a9dc079 11 #include "mbed.h"
rlanders73 1:4e2e6a9dc079 12 #include "ResetSupervisor.h"
rlanders73 1:4e2e6a9dc079 13
rlanders73 1:4e2e6a9dc079 14 #ifdef FEATURE_COMMON_PAL
rlanders73 1:4e2e6a9dc079 15 #include "mbed_trace.h"
rlanders73 1:4e2e6a9dc079 16 #define TRACE_GROUP "WDT"
rlanders73 1:4e2e6a9dc079 17 #else
rlanders73 1:4e2e6a9dc079 18 #define tr_debug(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__)
rlanders73 1:4e2e6a9dc079 19 #define tr_info(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__)
rlanders73 1:4e2e6a9dc079 20 #define tr_warn(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__)
rlanders73 1:4e2e6a9dc079 21 #define tr_error(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__)
rlanders73 1:4e2e6a9dc079 22 #endif
rlanders73 1:4e2e6a9dc079 23
rlanders73 1:4e2e6a9dc079 24 /// Supervisor gets instantiated at the module level
rlanders73 1:4e2e6a9dc079 25 Supervisor::Supervisor() {
rlanders73 1:4e2e6a9dc079 26 // capture the cause of the previous reset
rlanders73 1:4e2e6a9dc079 27 if(__HAL_RCC_GET_FLAG(RCC_FLAG_BORRST))// BOR reset
rlanders73 1:4e2e6a9dc079 28 rstRsn = RCC_FLAG_BORRST;
rlanders73 1:4e2e6a9dc079 29 else if(__HAL_RCC_GET_FLAG(RCC_FLAG_OBLRST))// OBLRST reset
rlanders73 1:4e2e6a9dc079 30 rstRsn = RCC_FLAG_OBLRST;
rlanders73 1:4e2e6a9dc079 31 else if(__HAL_RCC_GET_FLAG(RCC_FLAG_PINRST))// Pin reset
rlanders73 1:4e2e6a9dc079 32 rstRsn = RCC_FLAG_PINRST;
rlanders73 1:4e2e6a9dc079 33 else if(__HAL_RCC_GET_FLAG(RCC_FLAG_FWRST))// FIREWALL reset
rlanders73 1:4e2e6a9dc079 34 rstRsn = RCC_FLAG_FWRST;
rlanders73 1:4e2e6a9dc079 35 else if(__HAL_RCC_GET_FLAG(RCC_FLAG_SFTRST))// Software reset
rlanders73 1:4e2e6a9dc079 36 rstRsn = RCC_FLAG_SFTRST;
rlanders73 1:4e2e6a9dc079 37 else if(__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST))// Independent Supervisor reset
rlanders73 1:4e2e6a9dc079 38 rstRsn = RCC_FLAG_IWDGRST;
rlanders73 1:4e2e6a9dc079 39 else if(__HAL_RCC_GET_FLAG(RCC_FLAG_WWDGRST))// Window Supervisor reset
rlanders73 1:4e2e6a9dc079 40 rstRsn = RCC_FLAG_WWDGRST;
rlanders73 1:4e2e6a9dc079 41 else if(__HAL_RCC_GET_FLAG(RCC_FLAG_LPWRRST))// Low Power reset
rlanders73 1:4e2e6a9dc079 42 rstRsn = RCC_FLAG_LPWRRST;
rlanders73 1:4e2e6a9dc079 43
rlanders73 1:4e2e6a9dc079 44 //Clear source Reset Flag
rlanders73 1:4e2e6a9dc079 45 __HAL_RCC_CLEAR_RESET_FLAGS();
rlanders73 1:4e2e6a9dc079 46 }
rlanders73 1:4e2e6a9dc079 47
rlanders73 1:4e2e6a9dc079 48 /// Load timeout value in watchdog timer and enable
rlanders73 2:72d1cb8fc13c 49 void Supervisor::initWD(float timeout) {
rlanders73 1:4e2e6a9dc079 50
rlanders73 1:4e2e6a9dc079 51 #define LsiFreq (45000)
rlanders73 1:4e2e6a9dc079 52 uint16_t PrescalerCode;
rlanders73 1:4e2e6a9dc079 53 uint16_t Prescaler;
rlanders73 1:4e2e6a9dc079 54 uint16_t ReloadValue;
rlanders73 1:4e2e6a9dc079 55 float Calculated_timeout;
rlanders73 1:4e2e6a9dc079 56
rlanders73 1:4e2e6a9dc079 57 if ((timeout * (LsiFreq/4)) < 0x7FF) {
rlanders73 1:4e2e6a9dc079 58 PrescalerCode = IWDG_PRESCALER_4;
rlanders73 1:4e2e6a9dc079 59 Prescaler = 4;
rlanders73 1:4e2e6a9dc079 60 }
rlanders73 1:4e2e6a9dc079 61 else if ((timeout * (LsiFreq/8)) < 0xFF0) {
rlanders73 1:4e2e6a9dc079 62 PrescalerCode = IWDG_PRESCALER_8;
rlanders73 1:4e2e6a9dc079 63 Prescaler = 8;
rlanders73 1:4e2e6a9dc079 64 }
rlanders73 1:4e2e6a9dc079 65 else if ((timeout * (LsiFreq/16)) < 0xFF0) {
rlanders73 1:4e2e6a9dc079 66 PrescalerCode = IWDG_PRESCALER_16;
rlanders73 1:4e2e6a9dc079 67 Prescaler = 16;
rlanders73 1:4e2e6a9dc079 68 }
rlanders73 1:4e2e6a9dc079 69 else if ((timeout * (LsiFreq/32)) < 0xFF0) {
rlanders73 1:4e2e6a9dc079 70 PrescalerCode = IWDG_PRESCALER_32;
rlanders73 1:4e2e6a9dc079 71 Prescaler = 32;
rlanders73 1:4e2e6a9dc079 72 }
rlanders73 1:4e2e6a9dc079 73 else if ((timeout * (LsiFreq/64)) < 0xFF0) {
rlanders73 1:4e2e6a9dc079 74 PrescalerCode = IWDG_PRESCALER_64;
rlanders73 1:4e2e6a9dc079 75 Prescaler = 64;
rlanders73 1:4e2e6a9dc079 76 }
rlanders73 1:4e2e6a9dc079 77 else if ((timeout * (LsiFreq/128)) < 0xFF0) {
rlanders73 1:4e2e6a9dc079 78 PrescalerCode = IWDG_PRESCALER_128;
rlanders73 1:4e2e6a9dc079 79 Prescaler = 128;
rlanders73 1:4e2e6a9dc079 80 }
rlanders73 1:4e2e6a9dc079 81 else {
rlanders73 1:4e2e6a9dc079 82 PrescalerCode = IWDG_PRESCALER_256;
rlanders73 1:4e2e6a9dc079 83 Prescaler = 256;
rlanders73 1:4e2e6a9dc079 84 }
rlanders73 1:4e2e6a9dc079 85
rlanders73 1:4e2e6a9dc079 86 // specifies the IWDG Reload value. This parameter must be a number between 0 and 0x0FFF.
rlanders73 1:4e2e6a9dc079 87 ReloadValue = (uint32_t)(timeout * (LsiFreq/Prescaler));
rlanders73 1:4e2e6a9dc079 88
rlanders73 1:4e2e6a9dc079 89 Calculated_timeout = ((float)(Prescaler * ReloadValue)) / LsiFreq;
rlanders73 1:4e2e6a9dc079 90 tr_debug("WATCHDOG set with prescaler:%d reload value: 0x%X - timeout:%f\n",Prescaler, ReloadValue, Calculated_timeout);
rlanders73 1:4e2e6a9dc079 91
rlanders73 1:4e2e6a9dc079 92 IWDG->KR = 0x5555; //Disable write protection of IWDG registers
rlanders73 1:4e2e6a9dc079 93 IWDG->PR = PrescalerCode; //Set PR value
rlanders73 1:4e2e6a9dc079 94 IWDG->RLR = ReloadValue; //Set RLR value
rlanders73 1:4e2e6a9dc079 95 IWDG->KR = 0xAAAA; //Reload IWDG
rlanders73 1:4e2e6a9dc079 96 IWDG->KR = 0xCCCC; //Start IWDG - See more at: http://embedded-lab.com/blog/?p=9662#sthash.6VNxVSn0.dpuf
rlanders73 1:4e2e6a9dc079 97
rlanders73 2:72d1cb8fc13c 98 pingWD();
rlanders73 1:4e2e6a9dc079 99 }
rlanders73 1:4e2e6a9dc079 100
rlanders73 2:72d1cb8fc13c 101 /// "Ping", "kick" or "feed" the dog - reset the watchdog timer
rlanders73 1:4e2e6a9dc079 102 /// by writing this required bit pattern
rlanders73 2:72d1cb8fc13c 103 void Supervisor::pingWD() {
rlanders73 1:4e2e6a9dc079 104 IWDG->KR = 0xAAAA; //Reload IWDG - See more at: http://embedded-lab.com/blog/?p=9662#sthash.6VNxVSn0.dpuf
rlanders73 1:4e2e6a9dc079 105 }
rlanders73 1:4e2e6a9dc079 106
rlanders73 2:72d1cb8fc13c 107 uint8_t Supervisor::resetReason(){
rlanders73 1:4e2e6a9dc079 108 return rstRsn;
rlanders73 1:4e2e6a9dc079 109 }
rlanders73 1:4e2e6a9dc079 110
rlanders73 3:b7a9432fe880 111 void Supervisor::doReset() {
rlanders73 3:b7a9432fe880 112 NVIC_SystemReset(); // pull the plug
rlanders73 3:b7a9432fe880 113 }
rlanders73 3:b7a9432fe880 114