- RISC-V Reset and NMI
- RISC-V Interrupts
- RISC-V Synchronous Exceptions
- RISC-V Scratch Registers
- Interrupt Handlers In C
RISC-V Reset and NMIThese vectors are implementation defined.
- Non Maskable Interrupt (NMI)
These are the interrupts that are defined by the base ISA.
Assertion and Service
- mcause.Exception_Code (Where Interrupt==1) describes the possible interrupt sources.
- When the interrupt condition is met, a bit in the interrupt pending register (mip) is set.
- To service an interrupt the global interrupt enable (mstatus.mie ) and the per interrupt enable bit (mie) both need to be set.
- If multiple interrupts are pending and enabled simultaneously then the order they are serviced is determined by a fixed priority.
- Interrupts can't be pre-empted without the ISR writing to (mstatus.mie).
Vectored or Direct
Vectored or direct interrupts are both possible.
- mtvec.Mode, the lower 2 bits of the vector.
- When this is 0, it points to a single interrupt service routine (ISR).
- When this is 0, it points to the base of table of ISR entry points (4 bytes per entry).
- Regardless, the address of the ISR is loaded to the PC, so for vectored interrupts the entry should be a jump.
The exception/interrupt handling seems to be designed around a few root interrupt sources, with external multiplexing of platform interrupts.
- The priority assignment is a simple fixed priority scheme. Within the priviledge level, the higher the bit the higher the priority.
- In the standard interrupts there is a sigle external interrupt bit ( mip.meip ). This can be used to service an external interrupt controller.
- Bits 16 and above of the mip/mie registers are platform specific. This can be used to bring platform interrupts in as root interrupt sources.
The entry procedure for a interrupt I into machine mode:
- mcause.interrupt = 1; mcause.exception_code = I
- mstatus.mpie = 1, save previous interrupt enable. (See ISR stack.)
- mstatus.mpp = Previous privilege mode (m, s or u).
- mstatus.mie = 0, interrupts are disabled unless the ISR re-writes this.
- mepc = Interrupted PC, save the return address.
- IF mtvec.Mode == Direct(0) THEN; PC = (mtvec & ~0xF)
- IF mtvec.Mode == Vectored(1) THEN; PC = (mtvec & ~0xF) + (I * 4)
Base + Offset
|msi||3||0x0000000c||m||Machine Software Interrupt||mip.msip = Memory mapped control registers allow this bit to be written to assert a software interrupt. (It is used to provide a software interrupt from other harts).|
|mti||7||0x0000001c||m||Machine Timer Interrupt||mip.mtip = mtime >= mtimecmp (mtimecmp needs to be written to clear the pending bit).|
|mei||11||0x0000002c||m||Machine External Interrupt||mip.meip = External interrupt signal asserted|
|ssi||1||0x00000004||s||Supervisor Software Interrupt||mip.ssi = Implementation defined.|
|sti||5||0x00000014||s||Supervisor Timer Interrupt||mip.sti = Implementation defined.|
|sei||9||0x00000024||s||Supervisor External Interrupt||mip.sei = Implementation defined.|
|usi||0||0x00000000||u||User Software Interrupt||mip.usi = Implementation defined.|
|uti||4||0x00000010||u||User Timer Interrupt||mip.uti = Implementation defined.|
|uei||8||0x00000020||u||User External Interrupt||mip.uei = Implementation defined.|
|platform_defined||16+||0x00000040||m||Optional platform defined interrupt sources.||mip.platform_defined = Implementation defined.|
Supervisor-level interrupts require support of the s mode privilege. The mideleg register needs to set by m mode to enable s mode to take the interrupts.
Supervisor mode CSRs matching machine mode CSRs are used to implement supervisor interrupts and exceptions. Some are a restricted view to the machine mode CSRs, with dedicated bits for supervisor status, while others are replicated to dedicated registers.
|Restricted View CSRs||sstatus, sip, sie|
|Replicated CSRs||scause, sepc, stvec, sscratch|
The entry procedure for a interrupt I into supervisor mode (Assuming mideleg[I] is set):Supervisor interrupts assuming mideleg.ssi, mideleg.sti, mideleg.sei are set:
- scause.interrupt = 1; scause.exception_code = I
- sstatus.spie = 1, save previous interrupt enable. (See ISR stack.)
- sstatus.spp = Previous privilege mode (s or u).
- sstatus.sie = 0, interrupts are disabled unless the ISR re-writes this.
- sepc = Interrupted PC, save the return address.
- IF stvec.mode == Direct THEN; PC = (stvec.Base & ~0xF)
- IF stvec.mode == Vectored THEN; PC = (stvec.Base & ~0xF) + (I * 4)
Base + Offset
|ssi||1||0x00000004||s||Supervisor Software Interrupt||sip.ssip = Implementation dependent, CSR is written by software on the local hart to assert a software interrupt.|
|sti||5||0x00000014||s||Supervisor Timer Interrupt||sip.stip = Implementation dependent, Written my 'm' mode timer interrupt handler, an SEE call needs to be made to clear this).|
|sei||9||0x00000024||s||Supervisor External Interrupt||sip.seip = Implementation dependent, External interrupt signal asserted|
User-level interrupts are optional for implementation. They rely on the n extension. This specification is not yet complete.User interrupts assuming sideleg.usi, sideleg.uti, sideleg.uei are set:
Base + Offset
|usi||0||0x00000000||u||User Software Interrupt|
|uti||4||0x00000010||u||User Timer Interrupt|
|uei||8||0x00000020||u||User External Interrupt|
Available for Platform Use
mcause.exception_code values greater than 16 are available for platform use, allowing use if bits 16..mxlen-1 in mip and mie. The platform can define a fixed priority scheme. These can be used to implement a fast vectored interrupt scheme.
RISC-V Synchronous Exceptions
These are the exceptions that are defined by the base ISA.
- Synchronous Exceptions are always caused by software execution. e.g. Faults, errors and environment calls.
- Mcause.Exception_Code (Where Interrupt==0) describes the possible interrupt sources.
- Simultaneous exceptions are serviced according to a fixed priority.
The entry procedure for an exception E into machine mode:
- mcause.interrupt = 0; mcause.exception_code = E
- mstatus.mpie = mstatus.mie, save previous interrupt enable
- mstatus.mpp = Previous privilege mode (m, s or u)
- mstatus.mie = 0
- Privilege mode = m
- mtval = Exception specific information related to the cause.
- mepc = PC, Instruction that caused trap.
- PC = (mtvec & ~0xF) (Exceptions are not vectored)
As for interrupts exception E can be taken in supervisor or user mode if available and configured via medeleg or sedeleg. The exception needs to be generated in the same or lower privilege level.
Delegation to Lower Privilege Mode
There are two methods to delegate exception E to lower privilege modes:
RISC-V Scratch Registers
Interrupt Handlers In C
For GCC RISC-V Function Attributes are used to mark a function as an interrupt handler. These are also supported by LLVM
void f (void) __attribute__ ((interrupt ("user")));As a parameter user, supervisor, and machine can be specified as the type. (To select the correct return instruction).