Merge pull request #2933 from simmel-project/wdt-nrf

Add Watchdog timer and add support for NRF watchdog
This commit is contained in:
Scott Shawcroft 2020-06-02 10:33:24 -07:00 committed by GitHub
commit db04fd1725
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 941 additions and 28 deletions

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-06-01 08:56-0500\n" "POT-Creation-Date: 2020-06-01 17:10-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -1652,6 +1652,26 @@ msgstr ""
msgid "WARNING: Your code filename has two extensions\n" msgid "WARNING: Your code filename has two extensions\n"
msgstr "" msgstr ""
#: shared-bindings/watchdog/WatchDogTimer.c
msgid "WatchDogTimer cannot be deinitialized once mode is set to RESET"
msgstr ""
#: shared-bindings/watchdog/WatchDogTimer.c
msgid "WatchDogTimer is not currently running"
msgstr ""
#: shared-bindings/watchdog/WatchDogTimer.c
msgid "WatchDogTimer.mode cannot be changed once set to WatchDogMode.RESET"
msgstr ""
#: shared-bindings/watchdog/WatchDogTimer.c
msgid "WatchDogTimer.timeout must be greater than 0"
msgstr ""
#: supervisor/shared/safe_mode.c
msgid "Watchdog timer expired."
msgstr ""
#: py/builtinhelp.c #: py/builtinhelp.c
#, c-format #, c-format
msgid "" msgid ""
@ -3059,6 +3079,10 @@ msgstr ""
msgid "time.struct_time() takes a 9-sequence" msgid "time.struct_time() takes a 9-sequence"
msgstr "" msgstr ""
#: ports/nrf/common-hal/watchdog/WatchDogTimer.c
msgid "timeout duration exceeded the maximum supported value"
msgstr ""
#: shared-bindings/busio/UART.c #: shared-bindings/busio/UART.c
msgid "timeout must be 0.0-100.0 seconds" msgid "timeout must be 0.0-100.0 seconds"
msgstr "" msgstr ""
@ -3212,6 +3236,10 @@ msgstr ""
msgid "value_count must be > 0" msgid "value_count must be > 0"
msgstr "" msgstr ""
#: shared-bindings/watchdog/WatchDogTimer.c
msgid "watchdog timeout must be greater than 0"
msgstr ""
#: shared-bindings/_bleio/Adapter.c #: shared-bindings/_bleio/Adapter.c
msgid "window must be <= interval" msgid "window must be <= interval"
msgstr "" msgstr ""

View File

@ -136,6 +136,7 @@ SRC_NRFX = $(addprefix nrfx/,\
drivers/src/nrfx_gpiote.c \ drivers/src/nrfx_gpiote.c \
drivers/src/nrfx_rtc.c \ drivers/src/nrfx_rtc.c \
drivers/src/nrfx_nvmc.c \ drivers/src/nrfx_nvmc.c \
drivers/src/nrfx_wdt.c \
) )
ifdef EXTERNAL_FLASH_DEVICES ifdef EXTERNAL_FLASH_DEVICES

View File

