alif/system_tick: Integrate soft timer.
Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
parent
975f84f2ad
commit
ada0939c5f
4 changed files with 63 additions and 2 deletions
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue