diff options
Diffstat (limited to 'shared/runtime/softtimer.c')
-rw-r--r-- | shared/runtime/softtimer.c | 75 |
1 files changed, 37 insertions, 38 deletions
diff --git a/shared/runtime/softtimer.c b/shared/runtime/softtimer.c index 267610b269..468fa95b72 100644 --- a/shared/runtime/softtimer.c +++ b/shared/runtime/softtimer.c @@ -30,42 +30,43 @@ #include "py/runtime.h" #include "softtimer.h" +#ifdef MICROPY_SOFT_TIMER_TICKS_MS + extern __IO uint32_t MICROPY_SOFT_TIMER_TICKS_MS; volatile uint32_t soft_timer_next; +static inline uint32_t soft_timer_get_ms(void) { + return MICROPY_SOFT_TIMER_TICKS_MS; +} + +static void soft_timer_schedule_at_ms(uint32_t ticks_ms) { + uint32_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); + uint32_t uw_tick = MICROPY_SOFT_TIMER_TICKS_MS; + if (soft_timer_ticks_diff(ticks_ms, uw_tick) <= 0) { + soft_timer_next = uw_tick + 1; + } else { + soft_timer_next = ticks_ms; + } + MICROPY_END_ATOMIC_SECTION(atomic_state); +} + +#endif + // Pointer to the pairheap of soft timer objects. // This may contain bss/data pointers as well as GC-heap pointers, // and is explicitly GC traced by soft_timer_gc_mark_all(). STATIC soft_timer_entry_t *soft_timer_heap; -static inline int32_t ticks_diff(uint32_t t1, uint32_t t0) { - // t1 is after t0 (i.e. positive result) if there exists a uint32_t X <= INT_MAX - // such that t0 + X = t1. Otherwise t1 is interpreted to be earlier than - // t0 (negative result). - return t1 - t0; -} - 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) { - uint32_t irq_state = disable_irq(); - uint32_t uw_tick = MICROPY_SOFT_TIMER_TICKS_MS; - if (ticks_diff(ticks_ms, uw_tick) <= 0) { - soft_timer_next = uw_tick + 1; - } else { - soft_timer_next = ticks_ms; - } - enable_irq(irq_state); + return soft_timer_ticks_diff(e1->expiry_ms, e2->expiry_ms) < 0; } void soft_timer_deinit(void) { // Pop off all the nodes which are allocated on the GC-heap. - uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); + MICROPY_PY_PENDSV_ENTER; soft_timer_entry_t *heap_from = soft_timer_heap; soft_timer_entry_t *heap_to = (soft_timer_entry_t *)mp_pairheap_new(soft_timer_lt); while (heap_from != NULL) { @@ -76,14 +77,14 @@ void soft_timer_deinit(void) { } } soft_timer_heap = heap_to; - restore_irq_pri(irq_state); + MICROPY_PY_PENDSV_EXIT; } // Must be executed at IRQ_PRI_PENDSV void soft_timer_handler(void) { - uint32_t ticks_ms = MICROPY_SOFT_TIMER_TICKS_MS; + uint32_t ticks_ms = soft_timer_get_ms(); soft_timer_entry_t *heap = soft_timer_heap; - while (heap != NULL && ticks_diff(heap->expiry_ms, ticks_ms) <= 0) { + while (heap != NULL && soft_timer_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); if (entry->flags & SOFT_TIMER_FLAG_PY_CALLBACK) { @@ -97,19 +98,17 @@ void soft_timer_handler(void) { } } soft_timer_heap = heap; - if (heap == NULL) { - // No more timers left, set largest delay possible - soft_timer_next = MICROPY_SOFT_TIMER_TICKS_MS; - } else { - // Set soft_timer_next so SysTick calls us back at the correct time - soft_timer_schedule_systick(heap->expiry_ms); + + // Schedule the port's timer to call us back at the correct time. + if (heap != NULL) { + soft_timer_schedule_at_ms(heap->expiry_ms); } } void soft_timer_gc_mark_all(void) { // Mark all soft timer nodes that are allocated on the GC-heap. // To avoid deep C recursion, pop and recreate the pairheap as nodes are marked. - uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); + MICROPY_PY_PENDSV_ENTER; soft_timer_entry_t *heap_from = soft_timer_heap; soft_timer_entry_t *heap_to = (soft_timer_entry_t *)mp_pairheap_new(soft_timer_lt); while (heap_from != NULL) { @@ -121,7 +120,7 @@ void soft_timer_gc_mark_all(void) { heap_to = (soft_timer_entry_t *)mp_pairheap_push(soft_timer_lt, &heap_to->pairheap, &entry->pairheap); } soft_timer_heap = heap_to; - restore_irq_pri(irq_state); + MICROPY_PY_PENDSV_EXIT; } void soft_timer_static_init(soft_timer_entry_t *entry, uint16_t mode, uint32_t delta_ms, void (*cb)(soft_timer_entry_t *)) { @@ -134,18 +133,18 @@ void soft_timer_static_init(soft_timer_entry_t *entry, uint16_t mode, uint32_t d void soft_timer_insert(soft_timer_entry_t *entry, uint32_t initial_delta_ms) { mp_pairheap_init_node(soft_timer_lt, &entry->pairheap); - entry->expiry_ms = MICROPY_SOFT_TIMER_TICKS_MS + initial_delta_ms; - uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); + entry->expiry_ms = soft_timer_get_ms() + initial_delta_ms; + MICROPY_PY_PENDSV_ENTER; soft_timer_heap = (soft_timer_entry_t *)mp_pairheap_push(soft_timer_lt, &soft_timer_heap->pairheap, &entry->pairheap); if (entry == soft_timer_heap) { - // This new timer became the earliest one so set soft_timer_next - soft_timer_schedule_systick(entry->expiry_ms); + // This new timer became the earliest one so schedule a callback. + soft_timer_schedule_at_ms(entry->expiry_ms); } - restore_irq_pri(irq_state); + MICROPY_PY_PENDSV_EXIT; } void soft_timer_remove(soft_timer_entry_t *entry) { - uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); + MICROPY_PY_PENDSV_ENTER; soft_timer_heap = (soft_timer_entry_t *)mp_pairheap_delete(soft_timer_lt, &soft_timer_heap->pairheap, &entry->pairheap); - restore_irq_pri(irq_state); + MICROPY_PY_PENDSV_EXIT; } |