@ -70,20 +70,6 @@ SECTIONS
_etext = .; /* define a global symbol at end of code */ _etext = .; /* define a global symbol at end of code */
} >FLASH_FIRMWARE } >FLASH_FIRMWARE
/*
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} >FLASH_FIRMWARE
.ARM :
{
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH_FIRMWARE
*/
/* used by the startup to initialize data */ /* used by the startup to initialize data */
_sidata = .; _sidata = .;
@ -147,6 +133,14 @@ SECTIONS
. = ALIGN(4); . = ALIGN(4);
} >RAM } >RAM
/* Remove exception unwinding information, since Circuit Python
does not support this GCC feature. */
/DISCARD/ :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
*(.ARM.exidx*)
}
/* Remove information from the standard libraries */ /* Remove information from the standard libraries */
/* /*
/DISCARD/ : /DISCARD/ :

View File

@ -8,9 +8,13 @@ MCU_CHIP = nrf52833
INTERNAL_FLASH_FILESYSTEM = 1 INTERNAL_FLASH_FILESYSTEM = 1
CIRCUITPY_AUDIOMP3 = 0 CIRCUITPY_AUDIOMP3 = 0
CIRCUITPY_BITBANGIO = 0
CIRCUITPY_BUSIO = 1 CIRCUITPY_BUSIO = 1
CIRCUITPY_COUNTIO = 0
CIRCUITPY_DISPLAYIO = 0 CIRCUITPY_DISPLAYIO = 0
CIRCUITPY_FRAMEBUFFERIO = 0 CIRCUITPY_FRAMEBUFFERIO = 0
CIRCUITPY_FREQUENCYIO = 0
CIRCUITPY_I2CSLAVE = 0
CIRCUITPY_NEOPIXEL_WRITE = 0 CIRCUITPY_NEOPIXEL_WRITE = 0
CIRCUITPY_NVM = 0 CIRCUITPY_NVM = 0
CIRCUITPY_PIXELBUF = 0 CIRCUITPY_PIXELBUF = 0
@ -20,6 +24,8 @@ CIRCUITPY_RTC = 1
CIRCUITPY_TOUCHIO = 0 CIRCUITPY_TOUCHIO = 0
CIRCUITPY_ULAB = 0 CIRCUITPY_ULAB = 0
SUPEROPT_GC = 0
# These defines must be overridden before mpconfigboard.h is included, which is # These defines must be overridden before mpconfigboard.h is included, which is
# why they are passed on the command line. # why they are passed on the command line.
CFLAGS += -DSPIM3_BUFFER_SIZE=0 -DSOFTDEVICE_RAM_SIZE='(32*1024)' CFLAGS += -DSPIM3_BUFFER_SIZE=0 -DSOFTDEVICE_RAM_SIZE='(32*1024)'

View File

@ -40,7 +40,7 @@
#endif #endif
#define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define CIRCUITPY_INTERNAL_NVM_SIZE 0
#define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE (80*1024) #define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE (76*1024)
#define BOOTLOADER_SIZE (0x4000) // 12 kiB #define BOOTLOADER_SIZE (0x4000) // 12 kiB
#define CIRCUITPY_BLE_CONFIG_SIZE (12*1024) #define CIRCUITPY_BLE_CONFIG_SIZE (12*1024)

View File

@ -24,6 +24,7 @@ CIRCUITPY_ROTARYIO = 0
CIRCUITPY_RTC = 1 CIRCUITPY_RTC = 1
CIRCUITPY_TOUCHIO = 0 CIRCUITPY_TOUCHIO = 0
CIRCUITPY_ULAB = 0 CIRCUITPY_ULAB = 0
CIRCUITPY_WATCHDOG = 1
# Enable micropython.native # Enable micropython.native
#CIRCUITPY_ENABLE_MPY_NATIVE = 1 #CIRCUITPY_ENABLE_MPY_NATIVE = 1

View File

@ -94,7 +94,7 @@ void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
void common_hal_mcu_reset(void) { void common_hal_mcu_reset(void) {
filesystem_flush(); filesystem_flush();
NVIC_SystemReset(); reset_cpu();
} }
// The singleton microcontroller.Processor object, bound to microcontroller.cpu // The singleton microcontroller.Processor object, bound to microcontroller.cpu
@ -106,7 +106,6 @@ const mcu_processor_obj_t common_hal_mcu_processor_obj = {
}; };
#if CIRCUITPY_INTERNAL_NVM_SIZE > 0 #if CIRCUITPY_INTERNAL_NVM_SIZE > 0
// The singleton nvm.ByteArray object. // The singleton nvm.ByteArray object.
const nvm_bytearray_obj_t common_hal_mcu_nvm_obj = { const nvm_bytearray_obj_t common_hal_mcu_nvm_obj = {
.base = { .base = {
@ -117,6 +116,17 @@ const nvm_bytearray_obj_t common_hal_mcu_nvm_obj = {
}; };
#endif #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
STATIC const mp_rom_map_elem_t mcu_pin_globals_table[] = { STATIC const mp_rom_map_elem_t mcu_pin_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_P0_00), MP_ROM_PTR(&pin_P0_00) }, { MP_ROM_QSTR(MP_QSTR_P0_00), MP_ROM_PTR(&pin_P0_00) },
{ MP_ROM_QSTR(MP_QSTR_P0_01), MP_ROM_PTR(&pin_P0_01) }, { MP_ROM_QSTR(MP_QSTR_P0_01), MP_ROM_PTR(&pin_P0_01) },

View File

@ -0,0 +1,189 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Nick Moore 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 <math.h>
#include <string.h>
#include "py/obj.h"
#include "py/objproperty.h"
#include "py/runtime.h"
#include "common-hal/watchdog/WatchDogTimer.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/watchdog/__init__.h"
#include "shared-bindings/watchdog/WatchDogTimer.h"
#include "supervisor/port.h"
#include "nrf/timers.h"
#include "nrf_wdt.h"
#include "nrfx_wdt.h"
#include "nrfx_timer.h"
STATIC uint8_t timer_refcount = 0;
STATIC nrfx_timer_t *timer = NULL;
STATIC nrfx_wdt_t wdt = NRFX_WDT_INSTANCE(0);
STATIC nrfx_wdt_channel_id wdt_channel_id;
STATIC void watchdogtimer_timer_event_handler(nrf_timer_event_t event_type, void *p_context) {
watchdog_watchdogtimer_obj_t *self = MP_OBJ_TO_PTR(p_context);
if (event_type != NRF_TIMER_EVENT_COMPARE0) {
// Spurious event.
return;
}
// If the timer hits without being cleared, pause the timer and raise an exception.
nrfx_timer_pause(timer);
self->mode = WATCHDOGMODE_NONE;
mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&mp_watchdog_timeout_exception));
MP_STATE_VM(mp_pending_exception) = &mp_watchdog_timeout_exception;
#if MICROPY_ENABLE_SCHEDULER
if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) {
MP_STATE_VM(sched_state) = MP_SCHED_PENDING;
}
#endif
}
static void timer_free(void) {
timer_refcount--;
if (timer_refcount == 0) {
nrf_peripherals_free_timer(timer);
timer = NULL;
}
}
// This function is called if the timer expires. The system will reboot
// in 1/16384 of a second. Issue a reboot ourselves so we can do any
// cleanup necessary.
STATIC void watchdogtimer_watchdog_event_handler(void) {
reset_cpu();
}
void common_hal_watchdog_feed(watchdog_watchdogtimer_obj_t *self) {
if (self->mode == WATCHDOGMODE_RESET) {
nrfx_wdt_feed(&wdt);
} else if (self->mode == WATCHDOGMODE_RAISE) {
nrfx_timer_clear(timer);
}
}
void common_hal_watchdog_deinit(watchdog_watchdogtimer_obj_t *self) {
if (timer) {
timer_free();
}
self->mode = WATCHDOGMODE_NONE;
}
void watchdog_reset(void) {
common_hal_watchdog_deinit(&common_hal_mcu_watchdogtimer_obj);
}
mp_float_t common_hal_watchdog_get_timeout(watchdog_watchdogtimer_obj_t *self) {
return self->timeout;
}
void common_hal_watchdog_set_timeout(watchdog_watchdogtimer_obj_t *self, mp_float_t timeout) {
if (self->mode == WATCHDOGMODE_RAISE) {
// If the WatchDogTimer is already running in "RAISE" mode, reset the timer
// with the new value.
uint64_t ticks = timeout * 31250ULL;
if (ticks > UINT32_MAX) {
mp_raise_ValueError(translate("timeout duration exceeded the maximum supported value"));
}
nrfx_timer_clear(timer);
nrfx_timer_compare(timer, NRF_TIMER_CC_CHANNEL0, ticks, true);
}
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) {
watchdog_watchdogmode_t current_mode = self->mode;
if (new_mode == WATCHDOGMODE_RAISE) {
if (timer_refcount == 0) {
timer = nrf_peripherals_allocate_timer_or_throw();
}
timer_refcount++;
nrfx_timer_config_t timer_config = {
.frequency = NRF_TIMER_FREQ_31250Hz,
.mode = NRF_TIMER_MODE_TIMER,
.bit_width = NRF_TIMER_BIT_WIDTH_32,
.interrupt_priority = NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY,
.p_context = self,
};
nrfx_timer_init(timer, &timer_config, &watchdogtimer_timer_event_handler);
uint64_t ticks = nrfx_timer_ms_to_ticks(timer, self->timeout * 1000);
if (ticks > UINT32_MAX) {
mp_raise_ValueError(translate("timeout duration exceeded the maximum supported value"));
}
// true enables interrupt.
nrfx_timer_clear(timer);
nrfx_timer_compare(timer, NRF_TIMER_CC_CHANNEL0, ticks, true);
nrfx_timer_resume(timer);
} else if (new_mode == WATCHDOGMODE_RESET) {
uint64_t ticks = self->timeout * 1000.0f;
if (ticks > UINT32_MAX) {
mp_raise_ValueError(translate("timeout duration exceeded the maximum supported value"));
}
nrfx_wdt_config_t config = {
.reload_value = ticks, // in units of ms
.behaviour = NRF_WDT_BEHAVIOUR_RUN_SLEEP,
NRFX_WDT_IRQ_CONFIG
};
nrfx_err_t err_code;
err_code = nrfx_wdt_init(&wdt, &config, watchdogtimer_watchdog_event_handler);
if (err_code != NRFX_SUCCESS) {
mp_raise_OSError(1);
}
err_code = nrfx_wdt_channel_alloc(&wdt, &wdt_channel_id);
if (err_code != NRFX_SUCCESS) {
mp_raise_OSError(1);
}
nrfx_wdt_enable(&wdt);
nrfx_wdt_feed(&wdt);
}
// If we just switched away from RAISE, disable the timmer.
if (current_mode == WATCHDOGMODE_RAISE && new_mode != WATCHDOGMODE_RAISE) {
timer_free();
}
self->mode = new_mode;
}

View File

@ -0,0 +1,44 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Noralf Trønnes
*
* 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_NRF_COMMON_HAL_WATCHDOG_WATCHDOGTIMER_H
#define MICROPY_INCLUDED_NRF_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 if it's set to
// "RAISE". If set to "RESET", then the watchdog cannot be reset.
void watchdog_reset(void);
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_WATCHDOG_WATCHDOGTIMER_H

View File

@ -0,0 +1,25 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Nick Moore 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.
*/

