Learning External interrupts

Hi @Ted usually mie is the last thing to enable, certainly after setting up everything else and, most importantly, mtvec. It’s good you remember to keep the handler on an 64-byte boundary. The first two bits determine absolute or vectored mode, you might check with gdb to make sure PC is going where you think.

Here is a discussion and picture of the PLIC interrupt flow and some tips I put together to initialize and set up GPIO pins for PLIC; they are from an assembly code perspective, which I think is clearer to work with.

You may also find my github repo Demonstrating MTVEC helpful: look at the start.s file.

When an interrupt occurs, you should first determine whether it’s a synchronous exception or asynchronous interrupt. Then, in latter case, you should determine whether the source of interrupt is software, timer, or external/PLIC. In that latter case you claim and acknowledge (complete) the interrupt, and jump as directed to the appropriate source ID.

Make sure the jump tables are on 2-byte or four-byte boundaries, depending whether you use compressed or long form versions of the j instruction.

Lastly, don’t forget the mret at the end, which automatically clears the mip flag.

It is easy to mix up the interrupt enable bits of CSR_MIE_MxIE (where x is S, T, or E for Software, Timer, or External, respectively) with CSR_MSTATUS_MIE which is the main on/off switch for the entire interrupt process. It looks like your C-code already does this correctly, though.

1 Like