Hazard3/test/sim/wfi_loop/main.c

54 lines
1.2 KiB
C

#include "tb_cxxrtl_io.h"
#define TIMER_INTERVAL 1000
#define MAX_IRQ_COUNT 10
#define __wfi() asm volatile ("wfi")
#define __compiler_mb() asm volatile ("" ::: "memory")
typedef struct {
volatile uint32_t mtime;
volatile uint32_t mtimeh;
volatile uint32_t mtimecmp;
volatile uint32_t mtimecmph;
} timer_hw;
timer_hw *const timer = (timer_hw*)(IO_BASE + 0x100);
int irq_count;
void __attribute__((interrupt)) isr_machine_timer() {
__compiler_mb();
++irq_count;
__compiler_mb();
tb_printf("IRQ %d\n", irq_count);
// Disable timer IRQ via MTIE, or set the next timer IRQ
if (irq_count >= MAX_IRQ_COUNT)
asm ("csrc mie, %0" :: "r" (1u << 7));
else
timer->mtimecmp = timer->mtime + TIMER_INTERVAL;
}
int main() {
irq_count = 0;
__compiler_mb();
// Per-IRQ enable for timer IRQ
asm ("csrs mie, %0" :: "r" (1u << 7));
tb_puts("Enabling IRQS...\n");
// Global IRQ enable. Timer IRQ will fire immediately.
asm ("csrsi mstatus, 0x8");
// Count the number of sleep loop iterations to make sure the wfi waits
int wait_spin_count;
while (irq_count < MAX_IRQ_COUNT) {
++wait_spin_count;
__wfi();
__compiler_mb();
}
tb_printf("Took %d IRQs, span %d times\n", irq_count, wait_spin_count);
return irq_count != wait_spin_count + 1;
}