View File

@ -0,0 +1,30 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Noralf Trønnes
*
* 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_NRF_COMMON_HAL_WATCHDOG___INIT___H
#define MICROPY_INCLUDED_NRF_COMMON_HAL_WATCHDOG___INIT___H
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_WATCHDOG___INIT___H

View File

@ -37,6 +37,7 @@ CIRCUITPY_RGBMATRIX ?= 1
CIRCUITPY_FRAMEBUFFERIO ?= 1 CIRCUITPY_FRAMEBUFFERIO ?= 1
CIRCUITPY_COUNTIO = 0 CIRCUITPY_COUNTIO = 0
CIRCUITPY_WATCHDOG ?= 1
# nRF52840-specific # nRF52840-specific

View File

@ -122,4 +122,11 @@
// NVM controller // NVM controller
#define NRFX_NVMC_ENABLED 1 #define NRFX_NVMC_ENABLED 1
// Watchdog timer
#define NRFX_WDT_ENABLED 1
#define NRFX_WDT0_ENABLED 1
// This IRQ indicates the system will reboot shortly, so give
// it a high priority.
#define NRFX_WDT_DEFAULT_CONFIG_IRQ_PRIORITY 2
#endif // NRFX_CONFIG_H__ #endif // NRFX_CONFIG_H__

View File

