diff options
| -rw-r--r-- | ports/alif/mpconfigport.h | 6 | ||||
| -rw-r--r-- | ports/alif/mphalport.c | 16 | ||||
| -rw-r--r-- | ports/alif/system_tick.c | 64 | ||||
| -rw-r--r-- | ports/alif/system_tick.h | 2 |
4 files changed, 82 insertions, 6 deletions
diff --git a/ports/alif/mpconfigport.h b/ports/alif/mpconfigport.h index b1a019106..0fee2c379 100644 --- a/ports/alif/mpconfigport.h +++ b/ports/alif/mpconfigport.h @@ -37,10 +37,14 @@ #endif // Select the low-level system tick implementation. -#if !defined(MICROPY_HW_SYSTEM_TICK_USE_LPTIMER) \ +#if !defined(MICROPY_HW_SYSTEM_TICK_USE_SYSTICK) \ + && !defined(MICROPY_HW_SYSTEM_TICK_USE_LPTIMER) \ && !defined(MICROPY_HW_SYSTEM_TICK_USE_UTIMER) #define MICROPY_HW_SYSTEM_TICK_USE_UTIMER (1) #endif +#if MICROPY_HW_SYSTEM_TICK_USE_SYSTICK +#define MICROPY_SOFT_TIMER_TICKS_MS system_tick_ms_counter +#endif #ifndef MICROPY_HW_ENABLE_OSPI #define MICROPY_HW_ENABLE_OSPI (CORE_M55_HP) diff --git a/ports/alif/mphalport.c b/ports/alif/mphalport.c index becac8f3b..5e3dad141 100644 --- a/ports/alif/mphalport.c +++ b/ports/alif/mphalport.c @@ -120,7 +120,9 @@ mp_uint_t mp_hal_ticks_cpu(void) { mp_uint_t mp_hal_ticks_us(void) { // Convert system tick to microsecond counter. - #if MICROPY_HW_SYSTEM_TICK_USE_LPTIMER + #if MICROPY_HW_SYSTEM_TICK_USE_SYSTICK + return system_tick_get_u64(); + #elif MICROPY_HW_SYSTEM_TICK_USE_LPTIMER return system_tick_get_u64() * 1000000 / system_tick_source_hz; #else return system_tick_get_u64() / system_core_clock_mhz; @@ -129,7 +131,9 @@ mp_uint_t mp_hal_ticks_us(void) { mp_uint_t mp_hal_ticks_ms(void) { // Convert system tick to millisecond counter. - #if MICROPY_HW_SYSTEM_TICK_USE_LPTIMER + #if MICROPY_HW_SYSTEM_TICK_USE_SYSTICK + return system_tick_get_u64() / 1000ULL; + #elif MICROPY_HW_SYSTEM_TICK_USE_LPTIMER return system_tick_get_u64() * 1000ULL / system_tick_source_hz; #else return system_tick_get_u64() / (SystemCoreClock / 1000); @@ -137,7 +141,9 @@ mp_uint_t mp_hal_ticks_ms(void) { } void mp_hal_delay_us(mp_uint_t us) { - #if MICROPY_HW_SYSTEM_TICK_USE_LPTIMER + #if MICROPY_HW_SYSTEM_TICK_USE_SYSTICK + uint64_t ticks_delay = (uint64_t)us; + #elif MICROPY_HW_SYSTEM_TICK_USE_LPTIMER uint64_t ticks_delay = (uint64_t)us * system_tick_source_hz / 1000000; #else uint64_t ticks_delay = (uint64_t)us * system_core_clock_mhz; @@ -167,6 +173,8 @@ void system_tick_schedule_callback(void) { pendsv_schedule_dispatch(PENDSV_DISPATCH_SOFT_TIMER, soft_timer_handler); } +#if !defined(MICROPY_SOFT_TIMER_TICKS_MS) + uint32_t soft_timer_get_ms(void) { return mp_hal_ticks_ms(); } @@ -177,3 +185,5 @@ void soft_timer_schedule_at_ms(uint32_t ticks_ms) { ms = MIN(ms, 4000000); // ensure ms * 1000 doesn't overflow system_tick_schedule_after_us(ms * 1000); } + +#endif diff --git a/ports/alif/system_tick.c b/ports/alif/system_tick.c index 72b8d021c..4f161e670 100644 --- a/ports/alif/system_tick.c +++ b/ports/alif/system_tick.c @@ -29,7 +29,69 @@ #define MIN(x, y) ((x) < (y) ? (x) : (y)) -#if MICROPY_HW_SYSTEM_TICK_USE_LPTIMER +#if MICROPY_HW_SYSTEM_TICK_USE_SYSTICK + +#include "shared/runtime/softtimer.h" +#include "pendsv.h" + +volatile uint32_t system_tick_ms_counter; + +void system_tick_init(void) { + // Configure SysTick to run at 1kHz (1ms interval) + SysTick_Config(SystemCoreClock / 1000); + NVIC_SetPriority(SysTick_IRQn, IRQ_PRI_SYSTEM_TICK); + NVIC_EnableIRQ(SysTick_IRQn); +} + +void SysTick_Handler(void) { + uint32_t uw_tick = system_tick_ms_counter + 1; + system_tick_ms_counter = uw_tick; + + // Read the systick control register to clear the COUNTFLAG bit. + SysTick->CTRL; + + if (soft_timer_next == uw_tick) { + pendsv_schedule_dispatch(PENDSV_DISPATCH_SOFT_TIMER, soft_timer_handler); + } +} + +uint32_t system_tick_get_u32(void) { + return system_tick_get_u64(); +} + +uint64_t system_tick_get_u64(void) { + mp_uint_t irq_state = disable_irq(); + uint32_t counter = SysTick->VAL; + uint32_t milliseconds = system_tick_ms_counter; + uint32_t status = SysTick->CTRL; + enable_irq(irq_state); + + // It's still possible for the COUNTFLAG bit to get set if the counter was + // reloaded between reading VAL and reading CTRL. With interrupts disabled + // it definitely takes less than 50 cycles between reading VAL and + // reading CTRL, so the test (counter > 50) is to cover the case where VAL + // is +ve and very close to zero, and the COUNTFLAG bit is also set. + if ((status & SysTick_CTRL_COUNTFLAG_Msk) && counter > 50) { + // This means that the HW reloaded VAL between the time we read VAL and the + // time we read CTRL, which implies that there is an interrupt pending + // to increment the tick counter. + milliseconds++; + } + uint32_t load = SysTick->LOAD; + counter = load - counter; // Convert from decrementing to incrementing + + // Calculate 64-bit microsecond counter. + return (uint64_t)milliseconds * 1000ULL + (uint64_t)((counter * 1000) / (load + 1)); +} + +void system_tick_wfe_with_timeout_us(uint32_t timeout_us) { + if (timeout_us > 1000) { + // SysTick will wake us in at most 1ms. + __WFI(); + } +} + +#elif MICROPY_HW_SYSTEM_TICK_USE_LPTIMER #include "lptimer.h" #include "sys_ctrl_lptimer.h" diff --git a/ports/alif/system_tick.h b/ports/alif/system_tick.h index d808b7632..a380808b2 100644 --- a/ports/alif/system_tick.h +++ b/ports/alif/system_tick.h @@ -30,7 +30,7 @@ #if MICROPY_HW_SYSTEM_TICK_USE_LPTIMER extern uint64_t system_tick_source_hz; -#else +#elif MICROPY_HW_SYSTEM_TICK_USE_UTIMER extern uint64_t system_core_clock_mhz; #endif |
