Skip to content

Commit e1f063a

Browse files
iabdalkaderdpgeorge
authored andcommitted
qemu/mcu/arm: Implement a SysTick driver.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
1 parent c04d2d6 commit e1f063a

File tree

4 files changed

+90
-1
lines changed

4 files changed

+90
-1
lines changed

ports/qemu/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
7777
SRC_C += \
7878
mcu/arm/errorhandler.c \
7979
mcu/arm/startup.c \
80+
mcu/arm/ticks.c \
8081
shared/runtime/semihosting_arm.c \
8182

8283
endif

ports/qemu/mcu/arm/errorhandler.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ __attribute__((naked)) MP_NORETURN void PendSV_Handler(void) {
191191
exception_handler(PENDING_SV);
192192
}
193193

194-
__attribute__((naked)) MP_NORETURN void SysTick_Handler(void) {
194+
__attribute__((naked, weak)) MP_NORETURN void SysTick_Handler(void) {
195195
exception_handler(SYSTEM_TICK);
196196
}
197197

ports/qemu/mcu/arm/startup.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ const uint32_t isr_vector[] __attribute__((section(".isr_vector"))) = {
118118
void _start(void) {
119119
mp_semihosting_init();
120120

121+
extern void ticks_init(void);
122+
ticks_init();
123+
121124
// Enable the UART
122125
uart_init();
123126

ports/qemu/mcu/arm/ticks.c

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2025 Ibrahim Abdelkader <iabdalkader@openmv.io>
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include <stdint.h>
28+
29+
// CPU frequency
30+
#ifndef CPU_FREQ_HZ
31+
#define CPU_FREQ_HZ 25000000u
32+
#endif
33+
34+
// SysTick registers
35+
#define SYSTICK_BASE 0xE000E010
36+
#define SYSTICK_CSR (*(volatile uint32_t *)(SYSTICK_BASE + 0x00))
37+
#define SYSTICK_RVR (*(volatile uint32_t *)(SYSTICK_BASE + 0x04))
38+
#define SYSTICK_CVR (*(volatile uint32_t *)(SYSTICK_BASE + 0x08))
39+
40+
// SysTick config bits
41+
#define SYSTICK_CSR_ENABLE (1 << 0)
42+
#define SYSTICK_CSR_TICKINT (1 << 1)
43+
#define SYSTICK_CSR_CLKSOURCE (1 << 2)
44+
45+
static volatile uint32_t _ticks_ms = 0;
46+
#if defined(__ARM_ARCH_ISA_ARM)
47+
static volatile uint32_t _ticks_us = 0;
48+
#endif
49+
50+
void ticks_init(void) {
51+
#if !defined(__ARM_ARCH_ISA_ARM)
52+
// Configure SysTick: reload at 1ms intervals (Cortex-M)
53+
SYSTICK_CVR = 0;
54+
SYSTICK_RVR = (CPU_FREQ_HZ / 1000) - 1;
55+
SYSTICK_CSR = SYSTICK_CSR_ENABLE | SYSTICK_CSR_TICKINT | SYSTICK_CSR_CLKSOURCE;
56+
#endif
57+
}
58+
59+
uintptr_t ticks_ms(void) {
60+
#if defined(__ARM_ARCH_ISA_ARM)
61+
return _ticks_us++ / 1000;
62+
#else
63+
return _ticks_ms;
64+
#endif
65+
}
66+
67+
uintptr_t ticks_us(void) {
68+
#if defined(__ARM_ARCH_ISA_ARM)
69+
return _ticks_us++;
70+
#else
71+
// Get current values atomically
72+
uint32_t ms = _ticks_ms;
73+
uint32_t cvr = SYSTICK_CVR;
74+
75+
// Calculate microseconds from the down-counter
76+
uint32_t elapsed_cycles = SYSTICK_RVR - cvr;
77+
uint32_t us_fraction = (elapsed_cycles * 1000) / (CPU_FREQ_HZ / 1000);
78+
79+
return (ms * 1000) + us_fraction;
80+
#endif
81+
}
82+
83+
void SysTick_Handler(void) {
84+
_ticks_ms++;
85+
}

0 commit comments

Comments
 (0)