@ -180,17 +180,17 @@ static inline bool _NRFX_IRQ_IS_PENDING(IRQn_Type irq_number)
return (NVIC_GetPendingIRQ(irq_number) == 1); return (NVIC_GetPendingIRQ(irq_number) == 1);
} }
//#include <nordic_common.h> void common_hal_mcu_disable_interrupts(void);
//#include <app_util_platform.h> void common_hal_mcu_enable_interrupts(void);
/** /**
* @brief Macro for entering into a critical section. * @brief Macro for entering into a critical section.
*/ */
#define NRFX_CRITICAL_SECTION_ENTER() CRITICAL_REGION_ENTER() #define NRFX_CRITICAL_SECTION_ENTER() common_hal_mcu_disable_interrupts()
/** /**
* @brief Macro for exiting from a critical section. * @brief Macro for exiting from a critical section.
*/ */
#define NRFX_CRITICAL_SECTION_EXIT() CRITICAL_REGION_EXIT() #define NRFX_CRITICAL_SECTION_EXIT() common_hal_mcu_enable_interrupts()
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -50,6 +50,7 @@
#include "common-hal/pulseio/PulseIn.h" #include "common-hal/pulseio/PulseIn.h"
#include "common-hal/rtc/RTC.h" #include "common-hal/rtc/RTC.h"
#include "common-hal/neopixel_write/__init__.h" #include "common-hal/neopixel_write/__init__.h"
#include "common-hal/watchdog/WatchDogTimer.h"
#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/rtc/__init__.h" #include "shared-bindings/rtc/__init__.h"
@ -77,13 +78,19 @@ const nrfx_rtc_config_t rtc_config = {
.interrupt_priority = 6 .interrupt_priority = 6
}; };
static volatile uint64_t overflowed_ticks = 0; #define OVERFLOW_CHECK_PREFIX 0x2cad564f
#define OVERFLOW_CHECK_SUFFIX 0x11343ef7
static volatile struct {
uint32_t prefix;
uint64_t overflowed_ticks;
uint32_t suffix;
} overflow_tracker __attribute__((section(".uninitialized")));
void rtc_handler(nrfx_rtc_int_type_t int_type) { void rtc_handler(nrfx_rtc_int_type_t int_type) {
if (int_type == NRFX_RTC_INT_OVERFLOW) { if (int_type == NRFX_RTC_INT_OVERFLOW) {
// Our RTC is 24 bits and we're clocking it at 32.768khz which is 32 (2 ** 5) subticks per // Our RTC is 24 bits and we're clocking it at 32.768khz which is 32 (2 ** 5) subticks per
// tick. // tick.
overflowed_ticks += (1L<< (24 - 5)); overflow_tracker.overflowed_ticks += (1L<< (24 - 5));
} else if (int_type == NRFX_RTC_INT_TICK && nrfx_rtc_counter_get(&rtc_instance) % 32 == 0) { } else if (int_type == NRFX_RTC_INT_TICK && nrfx_rtc_counter_get(&rtc_instance) % 32 == 0) {
// Do things common to all ports when the tick occurs // Do things common to all ports when the tick occurs
supervisor_tick(); supervisor_tick();
@ -100,6 +107,17 @@ void tick_init(void) {
nrfx_rtc_init(&rtc_instance, &rtc_config, rtc_handler); nrfx_rtc_init(&rtc_instance, &rtc_config, rtc_handler);
nrfx_rtc_enable(&rtc_instance); nrfx_rtc_enable(&rtc_instance);
nrfx_rtc_overflow_enable(&rtc_instance, true); nrfx_rtc_overflow_enable(&rtc_instance, true);
// If the check prefix and suffix aren't correct, then the structure
// in memory isn't correct and the clock will be wildly wrong. Initialize
// the prefix and suffix so that we know the value is correct, and reset
// the time to 0.
if (overflow_tracker.prefix != OVERFLOW_CHECK_PREFIX ||
overflow_tracker.suffix != OVERFLOW_CHECK_SUFFIX) {
overflow_tracker.prefix = OVERFLOW_CHECK_PREFIX;
overflow_tracker.suffix = OVERFLOW_CHECK_SUFFIX;
overflow_tracker.overflowed_ticks = 0;
}
} }
safe_mode_t port_init(void) { safe_mode_t port_init(void) {
@ -131,6 +149,21 @@ safe_mode_t port_init(void) {
analogin_init(); analogin_init();
#endif #endif
// If the board was reset by the WatchDogTimer, we may
// need to boot into safe mode. Reset the RESETREAS bit
// for the WatchDogTimer so we don't encounter this the
// next time we reboot.
if (NRF_POWER->RESETREAS & POWER_RESETREAS_DOG_Msk) {
NRF_POWER->RESETREAS = POWER_RESETREAS_DOG_Msk;
uint32_t usb_reg = NRF_POWER->USBREGSTATUS;
// If USB is connected, then the user might be editing `code.py`,
// in which case we should reboot into Safe Mode.
if (usb_reg & POWER_USBREGSTATUS_VBUSDETECT_Msk) {
return WATCHDOG_RESET;
}
}
return NO_SAFE_MODE; return NO_SAFE_MODE;
} }
@ -174,6 +207,10 @@ void reset_port(void) {
bleio_reset(); bleio_reset();
#endif #endif
#if CIRCUITPY_WATCHDOG
watchdog_reset();
#endif
reset_all_pins(); reset_all_pins();
} }
@ -185,6 +222,10 @@ void reset_to_bootloader(void) {
} }
void reset_cpu(void) { void reset_cpu(void) {
// We're getting ready to reset, so save the counter off.
// This counter will get reset to zero during the reboot.
uint32_t ticks = nrfx_rtc_counter_get(&rtc_instance);
overflow_tracker.overflowed_ticks += ticks / 32;
NVIC_SystemReset(); NVIC_SystemReset();
} }
@ -228,7 +269,7 @@ uint64_t port_get_raw_ticks(uint8_t* subticks) {
if (subticks != NULL) { if (subticks != NULL) {
*subticks = (rtc % 32); *subticks = (rtc % 32);
} }
return overflowed_ticks + rtc / 32; return overflow_tracker.overflowed_ticks + rtc / 32;
} }
// Enable 1/1024 second tick. // Enable 1/1024 second tick.

View File

@ -240,6 +240,9 @@ endif
ifeq ($(CIRCUITPY_USTACK),1) ifeq ($(CIRCUITPY_USTACK),1)
SRC_PATTERNS += ustack/% SRC_PATTERNS += ustack/%
endif endif
ifeq ($(CIRCUITPY_WATCHDOG),1)
SRC_PATTERNS += watchdog/%
endif
ifeq ($(CIRCUITPY_PEW),1) ifeq ($(CIRCUITPY_PEW),1)
SRC_PATTERNS += _pew/% SRC_PATTERNS += _pew/%
endif endif
@ -300,7 +303,10 @@ SRC_COMMON_HAL_ALL = \
rtc/RTC.c \ rtc/RTC.c \
rtc/__init__.c \ rtc/__init__.c \
supervisor/Runtime.c \ supervisor/Runtime.c \
supervisor/__init__.c supervisor/__init__.c \
watchdog/__init__.c \
watchdog/WatchDogMode.c \
watchdog/WatchDogTimer.c \
SRC_COMMON_HAL = $(filter $(SRC_PATTERNS), $(SRC_COMMON_HAL_ALL)) SRC_COMMON_HAL = $(filter $(SRC_PATTERNS), $(SRC_COMMON_HAL_ALL))

View File

@ -632,6 +632,14 @@ extern const struct _mp_obj_module_t ustack_module;
#define RE_MODULE #define RE_MODULE
#endif #endif
// This is not a top-level module; it's microcontroller.watchdog.
#if CIRCUITPY_WATCHDOG
extern const struct _mp_obj_module_t watchdog_module;
#define WATCHDOG_MODULE { MP_ROM_QSTR(MP_QSTR_watchdog), MP_ROM_PTR(&watchdog_module) },
#else
#define WATCHDOG_MODULE
#endif
// Define certain native modules with weak links so they can be replaced with Python // Define certain native modules with weak links so they can be replaced with Python
// implementations. This list may grow over time. // implementations. This list may grow over time.
#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \ #define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \
@ -702,6 +710,7 @@ extern const struct _mp_obj_module_t ustack_module;
USB_HID_MODULE \ USB_HID_MODULE \
USB_MIDI_MODULE \ USB_MIDI_MODULE \
USTACK_MODULE \ USTACK_MODULE \
WATCHDOG_MODULE \
// If weak links are enabled, just include strong links in the main list of modules, // If weak links are enabled, just include strong links in the main list of modules,
// and also include the underscore alternate names. // and also include the underscore alternate names.

View File

@ -228,6 +228,10 @@ CFLAGS += -DCIRCUITPY_SERIAL_UART=$(CIRCUITPY_SERIAL_UART)
CIRCUITPY_ULAB ?= $(CIRCUITPY_FULL_BUILD) CIRCUITPY_ULAB ?= $(CIRCUITPY_FULL_BUILD)
CFLAGS += -DCIRCUITPY_ULAB=$(CIRCUITPY_ULAB) CFLAGS += -DCIRCUITPY_ULAB=$(CIRCUITPY_ULAB)
# watchdog hardware support
CIRCUITPY_WATCHDOG ?= 0
CFLAGS += -DCIRCUITPY_WATCHDOG=$(CIRCUITPY_WATCHDOG)
# Enabled micropython.native decorator (experimental) # Enabled micropython.native decorator (experimental)
CIRCUITPY_ENABLE_MPY_NATIVE ?= 0 CIRCUITPY_ENABLE_MPY_NATIVE ?= 0
CFLAGS += -DCIRCUITPY_ENABLE_MPY_NATIVE=$(CIRCUITPY_ENABLE_MPY_NATIVE) CFLAGS += -DCIRCUITPY_ENABLE_MPY_NATIVE=$(CIRCUITPY_ENABLE_MPY_NATIVE)

View File

@ -167,6 +167,11 @@ STATIC const mp_rom_map_elem_t mcu_module_globals_table[] = {
#else #else
{ MP_ROM_QSTR(MP_QSTR_nvm), MP_ROM_PTR(&mp_const_none_obj) }, { MP_ROM_QSTR(MP_QSTR_nvm), MP_ROM_PTR(&mp_const_none_obj) },
#endif #endif
#if CIRCUITPY_WATCHDOG
{ MP_ROM_QSTR(MP_QSTR_watchdog), MP_ROM_PTR(&common_hal_mcu_watchdogtimer_obj) },
#else
{ MP_ROM_QSTR(MP_QSTR_watchdog), MP_ROM_PTR(&mp_const_none_obj) },
#endif
{ MP_ROM_QSTR(MP_QSTR_RunMode), MP_ROM_PTR(&mcu_runmode_type) }, { MP_ROM_QSTR(MP_QSTR_RunMode), MP_ROM_PTR(&mcu_runmode_type) },
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&mcu_pin_type) }, { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&mcu_pin_type) },
{ MP_ROM_QSTR(MP_QSTR_pin), MP_ROM_PTR(&mcu_pin_module) }, { MP_ROM_QSTR(MP_QSTR_pin), MP_ROM_PTR(&mcu_pin_module) },

