41
41
#include "nrfx_timer.h"
42
42
#include "nrf/timers.h"
43
43
44
- STATIC watchdog_watchdogtimer_obj_t * wdt_singleton ;
45
- STATIC mp_obj_t watchdog_watchdogtimer_feed (mp_obj_t self_in );
46
44
STATIC uint8_t timer_refcount = 0 ;
47
45
#define WATCHDOG_RELOAD_COUNT 2
48
46
STATIC nrfx_timer_t * timer = NULL ;
@@ -80,7 +78,7 @@ NORETURN void mp_raise_WatchDogTimeout(void) {
80
78
nlr_raise (MP_OBJ_FROM_PTR (& MP_STATE_VM (mp_watchdog_exception )));
81
79
}
82
80
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 ) {
84
82
(void )p_context ;
85
83
if (event_type != NRF_TIMER_EVENT_COMPARE0 ) {
86
84
// Spurious event.
@@ -105,107 +103,20 @@ void watchdog_watchdogtimer_reset(void) {
105
103
timer_refcount = 0 ;
106
104
}
107
105
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
-
197
106
//| def feed(self):
198
107
//| """Feed the watchdog timer. This must be called regularly, otherwise
199
- //| the system will reset ."""
108
+ //| the timer will expire ."""
200
109
//| ...
201
110
//|
202
111
STATIC mp_obj_t watchdog_watchdogtimer_feed (mp_obj_t self_in ) {
203
112
watchdog_watchdogtimer_obj_t * self = MP_OBJ_TO_PTR (self_in );
204
113
205
- if (self -> hardware ) {
114
+ if (self -> mode == WATCHDOGMODE_RESET ) {
206
115
watchdogtimer_hardware_feed ();
207
- } else {
116
+ } else if ( self -> mode == WATCHDOGMODE_RAISE ) {
208
117
nrfx_timer_clear (timer );
118
+ } else if (self -> mode == WATCHDOGMODE_NONE ) {
119
+ mp_raise_ValueError (translate ("WatchDogTimer is not currently running" ));
209
120
}
210
121
return mp_const_none ;
211
122
}
@@ -219,71 +130,178 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(watchdog_watchdogtimer_feed_obj, watchdog_watch
219
130
STATIC mp_obj_t watchdog_watchdogtimer_deinit (mp_obj_t self_in ) {
220
131
watchdog_watchdogtimer_obj_t * self = MP_OBJ_TO_PTR (self_in );
221
132
222
- if (! self -> hardware ) {
133
+ if (self -> mode == WATCHDOGMODE_RAISE ) {
223
134
timer_refcount -- ;
224
135
if (timer_refcount == 0 ) {
225
136
nrf_peripherals_free_timer (timer );
226
137
timer = NULL ;
227
138
}
139
+ } else if (self -> mode == WATCHDOGMODE_RESET ) {
140
+ mp_raise_NotImplementedError (translate ("WatchDogTimer cannot be deinitialized once mode is set to RESET" ));
228
141
}
229
142
230
143
return mp_const_none ;
231
144
}
232
145
STATIC MP_DEFINE_CONST_FUN_OBJ_1 (watchdog_watchdogtimer_deinit_obj , watchdog_watchdogtimer_deinit );
233
146
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
236
149
//| to feed()"""
237
150
//|
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 ) {
239
152
watchdog_watchdogtimer_obj_t * self = MP_OBJ_TO_PTR (self_in );
240
153
return mp_obj_new_float (self -> timeout );
241
154
}
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 );
243
184
244
185
const mp_obj_property_t watchdog_watchdogtimer_timeout_obj = {
245
186
.base .type = & mp_type_property ,
246
187
.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 ,
248
189
(mp_obj_t )& mp_const_none_obj },
249
190
};
250
191
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 ) {
252
208
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 );
256
213
}
257
- watchdog_watchdogtimer_feed (self_in );
258
- return self_in ;
259
214
}
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 );
268
265
}
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 ;
269
281
}
282
+
270
283
return mp_const_none ;
271
284
}
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
+ };
273
293
274
294
STATIC const mp_rom_map_elem_t watchdog_watchdogtimer_locals_dict_table [] = {
275
295
{ MP_ROM_QSTR (MP_QSTR_feed ), MP_ROM_PTR (& watchdog_watchdogtimer_feed_obj ) },
276
296
{ MP_ROM_QSTR (MP_QSTR_deinit ), MP_ROM_PTR (& watchdog_watchdogtimer_deinit_obj ) },
277
297
{ 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 ) },
281
299
};
282
300
STATIC MP_DEFINE_CONST_DICT (watchdog_watchdogtimer_locals_dict , watchdog_watchdogtimer_locals_dict_table );
283
301
284
302
const mp_obj_type_t watchdog_watchdogtimer_type = {
285
303
{ & mp_type_type },
286
304
.name = MP_QSTR_WatchDogTimer ,
287
- .make_new = watchdog_watchdogtimer_make_new ,
305
+ // .make_new = watchdog_watchdogtimer_make_new,
288
306
.locals_dict = (mp_obj_dict_t * )& watchdog_watchdogtimer_locals_dict ,
289
307
};
0 commit comments