Merge pull request #2933 from simmel-project/wdt-nrf
Add Watchdog timer and add support for NRF watchdog
This commit is contained in:
commit
db04fd1725
@ -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 ""
|
||||||
|
@ -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
|
||||||
|
@ -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/ :
|
||||||
|
@ -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)'
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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) },
|
||||||
|
0
ports/nrf/common-hal/watchdog/WatchDogMode.c
Normal file
0
ports/nrf/common-hal/watchdog/WatchDogMode.c
Normal file
189
ports/nrf/common-hal/watchdog/WatchDogTimer.c
Normal file
189
ports/nrf/common-hal/watchdog/WatchDogTimer.c
Normal 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;
|
||||||
|
}
|
44
ports/nrf/common-hal/watchdog/WatchDogTimer.h
Normal file
44
ports/nrf/common-hal/watchdog/WatchDogTimer.h
Normal 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
|
25
ports/nrf/common-hal/watchdog/__init__.c
Normal file
25
ports/nrf/common-hal/watchdog/__init__.c
Normal 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.
|
||||||
|
*/
|
30
ports/nrf/common-hal/watchdog/__init__.h
Normal file
30
ports/nrf/common-hal/watchdog/__init__.h
Normal 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
|
@ -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
|
||||||
|
|
||||||
|
@ -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__
|
||||||
|
@ -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()
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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))
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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)
|
||||||
|
@ -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) },
|
||||||
|
@ -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
|
||||||
|
99
shared-bindings/watchdog/WatchDogMode.c
Normal file
99
shared-bindings/watchdog/WatchDogMode.c
Normal 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,
|
||||||
|
};
|
49
shared-bindings/watchdog/WatchDogMode.h
Normal file
49
shared-bindings/watchdog/WatchDogMode.h
Normal 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
|
186
shared-bindings/watchdog/WatchDogTimer.c
Normal file
186
shared-bindings/watchdog/WatchDogTimer.c
Normal 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,
|
||||||
|
};
|
48
shared-bindings/watchdog/WatchDogTimer.h
Normal file
48
shared-bindings/watchdog/WatchDogTimer.h
Normal 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
|
81
shared-bindings/watchdog/__init__.c
Normal file
81
shared-bindings/watchdog/__init__.c
Normal 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,
|
||||||
|
};
|
34
shared-bindings/watchdog/__init__.h
Normal file
34
shared-bindings/watchdog/__init__.h
Normal 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
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user