Exceptions and Interrupts
CV32E40P implements trap handling for interrupts and exceptions according to the RISC-V Privileged Specification, version 1.11.
The irq_i[31:16]
interrupts are a custom extension.
When entering an interrupt/exception handler, the core sets the mepc
CSR to the current program counter and saves mstatus
.MIE to mstatus
.MPIE.
All exceptions cause the core to jump to the base address of the vector table in the mtvec
CSR.
Interrupts are handled in either direct mode or vectored mode depending on the value of mtvec
.MODE. In direct mode the core
jumps to the base address of the vector table in the mtvec
CSR. In vectored mode the core jumps to the base address
plus four times the interrupt ID. Upon executing an MRET instruction, the core jumps to the program counter previously saved in the
mepc
CSR and restores mstatus
.MPIE to mstatus
.MIE.
The base address of the vector table must be aligned to 256 bytes (i.e., its least significant byte must be 0x00) and can be programmed
by writing to the mtvec
CSR. For more information, see the Control and Status Registers documentation.
The core starts fetching at the address defined by boot_addr_i
. It is assumed that the boot address is supplied via a register
to avoid long paths to the instruction fetch unit.
Interrupt Interface
Table 15 describes the interrupt interface.
Signal |
Direction |
Description |
---|---|---|
|
input |
Active high, level sensistive interrupt inputs. Not all interrupt inputs can be used on CV32E40P. Specifically irq_i[15:12], irq_i[10:8], irq_i[6:4] and irq_i[2:0] shall be tied to 0 externally as they are reserved for future standard use (or for cores which are not Machine mode only) in the RISC-V Privileged specification. irq_i[11], irq_i[7], and irq_i[3] correspond to the Machine External Interrupt (MEI), Machine Timer Interrupt (MTI), and Machine Software Interrupt (MSI) respectively. The irq_i[31:16] interrupts are a CV32E40P specific extension to the RISC-V Basic (a.k.a. CLINT) interrupt scheme. |
|
output |
Interrupt acknowledge. Set to 1 for one cycle
when the interrupt with ID |
|
output |
Interrupt index for taken interrupt. Only valid
when |
Interrupts
The irq_i[31:0]
interrupts are controlled via the mstatus
, mie
and mip
CSRs. CV32E40P uses the upper 16 bits of mie
and mip
for custom interrupts (irq_i[31:16]
),
which reflects an intended custom extension in the RISC-V Basic (a.k.a. CLINT) interrupt architecture.
After reset, all interrupts are disabled.
To enable interrupts, both the global interrupt enable (MIE) bit in the mstatus
CSR and the corresponding individual interrupt enable bit in the mie
CSR need to be set.
For more information, see the Control and Status Registers documentation.
If multiple interrupts are pending, they are handled in the fixed priority order defined by the RISC-V Privileged Specification, version 1.11 (see Machine Interrupt Registers, Section 3.1.9).
The highest priority is given to the interrupt with the highest ID, except for the Machine Timer Interrupt, which has the lowest priority. So from high to low priority the interrupts are
ordered as follows: irq_i[31]
, irq_i[30]
, …, irq_i[16]
, irq_i[11]
, irq_i[3]
, irq_i[7]
.
All interrupt lines are level-sensitive. There are two supported mechanisms by which interrupts can be cleared at the external source.
A software-based mechanism in which the interrupt handler signals completion of the handling routine to the interrupt source, e.g., through a memory-mapped register, which then deasserts the corresponding interrupt line.
A hardware-based mechanism in which the
irq_ack_o
andirq_id_o[4:0]
signals are used to clear the interrupt sourcee, e.g. by an external interrupt controller.irq_ack_o
is a 1clk_i
cycle pulse during whichirq_id_o[4:0]
reflects the index inirq_id[]
of the taken interrupt.
In Debug Mode, all interrupts are ignored independent of mstatus
.MIE and the content of the mie
CSR.
Exceptions
CV32E40P can trigger an exception due to the following exception causes:
Exception Code |
Description |
2 |
Illegal instruction |
3 |
Breakpoint |
11 |
Environment call from M-Mode (ECALL) |
The illegal instruction exception and M-Mode ECALL instruction exceptions cannot be disabled and are always active. The core raises an illegal instruction exception for any instruction in the RISC-V privileged and unprivileged specifications that is explicitly defined as being illegal according to the ISA implemented by the core, as well as for any instruction that is left undefined in these specifications unless the instruction encoding is configured as a custom CV32E40P instruction for specific parameter settings as defined in (see :ref:custom-isa-extensions). For example, in case the parameter FPU is set to 0, the CV32E40P raises an illegal instruction exception for any RVF instruction. The same concerns for XPULP extensions everytime the parameter PULP_XPULP is set to 0 (see :ref:core-integration).
Nested Interrupt/Exception Handling
CV32E40P does support nested interrupt/exception handling in software.
The hardware automatically disables interrupts upon entering an interrupt/exception handler.
Otherwise, interrupts/exceptions during the critical part of the handler, i.e. before software has saved the mepc
and mstatus
CSRs, would cause those CSRs to be overwritten.
If desired, software can explicitly enable interrupts by setting mstatus
.MIE to 1 from within the handler.
However, software should only do this after saving mepc
and mstatus
.
There is no limit on the maximum number of nested interrupts.
Note that, after enabling interrupts by setting mstatus
.MIE to 1, the current handler will be interrupted also by lower priority interrupts.
To allow higher priority interrupts only, the handler must configure mie
accordingly.
The following pseudo-code snippet visualizes how to perform nested interrupt handling in software.
1isr_handle_nested_interrupts(id) {
2 // Save mpec and mstatus to stack
3 mepc_bak = mepc;
4 mstatus_bak = mstatus;
5
6 // Save mie to stack (optional)
7 mie_bak = mie;
8
9 // Keep lower-priority interrupts disabled (optional)
10 mie = mie & ~((1 << (id + 1)) - 1);
11
12 // Re-enable interrupts
13 mstatus.MIE = 1;
14
15 // Handle interrupt
16 // This code block can be interrupted by other interrupts.
17 // ...
18
19 // Restore mstatus (this disables interrupts) and mepc
20 mstatus = mstatus_bak;
21 mepc = mepc_bak;
22
23 // Restore mie (optional)
24 mie = mie_bak;
25}
Nesting of interrupts/exceptions in hardware is not supported.