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"
|
#include "Watchdog.h"
|
||||||
|
|
||||||
namespace mbed {
|
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)
|
|
||||||
{
|
{
|
||||||
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++) {
|
Watchdog *Watchdog::first;
|
||||||
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;
|
|
||||||
|
|
||||||
|
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) {
|
MBED_ASSERT(!_is_initialized);
|
||||||
return WATCHDOG_STATUS_INVALID_ARGUMENT;
|
core_util_critical_section_enter();
|
||||||
}
|
add_to_list();
|
||||||
|
core_util_critical_section_exit();
|
||||||
if (timeout > max_timeout()) {
|
|
||||||
return WATCHDOG_STATUS_INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
watchdog_config_t config;
|
|
||||||
config.timeout_ms = timeout;
|
|
||||||
return hal_watchdog_init(&config);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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();
|
void Watchdog::stop()
|
||||||
if(_is_initialized ) {
|
{
|
||||||
for(i =0 ; i < MAX_THREAD_WATCHDOG_SUPPORT; i++) {
|
MBED_ASSERT(_is_initialized);
|
||||||
if(_usr_info[i].tid == tid)
|
core_util_critical_section_enter();
|
||||||
{
|
remove_from_list();
|
||||||
_kick_bitmask |= (1 << _usr_info[i].bit_idx);
|
core_util_critical_section_exit();
|
||||||
break;
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
}
|
_is_initialized = false;
|
||||||
if(!_re_initialize && _bitmask == _kick_bitmask) {
|
break;
|
||||||
hal_watchdog_kick();
|
} else {
|
||||||
_kick_bitmask = 0;
|
prev_ptr = cur_ptr;
|
||||||
|
cur_ptr = cur_ptr->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ThreadSafeLockMutex.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Watchdog::is_alive()
|
||||||
mbed_error_status_t Watchdog::stop()
|
|
||||||
{
|
{
|
||||||
watchdog_status_t sts;
|
Watchdog *cur_ptr = first;
|
||||||
|
while(cur_ptr != NULL) {
|
||||||
if(_is_initialized ) {
|
if(cur_ptr->_current_count > cur_ptr->_max_timeout) {
|
||||||
sts = hal_watchdog_stop();
|
system_reset();
|
||||||
if(sts != WATCHDOG_STATUS_OK ) {
|
} else {
|
||||||
return MBED_ERROR_ALREADY_IN_USE;
|
cur_ptr->_current_count++;
|
||||||
}
|
cur_ptr = cur_ptr->next;
|
||||||
else
|
|
||||||
{
|
|
||||||
_is_initialized = 0;
|
|
||||||
_kick_bitmask = 0;
|
|
||||||
return MBED_SUCCESS;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return MBED_ERROR_OPERATION_PROHIBITED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mbed_error_status_t Watchdog::wd_unregister(const osThreadId_t tid)
|
Watchdog::~Watchdog()
|
||||||
{
|
{
|
||||||
int i;
|
if(_is_initialized)
|
||||||
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) {
|
|
||||||
stop();
|
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
|
} // namespace mbed
|
||||||
|
|
|
@ -20,21 +20,14 @@
|
||||||
|
|
||||||
#ifdef DEVICE_WATCHDOG
|
#ifdef DEVICE_WATCHDOG
|
||||||
|
|
||||||
#include "watchdog_api.h"
|
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
#include "mbed_error.h"
|
#include "mbed_error.h"
|
||||||
|
#include "rtos/ThisThread.h"
|
||||||
#include "rtos/Mutex.h"
|
#include "platform/mbed_critical.h"
|
||||||
|
#include "platform/mbed_power_mgmt.h"
|
||||||
#include "rtos/Thread.h"
|
#include <string>
|
||||||
|
namespace mbed
|
||||||
#define MAX_THREAD_WATCHDOG_SUPPORT 32
|
{
|
||||||
|
|
||||||
namespace mbed {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** \addtogroup drivers */
|
/** \addtogroup drivers */
|
||||||
/** A system timer that will reset the system in the case of system failures or
|
/** A system timer that will reset the system in the case of system failures or
|
||||||
|
@ -43,52 +36,41 @@ namespace mbed {
|
||||||
* Example:
|
* Example:
|
||||||
* @code
|
* @code
|
||||||
*
|
*
|
||||||
* Watchdog watchdog = Watchdog();
|
* Watchdog watchdog = Watchdog(300,"Software Watchdog");
|
||||||
* watchdog.register(tid, 2000);
|
* watchdog.start();
|
||||||
*
|
*
|
||||||
* while (true) {
|
* while (true) {
|
||||||
* watchdog.kick(tid);
|
* watchdog.kick();
|
||||||
*
|
*
|
||||||
* // Application code
|
* // Application code
|
||||||
* }
|
* }
|
||||||
* @endcode
|
* @endcode
|
||||||
* @ingroup drivers
|
* @ingroup drivers
|
||||||
*/
|
*/
|
||||||
class Watchdog {
|
class Watchdog
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
Watchdog() {}
|
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:
|
public:
|
||||||
|
|
||||||
|
/** Start an independent watchdog timer with specified parameters
|
||||||
|
|
||||||
/** 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
|
|
||||||
*
|
*
|
||||||
* @param tid Thread id
|
* Assert for multiple calls of start
|
||||||
*
|
|
||||||
* @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
|
|
||||||
*/
|
*/
|
||||||
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.
|
/** Refreshes the watchdog timer.
|
||||||
*
|
*
|
||||||
|
@ -99,75 +81,33 @@ public:
|
||||||
*/
|
*/
|
||||||
void kick();
|
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
|
/** 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;
|
void is_alive();
|
||||||
|
|
||||||
|
|
||||||
/** 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();
|
|
||||||
protected :
|
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
|
/** add_to_list is used to store the registered user into List.
|
||||||
*
|
* This API is only used to call from start.
|
||||||
* Calling this function will attempt to disable any currently running
|
*/
|
||||||
* watchdog timers if supported by the current platform.
|
void add_to_list();
|
||||||
*
|
|
||||||
* @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();
|
|
||||||
|
|
||||||
|
/** 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:
|
private:
|
||||||
static rtos::Mutex _ThreadSafeLockMutex;//Thread safe mutex for concurrent access protection
|
uint32_t _max_timeout; //_max_timeout initialized via constructor while creating instance of this class
|
||||||
|
const char *name;//To store the details of user
|
||||||
typedef struct
|
uint32_t _current_count;//this parameter is used to reset everytime threads/user calls kick
|
||||||
{
|
bool _is_initialized;//To control start and stop functionality
|
||||||
osThreadId_t tid;
|
static Watchdog *first;//List to store the user/threads who called start
|
||||||
uint32_t bit_idx;
|
Watchdog *next;
|
||||||
}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
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mbed
|
} // namespace mbed
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MBED_WATCHDOG_H
|
#ifndef MBED_WATCHDOG_MGR_H
|
||||||
#define MBED_WATCHDOG_H
|
#define MBED_WATCHDOG_MGR_H
|
||||||
|
|
||||||
#ifdef DEVICE_WATCHDOG
|
#ifdef DEVICE_WATCHDOG
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue