mirror of
https://github.com/micropython/micropython.git
synced 2025-12-15 17:30:14 +01:00
alif/system_tick: Implement optional ARM SysTick support for systick.
Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
@@ -37,10 +37,14 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Select the low-level system tick implementation.
|
// 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)
|
&& !defined(MICROPY_HW_SYSTEM_TICK_USE_UTIMER)
|
||||||
#define MICROPY_HW_SYSTEM_TICK_USE_UTIMER (1)
|
#define MICROPY_HW_SYSTEM_TICK_USE_UTIMER (1)
|
||||||
#endif
|
#endif
|
||||||
|
#if MICROPY_HW_SYSTEM_TICK_USE_SYSTICK
|
||||||
|
#define MICROPY_SOFT_TIMER_TICKS_MS system_tick_ms_counter
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef MICROPY_HW_ENABLE_OSPI
|
#ifndef MICROPY_HW_ENABLE_OSPI
|
||||||
#define MICROPY_HW_ENABLE_OSPI (CORE_M55_HP)
|
#define MICROPY_HW_ENABLE_OSPI (CORE_M55_HP)
|
||||||
|
|||||||
@@ -120,7 +120,9 @@ mp_uint_t mp_hal_ticks_cpu(void) {
|
|||||||
|
|
||||||
mp_uint_t mp_hal_ticks_us(void) {
|
mp_uint_t mp_hal_ticks_us(void) {
|
||||||
// Convert system tick to microsecond counter.
|
// 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;
|
return system_tick_get_u64() * 1000000 / system_tick_source_hz;
|
||||||
#else
|
#else
|
||||||
return system_tick_get_u64() / system_core_clock_mhz;
|
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) {
|
mp_uint_t mp_hal_ticks_ms(void) {
|
||||||
// Convert system tick to millisecond counter.
|
// 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;
|
return system_tick_get_u64() * 1000ULL / system_tick_source_hz;
|
||||||
#else
|
#else
|
||||||
return system_tick_get_u64() / (SystemCoreClock / 1000);
|
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) {
|
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;
|
uint64_t ticks_delay = (uint64_t)us * system_tick_source_hz / 1000000;
|
||||||
#else
|
#else
|
||||||
uint64_t ticks_delay = (uint64_t)us * system_core_clock_mhz;
|
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);
|
pendsv_schedule_dispatch(PENDSV_DISPATCH_SOFT_TIMER, soft_timer_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(MICROPY_SOFT_TIMER_TICKS_MS)
|
||||||
|
|
||||||
uint32_t soft_timer_get_ms(void) {
|
uint32_t soft_timer_get_ms(void) {
|
||||||
return mp_hal_ticks_ms();
|
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
|
ms = MIN(ms, 4000000); // ensure ms * 1000 doesn't overflow
|
||||||
system_tick_schedule_after_us(ms * 1000);
|
system_tick_schedule_after_us(ms * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -29,7 +29,69 @@
|
|||||||
|
|
||||||
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
#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 "lptimer.h"
|
||||||
#include "sys_ctrl_lptimer.h"
|
#include "sys_ctrl_lptimer.h"
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
#if MICROPY_HW_SYSTEM_TICK_USE_LPTIMER
|
#if MICROPY_HW_SYSTEM_TICK_USE_LPTIMER
|
||||||
extern uint64_t system_tick_source_hz;
|
extern uint64_t system_tick_source_hz;
|
||||||
#else
|
#elif MICROPY_HW_SYSTEM_TICK_USE_UTIMER
|
||||||
extern uint64_t system_core_clock_mhz;
|
extern uint64_t system_core_clock_mhz;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user