mirror of https://github.com/ARMmbed/mbed-os.git
Add Watchdog driver API
parent
3c18dcb882
commit
8fa38bb25b
|
@ -40,7 +40,7 @@ public:
|
|||
* const reset_reason_t reason = ResetReason::get();
|
||||
*
|
||||
* if (reason == RESET_REASON_WATCHDOG) {
|
||||
* std::cout << "Watchdog reset" << std::endl;
|
||||
* printf("Watchdog reset\n");
|
||||
* rollback();
|
||||
* }
|
||||
* @endcode
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2017 ARM Limited
|
||||
*
|
||||
* 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_WATCHDOG
|
||||
|
||||
#include "Watchdog.h"
|
||||
|
||||
namespace mbed
|
||||
{
|
||||
|
||||
watchdog_status_t Watchdog::start(const uint32_t timeout, const bool enable_sleep)
|
||||
{
|
||||
return start(timeout, 0, enable_sleep);
|
||||
}
|
||||
|
||||
|
||||
watchdog_status_t Watchdog::start(const uint32_t timeout, const uint32_t window, const bool enable_sleep)
|
||||
{
|
||||
watchdog_config_t config;
|
||||
config.timeout_ms = timeout;
|
||||
config.window_ms = window;
|
||||
config.enable_window = (window != 0);
|
||||
config.enable_sleep = enable_sleep;
|
||||
|
||||
return hal_watchdog_init(&config);
|
||||
}
|
||||
|
||||
|
||||
void Watchdog::kick()
|
||||
{
|
||||
hal_watchdog_kick();
|
||||
}
|
||||
|
||||
|
||||
watchdog_status_t Watchdog::stop()
|
||||
{
|
||||
return hal_watchdog_stop();
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
||||
#endif // DEVICE_WATCHDOG
|
|
@ -0,0 +1,137 @@
|
|||
/** \addtogroup hal */
|
||||
/** @{*/
|
||||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2017 ARM Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MBED_WATCHDOG_H
|
||||
#define MBED_WATCHDOG_H
|
||||
|
||||
#ifdef DEVICE_WATCHDOG
|
||||
|
||||
#include "watchdog_api.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
namespace mbed {
|
||||
/** \addtogroup drivers */
|
||||
/** @{*/
|
||||
/** A system timer that will reset the system in the case of system failures or
|
||||
* malfunctions.
|
||||
*
|
||||
* Example:
|
||||
* @code
|
||||
*
|
||||
* Watchdog watchdog = Watchdog();
|
||||
* watchdog.set_timeout(2000);
|
||||
* watchdog.start();
|
||||
*
|
||||
* while (true) {
|
||||
* watchdog.kick();
|
||||
*
|
||||
* // Application code
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
*/
|
||||
class Watchdog
|
||||
{
|
||||
public:
|
||||
Watchdog() {}
|
||||
|
||||
public:
|
||||
/** Start an independent watchdog timer with specified parameters
|
||||
*
|
||||
* @param timeout Timeout of the watchdog in milliseconds
|
||||
* @param enable_sleep Sets sleep mode behaviour. When enabled the watchdog
|
||||
* will continue to run in sleep mode. When disable the
|
||||
* watchdog will be paused. This feature is not
|
||||
* supported on all platforms.
|
||||
*
|
||||
* @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, const bool enable_sleep = true);
|
||||
|
||||
|
||||
/** Start a windowed watchdog timer with specified parameters
|
||||
*
|
||||
* @param timeout Timeout of the watchdog in milliseconds
|
||||
* @param window Time period of the window of the watchdog
|
||||
* @param enable_sleep Sets sleep mode behaviour. When enabled the watchdog
|
||||
* will continue to run in sleep mode. When disable the
|
||||
* watchdog will be paused. This feature is not
|
||||
* supported on all platforms.
|
||||
*
|
||||
* @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, const uint32_t window, const bool enable_sleep = true);
|
||||
|
||||
|
||||
/** Refreshes the watchdog timer.
|
||||
*
|
||||
* This function should be called periodically before the watchdog times out.
|
||||
* Otherwise, the system is reset.
|
||||
*
|
||||
* If the watchdog timer is not currently running this function does nothing
|
||||
*/
|
||||
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 succesfully
|
||||
* 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.
|
||||
*
|
||||
* @return Reload value for the watchdog timer in milliseconds.
|
||||
*/
|
||||
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();
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
/**@}*/
|
||||
/**@}*/
|
||||
|
||||
#endif // DEVICE_WATCHDOG
|
||||
#endif // MBED_WATCHDOG_H
|
|
@ -21,10 +21,6 @@
|
|||
|
||||
#if DEVICE_WATCHDOG
|
||||
|
||||
#if !(DEVICE_RESET_REASON)
|
||||
#error "Watchdog feature depends on reset reason API also being implemented"
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
@ -53,7 +49,10 @@ typedef struct
|
|||
/**
|
||||
* Refresh value for the watchdog in milliseconds. The maximum value of this
|
||||
* setting is platform dependent, to find the maximum value for the current
|
||||
* platform call hal_watchdog_get_max_timeout(void)
|
||||
* platform call hal_watchdog_get_features() and check the timeout value
|
||||
* member. The minimum valid value for this setting is 1, attempting to
|
||||
* initialise the watchdog with a timeout of 0ms will return
|
||||
* WATCHDOG_STATUS_INVALID_ARGUMENT.
|
||||
*/
|
||||
uint32_t timeout_ms;
|
||||
/**
|
||||
|
@ -81,6 +80,36 @@ typedef struct
|
|||
} watchdog_config_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/**
|
||||
* Maximum timeout value for the watchdog in milliseconds.
|
||||
*/
|
||||
uint32_t max_timeout;
|
||||
/**
|
||||
* Maximum timeout value for the watchdog in milliseconds during window
|
||||
* operation mode
|
||||
*/
|
||||
uint32_t max_timeout_window_mode;
|
||||
/**
|
||||
* Watchdog timer supports window mode operation
|
||||
*/
|
||||
bool window_mode;
|
||||
/**
|
||||
* Watchdog configuration can be updated after the watchdog has been started
|
||||
*/
|
||||
bool update_config;
|
||||
/**
|
||||
* Watchdog can be stopped after it is started without a reset
|
||||
*/
|
||||
bool disable_watchdog;
|
||||
/**
|
||||
* Watchdog can be paused while the core is in sleep mode
|
||||
*/
|
||||
bool pause_during_sleep;
|
||||
} watchdog_features_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
WATCHDOG_STATUS_OK,
|
||||
WATCHDOG_STATUS_NOT_SUPPORTED,
|
||||
|
@ -143,18 +172,12 @@ watchdog_status_t hal_watchdog_stop(void);
|
|||
*/
|
||||
uint32_t hal_watchdog_get_reload_value(void);
|
||||
|
||||
/** Checks if the last system reset was caused by a watchdog timer.
|
||||
/** Get information on the current platforms supported watchdog functionality
|
||||
*
|
||||
* @return True if last reset was triggered by a watchdog, False if not.
|
||||
* @return watchdog_feature_t indicating supported watchdog features on the
|
||||
* current platform
|
||||
*/
|
||||
bool hal_watchdog_caused_last_reset(void);
|
||||
|
||||
/** 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
|
||||
*/
|
||||
uint32_t hal_watchdog_get_max_timeout(void);
|
||||
watchdog_features_t hal_watchdog_get_platform_features(void);
|
||||
|
||||
/**@}*/
|
||||
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
// Platform specific watchdog definitions
|
||||
#define LPO_CLOCK_FREQUENCY 1000
|
||||
#define MAX_PRESCALER 8
|
||||
#define MAX_TIMEOUT 0xFFFFFFFF
|
||||
#define MAX_TIMEOUT 0xFFFFFFFFULL
|
||||
|
||||
// Number of decrements in the timeout register per millisecond
|
||||
#define TICKS_PER_MS (LPO_CLOCK_FREQUENCY / 1000)
|
||||
// Maximum timeout that can be specified in milliseconds
|
||||
#define MAX_TIMEOUT_MS ((MAX_TIMEOUT / TICKS_PER_MS) * MAX_PRESCALER)
|
||||
const uint64_t max_timeout_ms = ((MAX_TIMEOUT / TICKS_PER_MS) * MAX_PRESCALER);
|
||||
|
||||
// Maximum supported watchdog timeout for given prescaler value
|
||||
#define CALCULATE_MAX_TIMEOUT_MS(scale) \
|
||||
|
@ -28,11 +28,11 @@
|
|||
|
||||
static uint32_t calculate_prescaler_value(const uint32_t timeout_ms)
|
||||
{
|
||||
if (timeout_ms > MAX_TIMEOUT_MS) {
|
||||
if (timeout_ms > max_timeout_ms) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (uint32_t scale = 1; scale < MAX_PRESCALER; ++scale) {
|
||||
for (uint32_t scale = 1; scale <= MAX_PRESCALER; ++scale) {
|
||||
if (timeout_ms < CALCULATE_MAX_TIMEOUT_MS(scale)) {
|
||||
return scale;
|
||||
}
|
||||
|
@ -49,11 +49,15 @@ watchdog_status_t hal_watchdog_init(const watchdog_config_t *config)
|
|||
return WATCHDOG_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (config->timeout_ms > MAX_TIMEOUT_MS) {
|
||||
if (config->timeout_ms == 0) {
|
||||
return WATCHDOG_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (config->window_ms > MAX_TIMEOUT_MS) {
|
||||
if (config->timeout_ms > max_timeout_ms) {
|
||||
return WATCHDOG_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (config->window_ms > max_timeout_ms) {
|
||||
return WATCHDOG_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
|
@ -114,12 +118,15 @@ uint32_t hal_watchdog_get_reload_value(void)
|
|||
return ((timeout / TICKS_PER_MS) * (prescaler + 1));
|
||||
}
|
||||
|
||||
bool hal_watchdog_caused_last_reset(void)
|
||||
{
|
||||
return (hal_reset_reason_get() == RESET_REASON_WATCHDOG);
|
||||
}
|
||||
|
||||
uint32_t hal_watchdog_get_max_timeout(void)
|
||||
watchdog_features_t hal_watchdog_get_max_timeout(void)
|
||||
{
|
||||
return MAX_TIMEOUT_MS;
|
||||
watchdog_features_t features;
|
||||
features.max_timeout = max_timeout_ms;
|
||||
features.max_timeout_window_mode = max_timeout_ms;
|
||||
features.update_config = true;
|
||||
features.disable_watchdog = true;
|
||||
features.pause_during_sleep = true;
|
||||
|
||||
return features;
|
||||
}
|
||||
|
|
|
@ -8,12 +8,13 @@
|
|||
// Platform specific watchdog definitions
|
||||
#define LPO_CLOCK_FREQUENCY 40000
|
||||
#define MAX_PRESCALER 256
|
||||
#define MAX_TIMEOUT 0xFFF
|
||||
#define MAX_TIMEOUT 0xFFFULL
|
||||
|
||||
// Number of decrements in the timeout register per millisecond
|
||||
#define TICKS_PER_MS (LPO_CLOCK_FREQUENCY / 1000)
|
||||
// Maximum timeout that can be specified in milliseconds
|
||||
#define MAX_TIMEOUT_MS ((MAX_TIMEOUT / TICKS_PER_MS) * MAX_PRESCALER)
|
||||
const uint64_t max_timeout_ms = ((MAX_TIMEOUT / TICKS_PER_MS) * MAX_PRESCALER);
|
||||
|
||||
// Maximum supported watchdog timeout for given prescaler value
|
||||
#define CALCULATE_MAX_TIMEOUT_MS(scale) \
|
||||
((MAX_TIMEOUT / TICKS_PER_MS) * scale)
|
||||
|
@ -44,6 +45,10 @@ watchdog_status_t hal_watchdog_init(const watchdog_config_t *config)
|
|||
return WATCHDOG_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (config->timeout_ms == 0) {
|
||||
return WATCHDOG_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (config->timeout_ms > MAX_TIMEOUT_MS) {
|
||||
return WATCHDOG_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
@ -103,14 +108,14 @@ uint32_t hal_watchdog_get_reload_value(void)
|
|||
return ((timeout / TICKS_PER_MS) * prescaler);
|
||||
}
|
||||
|
||||
|
||||
bool hal_watchdog_caused_last_reset(void)
|
||||
watchdog_features_t hal_watchdog_get_max_timeout(void)
|
||||
{
|
||||
return (hal_reset_reason_get() == RESET_REASON_WATCHDOG);
|
||||
}
|
||||
watchdog_features_t features;
|
||||
features.max_timeout = max_timeout_ms;
|
||||
features.max_timeout_window_mode = max_timeout_ms;
|
||||
features.update_config = true;
|
||||
features.disable_watchdog = false;
|
||||
features.pause_during_sleep = true;
|
||||
|
||||
|
||||
uint32_t hal_watchdog_get_max_timeout(void)
|
||||
{
|
||||
return MAX_TIMEOUT_MS;
|
||||
return features;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue