Skip to content

Commit ada0939

Browse files
committed
alif/system_tick: Integrate soft timer.
Signed-off-by: Damien George <damien@micropython.org>
1 parent 975f84f commit ada0939

4 files changed

Lines changed: 63 additions & 2 deletions

File tree

ports/alif/main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "shared/readline/readline.h"
3434
#include "shared/runtime/gchelper.h"
3535
#include "shared/runtime/pyexec.h"
36+
#include "shared/runtime/softtimer.h"
3637
#include "shared/tinyusb/mp_usbd.h"
3738
#include "tusb.h"
3839
#include "mpuart.h"
@@ -119,6 +120,7 @@ void _start(void) {
119120

120121
soft_reset_exit:
121122
mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n");
123+
soft_timer_deinit();
122124
gc_sweep_all();
123125
mp_deinit();
124126
}

ports/alif/mphalport.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@
3131
#include "py/stream.h"
3232
#include "extmod/misc.h"
3333
#include "shared/runtime/interrupt_char.h"
34+
#include "shared/runtime/softtimer.h"
3435
#include "shared/timeutils/timeutils.h"
3536
#include "shared/tinyusb/mp_usbd.h"
3637
#include "shared/tinyusb/mp_usbd_cdc.h"
3738
#include "tusb.h"
3839
#include "mpuart.h"
40+
#include "pendsv.h"
3941
#include "system_tick.h"
4042

4143
#ifndef MICROPY_HW_STDIN_BUFFER_LEN
@@ -146,3 +148,18 @@ void mp_hal_delay_ms(mp_uint_t ms) {
146148
uint64_t mp_hal_time_ns(void) {
147149
return 0;
148150
}
151+
152+
void system_tick_schedule_callback(void) {
153+
pendsv_schedule_dispatch(PENDSV_DISPATCH_SOFT_TIMER, soft_timer_handler);
154+
}
155+
156+
uint32_t soft_timer_get_ms(void) {
157+
return mp_hal_ticks_ms();
158+
}
159+
160+
void soft_timer_schedule_at_ms(uint32_t ticks_ms) {
161+
int32_t ms = soft_timer_ticks_diff(ticks_ms, mp_hal_ticks_ms());
162+
ms = MAX(0, ms);
163+
ms = MIN(ms, 4000000); // ensure ms * 1000 doesn't overflow
164+
system_tick_schedule_after_us(ms * 1000);
165+
}

ports/alif/system_tick.c

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,13 @@ void system_tick_init(void) {
5959
utimer_control_enable(UTIMER, UTIMER_CHANNEL);
6060
utimer_counter_start(UTIMER, UTIMER_CHANNEL);
6161

62-
// Set up the UTIMER compare interrupt, to be used later.
62+
// Set up the UTIMER compare A interrupt, to be used by system_tick_wfe_with_timeout_us.
6363
system_tick_nvic_config(2);
6464
UTIMER->UTIMER_CHANNEL_CFG[UTIMER_CHANNEL].UTIMER_COMPARE_CTRL_A |= COMPARE_CTRL_DRV_COMPARE_EN;
65+
66+
// Set up the UTIMER compare B interrupt, to be used by soft-timer.
67+
system_tick_nvic_config(4);
68+
UTIMER->UTIMER_CHANNEL_CFG[UTIMER_CHANNEL].UTIMER_COMPARE_CTRL_B |= COMPARE_CTRL_DRV_COMPARE_EN;
6569
}
6670

6771
// COMPARE_A_BUF1
@@ -73,6 +77,17 @@ void UTIMER_IRQ90Handler(void) {
7377
}
7478
}
7579

