summaryrefslogtreecommitdiff
path: root/ports/risc-v64/gnu/example_build/qemu_virt/hwtimer.c
diff options
context:
space:
mode:
Diffstat (limited to 'ports/risc-v64/gnu/example_build/qemu_virt/hwtimer.c')
-rw-r--r--ports/risc-v64/gnu/example_build/qemu_virt/hwtimer.c31
1 files changed, 21 insertions, 10 deletions
diff --git a/ports/risc-v64/gnu/example_build/qemu_virt/hwtimer.c b/ports/risc-v64/gnu/example_build/qemu_virt/hwtimer.c
index 122e71a1..5cd21f1b 100644
--- a/ports/risc-v64/gnu/example_build/qemu_virt/hwtimer.c
+++ b/ports/risc-v64/gnu/example_build/qemu_virt/hwtimer.c
@@ -9,7 +9,7 @@
/* SPDX-License-Identifier: MIT */
/***************************************************************************/
-#include "tx_port.h"
+#include "tx_api.h"
#include "csr.h"
#include "hwtimer.h"
@@ -17,20 +17,31 @@
#define CLINT_TIME (CLINT+0xBFF8)
#define CLINT_TIMECMP(hart_id) (CLINT+0x4000+8*(hart_id))
+/* RV64: naturally aligned 64-bit MMIO accesses are single loads/stores;
+ volatile keeps the compiler from caching or reordering them. */
+#define MTIME (*(volatile uint64_t *)CLINT_TIME)
+#define MTIMECMP(hart) (*(volatile uint64_t *)CLINT_TIMECMP(hart))
int hwtimer_init(void)
{
- int hart = riscv_get_core();
- uint64_t time = *((uint64_t*)CLINT_TIME);
- *((uint64_t*)CLINT_TIMECMP(hart)) = time + TICKNUM_PER_TIMER;
- return 0;
+ int hart = riscv_get_core();
+
+ MTIMECMP(hart) = MTIME + TICKNUM_PER_TIMER;
+ return 0;
}
int hwtimer_handler(void)
{
- int hart = riscv_get_core();
- uint64_t time = *((uint64_t*)CLINT_TIME);
- *((uint64_t*)CLINT_TIMECMP(hart)) = time + TICKNUM_PER_TIMER;
- return 0;
-}
+ int hart = riscv_get_core();
+
+ /* Advance from the previous compare value, so trap latency
+ does not accumulate as tick drift. */
+ uint64_t next = MTIMECMP(hart) + TICKNUM_PER_TIMER;
+ uint64_t now = MTIME;
+ if (next <= now)
+ next = now + TICKNUM_PER_TIMER;
+
+ MTIMECMP(hart) = next;
+ return 0;
+}