Skip to content

Commit 7b0915c

Browse files
committed
Watchdog: refactor driver
Watchdog is hardware driver. It interacts with HAL - provides wrapper to interact with the peripheral. Provides basic functionality: start/stop, get timeout/max timeout. It is automatically kicked by a timer, according to the timeout set in ctor.
1 parent c497010 commit 7b0915c

File tree

3 files changed

+131
-108
lines changed

3 files changed

+131
-108
lines changed

drivers/Watchdog.cpp

Lines changed: 80 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -17,92 +17,119 @@
1717
#ifdef DEVICE_WATCHDOG
1818

1919
#include "Watchdog.h"
20+
#include "VirtualWatchdog.h"
21+
22+
#define MS_TO_US(x) ((x) * 1000) //macro to convert millisecond to microsecond
2023

2124
namespace mbed {
2225

23-
Watchdog *Watchdog::_first = NULL;
26+
#if DEVICE_LPTICKER
27+
/** Create singleton instance of LowPowerTicker for watchdog periodic call back of kick.
28+
*/
29+
SingletonPtr<LowPowerTicker> Watchdog::_ticker;
30+
#else
31+
/** Create singleton instance of Ticker for watchdog periodic call back of kick.
32+
*/
33+
SingletonPtr<Ticker> Watchdog::_ticker;
34+
#endif
35+
36+
bool Watchdog::_running = false;
37+
static const uint32_t elapsed_ms = MBED_CONF_TARGET_WATCHDOG_TIMEOUT / 2;
2438

25-
Watchdog::Watchdog(uint32_t timeout, const char *const str): _name(str)
39+
Watchdog::Watchdog()
2640
{
27-
_current_count = 0;
28-
_is_initialized = false;
29-
_next = NULL;
30-
_max_timeout = timeout;
41+
core_util_critical_section_enter();
42+
if (_running) {
43+
// error function does not return thus exit critical section and print an error
44+
core_util_critical_section_exit();
45+
MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER, MBED_ERROR_CODE_OUT_OF_RESOURCES), "There's already watchdog in the system");
46+
}
47+
core_util_critical_section_exit();
3148
}
3249

33-
void Watchdog::add_to_list()
50+
Watchdog::~Watchdog()
3451
{
35-
this->_next = _first;
36-
_first = this;
37-
_is_initialized = true;
52+
core_util_critical_section_enter();
53+
if (_running) {
54+
if (stop()) {
55+
// some targets might not support stop, thus keep running true in that case
56+
_running = false;
57+
}
58+
}
59+
core_util_critical_section_exit();
3860
}
3961

40-
void Watchdog::start()
62+
63+
bool Watchdog::start()
4164
{
42-
MBED_ASSERT(!_is_initialized);
65+
watchdog_status_t sts;
66+
MBED_ASSERT(MBED_CONF_TARGET_WATCHDOG_TIMEOUT < get_max_timeout());
4367
core_util_critical_section_enter();
44-
add_to_list();
68+
if (_running) {
69+
core_util_critical_section_exit();
70+
return false;
71+
}
72+
watchdog_config_t config;
73+
config.timeout_ms = MBED_CONF_TARGET_WATCHDOG_TIMEOUT;
74+
sts = hal_watchdog_init(&config);
75+
if (sts == WATCHDOG_STATUS_OK) {
76+
_running = true;
77+
}
4578
core_util_critical_section_exit();
79+
if (_running) {
80+
us_timestamp_t timeout = (MS_TO_US(((elapsed_ms <= 0) ? 1 : elapsed_ms)));
81+
_ticker->attach_us(callback(&Watchdog::kick), timeout);
82+
}
83+
return _running;
4684
}
4785

4886

49-
void Watchdog::kick()
87+
bool Watchdog::stop()
5088
{
51-
MBED_ASSERT(_is_initialized);
89+
watchdog_status_t sts;
90+
bool msts = true;
5291
core_util_critical_section_enter();
53-
_current_count = 0;
92+
if (_running) {
93+
sts = hal_watchdog_stop();
94+
if (sts != WATCHDOG_STATUS_OK) {
95+
msts = false;
96+
} else {
97+
_ticker->detach();
98+
_running = false;
99+
}
100+
101+
} else {
102+
msts = false;
103+
}
54104
core_util_critical_section_exit();
105+
return msts;
55106
}
56107

57-
void Watchdog::stop()
108+
void Watchdog::kick()
58109
{
59-
MBED_ASSERT(_is_initialized);
60110
core_util_critical_section_enter();
61-
remove_from_list();
111+
hal_watchdog_kick();
112+
// VirtualWatchdog will access the watchdog process method to verify
113+
// all registered users/threads in alive state */
114+
VirtualWatchdog::process(((elapsed_ms <= 0) ? 1 : elapsed_ms));
62115
core_util_critical_section_exit();
63116
}
64117

65-
void Watchdog::remove_from_list()
118+
119+
bool Watchdog::is_running() const
66120
{
67-
Watchdog *cur_ptr = _first,
68-
*prev_ptr = NULL;
69-
while (cur_ptr != NULL) {
70-
if (cur_ptr == this) {
71-
if (cur_ptr == _first) {
72-
prev_ptr = _first;
73-
_first = cur_ptr->_next;
74-
prev_ptr->_next = NULL;
75-
} else {
76-
prev_ptr->_next = cur_ptr->_next;
77-
cur_ptr->_next = NULL;
78-
}
79-
_is_initialized = false;
80-
break;
81-
} else {
82-
prev_ptr = cur_ptr;
83-
cur_ptr = cur_ptr->_next;
84-
}
85-
}
121+
return _running;
86122
}
87123

88-
void Watchdog::process(uint32_t elapsed_ms)
124+
uint32_t Watchdog::get_timeout()
89125
{
90-
Watchdog *cur_ptr = _first;
91-
while (cur_ptr != NULL) {
92-
if (cur_ptr->_current_count > cur_ptr->_max_timeout) {
93-
system_reset();
94-
} else {
95-
cur_ptr->_current_count += elapsed_ms;
96-
}
97-
cur_ptr = cur_ptr->_next;
98-
}
126+
return hal_watchdog_get_reload_value();
99127
}
100128

101-
Watchdog::~Watchdog()
129+
uint32_t Watchdog::get_max_timeout()
102130
{
103-
if (_is_initialized) {
104-
stop();
105-
}
131+
const watchdog_features_t features = hal_watchdog_get_platform_features();
132+
return features.max_timeout;
106133
}
107134

108135
} // namespace mbed

drivers/Watchdog.h

Lines changed: 48 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -20,98 +20,95 @@
2020

2121
#ifdef DEVICE_WATCHDOG
2222

23-
#include <cstdio>
2423
#include "mbed_error.h"
25-
#include "platform/mbed_critical.h"
26-
#include "platform/mbed_power_mgmt.h"
2724
#include "mbed_assert.h"
25+
#include "platform/mbed_critical.h"
26+
#include "watchdog_api.h"
27+
#include <cstdio>
2828

