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 optimization
pull/10645/head
Rajkumar Kanagaraj 2019-01-17 11:57:56 +00:00 committed by Filip Jagodzinski
parent 400b2ee8a7
commit bcea865db2
3 changed files with 101 additions and 245 deletions

View File

@ -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

View File

@ -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

View File

@ -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