There are two different types of interrupts in RISC-V architecture: local and global. Local interrupts have higher priorities. CLINT (Coreplex-Local Interrupts) module is responsible for interrupts in E31-Coreplex core (RISC-V Core in FE310 SoC). There are several local interrupts in CLINT: Machine Software Interrupt, Machine Timer Interrupt, Machine External interrupt, Local Interrupts ID 0-15.
Machine Software Interrupt can be generated by any hart - local or remote. Machine Timer interrupt is for timer interrupts and Machine External interrupt is for interrupts from global interrupts controller. In order to enable local interrupts, we should:
0 (optional). Set interrupt handlers vector address (aligned to 4) in mtvec register and set mtvec.MODE to 1 (mtvec.Mode is hardwired to zero in FE310-G000).
- Set the required fields of mie register to 1.
- Set mstatus register field mie to 1.
After this step, interrupts are enabled.
In order to handle interrupts you have to make several steps:
- Save context in stack
- Call interrupt handling routine
- Read the value in mcause register
- Call an appropriate interrupt handler
- Turn off interrupts
- Make routine and clean* interrupt pending register
- Turn on interrupts
- Restore context
- Return to the state before entering to routine (with mret instruction).
In step 4.2 you have to clean interrupts pending bits in mip [1, p.28]. For each interrupt cause there are different ways to clean a pending bit . For external interrupts, mip is cleaned by PLIC (external interrupt controller), for software interrupts, generated by writing '1' to address 0x02000000 - '0' should be written to the same address, and for timer interrupts, mtimecmp (memory mapped register, 0x02004000) should be written with a value greater than one in mtime (memory mapped register, 0x0200bff8).
The description of mie register is provided in [1, p.28].