Add independent watchdog reference implementation for STM32

pull/10657/head
Steven Cartmell 2017-11-27 17:20:58 +00:00 committed by Filip Jagodzinski
parent 6b3d790fc1
commit 366893ae71
4 changed files with 118 additions and 1 deletions

View File

@ -0,0 +1,116 @@
#include "watchdog_api.h"
#include "reset_reason_api.h"
#include "device.h"
// Platform specific watchdog definitions
#define LPO_CLOCK_FREQUENCY 40000
#define MAX_PRESCALER 256
#define MAX_TIMEOUT 0xFFF
// 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)
// Maximum supported watchdog timeout for given prescaler value
#define CALCULATE_MAX_TIMEOUT_MS(scale) \
((MAX_TIMEOUT / TICKS_PER_MS) * scale)
static uint32_t calculate_prescaler_value(const uint32_t timeout_ms)
{
if (timeout_ms > MAX_TIMEOUT_MS) {
return 0;
}
for (uint32_t scale = 0; scale < 7; ++scale) {
const uint32_t prescaler = (4U << scale);
if (timeout_ms < CALCULATE_MAX_TIMEOUT_MS(prescaler)) {
return scale;
}
}
return 0;
}
watchdog_status_t hal_watchdog_init(const watchdog_config_t *config)
{
// Validate the input parameters
if (config == NULL) {
return WATCHDOG_STATUS_INVALID_ARGUMENT;
}
if (config->timeout_ms > MAX_TIMEOUT_MS) {
return WATCHDOG_STATUS_INVALID_ARGUMENT;
}
if (config->window_ms > MAX_TIMEOUT_MS) {
return WATCHDOG_STATUS_INVALID_ARGUMENT;
}
if (config->window_ms > config->timeout_ms) {
return WATCHDOG_STATUS_INVALID_ARGUMENT;
}
if (config->enable_sleep == false) {
return WATCHDOG_STATUS_NOT_SUPPORTED;
}
const uint32_t prescaler = calculate_prescaler_value(config->timeout_ms);
if (prescaler == 0) {
return WATCHDOG_STATUS_INVALID_ARGUMENT;
}
// Enable write access to Prescaler(IWDG_PR) and Reload(IWDG_RLR) registers
IWDG->KR = 0x5555;
// Set the prescaler and timeout values
IWDG->RLR = (TICKS_PER_MS * config->timeout_ms) / (4U << prescaler);
IWDG->PR = prescaler;
// Reload the Watchdog Counter.
IWDG->KR = 0xAAAA;
// Enable the Independent Watchdog.
IWDG->KR = 0xCCCC;
return WATCHDOG_STATUS_OK;
}
void hal_watchdog_kick(void)
{
IWDG->KR = 0xAAAA;
}
watchdog_status_t hal_watchdog_stop(void)
{
return WATCHDOG_STATUS_NOT_SUPPORTED;
}
uint32_t hal_watchdog_get_reload_value(void)
{
const uint32_t timeout = (IWDG->RLR & 0xFFF);
const uint32_t prescaler = (4U << (IWDG->PR & 0x7));
return ((timeout / TICKS_PER_MS) * prescaler);
}
bool hal_watchdog_caused_last_reset(void)
{
return (hal_reset_reason_get() == RESET_REASON_WATCHDOG);
}
uint32_t hal_watchdog_get_max_timeout(void)
{
return MAX_TIMEOUT_MS;
}

View File

@ -1904,7 +1904,8 @@
"SPI",
"SPISLAVE",
"SPI_ASYNCH",
"STDIO_MESSAGES"
"STDIO_MESSAGES",
"WATCHDOG"
]
},
"MIMXRT1050_EVK": {