2929
namespace mbed {
3030

3131
/** \addtogroup drivers */
32-
/** Services that need to monitor nonblocking periodic behavior or
33-
* malfunctions, such as Wi-Fi and TLS, use a software watchdog.
34-
* Normally, one instance of a software watchdog gets created during hardware watchdog startup, so you can access the software watchdog.
35-
* The hardware watchdog periodically calls the "process" method of the services to check nonblocking periodic behavior.
32+
/** Hardware system timer that will reset the system in the case of system failures or
33+
* malfunctions.
3634
*
3735
* Example:
3836
* @code
3937
*
40-
* Watchdog watchdog(300,"Software Watchdog");
38+
* Watchdog watchdog();
4139
* watchdog.start();
4240
*
4341
* while (true) {
44-
* watchdog.kick();
45-
*
4642
* // Application code
4743
* }
4844
* @endcode
4945
* @ingroup drivers
5046
*/
51-
class Watchdog {
47+
class Watchdog : private NonCopyable<Watchdog> {
5248
public:
5349

54-
/** Constructor configured with timeout and name for this software watchdog instance.
50+
/** Constructor configured with timeout
5551
*
5652
*/
57-
Watchdog(uint32_t timeout = 1, const char *const str = NULL);
53+
Watchdog();
5854
~Watchdog();
5955
public:
6056

61-
/** Start an independent watchdog timer with specified parameters.
57+
/** Start the watchdog timer
58+
*
6259
*
63-
* Assert for multiple calls of start.
60+
* @return status true if the watchdog timer was started
61+
* successfully. assert if one of the input parameters is out of range for the current platform.
62+
* false if watchdog timer was not started
6463
*/
65-
void start();
64+
bool start();
6665

67-
/** This stops the watchdog timer.
66+
/** Stops the watchdog timer
6867
*
69-
* Calling this function disables any running
70-
* watchdog timers if the platform supports them.
68+
* Calling this function will attempt to disable any currently running
69+
* watchdog timers if supported by the current platform.
7170
*
72-
* Assert without calling start.
71+
* @return Returns true if the watchdog timer was successfully
72+
* stopped, Returns false if the watchdog cannot be disabled
73+
* on the current platform or if the timer was never started.
7374
*/
74-
void stop();
75+
bool stop();
7576

76-
/** This function refreshes the watchdog timer.
77+
/** Get the watchdog timer refresh value
7778
*
78-
* Call this function periodically before the watchdog times out.
79-
* Otherwise, the system resets.
79+
* This function returns the refresh timeout of the watchdog timer.
8080
*
81-
* If the watchdog timer is not running, this function does nothing.
81+
* @return Reload value for the watchdog timer in milliseconds.
8282
*/
83-
void kick();
83+
uint32_t get_timeout() const;
8484

85-
/** mbed_watchdog_manager (runs by periodic call from ticker) used this API interface
86-
* to go through all the registered user/threads of watchdog.
85+
/** Get the maximum refresh value for the current platform in milliseconds
8786
*
88-
* @param elapsed_ms completed ticker callback elapsed milliseconds
89-
*
90-
* Call this function from mbed_watchdog_manager_kick to monitor all the
91-
* user/threads alive states.
92-
*
93-
* Otherwise, the system resets.
87+
* @return Maximum refresh value supported by the watchdog for the current
88+
* platform in milliseconds
9489
*/
95-
static void process(uint32_t elapsed_ms);
96-
protected :
90+
uint32_t get_max_timeout() const;
9791

98-
/** Use add_to_list to store the registered user in the list.
99-
* This API is only used to call from start.
100-
*/
101-
void add_to_list();
92+
/** Check if watchdog is already running
93+
*
94+
* @return Maximum refresh value supported by the watchdog for the current
95+
* platform in milliseconds
96+
*/
97+
bool is_running() const;
10298

103-
/** Use remove_from_list to remove the entry from the list.
104-
* This API is only used to call from stop.
105-
*
106-
*/
107-
void remove_from_list();
10899
private:
109-
uint32_t _max_timeout; //_max_timeout initialized via constructor while creating instance of this class
110-
const char *_name; //To store the details of user
111-
uint32_t _current_count; //this parameter is used to reset everytime threads/user calls kick
112-
bool _is_initialized; //To control start and stop functionality
113-
static Watchdog *_first; //List to store the user/threads who called start
114-
Watchdog *_next;
100+
static void kick();
101+
static uint32_t _elapsed_ms;
102+
static bool _running;
103+
#if DEVICE_LPTICKER
104+
/** Create singleton instance of LowPowerTicker for watchdog periodic call back of kick.
105+
*/
106+
static SingletonPtr<LowPowerTicker> _ticker;
107+
#else
108+
/** Create singleton instance of Ticker for watchdog periodic call back of kick.
109+
*/
110+
static SingletonPtr<Ticker> _ticker;
111+
#endif
115112
};
116113

117114
} // namespace mbed

targets/targets.json

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,9 @@
4848
"help": "Run tickless from the microsecond ticker rather than the low power ticker. Running tickless off of the microsecond ticker improves interrupt latency on targets which use lpticker_delay_ticks",
4949
"value": false
5050
},
51-
"hw-watchdog_timeout": {
52-
"help": "Define the timeout in ms value LowPowerTicker to do HW kick",
53-
"value": "800",
54-
"macro_name": "HW_WATCHDOG_TIMEOUT"
51+
"watchdog-timeout": {
52+
"help": "Define the timeout in ms to do HW kick",
53+
"value": "800"
5554
}
5655
}
5756
},

0 commit comments

Comments
 (0)