Rework sleep timing

It didn't account for background task time and could end up
sleeping for way longer than it should because the RTC compare time
had already passed.
This commit is contained in:
Scott Shawcroft 2020-04-03 18:07:56 -07:00
parent 7e69d30c02
commit e99cf6e441
No known key found for this signature in database
GPG Key ID: 9349BC7E64B1921E
3 changed files with 27 additions and 20 deletions

View File

@ -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++;

View File

@ -306,6 +306,7 @@ void reset_port(void) {
#endif
eic_reset();
#if CIRCUITPY_PULSEIO
pulsein_reset();
pulseout_reset();
pwmout_reset();
#endif

View File

@ -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);
}
}