1
1
#include " independent_watchdog.h"
2
2
3
- /* *
4
- * @brief Borrow the configuration of an already existing watchdog and set it
5
- * to the prescaler and Reload values.
6
- *
7
- */
8
- IndependentWatchdog::IndependentWatchdog (IWDG_HandleTypeDef *watchdog) {
9
- this ->watchdog = watchdog;
3
+ #define MAX_PR 6
4
+ #define RELOAD_LENGTH 12
5
+ #define WINDOW_LENGTH 12
6
+ #define LSI_SPEED 32000
7
+ #define PR_OFFSET 2
8
+ #define MAX_TIMEOUT_MS (((1 << RELOAD_LENGTH)*4 *(1 << MAX_PR)*1000 ) / LSI_SPEED) // should be about 32768
9
+
10
+ /* A general watchdog, the window feature is not used
11
+ If it fails, no one could notice it, which is not really desired
12
+ @param: timeout - timeout in ms
13
+ */
14
+ IndependentWatchdog::IndependentWatchdog (uint32_t timeout){
15
+ if (timeout >= MAX_TIMEOUT_MS) {
16
+ return ;
17
+ }
18
+
19
+ if (counterCalculation (timeout, this ->prescaler_ , this ->reload_ ) == false ){
20
+ // Error_Handler();
21
+ return ;
22
+ }
23
+ this ->window_ = this ->reload_ ;
24
+ this ->watchdog_ = &hiwdg;
25
+
26
+ hiwdg.Instance = IWDG;
27
+ hiwdg.Init .Prescaler = this ->prescaler_ ;
28
+ hiwdg.Init .Window = this ->window_ ;
29
+ hiwdg.Init .Reload = this ->reload_ ;
30
+ if (HAL_IWDG_Init (this ->watchdog_ ) != HAL_OK)
31
+ {
32
+ Error_Handler ();
33
+ }
34
+ }
35
+
36
+ /* I don't know why STM added this feature, but you turn IWDG into a WWDG which is confusing
37
+ Now the watchdog triggers the reset when refresh comes too early or when downcounter reaches zero
38
+
39
+ |------- Refresh triggers reset -------- | ------- Refresh Allowed -------- |--- reset ---|
40
+ ^ ^ ^
41
+ counter value: reload window 0
42
+
43
+ @param: counter_timeout - in ms
44
+ @param: window_timeout - in ms
45
+ */
46
+ IndependentWatchdog::IndependentWatchdog (uint32_t counter_timeout, uint32_t window_timeout){
47
+ if (counter_timeout >= MAX_TIMEOUT_MS || window_timeout >= MAX_TIMEOUT_MS) {
48
+ return ;
49
+ }
50
+
51
+ if (counterCalculation (counter_timeout, this ->prescaler_ , this ->reload_ ) == false ){
52
+ // Error_Handler();
53
+ return ;
54
+ }
55
+ if (windowCalculation (window_timeout, this ->prescaler_ , this ->window_ ) == false ){
56
+ // Error_Handler();
57
+ return ;
58
+ }
59
+ this ->watchdog_ = &hiwdg;
60
+
61
+ hiwdg.Instance = IWDG;
62
+ hiwdg.Init .Prescaler = this ->prescaler_ ;
63
+ hiwdg.Init .Window = this ->window_ ;
64
+ hiwdg.Init .Reload = this ->reload_ ;
65
+ if (HAL_IWDG_Init (this ->watchdog_ ) != HAL_OK)
66
+ {
67
+ Error_Handler ();
68
+ }
10
69
}
11
70
12
71
@@ -15,10 +74,44 @@ IndependentWatchdog::IndependentWatchdog(IWDG_HandleTypeDef *watchdog) {
15
74
* @brief Refreshes the watchdog that is a member variable of the class
16
75
* @returns true on success, false on failure
17
76
*/
18
-
19
77
bool IndependentWatchdog::refreshWatchdog () {
20
- if (this ->watchdog == nullptr ) {
78
+ if (this ->watchdog_ == nullptr ) {
21
79
return false ;
22
80
}
23
- return (HAL_IWDG_Refresh (watchdog) == HAL_OK);
81
+ return (HAL_IWDG_Refresh (this ->watchdog_ ) == HAL_OK);
82
+ }
83
+
84
+
85
+ /* Helper function
86
+ Updates the prescaler and reload depending on the timeout
87
+ */
88
+ bool IndependentWatchdog::counterCalculation (uint32_t timeout, uint32_t &prescaler, uint32_t &counter){
89
+ int prescalerPR = 0 ; // start prescaler = 4
90
+ const uint32_t MAX_COUNTER = (1 << RELOAD_LENGTH);
91
+
92
+ for (; prescalerPR <= MAX_PR; prescalerPR++){
93
+ prescaler = prescalerPR;
94
+ uint32_t prescalerValue = 1 << (prescalerPR + PR_OFFSET);
95
+ counter = ((timeout * LSI_SPEED) / (prescalerValue * 1000 )) - 1 ;
96
+ if (counter <= MAX_COUNTER) {
97
+ return true ;
98
+ }
99
+ }
100
+
101
+ return false ;
102
+ }
103
+
104
+ /* Helper function
105
+ Only update the window depending on the timeout
106
+ */
107
+ bool IndependentWatchdog::windowCalculation (uint32_t timeout, uint32_t prescaler, uint32_t &window){
108
+ const uint32_t MAX_WINDOW = (1 << WINDOW_LENGTH);
109
+
110
+ uint32_t prescalerValue = 1 << (prescaler + PR_OFFSET);
111
+ window = ((timeout * LSI_SPEED) / (prescalerValue * 1000 )) - 1 ;
112
+ if (window <= MAX_WINDOW) {
113
+ return true ;
114
+ }
115
+
116
+ return false ;
24
117
}
0 commit comments