stm32/softtimer: Change linear linked list to a pairing heap.
This commit is contained in:
parent
fe203bb3e2
commit
f70373c7b2
@ -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;
|
||||
|
@ -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]; \
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user