diff --git a/ports/atmel-samd/common-hal/microcontroller/__init__.c b/ports/atmel-samd/common-hal/microcontroller/__init__.c index 751f4dcab7..983af7a647 100644 --- a/ports/atmel-samd/common-hal/microcontroller/__init__.c +++ b/ports/atmel-samd/common-hal/microcontroller/__init__.c @@ -103,6 +103,17 @@ const nvm_bytearray_obj_t common_hal_mcu_nvm_obj = { }; #endif +#if CIRCUITPY_WATCHDOG +// The singleton watchdog.WatchDogTimer object. +watchdog_watchdogtimer_obj_t common_hal_mcu_watchdogtimer_obj = { + .base = { + .type = &watchdog_watchdogtimer_type, + }, + .timeout = 0.0f, + .mode = WATCHDOGMODE_NONE, +}; +#endif + // This maps MCU pin names to pin objects. STATIC const mp_rom_map_elem_t mcu_pin_global_dict_table[] = { #if defined(PIN_PA00) && !defined(IGNORE_PIN_PA00) diff --git a/ports/atmel-samd/common-hal/watchdog/WatchDogMode.c b/ports/atmel-samd/common-hal/watchdog/WatchDogMode.c new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ports/atmel-samd/common-hal/watchdog/WatchDogTimer.c b/ports/atmel-samd/common-hal/watchdog/WatchDogTimer.c new file mode 100644 index 0000000000..70901aadf5 --- /dev/null +++ b/ports/atmel-samd/common-hal/watchdog/WatchDogTimer.c @@ -0,0 +1,109 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "py/runtime.h" + +#include "shared-bindings/watchdog/__init__.h" +#include "shared-bindings/watchdog/WatchDogTimer.h" +#include "common-hal/watchdog/WatchDogTimer.h" + +#include "component/wdt.h" + +void pet(void) { + WDT->CLEAR.reg = WDT_CLEAR_CLEAR_KEY; +} + +void common_hal_watchdog_feed(watchdog_watchdogtimer_obj_t *self) { + pet(); +} + +void common_hal_watchdog_deinit(watchdog_watchdogtimer_obj_t *self) { + if (self->mode == WATCHDOGMODE_RESET) { + mp_raise_RuntimeError(translate("WatchDogTimer cannot be deinitialized once mode is set to RESET")); + } else { + self->mode = WATCHDOGMODE_NONE; + } +} + +mp_float_t common_hal_watchdog_get_timeout(watchdog_watchdogtimer_obj_t *self) { + return self->timeout; +} + +void setup_wdt(int setting) { + OSC32KCTRL->OSCULP32K.bit.EN1K = 1; // Enable out 1K (for WDT) + + // disable watchdog for config + WDT->CTRLA.reg = 0; + while (WDT->SYNCBUSY.reg) { // Sync CTRL write + } + + WDT->INTENCLR.bit.EW = 1; // Disable early warning interrupt + WDT->CONFIG.bit.PER = setting; // Set period for chip reset + WDT->CTRLA.bit.WEN = 0; // Disable window mode + while (WDT->SYNCBUSY.reg) { // Sync CTRL write + } + pet(); // Clear watchdog interval + WDT->CTRLA.bit.ENABLE = 1; // Start watchdog now! + while (WDT->SYNCBUSY.reg) { + } +} + +void common_hal_watchdog_set_timeout(watchdog_watchdogtimer_obj_t *self, mp_float_t new_timeout) { + int wdt_cycles = (int)(new_timeout * 1000); + if (wdt_cycles < 8) { + wdt_cycles = 8; + } + if (wdt_cycles > 16384) { + mp_raise_ValueError(translate("timeout duration exceeded the maximum supported value")); + } + // ceil(log2(n)) = 32 - __builtin_clz(n - 1) when n > 1 (if int is 32 bits) + int log2_wdt_cycles = (sizeof(int) * CHAR_BIT) - __builtin_clz(wdt_cycles - 1); + int setting = log2_wdt_cycles - 3; // CYC8_Val is 0 + float timeout = (8 << setting) / 1024.f; + + if (self->mode == WATCHDOGMODE_RESET) { + setup_wdt(setting); + } + self->timeout = timeout; +} + +watchdog_watchdogmode_t common_hal_watchdog_get_mode(watchdog_watchdogtimer_obj_t *self) { + return self->mode; +} + +void common_hal_watchdog_set_mode(watchdog_watchdogtimer_obj_t *self, watchdog_watchdogmode_t new_mode) { + if (self->mode != new_mode) { + if (new_mode == WATCHDOGMODE_RAISE) { + mp_raise_NotImplementedError(translate("RAISE mode is not implemented")); + } else if (new_mode == WATCHDOGMODE_NONE) { + common_hal_watchdog_deinit(self); + } + self->mode = new_mode; + common_hal_watchdog_set_timeout(self, self->timeout); + } +} diff --git a/ports/atmel-samd/common-hal/watchdog/WatchDogTimer.h b/ports/atmel-samd/common-hal/watchdog/WatchDogTimer.h new file mode 100644 index 0000000000..ce34f0b8ab --- /dev/null +++ b/ports/atmel-samd/common-hal/watchdog/WatchDogTimer.h @@ -0,0 +1,43 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 microDev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_WATCHDOG_WATCHDOGTIMER_H +#define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_WATCHDOG_WATCHDOGTIMER_H + +#include "py/obj.h" +#include "shared-bindings/watchdog/WatchDogMode.h" +#include "shared-bindings/watchdog/WatchDogTimer.h" + +struct _watchdog_watchdogtimer_obj_t { + mp_obj_base_t base; + mp_float_t timeout; + watchdog_watchdogmode_t mode; +}; + +// This needs to be called in order to disable the watchdog +// void watchdog_reset(void); + +#endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_WATCHDOG_WATCHDOGTIMER_H diff --git a/ports/atmel-samd/common-hal/watchdog/__init__.c b/ports/atmel-samd/common-hal/watchdog/__init__.c new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ports/atmel-samd/mpconfigport.mk b/ports/atmel-samd/mpconfigport.mk index 8994f0f52a..4a5c7a41d6 100644 --- a/ports/atmel-samd/mpconfigport.mk +++ b/ports/atmel-samd/mpconfigport.mk @@ -102,6 +102,7 @@ CIRCUITPY_PS2IO ?= 1 CIRCUITPY_SAMD ?= 1 CIRCUITPY_RGBMATRIX ?= $(CIRCUITPY_FULL_BUILD) CIRCUITPY_FRAMEBUFFERIO ?= $(CIRCUITPY_FULL_BUILD) +CIRCUITPY_WATCHDOG ?= 1 endif # samd51 ###################################################################### diff --git a/shared-bindings/watchdog/__init__.h b/shared-bindings/watchdog/__init__.h index b5a0ad71d1..0921141129 100644 --- a/shared-bindings/watchdog/__init__.h +++ b/shared-bindings/watchdog/__init__.h @@ -27,6 +27,9 @@ #ifndef MICROPY_INCLUDED_SHARED_BINDINGS_WATCHDOG___INIT___H #define MICROPY_INCLUDED_SHARED_BINDINGS_WATCHDOG___INIT___H +#include "py/obj.h" +#include "py/objexcept.h" + extern const mp_obj_module_t watchdog_module; extern mp_obj_exception_t mp_watchdog_timeout_exception; extern const mp_obj_type_t mp_type_WatchDogTimeout;