diff options
| -rw-r--r-- | ports/alif/main.c | 2 | ||||
| -rw-r--r-- | ports/alif/mphalport.c | 17 | ||||
| -rw-r--r-- | ports/alif/system_tick.c | 44 | ||||
| -rw-r--r-- | ports/alif/system_tick.h | 2 |
4 files changed, 63 insertions, 2 deletions
diff --git a/ports/alif/main.c b/ports/alif/main.c index 9293d74c0..b4e243439 100644 --- a/ports/alif/main.c +++ b/ports/alif/main.c @@ -33,6 +33,7 @@ #include "shared/readline/readline.h" #include "shared/runtime/gchelper.h" #include "shared/runtime/pyexec.h" +#include "shared/runtime/softtimer.h" #include "shared/tinyusb/mp_usbd.h" #include "tusb.h" #include "mpuart.h" @@ -119,6 +120,7 @@ void _start(void) { soft_reset_exit: mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n"); + soft_timer_deinit(); gc_sweep_all(); mp_deinit(); } diff --git a/ports/alif/mphalport.c b/ports/alif/mphalport.c index 8d0fa1b92..ba58923f2 100644 --- a/ports/alif/mphalport.c +++ b/ports/alif/mphalport.c @@ -31,11 +31,13 @@ #include "py/stream.h" #include "extmod/misc.h" #include "shared/runtime/interrupt_char.h" +#include "shared/runtime/softtimer.h" #include "shared/timeutils/timeutils.h" #include "shared/tinyusb/mp_usbd.h" #include "shared/tinyusb/mp_usbd_cdc.h" #include "tusb.h" #include "mpuart.h" +#include "pendsv.h" #include "system_tick.h" #ifndef MICROPY_HW_STDIN_BUFFER_LEN @@ -146,3 +148,18 @@ void mp_hal_delay_ms(mp_uint_t ms) { uint64_t mp_hal_time_ns(void) { return 0; } + +void system_tick_schedule_callback(void) { + pendsv_schedule_dispatch(PENDSV_DISPATCH_SOFT_TIMER, soft_timer_handler); +} + +uint32_t soft_timer_get_ms(void) { + return mp_hal_ticks_ms(); +} + +void soft_timer_schedule_at_ms(uint32_t ticks_ms) { + int32_t ms = soft_timer_ticks_diff(ticks_ms, mp_hal_ticks_ms()); + ms = MAX(0, ms); + ms = MIN(ms, 4000000); // ensure ms * 1000 doesn't overflow + system_tick_schedule_after_us(ms * 1000); +} diff --git a/ports/alif/system_tick.c b/ports/alif/system_tick.c index 95d5391c0..5cdf45cba 100644 --- a/ports/alif/system_tick.c +++ b/ports/alif/system_tick.c @@ -59,9 +59,13 @@ void system_tick_init(void) { utimer_control_enable(UTIMER, UTIMER_CHANNEL); utimer_counter_start(UTIMER, UTIMER_CHANNEL); - // Set up the UTIMER compare interrupt, to be used later. + // Set up the UTIMER compare A interrupt, to be used by system_tick_wfe_with_timeout_us. system_tick_nvic_config(2); UTIMER->UTIMER_CHANNEL_CFG[UTIMER_CHANNEL].UTIMER_COMPARE_CTRL_A |= COMPARE_CTRL_DRV_COMPARE_EN; + + // Set up the UTIMER compare B interrupt, to be used by soft-timer. + system_tick_nvic_config(4); + UTIMER->UTIMER_CHANNEL_CFG[UTIMER_CHANNEL].UTIMER_COMPARE_CTRL_B |= COMPARE_CTRL_DRV_COMPARE_EN; } // COMPARE_A_BUF1 @@ -73,6 +77,17 @@ void UTIMER_IRQ90Handler(void) { } } +// COMPARE_B_BUF1 +void UTIMER_IRQ92Handler(void) { + uint32_t chan_interrupt = UTIMER->UTIMER_CHANNEL_CFG[UTIMER_CHANNEL].UTIMER_CHAN_INTERRUPT; + if (chan_interrupt & CHAN_INTERRUPT_COMPARE_B_BUF1_MASK) { + utimer_clear_interrupt(UTIMER, UTIMER_CHANNEL, CHAN_INTERRUPT_COMPARE_B_BUF1_MASK); + utimer_mask_interrupt(UTIMER, UTIMER_CHANNEL, CHAN_INTERRUPT_COMPARE_B_BUF1_MASK); + system_tick_schedule_callback(); + __SEV(); + } +} + // OVER_FLOW void UTIMER_IRQ95Handler(void) { uint32_t chan_interrupt = UTIMER->UTIMER_CHANNEL_CFG[UTIMER_CHANNEL].UTIMER_CHAN_INTERRUPT; @@ -106,7 +121,7 @@ uint64_t system_tick_get_u64(void) { } void system_tick_wfe_with_timeout_us(uint32_t timeout_us) { - // Maximum 10 second timeout, to not overflow signed 32-bit ticks when + // Maximum 10 second timeout, to not overflow 32-bit ticks when // system_core_clock_mhz==400. uint32_t timeout_ticks = MIN(timeout_us, 10000000) * system_core_clock_mhz; @@ -126,3 +141,28 @@ void system_tick_wfe_with_timeout_us(uint32_t timeout_us) { // Disable the UTIMER compare interrupt. utimer_mask_interrupt(UTIMER, UTIMER_CHANNEL, CHAN_INTERRUPT_COMPARE_A_BUF1_MASK); } + +void system_tick_schedule_after_us(uint32_t ticks_us) { + // Disable the interrupt in case it's still active. + utimer_mask_interrupt(UTIMER, UTIMER_CHANNEL, CHAN_INTERRUPT_COMPARE_B_BUF1_MASK); + + // Maximum 10 second timeout, to not overflow 32-bit ticks when + // system_core_clock_mhz==400. + uint32_t timeout_ticks = MIN(ticks_us, 10000000) * system_core_clock_mhz; + + // Set up the UTIMER compare interrupt to fire after the given timeout. + uint32_t cntr = utimer_get_count(UTIMER, UTIMER_CHANNEL, UTIMER_CNTR); + utimer_set_count(UTIMER, UTIMER_CHANNEL, UTIMER_COMPARE_B_BUF1, cntr + timeout_ticks); + utimer_clear_interrupt(UTIMER, UTIMER_CHANNEL, CHAN_INTERRUPT_COMPARE_B_BUF1_MASK); + utimer_unmask_interrupt(UTIMER, UTIMER_CHANNEL, CHAN_INTERRUPT_COMPARE_B_BUF1_MASK); + + // Handle the case of short timeouts. + uint32_t cntr2 = utimer_get_count(UTIMER, UTIMER_CHANNEL, UTIMER_CNTR); + if ((uint32_t)(cntr2 - cntr) >= timeout_ticks) { + if (!(UTIMER->UTIMER_CHANNEL_CFG[UTIMER_CHANNEL].UTIMER_CHAN_INTERRUPT_MASK & CHAN_INTERRUPT_COMPARE_B_BUF1_MASK)) { + // Interrupt is still enabled, so disable it and manually call the callback. + utimer_mask_interrupt(UTIMER, UTIMER_CHANNEL, CHAN_INTERRUPT_COMPARE_B_BUF1_MASK); + system_tick_schedule_callback(); + } + } +} diff --git a/ports/alif/system_tick.h b/ports/alif/system_tick.h index 307c87a34..2373f9421 100644 --- a/ports/alif/system_tick.h +++ b/ports/alif/system_tick.h @@ -34,5 +34,7 @@ void system_tick_init(void); uint32_t system_tick_get_u32(void); uint64_t system_tick_get_u64(void); void system_tick_wfe_with_timeout_us(uint32_t timeout_us); +void system_tick_schedule_after_us(uint32_t ticks_us); +void system_tick_schedule_callback(void); #endif // MICROPY_INCLUDED_ALIF_SYSTEM_TICK_H |
