Skip to content

Commit f700460

Browse files
committed
nrf/machine/timer: Support soft IRQ timer callbacks.
machine.Timer() has inconsistent behaviour between ports: some run callbacks in hard IRQ context whereas others schedule them like soft IRQs. The rp2 Timer constructor now has a hard= argument to explicitly choose between these. Add support for this to the nrf port, setting the default to True to match the existing behaviour. The existing hard-IRQ path doesn't seem to call mp_sched_lock() or gc_lock() before using mp_call_function_1(callback, self) from IRQ context. This is probably incorrect unless I have missed something; if so, I will fix it too. Signed-off-by: Chris Webb <chris@arachsys.com>
1 parent 3a27e1f commit f700460

File tree

1 file changed

+9
-2
lines changed

1 file changed

+9
-2
lines changed

ports/nrf/modules/machine/timer.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ enum {
3939
typedef struct _machine_timer_obj_t {
4040
mp_obj_base_t base;
4141
nrfx_timer_t p_instance;
42+
bool ishard;
4243
} machine_timer_obj_t;
4344

4445
static mp_obj_t machine_timer_callbacks[] = {
@@ -89,20 +90,25 @@ static void timer_event_handler(nrf_timer_event_t event_type, void *p_context) {
8990
machine_timer_obj_t *self = p_context;
9091
mp_obj_t callback = machine_timer_callbacks[self->p_instance.instance_id];
9192
if (callback != NULL) {
92-
mp_call_function_1(callback, self);
93+
if (self->ishard) {
94+
mp_call_function_1(callback, self);
95+
} else {
96+
mp_sched_schedule(callback, self);
97+
}
9398
}
9499
}
95100

96101
/******************************************************************************/
97102
/* MicroPython bindings for machine API */
98103

99104
static mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
100-
enum { ARG_id, ARG_period, ARG_mode, ARG_callback };
105+
enum { ARG_id, ARG_period, ARG_mode, ARG_callback, ARG_hard };
101106
static const mp_arg_t allowed_args[] = {
102107
{ MP_QSTR_id, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(-1)} },
103108
{ MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000000} }, // 1 second
104109
{ MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = TIMER_MODE_PERIODIC} },
105110
{ MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
111+
{ MP_QSTR_hard, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
106112
};
107113

108114
// parse args
@@ -133,6 +139,7 @@ static mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args,
133139
} else {
134140
mp_raise_ValueError(MP_ERROR_TEXT("callback must be a function"));
135141
}
142+
self->ishard = args[ARG_hard].u_bool;
136143

137144
// Timer peripheral usage:
138145
// Every timer instance has a number of capture/compare (CC) registers.

0 commit comments

Comments
 (0)