Class to add reset supervision with a watchdog timer functionality
Dependents: Example_WatchDog_Timer
ResetSupervisor.cpp@4:f31b32884780, 2019-10-05 (annotated)
- Committer:
- rlanders73
- Date:
- Sat Oct 05 19:40:12 2019 +0000
- Revision:
- 4:f31b32884780
- Parent:
- 3:b7a9432fe880
- Child:
- 5:7af579ded04f
comment out some obscure reset causes for better portability
Who changed what in which revision?
User | Revision | Line number | New 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 | 4:f31b32884780 | 29 | // else if(__HAL_RCC_GET_FLAG(RCC_FLAG_OBLRST))// OBLRST reset |
rlanders73 | 4:f31b32884780 | 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 | 4:f31b32884780 | 33 | // else if(__HAL_RCC_GET_FLAG(RCC_FLAG_FWRST))// FIREWALL reset |
rlanders73 | 4:f31b32884780 | 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 |