3737#include "shared-bindings/watchdog/__init__.h"
3838#include "shared-bindings/watchdog/WatchDogTimer.h"
3939
40+ #include "supervisor/port.h"
41+
42+ #include "nrf/timers.h"
4043#include "nrf_wdt.h"
44+ #include "nrfx_wdt.h"
4145#include "nrfx_timer.h"
42- #include "nrf/timers.h"
4346
4447STATIC uint8_t timer_refcount = 0 ;
45- #define WATCHDOG_RELOAD_COUNT 2
4648STATIC nrfx_timer_t * timer = NULL ;
47-
48- STATIC void watchdogtimer_hardware_init (mp_float_t duration , bool pause_during_sleep ) {
49- unsigned int channel ;
50- nrf_wdt_behaviour_t behaviour = NRF_WDT_BEHAVIOUR_RUN_SLEEP_HALT ;
51- if (pause_during_sleep ) {
52- behaviour = NRF_WDT_BEHAVIOUR_PAUSE_SLEEP_HALT ;
53- }
54-
55- nrf_wdt_behaviour_set (NRF_WDT , behaviour );
56-
57- uint64_t ticks = duration * 32768ULL ;
58- if (ticks > UINT32_MAX ) {
59- mp_raise_ValueError (translate ("timeout duration exceeded the maximum supported value" ));
60- }
61- nrf_wdt_reload_value_set (NRF_WDT , (uint32_t ) ticks );
62-
63- for (channel = 0 ; channel < WATCHDOG_RELOAD_COUNT ; channel ++ ) {
64- nrf_wdt_reload_request_enable (NRF_WDT , channel );
65- }
66-
67- nrf_wdt_task_trigger (NRF_WDT , NRF_WDT_TASK_START );
68- }
69-
70- STATIC void watchdogtimer_hardware_feed (void ) {
71- unsigned int channel ;
72- for (channel = 0 ; channel < WATCHDOG_RELOAD_COUNT ; channel ++ ) {
73- nrf_wdt_reload_request_set (NRF_WDT , (nrf_wdt_rr_register_t )(NRF_WDT_RR0 + channel ));
74- }
75- }
49+ STATIC nrfx_wdt_t wdt = NRFX_WDT_INSTANCE (0 );
50+ STATIC nrfx_wdt_channel_id wdt_channel_id ;
7651
7752NORETURN void mp_raise_WatchDogTimeout (void ) {
7853 nlr_raise (MP_OBJ_FROM_PTR (& MP_STATE_VM (mp_watchdog_exception )));
@@ -95,6 +70,12 @@ STATIC void watchdogtimer_timer_event_handler(nrf_timer_event_t event_type, void
9570#endif
9671}
9772
73+ // This function is called if the timer expires. The system will reboot in 1/16384 of a second.
74+ // Issue a reboot ourselves so we can do any cleanup necessary.
75+ STATIC void watchdogtimer_watchdog_event_handler (void ) {
76+ reset_cpu ();
77+ }
78+
9879void watchdog_watchdogtimer_reset (void ) {
9980 if (timer != NULL ) {
10081 nrf_peripherals_free_timer (timer );
@@ -112,7 +93,7 @@ STATIC mp_obj_t watchdog_watchdogtimer_feed(mp_obj_t self_in) {
11293 watchdog_watchdogtimer_obj_t * self = MP_OBJ_TO_PTR (self_in );
11394
11495 if (self -> mode == WATCHDOGMODE_RESET ) {
115- watchdogtimer_hardware_feed ( );
96+ nrfx_wdt_feed ( & wdt );
11697 } else if (self -> mode == WATCHDOGMODE_RAISE ) {
11798 nrfx_timer_clear (timer );
11899 } else if (self -> mode == WATCHDOGMODE_NONE ) {
@@ -276,7 +257,29 @@ STATIC mp_obj_t watchdog_watchdogtimer_obj_set_mode(mp_obj_t self_in, mp_obj_t m
276257 timer = NULL ;
277258 }
278259 }
279- watchdogtimer_hardware_init (self -> timeout , self -> sleep );
260+
261+ uint64_t ticks = self -> timeout * 1000.0f ;
262+ if (ticks > UINT32_MAX ) {
263+ mp_raise_ValueError (translate ("timeout duration exceeded the maximum supported value" ));
264+ }
265+
266+ nrfx_wdt_config_t config = {
267+ .reload_value = ticks , // in units of ms
268+ .behaviour = NRF_WDT_BEHAVIOUR_RUN_SLEEP ,
269+ NRFX_WDT_IRQ_CONFIG
270+ };
271+
272+ nrfx_err_t err_code ;
273+ err_code = nrfx_wdt_init (& wdt , & config , watchdogtimer_watchdog_event_handler );
274+ if (err_code != NRFX_SUCCESS ) {
275+ mp_raise_OSError (1 );
276+ }
277+ err_code = nrfx_wdt_channel_alloc (& wdt , & wdt_channel_id );
278+ if (err_code != NRFX_SUCCESS ) {
279+ mp_raise_OSError (1 );
280+ }
281+ nrfx_wdt_enable (& wdt );
282+ nrfx_wdt_feed (& wdt );
280283 self -> mode = WATCHDOGMODE_RESET ;
281284 }
282285
0 commit comments