Five EmbedDev logo Five EmbedDev

An Embedded RISC-V Blog

When writing low level interrupt service routines (ISRs) for RISC-V we must consider what happens when an interrupt occurs while another interrupt is being serviced. While this consideration is required for all processor architectures, RISC-V requires software to manage this situation.

This article will take a dive into using nested interrupts on RISC-V. For the sake of simplicity this article only deals with a single core operating in m machine mode.

For example let’s consider the case of an mti timer interrupt occuring while an msi software interrupt is being serviced. One of the following must occur:

It should be noted that this is not restricted to just different interrupt sources. Consider an external mei interrupt that is multiplexed by an external interrupt controller. We may wish to service a higher priority mei while servicing a lower priority mei.

Finally exceptions can occur during interrupt handling, so these must be considered.

Direct vs Vectored

Recall that RISC-V has two standard interrupts modes, direct and vectored modes.

Nested interrupts are possible in both modes, however it should be noted:

Enabling Nested Interrupt Handling

Recall these steps occur automatically before entry to an interrupt:

To enable nested interrupts we simply need to re-enable interrupts:

It is possible to do that, but consider what will happen to the global state when the next interrupt is entered. Global state in the CSRs will be overwritten and the return address and return state will be lost.

Managing Global State

On entry to an ISR RISC-V specifies that:

At the entry to an ISR, before a enabling a nested interrupt this state needs to be saved. The extent of the state to be stored depends on the system. If vectored mode is used the mcause register may not be of interest.

At the exit of an ISR, nested interrupts must be disabled and the global state restored.

The flow is as follows:


In the case of exceptions, the mstatus.mpie will be of value. It is possible to enter an exception when mstatus.mie is disabled.

Ensure no exceptions can occur in an ISR while mstatus.mie is disabled as the global state will be clobbered and the return address in mepc lost.

For example no page faults or memory protection.

An Example in Code

Vectored mode will allow a different ISR functions for exceptions, and the various interrupts defined in the mip register.

However, when using an external interrupt controllers, such as the PLIC, only one ISR handler (the mei) is used.

This leads to a few questions: x