diff --git a/ports/stm32/machine_timer.c b/ports/stm32/machine_timer.c index 22fa67d7d9..1e9be42627 100644 --- a/ports/stm32/machine_timer.c +++ b/ports/stm32/machine_timer.c @@ -77,7 +77,7 @@ STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, size_t n_ar 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) { machine_timer_obj_t *self = m_new_obj(machine_timer_obj_t); - self->base.type = &machine_timer_type; + self->pairheap.base.type = &machine_timer_type; // Get timer id (only soft timer (-1) supported at the moment) mp_int_t id = -1; diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 55f09f81f0..2e4fc04061 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -281,7 +281,7 @@ struct _mp_bluetooth_nimble_root_pointers_t; \ mp_obj_t pyb_extint_callback[PYB_EXTI_NUM_VECTORS]; \ \ - struct _soft_timer_entry_t *soft_timer_head; \ + struct _soft_timer_entry_t *soft_timer_heap; \ \ /* pointers to all Timer objects (if they have been created) */ \ struct _pyb_timer_obj_t *pyb_timer_obj_all[MICROPY_HW_MAX_TIMER]; \ diff --git a/ports/stm32/softtimer.c b/ports/stm32/softtimer.c index c598bac177..60c2709d93 100644 --- a/ports/stm32/softtimer.c +++ b/ports/stm32/softtimer.c @@ -37,7 +37,13 @@ extern __IO uint32_t uwTick; volatile uint32_t soft_timer_next; void soft_timer_deinit(void) { - MP_STATE_PORT(soft_timer_head) = NULL; + MP_STATE_PORT(soft_timer_heap) = NULL; +} + +STATIC int soft_timer_lt(mp_pairheap_t *n1, mp_pairheap_t *n2) { + soft_timer_entry_t *e1 = (soft_timer_entry_t*)n1; + soft_timer_entry_t *e2 = (soft_timer_entry_t*)n2; + return TICKS_DIFF(e1->expiry_ms, e2->expiry_ms) < 0; } STATIC void soft_timer_schedule_systick(uint32_t ticks_ms) { @@ -54,59 +60,38 @@ STATIC void soft_timer_schedule_systick(uint32_t ticks_ms) { // Must be executed at IRQ_PRI_PENDSV void soft_timer_handler(void) { uint32_t ticks_ms = uwTick; - soft_timer_entry_t *head = MP_STATE_PORT(soft_timer_head); - while (head != NULL && TICKS_DIFF(head->expiry_ms, ticks_ms) <= 0) { - mp_sched_schedule(head->callback, MP_OBJ_FROM_PTR(head)); - if (head->mode == SOFT_TIMER_MODE_PERIODIC) { - head->expiry_ms += head->delta_ms; - // Shift this node along to its new position - soft_timer_entry_t *cur = head; - while (cur->next != NULL && TICKS_DIFF(head->expiry_ms, cur->next->expiry_ms) >= 0) { - cur = cur->next; - } - if (cur != head) { - soft_timer_entry_t *next = head->next; - head->next = cur->next; - cur->next = head; - head = next; - } - } else { - head = head->next; + soft_timer_entry_t *heap = MP_STATE_PORT(soft_timer_heap); + while (heap != NULL && TICKS_DIFF(heap->expiry_ms, ticks_ms) <= 0) { + soft_timer_entry_t *entry = heap; + heap = (soft_timer_entry_t*)mp_pairheap_pop(soft_timer_lt, &heap->pairheap); + mp_sched_schedule(entry->callback, MP_OBJ_FROM_PTR(entry)); + if (entry->mode == SOFT_TIMER_MODE_PERIODIC) { + entry->expiry_ms += entry->delta_ms; + heap = (soft_timer_entry_t*)mp_pairheap_push(soft_timer_lt, &heap->pairheap, &entry->pairheap); } } - MP_STATE_PORT(soft_timer_head) = head; - if (head == NULL) { + MP_STATE_PORT(soft_timer_heap) = heap; + if (heap == NULL) { // No more timers left, set largest delay possible soft_timer_next = uwTick; } else { // Set soft_timer_next so SysTick calls us back at the correct time - soft_timer_schedule_systick(head->expiry_ms); + soft_timer_schedule_systick(heap->expiry_ms); } } void soft_timer_insert(soft_timer_entry_t *entry) { uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); - soft_timer_entry_t **head_ptr = &MP_STATE_PORT(soft_timer_head); - while (*head_ptr != NULL && TICKS_DIFF(entry->expiry_ms, (*head_ptr)->expiry_ms) >= 0) { - head_ptr = &(*head_ptr)->next; - } - entry->next = *head_ptr; - *head_ptr = entry; - if (head_ptr == &MP_STATE_PORT(soft_timer_head)) { + MP_STATE_PORT(soft_timer_heap) = (soft_timer_entry_t*)mp_pairheap_push(soft_timer_lt, &MP_STATE_PORT(soft_timer_heap)->pairheap, &entry->pairheap); + if (entry == MP_STATE_PORT(soft_timer_heap)) { // This new timer became the earliest one so set soft_timer_next - soft_timer_schedule_systick((*head_ptr)->expiry_ms); + soft_timer_schedule_systick(entry->expiry_ms); } restore_irq_pri(irq_state); } void soft_timer_remove(soft_timer_entry_t *entry) { uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); - soft_timer_entry_t **cur = &MP_STATE_PORT(soft_timer_head); - while (*cur != NULL) { - if (*cur == entry) { - *cur = entry->next; - break; - } - } + MP_STATE_PORT(soft_timer_heap) = (soft_timer_entry_t*)mp_pairheap_delete(soft_timer_lt, &MP_STATE_PORT(soft_timer_heap)->pairheap, &entry->pairheap); restore_irq_pri(irq_state); } diff --git a/ports/stm32/softtimer.h b/ports/stm32/softtimer.h index 2550446d83..a80d9087b5 100644 --- a/ports/stm32/softtimer.h +++ b/ports/stm32/softtimer.h @@ -26,14 +26,13 @@ #ifndef MICROPY_INCLUDED_STM32_SOFTTIMER_H #define MICROPY_INCLUDED_STM32_SOFTTIMER_H -#include "py/obj.h" +#include "py/pairheap.h" #define SOFT_TIMER_MODE_ONE_SHOT (1) #define SOFT_TIMER_MODE_PERIODIC (2) typedef struct _soft_timer_entry_t { - mp_obj_base_t base; // so struct can be used as an object and still be traced by GC - struct _soft_timer_entry_t *next; + mp_pairheap_t pairheap; uint32_t mode; uint32_t expiry_ms; uint32_t delta_ms; // for periodic mode