View File

@ -49,10 +49,13 @@ extern const mcu_processor_obj_t common_hal_mcu_processor_obj;
#if CIRCUITPY_INTERNAL_NVM_SIZE > 0 #if CIRCUITPY_INTERNAL_NVM_SIZE > 0
#include "common-hal/nvm/ByteArray.h" #include "common-hal/nvm/ByteArray.h"
extern const nvm_bytearray_obj_t common_hal_mcu_nvm_obj; extern const nvm_bytearray_obj_t common_hal_mcu_nvm_obj;
#endif
#if CIRCUITPY_WATCHDOG
#include "common-hal/watchdog/WatchDogTimer.h"
extern watchdog_watchdogtimer_obj_t common_hal_mcu_watchdogtimer_obj;
#endif #endif
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER___INIT___H #endif // MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER___INIT___H

View File

@ -0,0 +1,99 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Sean Cross 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 "shared-bindings/watchdog/WatchDogMode.h"
//| class WatchDogMode:
//| """run state of the watchdog timer"""
//|
//| def __init__(self, ):
//| """Enum-like class to define the run mode of the watchdog timer."""
//|
//| RAISE: Any = ...
//| """Raise an exception when the WatchDogTimer expires.
//|
//| :type watchdog.WatchDogMode:"""
//|
//| RESET: Any = ...
//| """Reset the system if the WatchDogTimer expires.
//|
//| :type watchdog.WatchDogMode:"""
//|
const mp_obj_type_t watchdog_watchdogmode_type;
const watchdog_watchdogmode_obj_t watchdog_watchdogmode_raise_obj = {
{ &watchdog_watchdogmode_type },
};
const watchdog_watchdogmode_obj_t watchdog_watchdogmode_reset_obj = {
{ &watchdog_watchdogmode_type },
};
watchdog_watchdogmode_t watchdog_watchdogmode_obj_to_type(mp_obj_t obj) {
if (obj == MP_ROM_PTR(&watchdog_watchdogmode_raise_obj)) {
return WATCHDOGMODE_RAISE;
} else if (obj == MP_ROM_PTR(&watchdog_watchdogmode_reset_obj)) {
return WATCHDOGMODE_RESET;
}
return WATCHDOGMODE_NONE;
}
mp_obj_t watchdog_watchdogmode_type_to_obj(watchdog_watchdogmode_t mode) {
switch (mode) {
case WATCHDOGMODE_RAISE:
return (mp_obj_t)MP_ROM_PTR(&watchdog_watchdogmode_raise_obj);
case WATCHDOGMODE_RESET:
return (mp_obj_t)MP_ROM_PTR(&watchdog_watchdogmode_reset_obj);
case WATCHDOGMODE_NONE:
default:
return (mp_obj_t)MP_ROM_PTR(&mp_const_none_obj);
}
}
STATIC const mp_rom_map_elem_t watchdog_watchdogmode_locals_dict_table[] = {
{MP_ROM_QSTR(MP_QSTR_RAISE), MP_ROM_PTR(&watchdog_watchdogmode_raise_obj)},
{MP_ROM_QSTR(MP_QSTR_RESET), MP_ROM_PTR(&watchdog_watchdogmode_reset_obj)},
};
STATIC MP_DEFINE_CONST_DICT(watchdog_watchdogmode_locals_dict, watchdog_watchdogmode_locals_dict_table);
STATIC void watchdog_watchdogmode_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
qstr runmode = MP_QSTR_None;
if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&watchdog_watchdogmode_raise_obj)) {
runmode = MP_QSTR_RAISE;
}
else if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&watchdog_watchdogmode_reset_obj)) {
runmode = MP_QSTR_RESET;
}
mp_printf(print, "%q.%q.%q", MP_QSTR_watchdog, MP_QSTR_WatchDogMode,
runmode);
}
const mp_obj_type_t watchdog_watchdogmode_type = {
{ &mp_type_type },
.name = MP_QSTR_WatchDogMode,
.print = watchdog_watchdogmode_print,
.locals_dict = (mp_obj_t)&watchdog_watchdogmode_locals_dict,
};

