diff options
| author | iabdalkader <i.abdalkader@gmail.com> | 2025-10-11 15:50:37 +0200 |
|---|---|---|
| committer | Damien George <damien@micropython.org> | 2025-10-24 17:31:43 +1100 |
| commit | e1f063a1fa622b0317a22e907ddb643d17514f40 (patch) | |
| tree | b1a5a8e050c941be432e869fd4e6cde39b7c67ea | |
| parent | c04d2d691c77ca3a4a623e0af866e58f67914573 (diff) | |
qemu/mcu/arm: Implement a SysTick driver.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
| -rw-r--r-- | ports/qemu/Makefile | 1 | ||||
| -rw-r--r-- | ports/qemu/mcu/arm/errorhandler.c | 2 | ||||
| -rw-r--r-- | ports/qemu/mcu/arm/startup.c | 3 | ||||
| -rw-r--r-- | ports/qemu/mcu/arm/ticks.c | 85 |
4 files changed, 90 insertions, 1 deletions
diff --git a/ports/qemu/Makefile b/ports/qemu/Makefile index 84711cc45..4325a96f9 100644 --- a/ports/qemu/Makefile +++ b/ports/qemu/Makefile @@ -77,6 +77,7 @@ LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) SRC_C += \ mcu/arm/errorhandler.c \ mcu/arm/startup.c \ + mcu/arm/ticks.c \ shared/runtime/semihosting_arm.c \ endif diff --git a/ports/qemu/mcu/arm/errorhandler.c b/ports/qemu/mcu/arm/errorhandler.c index 278bc8d4e..9f79aa5f7 100644 --- a/ports/qemu/mcu/arm/errorhandler.c +++ b/ports/qemu/mcu/arm/errorhandler.c @@ -191,7 +191,7 @@ __attribute__((naked)) MP_NORETURN void PendSV_Handler(void) { exception_handler(PENDING_SV); } -__attribute__((naked)) MP_NORETURN void SysTick_Handler(void) { +__attribute__((naked, weak)) MP_NORETURN void SysTick_Handler(void) { exception_handler(SYSTEM_TICK); } diff --git a/ports/qemu/mcu/arm/startup.c b/ports/qemu/mcu/arm/startup.c index 56d246b14..add045b26 100644 --- a/ports/qemu/mcu/arm/startup.c +++ b/ports/qemu/mcu/arm/startup.c @@ -118,6 +118,9 @@ const uint32_t isr_vector[] __attribute__((section(".isr_vector"))) = { void _start(void) { mp_semihosting_init(); + extern void ticks_init(void); + ticks_init(); + // Enable the UART uart_init(); diff --git a/ports/qemu/mcu/arm/ticks.c b/ports/qemu/mcu/arm/ticks.c new file mode 100644 index 000000000..7a5d16ed5 --- /dev/null +++ b/ports/qemu/mcu/arm/ticks.c @@ -0,0 +1,85 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2025 Ibrahim Abdelkader <iabdalkader@openmv.io> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <stdint.h> + +// CPU frequency +#ifndef CPU_FREQ_HZ +#define CPU_FREQ_HZ 25000000u +#endif + +// SysTick registers +#define SYSTICK_BASE 0xE000E010 +#define SYSTICK_CSR (*(volatile uint32_t *)(SYSTICK_BASE + 0x00)) +#define SYSTICK_RVR (*(volatile uint32_t *)(SYSTICK_BASE + 0x04)) +#define SYSTICK_CVR (*(volatile uint32_t *)(SYSTICK_BASE + 0x08)) + +// SysTick config bits +#define SYSTICK_CSR_ENABLE (1 << 0) +#define SYSTICK_CSR_TICKINT (1 << 1) +#define SYSTICK_CSR_CLKSOURCE (1 << 2) + +static volatile uint32_t _ticks_ms = 0; +#if defined(__ARM_ARCH_ISA_ARM) +static volatile uint32_t _ticks_us = 0; +#endif + +void ticks_init(void) { + #if !defined(__ARM_ARCH_ISA_ARM) + // Configure SysTick: reload at 1ms intervals (Cortex-M) + SYSTICK_CVR = 0; + SYSTICK_RVR = (CPU_FREQ_HZ / 1000) - 1; + SYSTICK_CSR = SYSTICK_CSR_ENABLE | SYSTICK_CSR_TICKINT | SYSTICK_CSR_CLKSOURCE; + #endif +} + +uintptr_t ticks_ms(void) { + #if defined(__ARM_ARCH_ISA_ARM) + return _ticks_us++ / 1000; + #else + return _ticks_ms; + #endif +} + +uintptr_t ticks_us(void) { + #if defined(__ARM_ARCH_ISA_ARM) + return _ticks_us++; + #else + // Get current values atomically + uint32_t ms = _ticks_ms; + uint32_t cvr = SYSTICK_CVR; + + // Calculate microseconds from the down-counter + uint32_t elapsed_cycles = SYSTICK_RVR - cvr; + uint32_t us_fraction = (elapsed_cycles * 1000) / (CPU_FREQ_HZ / 1000); + + return (ms * 1000) + us_fraction; + #endif +} + +void SysTick_Handler(void) { + _ticks_ms++; +} |
