summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/alif/main.c2
-rw-r--r--ports/alif/mphalport.c17
-rw-r--r--ports/alif/system_tick.c44
-rw-r--r--ports/alif/system_tick.h2
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