View File

@ -0,0 +1,49 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Sean Cross 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.
*/
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_WATCHDOG_WATCHDOGMODE_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_WATCHDOG_WATCHDOGMODE_H
#include "py/obj.h"
typedef enum {
WATCHDOGMODE_NONE,
WATCHDOGMODE_RAISE,
WATCHDOGMODE_RESET,
} watchdog_watchdogmode_t;
const mp_obj_type_t watchdog_watchdogmode_type;
watchdog_watchdogmode_t watchdog_watchdogmode_obj_to_type(mp_obj_t obj);
mp_obj_t watchdog_watchdogmode_type_to_obj(watchdog_watchdogmode_t mode);
typedef struct {
mp_obj_base_t base;
} watchdog_watchdogmode_obj_t;
extern const watchdog_watchdogmode_obj_t watchdog_watchdogmode_raise_obj;
extern const watchdog_watchdogmode_obj_t watchdog_watchdogmode_reset_obj;
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_WATCHDOG_WATCHDOGMODE_H

View File

@ -0,0 +1,186 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Nick Moore 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 <math.h>
#include <string.h>
#include "py/obj.h"
#include "py/objproperty.h"
#include "py/runtime.h"
#include "common-hal/watchdog/WatchDogTimer.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/watchdog/__init__.h"
#include "shared-bindings/watchdog/WatchDogTimer.h"
#include "supervisor/port.h"
//| class WatchDogTimer:
//| """Timer that is used to detect code lock ups and automatically reset the microcontroller
//| when one is detected.
//|
//| A lock up is detected when the watchdog hasn't been fed after a given duration. So, make
//| sure to call `feed` within the timeout.
//| """
//|
//| def __init__(self, ):
//| """Not currently dynamically supported. Access the sole instance through `microcontroller.watchdog`."""
//| ...
//|
//| def feed(self):
//| """Feed the watchdog timer. This must be called regularly, otherwise
//| the timer will expire."""
//| ...
//|
STATIC mp_obj_t watchdog_watchdogtimer_feed(mp_obj_t self_in) {
watchdog_watchdogtimer_obj_t *self = MP_OBJ_TO_PTR(self_in);
watchdog_watchdogmode_t current_mode = common_hal_watchdog_get_mode(self);
if (current_mode == WATCHDOGMODE_NONE) {
mp_raise_ValueError(translate("WatchDogTimer is not currently running"));
}
common_hal_watchdog_feed(self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(watchdog_watchdogtimer_feed_obj, watchdog_watchdogtimer_feed);
//| def deinit(self):
//| """Stop the watchdog timer. This may raise an error if the watchdog
//| timer cannot be disabled on this platform."""
//| ...
//|
STATIC mp_obj_t watchdog_watchdogtimer_deinit(mp_obj_t self_in) {
watchdog_watchdogtimer_obj_t *self = MP_OBJ_TO_PTR(self_in);
watchdog_watchdogmode_t current_mode = common_hal_watchdog_get_mode(self);
if (current_mode == WATCHDOGMODE_RESET) {
mp_raise_NotImplementedError(translate("WatchDogTimer cannot be deinitialized once mode is set to RESET"));
}
common_hal_watchdog_deinit(self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(watchdog_watchdogtimer_deinit_obj, watchdog_watchdogtimer_deinit);
//| timeout: float = ...
//| """The maximum number of seconds that can elapse between calls
//| to feed()"""
//|
STATIC mp_obj_t watchdog_watchdogtimer_obj_get_timeout(mp_obj_t self_in) {
watchdog_watchdogtimer_obj_t *self = MP_OBJ_TO_PTR(self_in);
return mp_obj_new_float(common_hal_watchdog_get_timeout(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(watchdog_watchdogtimer_get_timeout_obj, watchdog_watchdogtimer_obj_get_timeout);
STATIC mp_obj_t watchdog_watchdogtimer_obj_set_timeout(mp_obj_t self_in, mp_obj_t timeout_obj) {
watchdog_watchdogtimer_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_float_t timeout = mp_obj_get_float(timeout_obj);
if (timeout <= 0) {
mp_raise_ValueError(translate("watchdog timeout must be greater than 0"));
}
common_hal_watchdog_set_timeout(self, timeout);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(watchdog_watchdogtimer_set_timeout_obj, watchdog_watchdogtimer_obj_set_timeout);
const mp_obj_property_t watchdog_watchdogtimer_timeout_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&watchdog_watchdogtimer_get_timeout_obj,
(mp_obj_t)&watchdog_watchdogtimer_set_timeout_obj,
(mp_obj_t)&mp_const_none_obj},
};
//| mode: watchdog.WatchDogMode = ...
//| """The current operating mode of the WatchDogTimer `watchdog.WatchDogMode`.
//|
//| Setting a WatchDogMode activates the WatchDog::
//|
//| import microcontroller
//| import watchdog
//|
//| w = microcontroller.watchdog
//| w.timeout = 5
//| w.mode = watchdog.WatchDogMode.RAISE
//|
//|
//| Once set, the WatchDogTimer will perform the specified action if the timer expires."""
//|
STATIC mp_obj_t watchdog_watchdogtimer_obj_get_mode(mp_obj_t self_in) {
watchdog_watchdogtimer_obj_t *self = MP_OBJ_TO_PTR(self_in);
return watchdog_watchdogmode_type_to_obj(common_hal_watchdog_get_mode(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(watchdog_watchdogtimer_get_mode_obj, watchdog_watchdogtimer_obj_get_mode);
STATIC mp_obj_t watchdog_watchdogtimer_obj_set_mode(mp_obj_t self_in, mp_obj_t mode_obj) {
watchdog_watchdogtimer_obj_t *self = MP_OBJ_TO_PTR(self_in);
watchdog_watchdogmode_t current_mode = common_hal_watchdog_get_mode(self);
watchdog_watchdogmode_t new_mode = watchdog_watchdogmode_obj_to_type(mode_obj);
mp_float_t current_timeout = common_hal_watchdog_get_timeout(self);
// When setting the mode, the timeout value must be greater than zero
if (new_mode == WATCHDOGMODE_RESET || new_mode == WATCHDOGMODE_RAISE) {
if (current_timeout <= 0) {
mp_raise_ValueError(translate("WatchDogTimer.timeout must be greater than 0"));
}
}
// Don't allow changing the mode once the watchdog timer has been started
if (current_mode == WATCHDOGMODE_RESET && new_mode != WATCHDOGMODE_RESET) {
mp_raise_TypeError(translate("WatchDogTimer.mode cannot be changed once set to WatchDogMode.RESET"));
}
common_hal_watchdog_set_mode(self, new_mode);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(watchdog_watchdogtimer_set_mode_obj, watchdog_watchdogtimer_obj_set_mode);
const mp_obj_property_t watchdog_watchdogtimer_mode_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&watchdog_watchdogtimer_get_mode_obj,
(mp_obj_t)&watchdog_watchdogtimer_set_mode_obj,
(mp_obj_t)&mp_const_none_obj},
};
STATIC const mp_rom_map_elem_t watchdog_watchdogtimer_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_feed), MP_ROM_PTR(&watchdog_watchdogtimer_feed_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&watchdog_watchdogtimer_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_timeout), MP_ROM_PTR(&watchdog_watchdogtimer_timeout_obj) },
{ MP_ROM_QSTR(MP_QSTR_mode), MP_ROM_PTR(&watchdog_watchdogtimer_mode_obj) },
};
STATIC MP_DEFINE_CONST_DICT(watchdog_watchdogtimer_locals_dict, watchdog_watchdogtimer_locals_dict_table);
const mp_obj_type_t watchdog_watchdogtimer_type = {
{ &mp_type_type },
.name = MP_QSTR_WatchDogTimer,
// .make_new = watchdog_watchdogtimer_make_new,
.locals_dict = (mp_obj_dict_t*)&watchdog_watchdogtimer_locals_dict,
};

View File

@ -0,0 +1,48 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Noralf Trønnes
*
* 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_SHARED_BINDINGS_WATCHDOG_WATCHDOGTIMER_H
#define MICROPY_INCLUDED_SHARED_BINDINGS_WATCHDOG_WATCHDOGTIMER_H
#include <py/obj.h>
#include "shared-bindings/watchdog/WatchDogMode.h"
typedef struct _watchdog_watchdogtimer_obj_t watchdog_watchdogtimer_obj_t;
extern void common_hal_watchdog_feed(watchdog_watchdogtimer_obj_t *self);
extern void common_hal_watchdog_set_mode(watchdog_watchdogtimer_obj_t *self, watchdog_watchdogmode_t);
extern watchdog_watchdogmode_t common_hal_watchdog_get_mode(watchdog_watchdogtimer_obj_t *self);
extern void common_hal_watchdog_set_timeout(watchdog_watchdogtimer_obj_t *self, mp_float_t timeout);
extern mp_float_t common_hal_watchdog_get_timeout(watchdog_watchdogtimer_obj_t *self);
extern void common_hal_watchdog_enable(watchdog_watchdogtimer_obj_t *self);
extern void common_hal_watchdog_deinit(watchdog_watchdogtimer_obj_t *self);
extern const mp_obj_type_t watchdog_watchdogtimer_type;
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_WATCHDOG_WATCHDOGTIMER_H

View File

@ -0,0 +1,81 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Paul Sokolovsky
*
* 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 <string.h>
#include "py/runtime.h"
#include "shared-bindings/watchdog/__init__.h"
#include "shared-bindings/watchdog/WatchDogMode.h"
//| """Watchdog Timer
//|
//| The `watchdog` module provides support for a Watchdog Timer. This timer will reset the device
//| if it hasn't been fed after a specified amount of time. This is useful to ensure the board
//| has not crashed or locked up. Note that on some platforms the watchdog timer cannot be disabled
//| once it has been enabled.
//|
//| The `WatchDogTimer` is used to restart the system when the application crashes and ends
//| up into a non recoverable state. Once started it cannot be stopped or
//| reconfigured in any way. After enabling, the application must "feed" the
//| watchdog periodically to prevent it from expiring and resetting the system.
//|
//| Example usage::
//|
//| from microcontroller import watchdog as w
//| from watchdog import WatchDogMode
//| w.timeout=2.5 # Set a timeout of 2.5 seconds
//| w.mode = WatchDogMode.RAISE
//| w.feed()"""
//|
const mp_obj_type_t mp_type_WatchDogTimeout = {
{ &mp_type_type },
.name = MP_QSTR_WatchDogTimeout,
.make_new = mp_obj_exception_make_new,
.attr = mp_obj_exception_attr,
.parent = &mp_type_Exception,
};
mp_obj_exception_t mp_watchdog_timeout_exception = {
.base.type = &mp_type_WatchDogTimeout,
.traceback_alloc = 0,
.traceback_len = 0,
.traceback_data = NULL,
.args = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj,
};
STATIC const mp_rom_map_elem_t watchdog_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_watchdog) },
{ MP_ROM_QSTR(MP_QSTR_WatchDogMode), MP_ROM_PTR(&watchdog_watchdogmode_type) },
{ MP_ROM_QSTR(MP_QSTR_WatchDogTimeout), MP_ROM_PTR(&mp_type_WatchDogTimeout) },
};
STATIC MP_DEFINE_CONST_DICT(watchdog_module_globals, watchdog_module_globals_table);
const mp_obj_module_t watchdog_module = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&watchdog_module_globals,
};

View File

@ -0,0 +1,34 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Scott Shawcroft 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.
*/
#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_WATCHDOG___INIT___H
#define MICROPY_INCLUDED_SHARED_BINDINGS_WATCHDOG___INIT___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;
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_WATCHDOG___INIT___H

View File

@ -160,6 +160,9 @@ void print_safe_mode_message(safe_mode_t reason) {
case MEM_MANAGE: case MEM_MANAGE:
serial_write_compressed(translate("Invalid memory access.")); serial_write_compressed(translate("Invalid memory access."));
break; break;
case WATCHDOG_RESET:
serial_write_compressed(translate("Watchdog timer expired."));
break;
default: default:
serial_write_compressed(translate("Unknown reason.")); serial_write_compressed(translate("Unknown reason."));
break; break;

View File

@ -41,6 +41,7 @@ typedef enum {
NORDIC_SOFT_DEVICE_ASSERT, NORDIC_SOFT_DEVICE_ASSERT,
FLASH_WRITE_FAIL, FLASH_WRITE_FAIL,
MEM_MANAGE, MEM_MANAGE,
WATCHDOG_RESET,
} safe_mode_t; } safe_mode_t;
safe_mode_t wait_for_safe_mode_reset(void); safe_mode_t wait_for_safe_mode_reset(void);

View File

@ -44,6 +44,13 @@ static volatile uint64_t PLACE_IN_DTCM_BSS(background_ticks);
#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/__init__.h"
#if CIRCUITPY_WATCHDOG
#include "shared-bindings/watchdog/__init__.h"
#define WATCHDOG_EXCEPTION_CHECK() (MP_STATE_VM(mp_pending_exception) == &mp_watchdog_timeout_exception)
#else
#define WATCHDOG_EXCEPTION_CHECK() 0
#endif
void supervisor_tick(void) { void supervisor_tick(void) {
#if CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS > 0 #if CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS > 0
filesystem_tick(); filesystem_tick();
@ -96,7 +103,8 @@ void mp_hal_delay_ms(mp_uint_t delay) {
RUN_BACKGROUND_TASKS; RUN_BACKGROUND_TASKS;
// Check to see if we've been CTRL-Ced by autoreload or the user. // Check to see if we've been CTRL-Ced by autoreload or the user.
if(MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)) || if(MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)) ||
MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) { MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception)) ||
WATCHDOG_EXCEPTION_CHECK()) {
break; break;
} }
remaining = end_tick - port_get_raw_ticks(NULL); remaining = end_tick - port_get_raw_ticks(NULL);