mirror of
https://github.com/apache/nuttx.git
synced 2026-09-13 22:20:24 +00:00
arch/risc-v: Add CLIC interrupt threshold support
Some checks are pending
Build Documentation / build-html (push) Waiting to run
MemBrowse Memory Report / changes-filter (push) Waiting to run
MemBrowse Memory Report / load-targets (push) Waiting to run
MemBrowse Memory Report / identical (push) Blocked by required conditions
MemBrowse Memory Report / analyze (push) Blocked by required conditions
Some checks are pending
Build Documentation / build-html (push) Waiting to run
MemBrowse Memory Report / changes-filter (push) Waiting to run
MemBrowse Memory Report / load-targets (push) Waiting to run
MemBrowse Memory Report / identical (push) Blocked by required conditions
MemBrowse Memory Report / analyze (push) Blocked by required conditions
and documentation it Signed-off-by: Huang Qi <huangqi3@xiaomi.com>
This commit is contained in:
parent
0577a674e7
commit
4e196729e7
5 changed files with 261 additions and 4 deletions
151
Documentation/platforms/risc-v/common/index.rst
Normal file
151
Documentation/platforms/risc-v/common/index.rst
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
===========================================================================
|
||||
RISC-V Specific Features
|
||||
===========================================================================
|
||||
|
||||
RISC-V CLIC Interrupt Threshold Configuration
|
||||
==============================================
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
The RISC-V Core-Level Interrupt Controller (CLIC) provides more flexible interrupt
|
||||
control compared to the legacy CLINT. One key feature is the interrupt threshold
|
||||
mechanism (INTTHRESH), which allows fine-grained control over which interrupts
|
||||
are processed based on their priority levels.
|
||||
|
||||
CLIC Interrupt Threshold Basics
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The CLIC interrupt threshold works by:
|
||||
|
||||
1. **Threshold Register**: Each privilege mode has its own interrupt threshold register:
|
||||
- Machine mode: ``CSR_MINTTHRESH`` (0x347)
|
||||
- Supervisor mode: ``CSR_SINTTHRESH`` (0x147)
|
||||
|
||||
2. **Interrupt Filtering**: Only interrupts with priority levels above the current
|
||||
threshold are delivered to the processor.
|
||||
|
||||
3. **Context Preservation**: The threshold value must be saved and restored during
|
||||
context switches to maintain proper interrupt priority handling.
|
||||
|
||||
Configuration in Custom Chip Layer
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Kconfig Configuration
|
||||
"""""""""""""""""""""
|
||||
|
||||
To enable CLIC interrupt threshold support in your custom chip, add the following
|
||||
to your chip's Kconfig file:
|
||||
|
||||
.. code-block:: kconfig
|
||||
|
||||
config ARCH_CHIP_MYCUSTOM_CHIP
|
||||
bool "My Custom RISC-V Chip"
|
||||
select ARCH_RV32 # or ARCH_RV64
|
||||
select ARCH_RV_HAVE_CLIC
|
||||
---help---
|
||||
My custom RISC-V chip with CLIC support
|
||||
|
||||
Required Definitions
|
||||
""""""""""""""""""""
|
||||
|
||||
In your chip-specific header file (e.g., ``arch/risc-v/include/mycustom/irq.h``):
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* Define maximum interrupt threshold value for your CLIC implementation */
|
||||
#define RISCV_MAX_INTTHRESH 255 /* Adjust based on your CLIC design */
|
||||
|
||||
/* Optional: Define interrupt priority levels */
|
||||
#define CLIC_PRIO_CRITICAL 200
|
||||
#define CLIC_PRIO_HIGH 150
|
||||
#define CLIC_PRIO_NORMAL 100
|
||||
#define CLIC_PRIO_LOW 50
|
||||
|
||||
.. note::
|
||||
If ``RISCV_MAX_INTTHRESH`` is not defined by the chip, NuttX will use a default
|
||||
value of ``0xff`` (255). This default should work for most CLIC implementations
|
||||
that support 8-bit interrupt threshold values. Chips with different threshold
|
||||
widths should define their own maximum value accordingly.
|
||||
|
||||
Implementation Details
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Interrupt Save/Restore Mechanism
|
||||
"""""""""""""""""""""""""""""""""
|
||||
|
||||
When ``ARCH_RV_HAVE_CLIC`` is enabled, NuttX automatically uses the
|
||||
interrupt threshold register instead of the standard status register for
|
||||
interrupt control. The CLIC implementation uses the ``SWAP_CSR()`` macro
|
||||
for atomic read-modify-write operations on the threshold register:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* Standard RISC-V interrupt disable (without CLIC) */
|
||||
noinstrument_function static inline_function irqstate_t up_irq_save(void)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
/* Read mstatus & clear machine interrupt enable (MIE) in mstatus */
|
||||
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"csrrc %0, " __XSTR(CSR_STATUS) ", %1\n"
|
||||
: "=r" (flags)
|
||||
: "r"(STATUS_IE)
|
||||
: "memory"
|
||||
);
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/* CLIC interrupt threshold disable (with ARCH_RV_HAVE_CLIC) */
|
||||
noinstrument_function static inline_function irqstate_t up_irq_save(void)
|
||||
{
|
||||
/* Read current interrupt threshold and set to maximum to mask all */
|
||||
|
||||
return SWAP_CSR(CSR_INTTHRESH, RISCV_MAX_INTTHRESH);
|
||||
}
|
||||
|
||||
Context Switch Handling
|
||||
"""""""""""""""""""""""
|
||||
|
||||
The interrupt context register (``REG_INT_CTX``) stores different values
|
||||
depending on CLIC configuration:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/*
|
||||
* Without CLIC (standard RISC-V): REG_INT_CTX stores CSR_MSTATUS or CSR_SSTATUS
|
||||
* With CLIC (ARCH_RV_HAVE_CLIC): REG_INT_CTX stores CSR_MINTTHRESH or CSR_SINTTHRESH
|
||||
*
|
||||
* The interrupt context is automatically determined by the CONFIG_ARCH_RV_HAVE_CLIC
|
||||
* configuration, eliminating the need for a separate threshold enable option.
|
||||
*/
|
||||
|
||||
CLIC Driver Implementation
|
||||
""""""""""""""""""""""""""
|
||||
|
||||
To implement the CLIC driver with interrupt threshold support, you may need to configure
|
||||
CLIC properly to handle priority management and threshold levels in your chip's
|
||||
driver code.
|
||||
|
||||
Integration Checklist
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When integrating CLIC interrupt threshold support:
|
||||
|
||||
☐ Enable ``ARCH_RV_HAVE_CLIC`` in Kconfig
|
||||
☐ Define ``RISCV_MAX_INTTHRESH`` for your chip (optional - defaults to 0xff/255)
|
||||
☐ Implement CLIC driver with priority management
|
||||
☐ Verify interrupt threshold save/restore in context switches
|
||||
☐ Test interrupt priority levels and threshold functionality
|
||||
☐ Add debug support for troubleshooting
|
||||
|
||||
References
|
||||
^^^^^^^^^^
|
||||
|
||||
* RISC-V CLIC Specification
|
||||
* NuttX RISC-V Architecture Documentation
|
||||
* ``arch/risc-v/include/irq.h`` - Core interrupt handling definitions
|
||||
* ``arch/risc-v/src/common/riscv_exception_common.S`` - Assembly interrupt handling
|
||||
|
|
@ -776,6 +776,15 @@ config ARCH_RV_HAVE_APLIC
|
|||
Controller (APLIC) to provide flexible interrupt control. This device
|
||||
is not backward compatible with PLIC.
|
||||
|
||||
config ARCH_RV_HAVE_CLIC
|
||||
bool
|
||||
default n
|
||||
---help---
|
||||
RISC-V defines Core-Level Interrupt Controller (CLIC) to provide
|
||||
flexible interrupt control. When enabled, CLIC uses interrupt
|
||||
threshold (MINTTHRESH/SINTTHRESH) CSRs for interrupt control
|
||||
instead of the standard IE bit in STATUS register.
|
||||
|
||||
config ARCH_RV_EXT_AIA
|
||||
bool "Enable RISC-V SxAIA support"
|
||||
default n
|
||||
|
|
|
|||
|
|
@ -130,6 +130,14 @@
|
|||
|
||||
#define RISCV_IRQ_MASK (~RISCV_IRQ_BIT)
|
||||
|
||||
#ifndef RISCV_MAX_INTTHRESH
|
||||
/* The maximum interrupt threshold value. This is the maximum value that
|
||||
* can be set in the MINTTHRESH or SINTTHRESH CSR registers to mask all
|
||||
* interrupts.
|
||||
*/
|
||||
# define RISCV_MAX_INTTHRESH (0xff)
|
||||
#endif
|
||||
|
||||
/* Configuration ************************************************************/
|
||||
|
||||
/* Processor PC */
|
||||
|
|
@ -197,14 +205,47 @@
|
|||
#define REG_X30_NDX 30
|
||||
#define REG_X31_NDX 31
|
||||
|
||||
/* Interrupt Context register */
|
||||
/* Interrupt Context register
|
||||
* This register stores interrupt-related state that needs to be preserved
|
||||
* across context switches and interrupt handling.
|
||||
*
|
||||
* If ARCH_RV_HAVE_CLIC is enabled:
|
||||
* - Both machine mode and supervisor mode use CLIC to mask interrupts
|
||||
* - Contains the value of CSR_MINTTHRESH (Machine Interrupt Threshold)
|
||||
* in machine mode or CSR_SINTTHRESH (Supervisor Interrupt Threshold)
|
||||
* in supervisor mode
|
||||
* - CLIC (Core Local Interrupt Controller) extension allows setting a
|
||||
* threshold level below which interrupts are masked
|
||||
* - This threshold value must be saved/restored to maintain proper
|
||||
* interrupt priority handling across context switches
|
||||
*
|
||||
* Otherwise (standard RISC-V interrupt handling):
|
||||
* - Contains the value of CSR_MSTATUS (Machine Status Register) in
|
||||
* machine mode or CSR_SSTATUS (Supervisor Status Register) in
|
||||
* supervisor mode
|
||||
* - Preserves critical status bits including:
|
||||
* * MIE/SIE (Machine/Supervisor Interrupt Enable)
|
||||
* * MPIE/SPIE (Machine/Supervisor Previous Interrupt Enable)
|
||||
* * MPP/SPP (Machine/Supervisor Previous Privilege)
|
||||
* * FS (Floating Point Status) - floating-point unit state
|
||||
* - Essential for proper interrupt state restoration when returning
|
||||
* from exceptions or switching between tasks
|
||||
*
|
||||
* This context preservation ensures that interrupt handling behavior
|
||||
* remains consistent across task switches and nested interrupt scenarios.
|
||||
*/
|
||||
|
||||
#define REG_INT_CTX_NDX 32
|
||||
#ifdef CONFIG_ARCH_RV_HAVE_CLIC
|
||||
# define REG_INT_THRESH_NDX 32
|
||||
# define REG_INT_CTX_NDX 33
|
||||
#else
|
||||
# define REG_INT_CTX_NDX 32
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_RISCV_INTXCPT_EXTREGS
|
||||
# define INT_XCPT_REGS (33 + CONFIG_ARCH_RISCV_INTXCPT_EXTREGS)
|
||||
# define INT_XCPT_REGS (REG_INT_CTX_NDX + 1 + CONFIG_ARCH_RISCV_INTXCPT_EXTREGS)
|
||||
#else
|
||||
# define INT_XCPT_REGS 33
|
||||
# define INT_XCPT_REGS (REG_INT_CTX_NDX + 1)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_RV32
|
||||
|
|
@ -346,6 +387,9 @@
|
|||
# define REG_X29 (INT_REG_SIZE*REG_X29_NDX)
|
||||
# define REG_X30 (INT_REG_SIZE*REG_X30_NDX)
|
||||
# define REG_X31 (INT_REG_SIZE*REG_X31_NDX)
|
||||
# ifdef CONFIG_ARCH_RV_HAVE_CLIC
|
||||
# define REG_INT_THRESH (INT_REG_SIZE*REG_INT_THRESH_NDX)
|
||||
# endif
|
||||
# define REG_INT_CTX (INT_REG_SIZE*REG_INT_CTX_NDX)
|
||||
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
|
|
@ -425,6 +469,9 @@
|
|||
# define REG_X29 REG_X29_NDX
|
||||
# define REG_X30 REG_X30_NDX
|
||||
# define REG_X31 REG_X31_NDX
|
||||
# ifdef CONFIG_ARCH_RV_HAVE_CLIC
|
||||
# define REG_INT_THRESH REG_INT_THRESH_NDX
|
||||
# endif
|
||||
# define REG_INT_CTX REG_INT_CTX_NDX
|
||||
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
|
|
@ -755,6 +802,42 @@ int up_this_cpu(void);
|
|||
* Inline Functions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_RV_HAVE_CLIC
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_irq_save
|
||||
*
|
||||
* Description:
|
||||
* Disable interrupts by setting interrupt threshold to maximum and return
|
||||
* the previous threshold value
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
noinstrument_function static inline_function irqstate_t up_irq_save(void)
|
||||
{
|
||||
/* Read current interrupt threshold and set to maximum to mask all */
|
||||
|
||||
return SWAP_CSR(CSR_INTTHRESH, RISCV_MAX_INTTHRESH);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_irq_restore
|
||||
*
|
||||
* Description:
|
||||
* Restore the value of the interrupt threshold register
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
noinstrument_function static inline_function
|
||||
void up_irq_restore(irqstate_t flags)
|
||||
{
|
||||
/* Restore the interrupt threshold value */
|
||||
|
||||
WRITE_CSR(CSR_INTTHRESH, flags);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_irq_save
|
||||
*
|
||||
|
|
@ -804,6 +887,8 @@ void up_irq_restore(irqstate_t flags)
|
|||
);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARCH_RV_HAVE_CLIC */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_set_interrupt_context
|
||||
*
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@
|
|||
# define CSR_IPH CSR_SIPH
|
||||
# define CSR_TOPEI CSR_STOPEI /* Top external interrupt register */
|
||||
# define CSR_TOPI CSR_STOPI /* Top interrupt register */
|
||||
# define CSR_INTTHRESH CSR_SINTTHRESH /* Interrupt threshold register */
|
||||
|
||||
/* In status register */
|
||||
|
||||
|
|
@ -102,6 +103,7 @@
|
|||
# define CSR_IPH CSR_MIPH
|
||||
# define CSR_TOPEI CSR_MTOPEI /* Top external interrupt register */
|
||||
# define CSR_TOPI CSR_MTOPI /* Top interrupt register */
|
||||
# define CSR_INTTHRESH CSR_MINTTHRESH /* Interrupt threshold register */
|
||||
|
||||
/* In status register */
|
||||
|
||||
|
|
|
|||
|
|
@ -147,6 +147,9 @@ exception_common:
|
|||
csrr s0, CSR_STATUS /* s0=status */
|
||||
csrr s1, CSR_EPC /* s1=exception PC */
|
||||
csrr s2, CSR_CAUSE /* s2=cause */
|
||||
#ifdef CONFIG_ARCH_RV_HAVE_CLIC
|
||||
csrr s4, CSR_INTTHRESH /* s4=interrupt threshold */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_KERNEL_STACK
|
||||
csrr s3, CSR_SCRATCH
|
||||
|
|
@ -158,6 +161,9 @@ exception_common:
|
|||
REGSTORE s0, REG_INT_CTX(sp)
|
||||
REGSTORE s1, REG_EPC(sp)
|
||||
REGSTORE s3, REG_SP(sp)
|
||||
#ifdef CONFIG_ARCH_RV_HAVE_CLIC
|
||||
REGSTORE s4, REG_INT_THRESH(sp)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LIB_SYSCALL
|
||||
csrr tp, CSR_SCRATCH /* Load kernel TP */
|
||||
|
|
@ -281,6 +287,10 @@ return_from_exception:
|
|||
|
||||
REGLOAD s0, REG_INT_CTX(sp) /* restore status */
|
||||
csrw CSR_STATUS, s0
|
||||
#ifdef CONFIG_ARCH_RV_HAVE_CLIC
|
||||
REGLOAD s0, REG_INT_THRESH(sp) /* restore interrupt threshold */
|
||||
csrw CSR_INTTHRESH, s0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LIB_SYSCALL
|
||||
/* Store tcb to scratch register */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue