Skip to content

Commit de76f73

Browse files
dybberdpgeorge
authored andcommitted
esp32/machine_timer: Reuse Timer handles, deallocate only on soft-reset.
The patch solves the problem where multiple Timer objects (e.g. multiple Timer(0) instances) could initialise multiple handles to the same internal timer. The list of timers is now maintained not for "active" timers (where init is called), but for all timers created. The timers are only removed from the list of timers on soft-reset (machine_timer_deinit_all). Fixes #4078.
1 parent ff91b05 commit de76f73

File tree

1 file changed

+24
-16
lines changed

1 file changed

+24
-16
lines changed

ports/esp32/machine_timer.c

+24-16
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,13 @@ STATIC esp_err_t check_esp_err(esp_err_t code) {
7373
}
7474

7575
void machine_timer_deinit_all(void) {
76-
while (MP_STATE_PORT(machine_timer_obj_head) != NULL) {
77-
machine_timer_disable(MP_STATE_PORT(machine_timer_obj_head));
76+
// Disable, deallocate and remove all timers from list
77+
machine_timer_obj_t **t = &MP_STATE_PORT(machine_timer_obj_head);
78+
while (*t != NULL) {
79+
machine_timer_disable(*t);
80+
machine_timer_obj_t *next = (*t)->next;
81+
m_del_obj(machine_timer_obj_t, *t);
82+
*t = next;
7883
}
7984
}
8085

@@ -93,12 +98,24 @@ STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_pr
9398

9499
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 *args) {
95100
mp_arg_check_num(n_args, n_kw, 1, 1, false);
101+
mp_uint_t group = (mp_obj_get_int(args[0]) >> 1) & 1;
102+
mp_uint_t index = mp_obj_get_int(args[0]) & 1;
103+
104+
// Check whether the timer is already initialized, if so return it
105+
for (machine_timer_obj_t *t = MP_STATE_PORT(machine_timer_obj_head); t; t = t->next) {
106+
if (t->group == group && t->index == index) {
107+
return t;
108+
}
109+
}
110+
96111
machine_timer_obj_t *self = m_new_obj(machine_timer_obj_t);
97112
self->base.type = &machine_timer_type;
113+
self->group = group;
114+
self->index = index;
98115

99-
self->group = (mp_obj_get_int(args[0]) >> 1) & 1;
100-
self->index = mp_obj_get_int(args[0]) & 1;
101-
self->next = NULL;
116+
// Add the timer to the linked-list of timers
117+
self->next = MP_STATE_PORT(machine_timer_obj_head);
118+
MP_STATE_PORT(machine_timer_obj_head) = self;
102119

103120
return self;
104121
}
@@ -110,13 +127,8 @@ STATIC void machine_timer_disable(machine_timer_obj_t *self) {
110127
self->handle = NULL;
111128
}
112129

113-
// Remove the timer from the linked-list of active timers
114-
for (machine_timer_obj_t **t = &MP_STATE_PORT(machine_timer_obj_head); *t; t = &(*t)->next) {
115-
if (*t == self) {
116-
*t = (*t)->next;
117-
break;
118-
}
119-
}
130+
// We let the disabled timer stay in the list, as it might be
131+
// referenced elsewhere
120132
}
121133

122134
STATIC void machine_timer_isr(void *self_in) {
@@ -150,10 +162,6 @@ STATIC void machine_timer_enable(machine_timer_obj_t *self) {
150162
check_esp_err(timer_enable_intr(self->group, self->index));
151163
check_esp_err(timer_isr_register(self->group, self->index, machine_timer_isr, (void*)self, TIMER_FLAGS, &self->handle));
152164
check_esp_err(timer_start(self->group, self->index));
153-
154-
// Add the timer to the linked-list of active timers
155-
self->next = MP_STATE_PORT(machine_timer_obj_head);
156-
MP_STATE_PORT(machine_timer_obj_head) = self;
157165
}
158166

159167
STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {

0 commit comments

Comments
 (0)