title: What is intended/correct way to handle interrupts and use the WFI risc-v cpu instruction?
body: <p>I am very new to bare metal programming and have never delt with interrupts before, but I've been learning on a RISC-V FE310-G002 SOC powered dev board.</p>
  <p>I've been reading about the RISC-V WFI (Wait for interrupt) instruction and from the manuals, it doesn't sound like you can rely on it to actually sleep the core.  Instead, it only suggests that execution can be halted to the system and that the instruction should be treated more like a NOP.  However, this seems rather useless to me.  Consider the following ASM program snippet:</p>
  <pre><code>wfi_loop:
  WFI
  J wfi_loop
  </code></pre>
  <p>This would have to be done since WFI can not be depended on.  However, upon MRET from the interrupt handler, you would still be caught in the loop.  So you would have to make it conditional against a global variable whose value is updated in the interrupt handler.  This seems very messy.</p>
  <p>Also, if your implementation does in fact honor the WFI instruction and the interrupt is triggered just prior to the execution of the WFI instruction, the entire core will stall until some other interrupt is triggered since it will return prior to the WFI instruction.</p>
  <p>It seems that the only correct usage of the instruction would be inside of a kernel scheduler when there is no work to be done.  But even then, I don't think you would ever want to return from the interrupt handler into such code, but rather restart the scheduler algorithm from the start.  But that would be a problem too since you would somehow have to roll back the stack, etc....</p>
  <p>I keep going round and round with this in my head and I can't seem to figure out a safe use.  Maybe, if you atomically, enable interrupts in with CSRRS and then immediately call WFI like this:</p>
  <pre><code>CSRRSI zero, mie, 0x80
  wfi_loop:
  WFI
  J wfi_loop
  NOP
  NOP
  </code></pre>
  <p>Then make sure to increment the mepc register by 8 bytes before calling MRET from the interrupt handler.  The interrupt would also have to be disabled again in the mie register inside of the interrupt handler before returning.  This solution would only be safe if WFI, J, and NOP are all encoded as 4 byte instructions, regardless of whether compressed instructions are used.  It also depends on the program counter reaching the WFI instruction before it is possible for the interrupt to be triggered, after being enabled by the CSRRSI instruction.  This would then allow the interrupt to be triggered in a safe place in code and to return in such a way that it breaks out of the loop that was waiting for it.</p>
  <p>I guess I am just trying to understand what behavior I can expect from the hardware and, therefore, how to correctly call and return from interrupts and use the WFI instruction?</p>