Class to add reset supervision with a watchdog timer functionality

Dependents:   Example_WatchDog_Timer

Committer:
rlanders73
Date:
Tue Jun 15 14:00:35 2021 +0000
Revision:
5:7af579ded04f
Parent:
4:f31b32884780
removing COMMON_PAL requirement, as this has been depricated.

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 #include "mbed_trace.h"
rlanders73 1:4e2e6a9dc079 15 #define TRACE_GROUP "WDT"
rlanders73 1:4e2e6a9dc079 16
rlanders73 1:4e2e6a9dc079 17 /// Supervisor gets instantiated at the module level
rlanders73 1:4e2e6a9dc079 18 Supervisor::Supervisor() {
rlanders73 1:4e2e6a9dc079 19 // capture the cause of the previous reset
rlanders73 1:4e2e6a9dc079 20 if(__HAL_RCC_GET_FLAG(RCC_FLAG_BORRST))// BOR reset
rlanders73 1:4e2e6a9dc079 21 rstRsn = RCC_FLAG_BORRST;
rlanders73 4:f31b32884780 22 // else if(__HAL_RCC_GET_FLAG(RCC_FLAG_OBLRST))// OBLRST reset
rlanders73 4:f31b32884780 23 // rstRsn = RCC_FLAG_OBLRST;
rlanders73 1:4e2e6a9dc079 24 else if(__HAL_RCC_GET_FLAG(RCC_FLAG_PINRST))// Pin reset
rlanders73 1:4e2e6a9dc079 25 rstRsn = RCC_FLAG_PINRST;
rlanders73 4:f31b32884780 26 // else if(__HAL_RCC_GET_FLAG(RCC_FLAG_FWRST))// FIREWALL reset
rlanders73 4:f31b32884780 27 // rstRsn = RCC_FLAG_FWRST;
rlanders73 1:4e2e6a9dc079 28 else if(__HAL_RCC_GET_FLAG(RCC_FLAG_SFTRST))// Software reset
rlanders73 1:4e2e6a9dc079 29 rstRsn = RCC_FLAG_SFTRST;
rlanders73 1:4e2e6a9dc079 30 else if(__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST))// Independent Supervisor reset
rlanders73 1:4e2e6a9dc079 31 rstRsn = RCC_FLAG_IWDGRST;
rlanders73 1:4e2e6a9dc079 32 else if(__HAL_RCC_GET_FLAG(RCC_FLAG_WWDGRST))// Window Supervisor reset
rlanders73 1:4e2e6a9dc079 33 rstRsn = RCC_FLAG_WWDGRST;
rlanders73 1:4e2e6a9dc079 34 else if(__HAL_RCC_GET_FLAG(RCC_FLAG_LPWRRST))// Low Power reset
rlanders73 1:4e2e6a9dc079 35 rstRsn = RCC_FLAG_LPWRRST;
rlanders73 1:4e2e6a9dc079 36
rlanders73 1:4e2e6a9dc079 37 //Clear source Reset Flag
rlanders73 1:4e2e6a9dc079 38 __HAL_RCC_CLEAR_RESET_FLAGS();
rlanders73 1:4e2e6a9dc079 39 }
rlanders73 1:4e2e6a9dc079 40
rlanders73 1:4e2e6a9dc079 41 /// Load timeout value in watchdog timer and enable
rlanders73 2:72d1cb8fc13c 42 void Supervisor::initWD(float timeout) {
rlanders73 1:4e2e6a9dc079 43
rlanders73 1:4e2e6a9dc079 44 #define LsiFreq (45000)
rlanders73 1:4e2e6a9dc079 45 uint16_t PrescalerCode;
rlanders73 1:4e2e6a9dc079 46 uint16_t Prescaler;
rlanders73 1:4e2e6a9dc079 47 uint16_t ReloadValue;
rlanders73 1:4e2e6a9dc079 48 float Calculated_timeout;
rlanders73 1:4e2e6a9dc079 49
rlanders73 1:4e2e6a9dc079 50 if ((timeout * (LsiFreq/4)) < 0x7FF) {
rlanders73 1:4e2e6a9dc079 51 PrescalerCode = IWDG_PRESCALER_4;
rlanders73 1:4e2e6a9dc079 52 Prescaler = 4;
rlanders73 1:4e2e6a9dc079 53 }
rlanders73 1:4e2e6a9dc079 54 else if ((timeout * (LsiFreq/8)) < 0xFF0) {
rlanders73 1:4e2e6a9dc079 55 PrescalerCode = IWDG_PRESCALER_8;
rlanders73 1:4e2e6a9dc079 56 Prescaler = 8;
rlanders73 1:4e2e6a9dc079 57 }
rlanders73 1:4e2e6a9dc079 58 else if ((timeout * (LsiFreq/16)) < 0xFF0) {
rlanders73 1:4e2e6a9dc079 59 PrescalerCode = IWDG_PRESCALER_16;
rlanders73 1:4e2e6a9dc079 60 Prescaler = 16;
rlanders73 1:4e2e6a9dc079 61 }
rlanders73 1:4e2e6a9dc079 62 else if ((timeout * (LsiFreq/32)) < 0xFF0) {
rlanders73 1:4e2e6a9dc079 63 PrescalerCode = IWDG_PRESCALER_32;
rlanders73 1:4e2e6a9dc079 64 Prescaler = 32;
rlanders73 1:4e2e6a9dc079 65 }
rlanders73 1:4e2e6a9dc079 66 else if ((timeout * (LsiFreq/64)) < 0xFF0) {
rlanders73 1:4e2e6a9dc079 67 PrescalerCode = IWDG_PRESCALER_64;
rlanders73 1:4e2e6a9dc079 68 Prescaler = 64;
rlanders73 1:4e2e6a9dc079 69 }
rlanders73 1:4e2e6a9dc079 70 else if ((timeout * (LsiFreq/128)) < 0xFF0) {
rlanders73 1:4e2e6a9dc079 71 PrescalerCode = IWDG_PRESCALER_128;
rlanders73 1:4e2e6a9dc079 72 Prescaler = 128;
rlanders73 1:4e2e6a9dc079 73 }
rlanders73 1:4e2e6a9dc079 74 else {
rlanders73 1:4e2e6a9dc079 75 PrescalerCode = IWDG_PRESCALER_256;
rlanders73 1:4e2e6a9dc079 76 Prescaler = 256;
rlanders73 1:4e2e6a9dc079 77 }
rlanders73 1:4e2e6a9dc079 78
rlanders73 1:4e2e6a9dc079 79 // specifies the IWDG Reload value. This parameter must be a number between 0 and 0x0FFF.
rlanders73 1:4e2e6a9dc079 80 ReloadValue = (uint32_t)(timeout * (LsiFreq/Prescaler));
rlanders73 1:4e2e6a9dc079 81
rlanders73 1:4e2e6a9dc079 82 Calculated_timeout = ((float)(Prescaler * ReloadValue)) / LsiFreq;
rlanders73 1:4e2e6a9dc079 83 tr_debug("WATCHDOG set with prescaler:%d reload value: 0x%X - timeout:%f\n",Prescaler, ReloadValue, Calculated_timeout);
rlanders73 1:4e2e6a9dc079 84
rlanders73 1:4e2e6a9dc079 85 IWDG->KR = 0x5555; //Disable write protection of IWDG registers
rlanders73 1:4e2e6a9dc079 86 IWDG->PR = PrescalerCode; //Set PR value
rlanders73 1:4e2e6a9dc079 87 IWDG->RLR = ReloadValue; //Set RLR value
rlanders73 1:4e2e6a9dc079 88 IWDG->KR = 0xAAAA; //Reload IWDG
rlanders73 1:4e2e6a9dc079 89 IWDG->KR = 0xCCCC; //Start IWDG - See more at: http://embedded-lab.com/blog/?p=9662#sthash.6VNxVSn0.dpuf
rlanders73 1:4e2e6a9dc079 90
rlanders73 2:72d1cb8fc13c 91 pingWD();
rlanders73 1:4e2e6a9dc079 92 }
rlanders73 1:4e2e6a9dc079 93
rlanders73 2:72d1cb8fc13c 94 /// "Ping", "kick" or "feed" the dog - reset the watchdog timer
rlanders73 1:4e2e6a9dc079 95 /// by writing this required bit pattern
rlanders73 2:72d1cb8fc13c 96 void Supervisor::pingWD() {
rlanders73 1:4e2e6a9dc079 97 IWDG->KR = 0xAAAA; //Reload IWDG - See more at: http://embedded-lab.com/blog/?p=9662#sthash.6VNxVSn0.dpuf
rlanders73 1:4e2e6a9dc079 98 }
rlanders73 1:4e2e6a9dc079 99
rlanders73 2:72d1cb8fc13c 100 uint8_t Supervisor::resetReason(){
rlanders73 1:4e2e6a9dc079 101 return rstRsn;
rlanders73 1:4e2e6a9dc079 102 }
rlanders73 1:4e2e6a9dc079 103
rlanders73 3:b7a9432fe880 104 void Supervisor::doReset() {
rlanders73 3:b7a9432fe880 105 NVIC_SystemReset(); // pull the plug
rlanders73 3:b7a9432fe880 106 }
rlanders73 3:b7a9432fe880 107