Clearing Timer Interrupts

I’ve got a Sparkfun RED-V board, which is very similar to the HiFive. It’s got an FE310-G002.

I’m having trouble clearing the timer interrupt. I enable interrupts (mstatus.mie=1, mie.mtie=1) and set mtimecmp to a value higher than mtime. I get the interrupt okay (mip.mtip=1, mcause.interrupt=1, mcause.code=7).

My understanding is that to clear the timer interrupt I need to write a value to mtimecmp that’s higher than the current value of mtime. I do that (keeping in mind that these are 64-bit registers split into two 32-bit registers), but mip.mtip stays set to one and the interrupt handler is immediately reentered when the handler executes the mret instruction.

Am I doing anything wrong here? The CLINT chapter in the FE310 manual is only one page long and is short on details, but I think I’m doing everything correctly.

unsigned long
handle_timer_trap(unsigned long mcause, unsigned long mepc)

{

unsigned long mtimelo, mtimehi;
unsigned long long mtime;

mtimelo = CLINT_REG(CLINT_MTIME);
mtimehi = CLINT_REG(CLINT_MTIME + 4);
mtime = ((unsigned long long)mtimehi << 32) + mtimelo;

mtime += MTIME_VALUE;

CLINT_REG(CLINT_MTIMECMP) = mtime & 0xffffffff;
CLINT_REG(CLINT_MTIMECMP + 4) = (mtime >> 32);

return(mepc);

}

I used the method shown in the privileged manual and now timer interrupts are getting cleared.

  CLINT_REG(CLINT_MTIMECMP) = 0xffffffff;
  CLINT_REG(CLINT_MTIMECMP + 4) = (mtime >> 32);
  CLINT_REG(CLINT_MTIMECMP) = mtime & 0xffffffff;