diff options
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.c | 31 |
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; +} |
