mbed-os/drivers/VirtualWatchdog.cpp

117 lines
2.8 KiB
C++

/*
* Copyright (c) 2019 Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef DEVICE_VIRTUAL_WATCHDOG
#include "VirtualWatchdog.h"
#include "Watchdog.h"
namespace mbed {
VirtualWatchdog *VirtualWatchdog::_first = NULL;
VirtualWatchdog::VirtualWatchdog(uint32_t timeout, const char *const str): _name(str)
{
_current_count = 0;
_is_initialized = false;
_next = NULL;
_max_timeout = timeout;
// start watchdog
Watchdog& watchdog = Watchdog::get_instance();
watchdog.start();
}
VirtualWatchdog::~VirtualWatchdog()
{
if (_is_initialized) {
stop();
// we do not need to stop hw watchdog, it's ticking by itself
}
}
void VirtualWatchdog::start()
{
MBED_ASSERT(!_is_initialized);
core_util_critical_section_enter();
add_to_list();
core_util_critical_section_exit();
}
void VirtualWatchdog::kick()
{
MBED_ASSERT(_is_initialized);
core_util_critical_section_enter();
_current_count = 0;
core_util_critical_section_exit();
}
void VirtualWatchdog::stop()
{
MBED_ASSERT(_is_initialized);
core_util_critical_section_enter();
remove_from_list();
core_util_critical_section_exit();
}
void VirtualWatchdog::add_to_list()
{
this->_next = _first;
_first = this;
_is_initialized = true;
}
void VirtualWatchdog::remove_from_list()
{
VirtualWatchdog *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;
break;
} else {
prev_ptr = cur_ptr;
cur_ptr = cur_ptr->_next;
}
}
}
void VirtualWatchdog::process(uint32_t elapsed_ms)
{
VirtualWatchdog *cur_ptr = _first;
while (cur_ptr != NULL) {
if (cur_ptr->_current_count > cur_ptr->_max_timeout) {
system_reset();
} else {
cur_ptr->_current_count += elapsed_ms;
}
cur_ptr = cur_ptr->_next;
}
}
} // namespace mbed
#endif // DEVICE_VIRTUAL_WATCHDOG