How to deal with local interrupts in HiFive1?

Hello, I am trying to handle local interrupts.
That’s what I do, in my handler for timer interrupts:

  • disable timer interrupts in mie
  • read a current value from mtime
  • copy it to mtimecmp (both are 64bit width types)
  • add some big value to mtimecmp
  • enable timer interrupts in mie.

And I have two boards and the problem is that on one of them interrupts are permanently generated because mip register is always 1 in mtip position, though mtimecmp is greater than mtime, and are not generated at all on the other.

In this piece of code, I turn on interrupts:
la t0, RISCV_Exception_default
csrs mtvec, t0
li t0, 0x88
csrs mie, t0
csrsi mstatus, 0x8

My start file:
and ISR:

Now my boards behave in the same way - I can’t clear interrupt pending bit in mtip, so interrupts keep generating.

MTIME and MTIMECMP are 64-bit values, as you mentioned above. But in your start.S, you seem to be treating them only as 32-bit values. MTIMECMP is not reset to 0, so you should, at least, set the upper bits of MTIMECMP as well. The RISC-V Privileged Spec has a snippet for how to safely set MTIMECMP on a 32-bit system.

In your irq.c you are treating them as 64-bit values, but I’m wondering if you are ever even getting that far since the first MTIMECMP may be wrong.

Another note, you probably want to use csrw, not csrs, to set mtvec.

Thank you,
yes, in my start.S it is only 32-bit value as a quick solution, because my counter never overflows 32-bit value(never runs so long). I will change it a bit later.

In my irq.c there is also a temporary static variable cntr, which is incremented at the handler. And after some time running I can see a big value in cntr. Also, there is a static array Times, and now for example, I can run my executable and print the values. These are first 10 values if mtime during interrupts’ triggering:

(gdb) p /x *times@10
$66 = {0x63650, 0x63669, 0x6366a, 0x6366a, 0x6366a, 0x6366b, 0x6366b, 0x6366c, 0x6366c, 0x6366d}

Yes, you are right about csrw.

I found the problem, I made a mistake in my code, instead of:
if ((cause & MCAUSE_MTIME) == MCAUSE_MTIME) {
I have written:
if (cause & MCAUSE_MTIME) {

now local interrupts work.

Great! I think that line might still be a little off, you may want if ((cause & MCAUSE_CAUSE) == MCAUSE_MTIME) to compare the entire cause.

EDIT: Corrected thanks to @tommythorn’s feedback below

I assume this was a typo and you really meant


otherwise it the compiler will treat this is



if (0)

Yes, thank you. Will edit above