diff --git a/ports/atmel-samd/common-hal/pulseio/PulseIn.c b/ports/atmel-samd/common-hal/pulseio/PulseIn.c index 4ddee4933c..54343a8e3e 100644 --- a/ports/atmel-samd/common-hal/pulseio/PulseIn.c +++ b/ports/atmel-samd/common-hal/pulseio/PulseIn.c @@ -79,6 +79,11 @@ void pulsein_interrupt_handler(uint8_t channel) { // Grab the current time first. uint32_t current_overflow = overflow_count; Tc* tc = tc_insts[pulsein_tc_index]; + #ifdef SAMD51 + tc->COUNT16.CTRLBSET.reg = TC_CTRLBSET_CMD_READSYNC; + while (tc->COUNT16.SYNCBUSY.bit.COUNT == 1 || + tc->COUNT16.CTRLBSET.bit.CMD == TC_CTRLBSET_CMD_READSYNC_Val) {} + #endif uint32_t current_count = tc->COUNT16.COUNT.reg; pulseio_pulsein_obj_t* self = get_eic_channel_data(channel); @@ -119,6 +124,12 @@ void pulsein_interrupt_handler(uint8_t channel) { self->last_count = current_count; } +void pulsein_reset() { + refcount = 0; + pulsein_tc_index = 0xff; + overflow_count = 0; +} + void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, const mcu_pin_obj_t* pin, uint16_t maxlen, bool idle_state) { if (!pin->has_extint) { @@ -189,8 +200,6 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, tc_enable_interrupts(pulsein_tc_index); tc->COUNT16.CTRLBSET.reg = TC_CTRLBSET_CMD_RETRIGGER; - //mp_printf(&mp_plat_print, "timer started\n"); - overflow_count = 0; } refcount++; diff --git a/ports/atmel-samd/supervisor/port.c b/ports/atmel-samd/supervisor/port.c index 92ef35680c..271faecd96 100644 --- a/ports/atmel-samd/supervisor/port.c +++ b/ports/atmel-samd/supervisor/port.c @@ -306,6 +306,7 @@ void reset_port(void) { #endif eic_reset(); #if CIRCUITPY_PULSEIO + pulsein_reset(); pulseout_reset(); pwmout_reset(); #endif diff --git a/supervisor/shared/tick.c b/supervisor/shared/tick.c index 516dff7470..dc38e76f61 100644 --- a/supervisor/shared/tick.c +++ b/supervisor/shared/tick.c @@ -79,39 +79,36 @@ uint32_t supervisor_ticks_ms32() { extern void run_background_tasks(void); void PLACE_IN_ITCM(supervisor_run_background_tasks_if_tick)() { - uint8_t subticks; - uint64_t now = port_get_raw_ticks(&subticks); - - if (now == background_ticks && (subticks & 0x3) != 0) { - return; - } - background_ticks = now; - + // TODO: Add a global that can be set by anyone to indicate we should run background tasks. That + // way we can short circuit the background tasks early. We used to do it based on time but it + // breaks cases where we wake up for a short period and then sleep. If we skipped the last + // background task or more before sleeping we may end up starving a task like USB. run_background_tasks(); } -void supervisor_fake_tick() { - uint32_t now = port_get_raw_ticks(NULL); - background_ticks = (now - 1); -} - void mp_hal_delay_ms(mp_uint_t delay) { uint64_t start_tick = port_get_raw_ticks(NULL); // Adjust the delay to ticks vs ms. delay = delay * 1024 / 1000; - uint64_t duration = 0; - port_interrupt_after_ticks(delay); - while (duration < delay) { + uint64_t end_tick = start_tick + delay; + int64_t remaining = delay; + while (remaining > 0) { RUN_BACKGROUND_TASKS; // Check to see if we've been CTRL-Ced by autoreload or the user. if(MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)) || MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) { break; } + remaining = end_tick - port_get_raw_ticks(NULL); + // We break a bit early so we don't risk setting the alarm before the time when we call + // sleep. + if (remaining < 1) { + break; + } + port_interrupt_after_ticks(remaining); // Sleep until an interrupt happens. port_sleep_until_interrupt(); - duration = (port_get_raw_ticks(NULL) - start_tick); - port_interrupt_after_ticks(duration); + remaining = end_tick - port_get_raw_ticks(NULL); } }