Watchdog refactoring to multithreaded thread.

-Added API to register muliple threads to watchdog drivers
-Watchdog timeout reconfigures everytime whenever new register thread with longer timeout period
-New APIs for watchdog
 wd_register(const osThreadId_t tid, const uint32_t timeout) to register to watchdog
 wd_unregister(const osThreadId_t tid) to unregister to watchdog
 kick(const osThreadId_t tid) to refresh the watchdog
pull/10645/head
Rajkumar Kanagaraj 2019-01-03 12:33:26 +00:00 committed by Filip Jagodzinski
parent f4e6966e14
commit 3cd52d4732
2 changed files with 203 additions and 16 deletions

View File

@ -20,6 +20,72 @@
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++) {
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_status_t Watchdog::start(const uint32_t timeout)
{
if (timeout == 0) {
@ -32,22 +98,75 @@ watchdog_status_t Watchdog::start(const uint32_t timeout)
watchdog_config_t config;
config.timeout_ms = timeout;
return hal_watchdog_init(&config);
}
void Watchdog::kick()
void Watchdog::kick(const osThreadId_t tid)
{
hal_watchdog_kick();
int i;
_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;
}
}
if(!_re_initialize && _bitmask == _kick_bitmask) {
hal_watchdog_kick();
_kick_bitmask = 0;
}
}
_ThreadSafeLockMutex.unlock();
}
watchdog_status_t Watchdog::stop()
mbed_error_status_t Watchdog::stop()
{
return hal_watchdog_stop();
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;
}
}
else
return MBED_ERROR_OPERATION_PROHIBITED;
}
mbed_error_status_t Watchdog::wd_unregister(const osThreadId_t tid)
{
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) {
stop();
}
_ThreadSafeLockMutex.unlock();
return MBED_SUCCESS;
}
uint32_t Watchdog::reload_value() const
{

View File

@ -24,8 +24,18 @@
#include <cstdio>
#include "mbed_error.h"
#include "rtos/Mutex.h"
#include "rtos/Thread.h"
#define MAX_THREAD_WATCHDOG_SUPPORT 32
namespace mbed {
/** \addtogroup drivers */
/** A system timer that will reset the system in the case of system failures or
* malfunctions.
@ -34,10 +44,10 @@ namespace mbed {
* @code
*
* Watchdog watchdog = Watchdog();
* watchdog.start(2000);
* watchdog.register(tid, 2000);
*
* while (true) {
* watchdog.kick();
* watchdog.kick(tid);
*
* // Application code
* }
@ -49,17 +59,35 @@ public:
Watchdog() {}
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 timeout Timeout of the watchdog in milliseconds
* @param tid Thread id
*
* @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.
* @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
*/
watchdog_status_t start(const uint32_t timeout);
mbed_error_status_t wd_unregister(const osThreadId_t tid);
/** Refreshes the watchdog timer.
@ -84,7 +112,6 @@ public:
*/
watchdog_status_t stop();
/** Get the watchdog timer refresh value
*
* This function returns the refresh timeout of the watchdog timer.
@ -100,6 +127,47 @@ public:
* platform in milliseconds
*/
static uint32_t max_timeout();
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();
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
};
} // namespace mbed