80+
// COMPARE_B_BUF1
81+
void UTIMER_IRQ92Handler(void) {
82+
uint32_t chan_interrupt = UTIMER->UTIMER_CHANNEL_CFG[UTIMER_CHANNEL].UTIMER_CHAN_INTERRUPT;
83+
if (chan_interrupt & CHAN_INTERRUPT_COMPARE_B_BUF1_MASK) {
84+
utimer_clear_interrupt(UTIMER, UTIMER_CHANNEL, CHAN_INTERRUPT_COMPARE_B_BUF1_MASK);
85+
utimer_mask_interrupt(UTIMER, UTIMER_CHANNEL, CHAN_INTERRUPT_COMPARE_B_BUF1_MASK);
86+
system_tick_schedule_callback();
87+
__SEV();
88+
}
89+
}
90+
7691
// OVER_FLOW
7792
void UTIMER_IRQ95Handler(void) {
7893
uint32_t chan_interrupt = UTIMER->UTIMER_CHANNEL_CFG[UTIMER_CHANNEL].UTIMER_CHAN_INTERRUPT;
@@ -106,7 +121,7 @@ uint64_t system_tick_get_u64(void) {
106121
}
107122

108123
void system_tick_wfe_with_timeout_us(uint32_t timeout_us) {
109-
// Maximum 10 second timeout, to not overflow signed 32-bit ticks when
124+
// Maximum 10 second timeout, to not overflow 32-bit ticks when
110125
// system_core_clock_mhz==400.
111126
uint32_t timeout_ticks = MIN(timeout_us, 10000000) * system_core_clock_mhz;
112127

@@ -126,3 +141,28 @@ void system_tick_wfe_with_timeout_us(uint32_t timeout_us) {
126141
// Disable the UTIMER compare interrupt.
127142
utimer_mask_interrupt(UTIMER, UTIMER_CHANNEL, CHAN_INTERRUPT_COMPARE_A_BUF1_MASK);
128143
}
144+
145+
void system_tick_schedule_after_us(uint32_t ticks_us) {
146+
// Disable the interrupt in case it's still active.
147+
utimer_mask_interrupt(UTIMER, UTIMER_CHANNEL, CHAN_INTERRUPT_COMPARE_B_BUF1_MASK);
148+
149+
// Maximum 10 second timeout, to not overflow 32-bit ticks when
150+
// system_core_clock_mhz==400.
151+
uint32_t timeout_ticks = MIN(ticks_us, 10000000) * system_core_clock_mhz;
152+
153+
// Set up the UTIMER compare interrupt to fire after the given timeout.
154+
uint32_t cntr = utimer_get_count(UTIMER, UTIMER_CHANNEL, UTIMER_CNTR);
155+
utimer_set_count(UTIMER, UTIMER_CHANNEL, UTIMER_COMPARE_B_BUF1, cntr + timeout_ticks);
156+
utimer_clear_interrupt(UTIMER, UTIMER_CHANNEL, CHAN_INTERRUPT_COMPARE_B_BUF1_MASK);
157+
utimer_unmask_interrupt(UTIMER, UTIMER_CHANNEL, CHAN_INTERRUPT_COMPARE_B_BUF1_MASK);
158+
159+
// Handle the case of short timeouts.
160+
uint32_t cntr2 = utimer_get_count(UTIMER, UTIMER_CHANNEL, UTIMER_CNTR);
161+
if ((uint32_t)(cntr2 - cntr) >= timeout_ticks) {
162+
if (!(UTIMER->UTIMER_CHANNEL_CFG[UTIMER_CHANNEL].UTIMER_CHAN_INTERRUPT_MASK & CHAN_INTERRUPT_COMPARE_B_BUF1_MASK)) {
163+
// Interrupt is still enabled, so disable it and manually call the callback.
164+
utimer_mask_interrupt(UTIMER, UTIMER_CHANNEL, CHAN_INTERRUPT_COMPARE_B_BUF1_MASK);
165+
system_tick_schedule_callback();
166+
}
167+
}
168+
}

ports/alif/system_tick.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,7 @@ void system_tick_init(void);
3434
uint32_t system_tick_get_u32(void);
3535
uint64_t system_tick_get_u64(void);
3636
void system_tick_wfe_with_timeout_us(uint32_t timeout_us);
37+
void system_tick_schedule_after_us(uint32_t ticks_us);
38+
void system_tick_schedule_callback(void);
3739

3840
#endif // MICROPY_INCLUDED_ALIF_SYSTEM_TICK_H

0 commit comments

Comments
 (0)