From d22404b8b736f304b6fb5576cb4f7a07063f1d2e Mon Sep 17 00:00:00 2001 From: Alexandre Abadie Date: Thu, 7 Nov 2019 09:58:27 +0100 Subject: [PATCH] cpu/atmega_common: add implementation for watchdog --- cpu/atmega_common/Makefile.features | 1 + cpu/atmega_common/include/periph_cpu_common.h | 13 +++ cpu/atmega_common/periph/wdt.c | 99 +++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 cpu/atmega_common/periph/wdt.c diff --git a/cpu/atmega_common/Makefile.features b/cpu/atmega_common/Makefile.features index 20e4be884a..bb8b5f4214 100644 --- a/cpu/atmega_common/Makefile.features +++ b/cpu/atmega_common/Makefile.features @@ -4,3 +4,4 @@ FEATURES_PROVIDED += atmega_pcint0 FEATURES_PROVIDED += periph_eeprom FEATURES_PROVIDED += periph_gpio periph_gpio_irq FEATURES_PROVIDED += periph_pm +FEATURES_PROVIDED += periph_wdt diff --git a/cpu/atmega_common/include/periph_cpu_common.h b/cpu/atmega_common/include/periph_cpu_common.h index 56dc154db4..8931f3128f 100644 --- a/cpu/atmega_common/include/periph_cpu_common.h +++ b/cpu/atmega_common/include/periph_cpu_common.h @@ -151,6 +151,19 @@ typedef struct { */ #define EEPROM_CLEAR_BYTE (0xff) +/** + * @name WDT upper and lower bound times in ms + * @{ + */ +#define NWDT_TIME_LOWER_LIMIT (1) +#define NWDT_TIME_UPPER_LIMIT (8192U) +/** @} */ + +/** + * @brief WDT can be stopped on AVR + */ +#define WDT_HAS_STOP (1) + #ifdef __cplusplus } #endif diff --git a/cpu/atmega_common/periph/wdt.c b/cpu/atmega_common/periph/wdt.c new file mode 100644 index 0000000000..4debf87926 --- /dev/null +++ b/cpu/atmega_common/periph/wdt.c @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2019 Inria + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup cpu_atmega_common + * @ingroup drivers_periph_wdt + * @{ + * + * @file + * @brief Implementation of the watchdog peripheral interface + * + * @author Alexandre Abadie + * + * @} + */ + +#include "cpu.h" +#include "periph/pm.h" +#include "periph/wdt.h" + +#include +#include "avr/wdt.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +uint8_t wdt_prescaler = WDTO_15MS; + +void wdt_start(void) +{ + DEBUG("[wdt] start the watchdog\n"); + wdt_enable(wdt_prescaler); +} + +void wdt_stop(void) +{ + DEBUG("[wdt] stop the watchdog\n"); + wdt_disable(); +} + +void wdt_kick(void) +{ + DEBUG("[wdt] reload the watchdog\n"); + wdt_reset(); + wdt_enable(wdt_prescaler); +} + +void wdt_setup_reboot(uint32_t min_time, uint32_t max_time) +{ + (void)min_time; + + /* Windowed wdt not supported */ + assert(min_time == 0); + + /* Check reset time limit */ + assert((max_time > NWDT_TIME_LOWER_LIMIT) || \ + (max_time < NWDT_TIME_UPPER_LIMIT)); + + /* disable watchdog */ + wdt_disable(); + + if (max_time >= 8000) { + wdt_prescaler = WDTO_8S; + } + else if (max_time >= 4000) { + wdt_prescaler = WDTO_4S; + } + else if (max_time >= 2000) { + wdt_prescaler = WDTO_2S; + } + else if (max_time >= 1000) { + wdt_prescaler = WDTO_1S; + } + else if (max_time >= 500) { + wdt_prescaler = WDTO_500MS; + } + else if (max_time >= 250) { + wdt_prescaler = WDTO_250MS; + } + else if (max_time >= 125) { + wdt_prescaler = WDTO_120MS; + } + else if (max_time >= 64) { + wdt_prescaler = WDTO_60MS; + } + else if (max_time >= 32) { + wdt_prescaler = WDTO_30MS; + } + else { + wdt_prescaler = WDTO_15MS; + } + + DEBUG("[wdt] watchdog setup complete\n"); +}