mirror of https://github.com/ARMmbed/mbed-os.git
Add SW Watchdog
-SW watchdog has interface name start(),stop(),kick() Sw watchdog internally has static list and shared across multiple instance of SW watchdog - Sw watchdog initialize timeout value,unique string via constructor whenever threads created sw watchdog object -Threads make sure pass proper timeout value,Unique string while creating the instance. -start() called by components(BLE,WIFI etc.,),it adds the entry into static list with few details current count ,etc., -kick() called by registered components(BLE,WIFI etc.) to reset current count to zero. -is_alive - interface API to mbed_watchdog_manager -implementation optimizationpull/10645/head
parent
400b2ee8a7
commit
bcea865db2
|
@ -18,167 +18,83 @@
|
|||
|
||||
#include "Watchdog.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
uint32_t Watchdog::_is_initialized = 0;
|
||||
uint32_t Watchdog::_re_initialize = 0;
|
||||
uint32_t Watchdog::_bitmask = 0;
|
||||
uint32_t Watchdog::_kick_bitmask = 0;
|
||||
Watchdog::watchdog_usr_info Watchdog::_usr_info[MAX_THREAD_WATCHDOG_SUPPORT] = {0};
|
||||
rtos::Mutex Watchdog::_ThreadSafeLockMutex;
|
||||
mbed_error_status_t Watchdog::wd_register(const osThreadId_t tid, const uint32_t timeout)
|
||||
namespace mbed
|
||||
{
|
||||
int store_index = -1;
|
||||
watchdog_status_t sts;
|
||||
int i;
|
||||
_ThreadSafeLockMutex.lock();
|
||||
uint32_t conf_timeout = hal_watchdog_get_reload_value();
|
||||
if(_is_initialized) {
|
||||
if(timeout > conf_timeout) {
|
||||
_re_initialize = 1;
|
||||
hal_watchdog_stop();
|
||||
}
|
||||
|
||||
for(i =0 ; i < MAX_THREAD_WATCHDOG_SUPPORT; i++) {
|
||||
if(_bitmask & (1 << i))
|
||||
{
|
||||
if(_usr_info[i].tid == tid) {
|
||||
if(_re_initialize) {
|
||||
store_index = i;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
_ThreadSafeLockMutex.unlock();
|
||||
return MBED_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(store_index < 0) {
|
||||
store_index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
store_index = 0;
|
||||
}
|
||||
|
||||
if(store_index >= 0) {
|
||||
_usr_info[store_index].tid = tid;
|
||||
_usr_info[store_index].bit_idx = store_index;
|
||||
_bitmask |= (1 << store_index);
|
||||
store_index = -1;
|
||||
|
||||
if(!_is_initialized || _re_initialize ) {
|
||||
sts = start(timeout);
|
||||
if(sts != WATCHDOG_STATUS_OK ) {
|
||||
_is_initialized = 0;
|
||||
_ThreadSafeLockMutex.unlock();
|
||||
return MBED_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
_is_initialized = 1;
|
||||
_re_initialize = 0;
|
||||
}
|
||||
} else {
|
||||
_ThreadSafeLockMutex.unlock();
|
||||
return MBED_ERROR_OVERFLOW;
|
||||
}
|
||||
_ThreadSafeLockMutex.unlock();
|
||||
return MBED_SUCCESS;
|
||||
Watchdog *Watchdog::first;
|
||||
|
||||
void Watchdog::add_to_list()
|
||||
{
|
||||
this->next = first;
|
||||
first = this;
|
||||
_is_initialized = true;
|
||||
}
|
||||
watchdog_status_t Watchdog::start(const uint32_t timeout)
|
||||
|
||||
void Watchdog::start()
|
||||
{
|
||||
if (timeout == 0) {
|
||||
return WATCHDOG_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (timeout > max_timeout()) {
|
||||
return WATCHDOG_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
watchdog_config_t config;
|
||||
config.timeout_ms = timeout;
|
||||
return hal_watchdog_init(&config);
|
||||
MBED_ASSERT(!_is_initialized);
|
||||
core_util_critical_section_enter();
|
||||
add_to_list();
|
||||
core_util_critical_section_exit();
|
||||
}
|
||||
|
||||
|
||||
void Watchdog::kick(const osThreadId_t tid)
|
||||
void Watchdog::kick()
|
||||
{
|
||||
int i;
|
||||
MBED_ASSERT(_is_initialized);
|
||||
core_util_critical_section_enter();
|
||||
_current_count = 0;
|
||||
core_util_critical_section_exit();
|
||||
}
|
||||
|
||||
_ThreadSafeLockMutex.lock();
|
||||
if(_is_initialized ) {
|
||||
for(i =0 ; i < MAX_THREAD_WATCHDOG_SUPPORT; i++) {
|
||||
if(_usr_info[i].tid == tid)
|
||||
{
|
||||
_kick_bitmask |= (1 << _usr_info[i].bit_idx);
|
||||
break;
|
||||
void Watchdog::stop()
|
||||
{
|
||||
MBED_ASSERT(_is_initialized);
|
||||
core_util_critical_section_enter();
|
||||
remove_from_list();
|
||||
core_util_critical_section_exit();
|
||||
}
|
||||
|
||||
void Watchdog::remove_from_list()
|
||||
{
|
||||
Watchdog *cur_ptr = first,
|
||||
*prev_ptr = NULL;
|
||||
while(cur_ptr != NULL) {
|
||||
if(cur_ptr == this) {
|
||||
if(cur_ptr == first) {
|
||||
prev_ptr = first;
|
||||
first = cur_ptr->next;
|
||||
prev_ptr->next = NULL;
|
||||
} else {
|
||||
prev_ptr->next = cur_ptr->next;
|
||||
cur_ptr->next = NULL;
|
||||
}
|
||||
}
|
||||
if(!_re_initialize && _bitmask == _kick_bitmask) {
|
||||
hal_watchdog_kick();
|
||||
_kick_bitmask = 0;
|
||||
_is_initialized = false;
|
||||
break;
|
||||
} else {
|
||||
prev_ptr = cur_ptr;
|
||||
cur_ptr = cur_ptr->next;
|
||||
}
|
||||
}
|
||||
_ThreadSafeLockMutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
mbed_error_status_t Watchdog::stop()
|
||||
void Watchdog::is_alive()
|
||||
{
|
||||
watchdog_status_t sts;
|
||||
|
||||
if(_is_initialized ) {
|
||||
sts = hal_watchdog_stop();
|
||||
if(sts != WATCHDOG_STATUS_OK ) {
|
||||
return MBED_ERROR_ALREADY_IN_USE;
|
||||
}
|
||||
else
|
||||
{
|
||||
_is_initialized = 0;
|
||||
_kick_bitmask = 0;
|
||||
return MBED_SUCCESS;
|
||||
Watchdog *cur_ptr = first;
|
||||
while(cur_ptr != NULL) {
|
||||
if(cur_ptr->_current_count > cur_ptr->_max_timeout) {
|
||||
system_reset();
|
||||
} else {
|
||||
cur_ptr->_current_count++;
|
||||
cur_ptr = cur_ptr->next;
|
||||
}
|
||||
}
|
||||
else
|
||||
return MBED_ERROR_OPERATION_PROHIBITED;
|
||||
}
|
||||
|
||||
mbed_error_status_t Watchdog::wd_unregister(const osThreadId_t tid)
|
||||
Watchdog::~Watchdog()
|
||||
{
|
||||
int i;
|
||||
uint32_t tbit = _bitmask;
|
||||
_ThreadSafeLockMutex.lock();
|
||||
for(i =0 ; i < MAX_THREAD_WATCHDOG_SUPPORT; i++) {
|
||||
if(_usr_info[i].tid == tid) {
|
||||
_bitmask &= (~(1 << _usr_info[i].bit_idx));
|
||||
_kick_bitmask &= (~(1 << _usr_info[i].bit_idx));
|
||||
_usr_info[i].tid = 0;
|
||||
_usr_info[i].bit_idx = 0;
|
||||
}
|
||||
}
|
||||
if(_bitmask == tbit) {
|
||||
_ThreadSafeLockMutex.unlock();
|
||||
return MBED_ERROR_OPERATION_PROHIBITED;
|
||||
}
|
||||
if(_bitmask == 0) {
|
||||
if(_is_initialized)
|
||||
stop();
|
||||
}
|
||||
_ThreadSafeLockMutex.unlock();
|
||||
return MBED_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t Watchdog::reload_value() const
|
||||
{
|
||||
return hal_watchdog_get_reload_value();
|
||||
}
|
||||
|
||||
|
||||
uint32_t Watchdog::max_timeout()
|
||||
{
|
||||
const watchdog_features_t features = hal_watchdog_get_platform_features();
|
||||
|
||||
return features.max_timeout;
|
||||
}
|
||||
|
||||
} // namespace mbed
|
||||
|
|
|
@ -20,21 +20,14 @@
|
|||
|
||||
#ifdef DEVICE_WATCHDOG
|
||||
|
||||
#include "watchdog_api.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include "mbed_error.h"
|
||||
|
||||
#include "rtos/Mutex.h"
|
||||
|
||||
#include "rtos/Thread.h"
|
||||
|
||||
#define MAX_THREAD_WATCHDOG_SUPPORT 32
|
||||
|
||||
namespace mbed {
|
||||
|
||||
|
||||
#include "rtos/ThisThread.h"
|
||||
#include "platform/mbed_critical.h"
|
||||
#include "platform/mbed_power_mgmt.h"
|
||||
#include <string>
|
||||
namespace mbed
|
||||
{
|
||||
|
||||
/** \addtogroup drivers */
|
||||
/** A system timer that will reset the system in the case of system failures or
|
||||
|
@ -43,52 +36,41 @@ namespace mbed {
|
|||
* Example:
|
||||
* @code
|
||||
*
|
||||
* Watchdog watchdog = Watchdog();
|
||||
* watchdog.register(tid, 2000);
|
||||
* Watchdog watchdog = Watchdog(300,"Software Watchdog");
|
||||
* watchdog.start();
|
||||
*
|
||||
* while (true) {
|
||||
* watchdog.kick(tid);
|
||||
* watchdog.kick();
|
||||
*
|
||||
* // Application code
|
||||
* }
|
||||
* @endcode
|
||||
* @ingroup drivers
|
||||
*/
|
||||
class Watchdog {
|
||||
class Watchdog
|
||||
{
|
||||
public:
|
||||
Watchdog() {}
|
||||
|
||||
Watchdog(uint32_t timeout = 0,const char *str = NULL):_max_timeout(timeout),name(str),_current_count(0),_is_initialized(false),next(NULL) {}
|
||||
|
||||
~Watchdog();
|
||||
public:
|
||||
|
||||
|
||||
|
||||
/** Register to watchdog timer with specified parameters,
|
||||
* This API is only to register to watchdog and Watchdog automatically starts
|
||||
* if atleast one user registered.
|
||||
*
|
||||
* @param timeout Timeout of the watchdog in milliseconds
|
||||
*
|
||||
* @param tid Thread id
|
||||
*
|
||||
* @return status MBED_SUCCESS if register to watchdog timer was succeeded
|
||||
* successfully. MBED_ERROR_INVALID_ARGUMENT if one of the input
|
||||
* parameters is out of range for the current platform.
|
||||
* MBED_ERROR_UNSUPPORTED if one of the enabled input
|
||||
* parameters is not supported by the current platform.
|
||||
*/
|
||||
mbed_error_status_t wd_register(const osThreadId_t tid, const uint32_t timeout);
|
||||
|
||||
/** Unregister from watchdog with specified parameters
|
||||
/** Start an independent watchdog timer with specified parameters
|
||||
*
|
||||
* @param tid Thread id
|
||||
*
|
||||
* @return status MBED_SUCCESS if register to watchdog timer was succeeded
|
||||
* successfully. MBED_ERROR_INVALID_ARGUMENT if tid is not registered
|
||||
* and try to do unregister
|
||||
* Assert for multiple calls of start
|
||||
*/
|
||||
mbed_error_status_t wd_unregister(const osThreadId_t tid);
|
||||
|
||||
void start();
|
||||
|
||||
/** Stops the watchdog timer
|
||||
*
|
||||
* Calling this function will attempt to disable any currently running
|
||||
* watchdog timers if supported by the current platform.
|
||||
*
|
||||
* Assert with out called start
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/** Refreshes the watchdog timer.
|
||||
*
|
||||
|
@ -99,75 +81,33 @@ public:
|
|||
*/
|
||||
void kick();
|
||||
|
||||
|
||||
/** Stops the watchdog timer
|
||||
*
|
||||
* Calling this function will attempt to disable any currently running
|
||||
* watchdog timers if supported by the current platform.
|
||||
*
|
||||
* @return Returns WATCHDOG_STATUS_OK if the watchdog timer was successfully
|
||||
* stopped, or if the timer was never started. Returns
|
||||
* WATCHDOG_STATUS_NOT_SUPPORTED if the watchdog cannot be disabled
|
||||
* on the current platform.
|
||||
*/
|
||||
watchdog_status_t stop();
|
||||
|
||||
/** Get the watchdog timer refresh value
|
||||
*
|
||||
* This function returns the refresh timeout of the watchdog timer.
|
||||
* This function should be called from mbed_watchdog_manager_kick to monitor all the
|
||||
* user/threads alive state.
|
||||
*
|
||||
* @return Reload value for the watchdog timer in milliseconds.
|
||||
* Otherwise, the system is reset.
|
||||
*/
|
||||
uint32_t reload_value() const;
|
||||
|
||||
|
||||
/** Get the maximum refresh value for the current platform in milliseconds
|
||||
*
|
||||
* @return Maximum refresh value supported by the watchdog for the current
|
||||
* platform in milliseconds
|
||||
*/
|
||||
static uint32_t max_timeout();
|
||||
void is_alive();
|
||||
protected :
|
||||
/** Start an independent watchdog timer with specified parameters
|
||||
*
|
||||
* @param timeout Timeout of the watchdog in milliseconds
|
||||
*
|
||||
* @return status WATCHDOG_STATUS_OK if the watchdog timer was started
|
||||
* successfully. WATCHDOG_INVALID_ARGUMENT if one of the input
|
||||
* parameters is out of range for the current platform.
|
||||
* WATCHDOG_NOT_SUPPORTED if one of the enabled input
|
||||
* parameters is not supported by the current platform.
|
||||
*/
|
||||
watchdog_status_t start(const uint32_t timeout);
|
||||
|
||||
/** Stops the watchdog timer
|
||||
*
|
||||
* Calling this function will attempt to disable any currently running
|
||||
* watchdog timers if supported by the current platform.
|
||||
*
|
||||
* @return Returns WATCHDOG_STATUS_OK if the watchdog timer was succesfully
|
||||
* stopped, or if the timer was never started. Returns
|
||||
* WATCHDOG_STATUS_NOT_SUPPORTED if the watchdog cannot be disabled
|
||||
* on the current platform.
|
||||
*/
|
||||
mbed_error_status_t stop();
|
||||
/** add_to_list is used to store the registered user into List.
|
||||
* This API is only used to call from start.
|
||||
*/
|
||||
void add_to_list();
|
||||
|
||||
/** Remove from list is uesed to remove the entry from the list.
|
||||
* This API is only used to call from stop.
|
||||
*
|
||||
*/
|
||||
void remove_from_list();
|
||||
private:
|
||||
static rtos::Mutex _ThreadSafeLockMutex;//Thread safe mutex for concurrent access protection
|
||||
|
||||
typedef struct
|
||||
{
|
||||
osThreadId_t tid;
|
||||
uint32_t bit_idx;
|
||||
}watchdog_usr_info ;
|
||||
|
||||
static watchdog_usr_info _usr_info[MAX_THREAD_WATCHDOG_SUPPORT];//Dats structure used to store the tid and their respective bit position of "_bitmask"
|
||||
|
||||
static uint32_t _bitmask; //Every bit is used to denote the registered threads/user
|
||||
static uint32_t _kick_bitmask;//Every bit is used to denote the registered threads/user called kick(tid)
|
||||
static uint32_t _is_initialized;//represents the watchdog initialized/un-initialized
|
||||
static uint32_t _re_initialize;//represents the watchdog reinitizliation
|
||||
|
||||
uint32_t _max_timeout; //_max_timeout initialized via constructor while creating instance of this class
|
||||
const char *name;//To store the details of user
|
||||
uint32_t _current_count;//this parameter is used to reset everytime threads/user calls kick
|
||||
bool _is_initialized;//To control start and stop functionality
|
||||
static Watchdog *first;//List to store the user/threads who called start
|
||||
Watchdog *next;
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MBED_WATCHDOG_H
|
||||
#define MBED_WATCHDOG_H
|
||||
#ifndef MBED_WATCHDOG_MGR_H
|
||||
#define MBED_WATCHDOG_MGR_H
|
||||
|
||||
#ifdef DEVICE_WATCHDOG
|
||||
|
||||
|
|
Loading…
Reference in New Issue