4141#include "nrfx_timer.h"
4242#include "nrf/timers.h"
4343
44- STATIC watchdog_watchdogtimer_obj_t * wdt_singleton ;
45- STATIC mp_obj_t watchdog_watchdogtimer_feed (mp_obj_t self_in );
4644STATIC uint8_t timer_refcount = 0 ;
4745#define WATCHDOG_RELOAD_COUNT 2
4846STATIC nrfx_timer_t * timer = NULL ;
@@ -80,7 +78,7 @@ NORETURN void mp_raise_WatchDogTimeout(void) {
8078 nlr_raise (MP_OBJ_FROM_PTR (& MP_STATE_VM (mp_watchdog_exception )));
8179}
8280
83- STATIC void watchdogtimer_event_handler (nrf_timer_event_t event_type , void * p_context ) {
81+ STATIC void watchdogtimer_timer_event_handler (nrf_timer_event_t event_type , void * p_context ) {
8482 (void )p_context ;
8583 if (event_type != NRF_TIMER_EVENT_COMPARE0 ) {
8684 // Spurious event.
@@ -105,107 +103,20 @@ void watchdog_watchdogtimer_reset(void) {
105103 timer_refcount = 0 ;
106104}
107105
108- //| class WDT:
109- //| """Watchdog Timer"""
110- //|
111- //| def __init__(self, ):
112- //| """This class represents the system's Watchdog Timer. It is a
113- //| singleton and will always return the same instance.
114- //|
115- //| """
116- //| ...
117- //|
118- STATIC mp_obj_t watchdog_watchdogtimer_make_new (const mp_obj_type_t * type , size_t n_args ,
119- const mp_obj_t * pos_args ,
120- mp_map_t * kw_args ) {
121- enum { ARG_timeout , ARG_sleep , ARG_hardware };
122- static const mp_arg_t allowed_args [] = {
123- {MP_QSTR_timeout , MP_ARG_OBJ | MP_ARG_REQUIRED },
124- {MP_QSTR_sleep , MP_ARG_BOOL , {.u_bool = false}},
125- {MP_QSTR_hardware , MP_ARG_BOOL , {.u_bool = false}},
126- };
127- mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
128- mp_obj_exception_clear_traceback (MP_OBJ_FROM_PTR (& MP_STATE_VM (mp_watchdog_exception )));
129-
130- mp_arg_parse_all (n_args , pos_args , kw_args , MP_ARRAY_SIZE (allowed_args ),
131- allowed_args , args );
132- mp_float_t timeout = mp_obj_get_float (args [ARG_timeout ].u_obj );
133- bool hardware = args [ARG_hardware ].u_bool ;
134- bool sleep = args [ARG_sleep ].u_bool ;
135-
136- // If the hardware timer is already running, return that timer.
137- // If the parameters have changed, then ignore them, but print
138- // an error.
139- if (wdt_singleton && hardware ) {
140- if ((sleep != wdt_singleton -> sleep )
141- || (hardware != wdt_singleton -> hardware )
142- || fabsf (timeout - wdt_singleton -> timeout ) > 0.01f ) {
143- // Print a warning indicating things aren't quite right
144- // mp_printf(&mp_stderr_print, translate("warning: hardware timer was already running"));
145- }
146- watchdogtimer_hardware_feed ();
147- return wdt_singleton ;
148- }
149-
150- if (timeout <= 0 ) {
151- mp_raise_ValueError (translate ("watchdog timeout must be greater than 0" ));
152- }
153-
154- watchdog_watchdogtimer_obj_t * self = m_new_obj (watchdog_watchdogtimer_obj_t );
155- self -> base .type = & watchdog_watchdogtimer_type ;
156- self -> timeout = timeout ;
157- self -> sleep = sleep ;
158- self -> hardware = hardware ;
159-
160- if (hardware ) {
161- watchdogtimer_hardware_init (self -> timeout , self -> sleep );
162- wdt_singleton = self ;
163- } else {
164- uint64_t ticks = timeout * 31250ULL ;
165- if (ticks > UINT32_MAX ) {
166- mp_raise_ValueError (translate ("timeout duration exceeded the maximum supported value" ));
167- }
168-
169- if (timer_refcount == 0 ) {
170- timer = nrf_peripherals_allocate_timer_or_throw ();
171- }
172- timer_refcount ++ ;
173-
174- nrfx_timer_config_t timer_config = {
175- .frequency = NRF_TIMER_FREQ_31250Hz ,
176- .mode = NRF_TIMER_MODE_TIMER ,
177- .bit_width = NRF_TIMER_BIT_WIDTH_32 ,
178- .interrupt_priority = NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY ,
179- .p_context = self ,
180- };
181-
182- nrfx_timer_init (timer , & timer_config , & watchdogtimer_event_handler );
183-
184- // true enables interrupt.
185- nrfx_timer_clear (timer );
186- nrfx_timer_compare (timer , NRF_TIMER_CC_CHANNEL0 , ticks , true);
187- nrfx_timer_resume (timer );
188- }
189-
190- // Feed the watchdog, in case there's a timer that's already running
191- // and it's only partially finished.
192- mp_obj_t * self_obj = MP_OBJ_FROM_PTR (self );
193- watchdog_watchdogtimer_feed (self_obj );
194- return self_obj ;
195- }
196-
197106//| def feed(self):
198107//| """Feed the watchdog timer. This must be called regularly, otherwise
199- //| the system will reset ."""
108+ //| the timer will expire ."""
200109//| ...
201110//|
202111STATIC mp_obj_t watchdog_watchdogtimer_feed (mp_obj_t self_in ) {
203112 watchdog_watchdogtimer_obj_t * self = MP_OBJ_TO_PTR (self_in );
204113
205- if (self -> hardware ) {
114+ if (self -> mode == WATCHDOGMODE_RESET ) {
206115 watchdogtimer_hardware_feed ();
207- } else {
116+ } else if ( self -> mode == WATCHDOGMODE_RAISE ) {
208117 nrfx_timer_clear (timer );
118+ } else if (self -> mode == WATCHDOGMODE_NONE ) {
119+ mp_raise_ValueError (translate ("WatchDogTimer is not currently running" ));
209120 }
210121 return mp_const_none ;
211122}
@@ -219,71 +130,178 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(watchdog_watchdogtimer_feed_obj, watchdog_watch
219130STATIC mp_obj_t watchdog_watchdogtimer_deinit (mp_obj_t self_in ) {
220131 watchdog_watchdogtimer_obj_t * self = MP_OBJ_TO_PTR (self_in );
221132
222- if (! self -> hardware ) {
133+ if (self -> mode == WATCHDOGMODE_RAISE ) {
223134 timer_refcount -- ;
224135 if (timer_refcount == 0 ) {
225136 nrf_peripherals_free_timer (timer );
226137 timer = NULL ;
227138 }
139+ } else if (self -> mode == WATCHDOGMODE_RESET ) {
140+ mp_raise_NotImplementedError (translate ("WatchDogTimer cannot be deinitialized once mode is set to RESET" ));
228141 }
229142
230143 return mp_const_none ;
231144}
232145STATIC MP_DEFINE_CONST_FUN_OBJ_1 (watchdog_watchdogtimer_deinit_obj , watchdog_watchdogtimer_deinit );
233146
234- //| timeout: int = ...
235- //| """The maximum number of milliseconds that can elapse between calls
147+ //| timeout: float = ...
148+ //| """The maximum number of seconds that can elapse between calls
236149//| to feed()"""
237150//|
238- STATIC mp_obj_t watchdog_watchdogtimer_get_timeout (mp_obj_t self_in ) {
151+ STATIC mp_obj_t watchdog_watchdogtimer_obj_get_timeout (mp_obj_t self_in ) {
239152 watchdog_watchdogtimer_obj_t * self = MP_OBJ_TO_PTR (self_in );
240153 return mp_obj_new_float (self -> timeout );
241154}
242- MP_DEFINE_CONST_FUN_OBJ_1 (watchdog_watchdogtimer_get_timeout_obj , watchdog_watchdogtimer_get_timeout );
155+ MP_DEFINE_CONST_FUN_OBJ_1 (watchdog_watchdogtimer_get_timeout_obj , watchdog_watchdogtimer_obj_get_timeout );
156+
157+ STATIC mp_obj_t watchdog_watchdogtimer_obj_set_timeout (mp_obj_t self_in , mp_obj_t timeout_obj ) {
158+ watchdog_watchdogtimer_obj_t * self = MP_OBJ_TO_PTR (self_in );
159+ mp_float_t timeout = mp_obj_get_float (timeout_obj );
160+
161+ if (timeout <= 0 ) {
162+ mp_raise_ValueError (translate ("watchdog timeout must be greater than 0" ));
163+ }
164+
165+ if (self -> mode == WATCHDOGMODE_RESET ) {
166+ // If the WatchDogTimer is already running in "RESET" mode, raise an error
167+ // since the mode cannot be changed once started.
168+ mp_raise_TypeError (translate ("Cannot change the timeout once mode is WatchDogMode.RESET" ));
169+ } else if (self -> mode == WATCHDOGMODE_RAISE ) {
170+ // If the WatchDogTimer is already running in "RAISE" mode, reset the timer
171+ // with the new value.
172+ uint64_t ticks = timeout * 31250ULL ;
173+ if (ticks > UINT32_MAX ) {
174+ mp_raise_ValueError (translate ("timeout duration exceeded the maximum supported value" ));
175+ }
176+ nrfx_timer_clear (timer );
177+ nrfx_timer_compare (timer , NRF_TIMER_CC_CHANNEL0 , ticks , true);
178+ }
179+
180+ self -> timeout = timeout ;
181+ return mp_const_none ;
182+ }
183+ MP_DEFINE_CONST_FUN_OBJ_2 (watchdog_watchdogtimer_set_timeout_obj , watchdog_watchdogtimer_obj_set_timeout );
243184
244185const mp_obj_property_t watchdog_watchdogtimer_timeout_obj = {
245186 .base .type = & mp_type_property ,
246187 .proxy = {(mp_obj_t )& watchdog_watchdogtimer_get_timeout_obj ,
247- (mp_obj_t )& mp_const_none_obj ,
188+ (mp_obj_t )& watchdog_watchdogtimer_set_timeout_obj ,
248189 (mp_obj_t )& mp_const_none_obj },
249190};
250191
251- mp_obj_t watchdog_watchdogtimer___enter__ (mp_obj_t self_in ) {
192+ //| mode: watchdog.WatchDogMode = ...
193+ //| """The current operating mode of the WatchDogTimer `watchdog.WatchDogMode`.
194+ //|
195+ //| Setting a WatchDogMode activates the WatchDog::
196+ //|
197+ //| import microcontroller
198+ //| import watchdog
199+ //|
200+ //| w = microcontroller.watchdog
201+ //| w.timeout = 5
202+ //| w.mode = watchdog.WatchDogMode.RAISE
203+ //|
204+ //|
205+ //| Once set, the WatchDogTimer will perform the specified action if the timer expires.
206+ //|
207+ STATIC mp_obj_t watchdog_watchdogtimer_obj_get_mode (mp_obj_t self_in ) {
252208 watchdog_watchdogtimer_obj_t * self = MP_OBJ_TO_PTR (self_in );
253-
254- if (!self -> hardware ) {
255- nrfx_timer_resume (timer );
209+ switch (self -> mode ) {
210+ case WATCHDOGMODE_NONE : default : return (mp_obj_t )MP_ROM_PTR (& watchdog_watchdogmode_none_obj );
211+ case WATCHDOGMODE_RAISE : return (mp_obj_t )MP_ROM_PTR (& watchdog_watchdogmode_raise_obj );
212+ case WATCHDOGMODE_RESET : return (mp_obj_t )MP_ROM_PTR (& watchdog_watchdogmode_reset_obj );
256213 }
257- watchdog_watchdogtimer_feed (self_in );
258- return self_in ;
259214}
260- MP_DEFINE_CONST_FUN_OBJ_1 (watchdog_watchdogtimer___enter___obj , watchdog_watchdogtimer___enter__ );
261-
262- STATIC mp_obj_t watchdog_watchdogtimer___exit__ (size_t n_args , const mp_obj_t * args ) {
263- (void )n_args ;
264- watchdog_watchdogtimer_obj_t * self = MP_OBJ_TO_PTR (args [0 ]);
265- if (!self -> hardware ) {
266- if (timer ) {
267- nrfx_timer_pause (timer );
215+ MP_DEFINE_CONST_FUN_OBJ_1 (watchdog_watchdogtimer_get_mode_obj , watchdog_watchdogtimer_obj_get_mode );
216+
217+ STATIC mp_obj_t watchdog_watchdogtimer_obj_set_mode (mp_obj_t self_in , mp_obj_t mode_obj ) {
218+ watchdog_watchdogtimer_obj_t * self = MP_OBJ_TO_PTR (self_in );
219+ watchdog_watchdogmode_obj_t * mode = MP_OBJ_TO_PTR (mode_obj );
220+ if (mode == MP_ROM_PTR (& watchdog_watchdogmode_none_obj )) {
221+ if (self -> mode == WATCHDOGMODE_RESET ) {
222+ mp_raise_TypeError (translate ("WatchDogTimer mode cannot be changed once set to WatchDogMode.RESET" ));
223+ }
224+ else if (self -> mode == WATCHDOGMODE_RAISE ) {
225+ timer_refcount -- ;
226+ if (timer_refcount == 0 ) {
227+ nrf_peripherals_free_timer (timer );
228+ timer = NULL ;
229+ }
230+ }
231+ self -> mode = WATCHDOGMODE_NONE ;
232+
233+ } else if (mode == MP_ROM_PTR (& watchdog_watchdogmode_raise_obj )) {
234+ if (self -> timeout <= 0 ) {
235+ mp_raise_ValueError (translate ("watchdog timeout must be greater than 0" ));
236+ }
237+ if (self -> mode == WATCHDOGMODE_RESET ) {
238+ mp_raise_ValueError (translate ("WatchDogTimer mode cannot be changed once set to WatchDogMode.RESET" ));
239+ }
240+ else if (self -> mode == WATCHDOGMODE_NONE ) {
241+ uint64_t ticks = self -> timeout * 31250ULL ;
242+ if (ticks > UINT32_MAX ) {
243+ mp_raise_ValueError (translate ("timeout duration exceeded the maximum supported value" ));
244+ }
245+
246+ if (timer_refcount == 0 ) {
247+ timer = nrf_peripherals_allocate_timer_or_throw ();
248+ }
249+ timer_refcount ++ ;
250+
251+ nrfx_timer_config_t timer_config = {
252+ .frequency = NRF_TIMER_FREQ_31250Hz ,
253+ .mode = NRF_TIMER_MODE_TIMER ,
254+ .bit_width = NRF_TIMER_BIT_WIDTH_32 ,
255+ .interrupt_priority = NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY ,
256+ .p_context = self ,
257+ };
258+
259+ nrfx_timer_init (timer , & timer_config , & watchdogtimer_timer_event_handler );
260+
261+ // true enables interrupt.
262+ nrfx_timer_clear (timer );
263+ nrfx_timer_compare (timer , NRF_TIMER_CC_CHANNEL0 , ticks , true);
264+ nrfx_timer_resume (timer );
268265 }
266+ self -> mode = WATCHDOGMODE_RAISE ;
267+
268+ } else if (mode == MP_ROM_PTR (& watchdog_watchdogmode_reset_obj )) {
269+ if (self -> timeout <= 0 ) {
270+ mp_raise_ValueError (translate ("watchdog timeout must be greater than 0" ));
271+ }
272+ if (self -> mode == WATCHDOGMODE_RAISE ) {
273+ timer_refcount -- ;
274+ if (timer_refcount == 0 ) {
275+ nrf_peripherals_free_timer (timer );
276+ timer = NULL ;
277+ }
278+ }
279+ watchdogtimer_hardware_init (self -> timeout , self -> sleep );
280+ self -> mode = WATCHDOGMODE_RESET ;
269281 }
282+
270283 return mp_const_none ;
271284}
272- STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (watchdog_watchdogtimer___exit___obj , 4 , 4 , watchdog_watchdogtimer___exit__ );
285+ MP_DEFINE_CONST_FUN_OBJ_2 (watchdog_watchdogtimer_set_mode_obj , watchdog_watchdogtimer_obj_set_mode );
286+
287+ const mp_obj_property_t watchdog_watchdogtimer_mode_obj = {
288+ .base .type = & mp_type_property ,
289+ .proxy = {(mp_obj_t )& watchdog_watchdogtimer_get_mode_obj ,
290+ (mp_obj_t )& watchdog_watchdogtimer_set_mode_obj ,
291+ (mp_obj_t )& mp_const_none_obj },
292+ };
273293
274294STATIC const mp_rom_map_elem_t watchdog_watchdogtimer_locals_dict_table [] = {
275295 { MP_ROM_QSTR (MP_QSTR_feed ), MP_ROM_PTR (& watchdog_watchdogtimer_feed_obj ) },
276296 { MP_ROM_QSTR (MP_QSTR_deinit ), MP_ROM_PTR (& watchdog_watchdogtimer_deinit_obj ) },
277297 { MP_ROM_QSTR (MP_QSTR_timeout ), MP_ROM_PTR (& watchdog_watchdogtimer_timeout_obj ) },
278- // { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
279- { MP_ROM_QSTR (MP_QSTR___enter__ ), MP_ROM_PTR (& watchdog_watchdogtimer___enter___obj ) },
280- { MP_ROM_QSTR (MP_QSTR___exit__ ), MP_ROM_PTR (& watchdog_watchdogtimer___exit___obj ) },
298+ { MP_ROM_QSTR (MP_QSTR_mode ), MP_ROM_PTR (& watchdog_watchdogtimer_mode_obj ) },
281299};
282300STATIC MP_DEFINE_CONST_DICT (watchdog_watchdogtimer_locals_dict , watchdog_watchdogtimer_locals_dict_table );
283301
284302const mp_obj_type_t watchdog_watchdogtimer_type = {
285303 { & mp_type_type },
286304 .name = MP_QSTR_WatchDogTimer ,
287- .make_new = watchdog_watchdogtimer_make_new ,
305+ // .make_new = watchdog_watchdogtimer_make_new,
288306 .locals_dict = (mp_obj_dict_t * )& watchdog_watchdogtimer_locals_dict ,
289307};
0 commit comments