diff --git a/ports/atmel-samd/background.c b/ports/atmel-samd/background.c index 92648f42ea..4cba7a1100 100644 --- a/ports/atmel-samd/background.c +++ b/ports/atmel-samd/background.c @@ -26,11 +26,19 @@ #include "background.h" #include "audio_dma.h" +#include "tick.h" #include "usb.h" #include "usb_mass_storage.h" +volatile uint64_t last_finished_tick = 0; + void run_background_tasks(void) { audio_dma_background(); usb_msc_background(); usb_cdc_background(); + last_finished_tick = ticks_ms; +} + +bool background_tasks_ok(void) { + return ticks_ms - last_finished_tick < 1000; } diff --git a/ports/atmel-samd/background.h b/ports/atmel-samd/background.h index f7fb10a1f7..e841049a4e 100644 --- a/ports/atmel-samd/background.h +++ b/ports/atmel-samd/background.h @@ -27,6 +27,9 @@ #ifndef MICROPY_INCLUDED_ATMEL_SAMD_BACKGROUND_H #define MICROPY_INCLUDED_ATMEL_SAMD_BACKGROUND_H +#include + void run_background_tasks(void); +bool background_tasks_ok(void); #endif // MICROPY_INCLUDED_ATMEL_SAMD_BACKGROUND_H diff --git a/ports/atmel-samd/common-hal/microcontroller/__init__.c b/ports/atmel-samd/common-hal/microcontroller/__init__.c index c57b6939ce..ad4d81ddd0 100644 --- a/ports/atmel-samd/common-hal/microcontroller/__init__.c +++ b/ports/atmel-samd/common-hal/microcontroller/__init__.c @@ -40,18 +40,10 @@ void common_hal_mcu_delay_us(uint32_t delay) { mp_hal_delay_us(delay); } -// Interrupt flags that will be saved and restored during disable/Enable -// interrupt functions below. - -// ASF4's interrupt disable doesn't handle duplicate calls -volatile uint32_t interrupt_flags; volatile uint32_t nesting_count = 0; void common_hal_mcu_disable_interrupts(void) { - if (nesting_count == 0) { - interrupt_flags = __get_PRIMASK(); - __disable_irq(); - __DMB(); - } + __disable_irq(); + __DMB(); nesting_count++; } @@ -66,7 +58,7 @@ void common_hal_mcu_enable_interrupts(void) { return; } __DMB(); - __set_PRIMASK(interrupt_flags); + __enable_irq(); } extern uint32_t _ezero; diff --git a/ports/atmel-samd/common-hal/pulseio/PulseIn.c b/ports/atmel-samd/common-hal/pulseio/PulseIn.c index 99a60a8297..dee32bbec1 100644 --- a/ports/atmel-samd/common-hal/pulseio/PulseIn.c +++ b/ports/atmel-samd/common-hal/pulseio/PulseIn.c @@ -31,6 +31,7 @@ #include "atmel_start_pins.h" #include "hal/include/hal_gpio.h" +#include "background.h" #include "mpconfigport.h" #include "py/gc.h" #include "py/runtime.h" @@ -60,10 +61,16 @@ void pulsein_interrupt_handler(uint8_t channel) { uint32_t current_us; uint64_t current_ms; current_tick(¤t_ms, ¤t_us); + // current_tick gives us the remaining us until the next tick but we want the number since the // last ms. current_us = 1000 - current_us; pulseio_pulsein_obj_t* self = get_eic_channel_data(channel); + if (!background_tasks_ok() || self->errored_too_fast) { + self->errored_too_fast = true; + common_hal_pulseio_pulsein_pause(self); + return; + } if (self->first_edge) { self->first_edge = false; pulsein_set_config(self, false); @@ -118,6 +125,7 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, self->first_edge = true; self->last_us = 0; self->last_ms = 0; + self->errored_too_fast = 0; set_eic_channel_data(pin->extint_channel, (void*) self); @@ -157,6 +165,9 @@ void common_hal_pulseio_pulsein_resume(pulseio_pulsein_obj_t* self, // Make sure we're paused. common_hal_pulseio_pulsein_pause(self); + // Reset erroring + self->errored_too_fast = false; + // Send the trigger pulse. if (trigger_duration > 0) { gpio_set_pin_pull_mode(self->pin, GPIO_PULL_OFF); @@ -207,6 +218,11 @@ uint16_t common_hal_pulseio_pulsein_get_len(pulseio_pulsein_obj_t* self) { return self->len; } +bool common_hal_pulseio_pulsein_get_paused(pulseio_pulsein_obj_t* self) { + uint32_t mask = 1 << self->channel; + return (EIC->INTENSET.reg & (mask << EIC_INTENSET_EXTINT_Pos)) == 0; +} + uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self, int16_t index) { common_hal_mcu_disable_interrupts(); diff --git a/ports/atmel-samd/common-hal/pulseio/PulseIn.h b/ports/atmel-samd/common-hal/pulseio/PulseIn.h index 3d79b50c3c..f5326d9e51 100644 --- a/ports/atmel-samd/common-hal/pulseio/PulseIn.h +++ b/ports/atmel-samd/common-hal/pulseio/PulseIn.h @@ -43,6 +43,7 @@ typedef struct { volatile bool first_edge; volatile uint64_t last_ms; volatile uint16_t last_us; + volatile bool errored_too_fast; } pulseio_pulsein_obj_t; void pulsein_reset(void); diff --git a/ports/atmel-samd/tick.c b/ports/atmel-samd/tick.c index 6cd7c7833f..81841c4af4 100644 --- a/ports/atmel-samd/tick.c +++ b/ports/atmel-samd/tick.c @@ -60,6 +60,13 @@ void tick_init() { uint32_t ticks_per_ms = common_hal_mcu_processor_get_frequency() / 1000; SysTick_Config(ticks_per_ms-1); NVIC_EnableIRQ(SysTick_IRQn); + // Set all peripheral interrupt priorities to the lowest priority by default. + for (uint16_t i = 0; i < PERIPH_COUNT_IRQn; i++) { + NVIC_SetPriority(i, (1UL << __NVIC_PRIO_BITS) - 1UL); + } + // Bump up the systick interrupt. + NVIC_SetPriority(SysTick_IRQn, 1); + NVIC_SetPriority(USB_IRQn, 1); } void tick_delay(uint32_t us) { diff --git a/shared-bindings/pulseio/PulseIn.c b/shared-bindings/pulseio/PulseIn.c index 736441c741..862dbd99d6 100644 --- a/shared-bindings/pulseio/PulseIn.c +++ b/shared-bindings/pulseio/PulseIn.c @@ -219,6 +219,26 @@ const mp_obj_property_t pulseio_pulsein_maxlen_obj = { (mp_obj_t)&mp_const_none_obj}, }; +//| .. attribute:: paused +//| +//| True when pulse capture is paused as a result of :py:func:`pause` or an error during capture +//| such as a signal that is too fast. +//| +STATIC mp_obj_t pulseio_pulsein_obj_get_paused(mp_obj_t self_in) { + pulseio_pulsein_obj_t *self = MP_OBJ_TO_PTR(self_in); + raise_error_if_deinited(common_hal_pulseio_pulsein_deinited(self)); + + return mp_obj_new_bool(common_hal_pulseio_pulsein_get_paused(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(pulseio_pulsein_get_paused_obj, pulseio_pulsein_obj_get_paused); + +const mp_obj_property_t pulseio_pulsein_paused_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&pulseio_pulsein_get_paused_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + //| .. method:: __len__() //| //| Returns the current pulse length @@ -285,7 +305,10 @@ STATIC const mp_rom_map_elem_t pulseio_pulsein_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_resume), MP_ROM_PTR(&pulseio_pulsein_resume_obj) }, { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&pulseio_pulsein_clear_obj) }, { MP_ROM_QSTR(MP_QSTR_popleft), MP_ROM_PTR(&pulseio_pulsein_popleft_obj) }, + + // Properties { MP_ROM_QSTR(MP_QSTR_maxlen), MP_ROM_PTR(&pulseio_pulsein_maxlen_obj) }, + { MP_ROM_QSTR(MP_QSTR_paused), MP_ROM_PTR(&pulseio_pulsein_paused_obj) }, }; STATIC MP_DEFINE_CONST_DICT(pulseio_pulsein_locals_dict, pulseio_pulsein_locals_dict_table); diff --git a/shared-bindings/pulseio/PulseIn.h b/shared-bindings/pulseio/PulseIn.h index 88b6f356ed..e28a3c2df4 100644 --- a/shared-bindings/pulseio/PulseIn.h +++ b/shared-bindings/pulseio/PulseIn.h @@ -41,6 +41,7 @@ extern void common_hal_pulseio_pulsein_resume(pulseio_pulsein_obj_t* self, uint1 extern void common_hal_pulseio_pulsein_clear(pulseio_pulsein_obj_t* self); extern uint16_t common_hal_pulseio_pulsein_popleft(pulseio_pulsein_obj_t* self); extern uint16_t common_hal_pulseio_pulsein_get_maxlen(pulseio_pulsein_obj_t* self); +extern bool common_hal_pulseio_pulsein_get_paused(pulseio_pulsein_obj_t* self); extern uint16_t common_hal_pulseio_pulsein_get_len(pulseio_pulsein_obj_t* self); extern uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self, int16_t index);