Nuclei RISC-V 中断体系学习笔记
一、中断基础与架构模式
1.1 核心术语
中断请求:外设 / 内核向 CPU 发起的异步处理请求
中断源:产生中断的硬件模块,分为外部中断(UART、GPIO 等外设)与内部中断(软件中断、定时器中断、核内自研中断)
中断服务程序(ISR):处理中断请求的专用代码段
上下文保存与恢复:中断进入 / 退出时,通过软件压栈 / 出栈保存内核寄存器与运行状态,保证主程序无缝继续执行
中断仲裁:多个中断同时触发时,按规则选出优先响应的中断
抢占与嵌套:高优先级中断可打断低优先级中断的执行,形成多层嵌套
1.2 中断类型分类
| 大类 | 子类 | 说明 |
| 外部中断 | - | 由核外外设发起,对接 UART、GPIO 等片上外设 |
| 内部中断 | 软件中断 | 通过 msip/ssip 寄存器软件触发,对应特权级分别为机器模式 / 监管模式 |
| 定时器中断 | 内核内置 TIMER 单元通过 mtime/mtimecmp 产生计时中断 | |
| Nuclei 自研内部中断 | 部分型号核额外实现的专属内部中断 |
1.3 两种中断架构对比
通过mtvec寄存器最低位可切换中断工作模式,二者特性差异如下:
| 维度 | CLINT 模式(传统模式) | CLIC 模式(增强模式) |
| 核心架构 | CLINT 管内部中断 + PLIC 管外部中断,分体式管理 | ECLIC 统一管理全部内部 + 外部中断,统一式管理 |
| 控制方式 | 依赖 mie/mip 等标准 CSR,外部中断由 PLIC 寄存器二次配置 | mie/mip 被硬件旁路(无效),完全由 ECLIC 内存映射寄存器控制 |
| 优先级能力 | 仅外部中断支持优先级配置,内部中断无等级 | 全中断源支持层级 + 优先级二维配置 |
| 核心特性 | 无硬件向量中断、不支持嵌套、无尾链优化 | 支持向量 / 非向量双模式、多级抢占嵌套、中断尾链优化 |
| 中断延迟 | 延迟固定,相对较高 | 延迟更低,向量模式可做到 6 周期响应 |
1.4 两级中断屏蔽机制
全局中断屏蔽
作用对象:机器模式下所有中断,作为总开关
实现方式:通过
mstatus.MIE位统一开关所有机器模式中断
单源中断屏蔽
CLINT 模式:内核 CSR 级(mie 寄存器单比特控制)+ PLIC 外设级(单路中断独立使能)两级屏蔽
CLIC 模式:所有中断源通过 ECLIC 的
clicintie[i]寄存器独立使能 / 屏蔽
二、CLIC 模式中断处理核心机制
2.1 中断仲裁规则
仲裁参与条件
中断源需同时满足 使能位 IE=1 且 挂起位 IP=1,才可参与仲裁。
仲裁优先级(从高到低)
中断层级(Level)数值越大,优先级越高(抢占唯一判断依据)
层级(Level)相同时,中断优先级(Priority)数值越大,优先级越高(同级仲裁第二依据)
层级(Level)与优先级(Priority)均相同时,中断 ID 号越大,优先级越高
最终输出规则
仲裁胜出的中断,仅当其层级Level 大于 mth阈值寄存器值 时,ECLIC 才会向 CPU 内核发送中断请求。
2.2 中断进入流程(硬件单周期自动完成)
中断响应所有硬件操作在单个时钟周期内同步完成,核心动作如下:
PC 跳转
向量模式(
clicintattr[i].shv=1):PC = mtvt + 4 * 中断ID,直接跳转专属 ISR 入口非向量模式(
clicintattr[i].shv=0):PC = mtvec / mtvt2,跳转统一公共入口
CSR 寄存器自动更新
mepc:保存被中断指令的 PC 地址,用于中断返回mstatus:将 MIE 原值保存到 MPIE,随后 MIE 清 0(关闭全局中断,默认禁止嵌套);将原特权模式保存到 MPP,切换为机器模式mcause:EXCCODE写入当前中断 ID;MPIL保存中断前的系统中断层级;记录中断前特权模式与全局中断使能状态mintstatus:MIL字段更新为当前中断的层级,用于后续抢占判断
模式切换
特权模式自动切换为机器模式
机器子模式:将原子模式保存到
msubm.PTYP,msubm.TYP更新为中断处理模式
核心结论:进入 ISR 前,硬件已自动完成返回地址保存、中断原因记录、全局中断关闭,上下文保存需软件实现。
2.3 中断退出流程(mret 指令触发)
软件执行mret指令触发中断返回,硬件单周期完成逆过程恢复:
从
mepc恢复 PC 值,回到被中断的指令处继续执行CSR 状态恢复
从
mcause.MPIL恢复mintstatus.MIL,还原中断层级从
mcause.MPIE恢复mstatus.MIE,还原全局中断使能状态从
mcause.MPP恢复特权模式
从
msubm.PTYP恢复机器子模式
2.4 向量 vs 非向量模式(每个中断源可独立配置clicintattr[i].shv)
两种中断处理模式对比
| 特性 | 向量模式(shv=1) | 非向量模式(shv=0) |
| 跳转方式 | 硬件直接查 mtvt 表,跳专属入口 | 统一跳公共入口(mtvec/mtvt2),软件分发 |
| 响应延迟 | 约 6 个周期(无上下文保存) | 约 4+3+8+5 ≈ 20 周期(含保存) |
| 抢占 | 默认关闭(MIE=0),需软件手动开 | 原生支持(通过 csrrw ra, CSR_JALMNXTI, ra 指令) |
| 尾链 | 不支持 | 支持(仅非向量) |
| C 函数要求 | 必须加 __attribute__((interrupt)),且建议为叶子函数 | 无特殊要求 |
| 维度 | 非向量模式(shv=0,默认) | 向量模式(shv=1) |
| 跳转逻辑 | 统一跳转公共入口,软件识别中断号分发 | 硬件直接查向量表,跳转专属 ISR 入口 |
| 响应延迟 | 较高,包含公共入口跳转、上下文保存、软件分发开销 | 极低,理想情况 6 周期到达 C 函数首指令 |
| 抢占支持 | 原生支持抢占 | 默认关闭(硬件自动关 MIE),需软件手动开中断开启 |
| 尾链支持 | 支持,优化收益显著 | 不支持 |
| 适用场景 | 绝大多数通用外设中断,兼容性好 | 对延迟要求极高的关键中断 |
非向量模式细节
公共入口配置
mtvt2.MTVT2EN=0:公共入口复用 mtvec 地址,异常与非向量中断共用入口mtvt2.MTVT2EN=1:公共入口由 mtvt2 寄存器指定,中断与异常入口分离,性能更优
标准处理流程
压栈保存 mepc、mcause、msubm 等 CSR 与通用寄存器上下文
执行
csrrw ra, CSR_JALMNXTI, ra指令:获取下一个待处理中断并跳转,同时自动开全局中断支持抢占,且具备跳转链接特性支撑尾链ISR 执行完成后,关中断、恢复上下文、执行 mret 返回
尾链实现原理 中断返回时回到 JALMNXTI 指令处,自动检测挂起中断;若存在同级 / 低优先级挂起中断,直接跳转对应 ISR,省去 “上下文恢复→返回主程序→重新保存上下文” 的往返开销。
向量模式细节
核心特性:硬件自动查表跳转,跳转前不保存上下文,延迟极低
函数约束:C 语言 ISR 需添加
attribute((interrupt))属性;若为叶子函数无额外开销,若调用子函数,编译器会自动插入上下文保存代码,延迟与非向量模式相当抢占开启方式:需在 ISR 开头手动保存关键 CSR,然后置位 mstatus.MIE 开中断;退出前先关中断再恢复上下文
向量表:一段连续内存空间,每个表项存储对应中断 ISR 的入口地址,基地址由
mtvt寄存器定义
2.5 中断抢占与嵌套
抢占判断依据:仅当新中断的层级 高于当前 mintstatus.MIL 时,才可抢占正在执行的低层级中断
多级嵌套规则:支持多层级嵌套,中断退出时按优先级从高到低依次返回
层级与优先级的区别:Level 决定抢占权,Priority 仅决定同级内的响应顺序,不参与抢占判断
2.6 中断尾链
触发场景:当前中断处理期间,有同级 / 低优先级中断挂起,无法抢占,需等待当前中断处理完成
优化效果:省去上下文恢复 + 重新保存的往返开销,连续处理多个挂起中断
支持范围:仅非向量模式支持,向量模式无尾链特性
三、ECLIC 单元与寄存器详解
3.1 ECLIC 概述
单核专属中断控制器,仅服务单个处理器核
通过
mtvec寄存器最低位切换为 ECLIC 模式,与 PLIC 功能互斥,不可同时启用内部逻辑:每路中断源独立经过触发检测、挂起标记、层级优先级配置、使能控制,最终通过全局仲裁选出最高优先级中断提交给 CPU
3.2 中断源 ID 分配
ECLIC 最多支持 4096 个中断源,ID 分配规则固定:
0~18 号:内核预留内部中断
3 号:机器模式软件中断
7 号:机器模式定时器中断
其余为保留位,部分型号扩展额外内部中断
19~4095 号:用户可用外部中断,对接片内外设
硬件实际支持的中断源总数可通过
clicinfo.NUM_INTERRUPT读取
3.3 ECLIC 内存映射寄存器
ECLIC 为内存映射外设,基址由具体芯片手册定义,寄存器仅支持字节 / 半字 / 字对齐访问。
全局配置类寄存器
| 寄存器名 | 地址偏移 | 位宽 | 权限 | 核心功能与关键位域 |
| cliccfg | 0x0000 | 8bit | 读写 | 全局配置:nlbits[4:1] 划分 clicintctl 的位域,高 nlbits 位为层级,剩余有效位为优先级 |
| clicinfo | 0x0004 | 32bit | 只读 | 硬件参数查询:NUM_INTERRUPT[12:0] 中断源总数;CLICINTCTLBITS[24:21] clicintctl 有效位宽;VERSION[20:13] 硬件版本 |
| mth | 0x000b | 8bit | 读写 | 中断阈值等级:仅层级高于该值的中断可向 CPU 发起请求,用于批量屏蔽低等级中断 |
单中断源控制寄存器
每个中断号i对应一组寄存器,地址计算公式:0x1000 + 4*i + 组内偏移
| 寄存器名 | 组内偏移 | 位宽 | 权限 | 核心功能与关键说明 |
| clicintip[i] | 0 | 8bit | 读写 | 中断挂起标志:IP[0] 标记中断待处理状态- 电平触发:IP 随输入电平实时变化,软件写无效- 边沿触发:检测到对应边沿硬件置位,中断响应后硬件自动清除,软件可手动修改 |
| clicintie[i] | 1 | 8bit | 读写 | 中断使能开关:IE[0]=1 使能中断参与仲裁,IE[0]=0 完全屏蔽该中断 |
| clicintattr[i] | 2 | 8bit | 读写 | 中断属性配置- trig[2:1]:触发方式(00 电平触发、01 上升沿、11 下降沿)- shv[0]:处理模式(0 非向量、1 向量) |
| clicintctl[i] | 3 | 8bit | 读写 | 层级与优先级控制:有效位由 CLICINTCTLBITS 决定,高位为层级(抢占依据),低位为同级优先级,数值越高优先级越高 |
3.4 内核中断相关 CSR 寄存器
通过 CSR 专用指令访问,分为 RISC-V 标准寄存器与 Nuclei 自定义扩展寄存器。
RISC-V 标准中断 CSR
| 寄存器名 | CSR 地址 | 核心功能 | 中断关键位域 |
| mstatus | 0x300 | 全局状态寄存器 | MIE:全局中断总使能;MPIE:保存中断前的全局中断使能状态;MPP:保存中断前的特权模式 |
| mtvec | 0x305 | 异常 / 中断入口配置 | ADDR[31:6]:入口基地址;MODE[5:0]:值为 0x3 时启用 ECLIC 模式,其余为 CLINT 模式 |
| mepc | 0x341 | 异常程序计数器 | 保存中断触发前的 PC 值,mret 指令执行时恢复 |
| mcause | 0x342 | 陷阱原因寄存器 | INTERRUPT[31]:1 为中断,0 为异常;EXCCODE[11:0]:中断 / 异常编号;MPIL[23:16]:中断前的系统层级;MPIE[27]、MPP[29:28]:与 mstatus 对应字段镜像 |
| mie / mip | 0x304 / 0x344 | 中断使能 / 挂起 | ECLIC 模式下完全无效,读写被硬件忽略,仅 CLINT 模式生效 |
Nuclei 自定义中断扩展 CSR
| 寄存器名 | CSR 地址 | 核心功能 | 关键说明 |
| mtvt | 0x307 | 向量中断表基址 | 存放向量模式中断向量表的起始地址,对齐要求随中断数提升 |
| mtvt2 | 0x7ec | 非向量公共入口配置 | MTVT2EN[0]:1 时非向量中断入口由本寄存器指定,0 时复用 mtvec 地址 |
| mnxti | 0x345 | 下一中断处理寄存器 | 读取即可获取下一个待处理中断的服务函数入口,同时自动更新中断状态,支撑尾链与快速嵌套 |
| jalmnxti | 0x7ed | 跳转下一中断寄存器 | mnxti 增强版,读取时自动完成开中断 + 跳转,进一步降低延迟,具备链接特性支撑尾链 |
| mintstatus | 0x346 | 当前中断状态 | MIL[31:24]:当前机器模式活跃中断等级,用于抢占判断 |
| mscratchcsw | 0x348 | 特权模式栈切换 | 不同特权级切换时,快速交换 mscratch 与 SP,实现栈空间隔离 |
| mscratchcswl | 0x349 | 中断等级栈切换 | 中断进出时快速切换任务栈与中断栈,是中断入口汇编栈切换的硬件支撑 |
四、Zephyr RTOS 中断工程实现
4.1 系统三套陷阱路径
所有陷阱事件按类型走三条独立路径,互不干扰:
异常(Exception)
入口:永远走 mtvec 寄存器
目标:
_isr_wrapper统一处理说明:非法指令、访存错误、系统调用等所有异常均走此路径,与 shv 配置无关
向量中断(shv=1)
入口:mtvt 指向的硬件向量表
目标:直接跳转对应中断的专属处理函数
说明:不经过
_isr_wrapper,响应速度最快,需显式配置启用
非向量中断(shv=0,默认)
入口:MTVT2EN=0 时走 mtvec 寄存器
目标:先跳转
_isr_wrapper,再软件分发到对应处理函数说明:系统默认路径,绝大多数外设中断走此路径
4.2 中断注册与模式选择
Zephyr 通过两个注册宏决定中断工作模式:
1.IRQ_CONNECT(默认,非向量模式)
展开后调用
ARCH_IRQ_CONNECT,保持shv=0默认值仅完成两件事:在软件中断表注册处理函数与参数、配置中断优先级
不修改 shv 位,中断触发后走
_isr_wrapper统一入口,经软件查表分发
2.IRQ_DIRECT_CONNECT(向量模式)
展开后调用
ARCH_IRQ_DIRECT_CONNECT,额外执行z_riscv_irq_vector_set()该函数会将对应中断的
clicintattr[i].shv位置 1,开启向量模式中断触发后硬件直接从 mtvt 向量表取地址跳转,跳过软件分发流程
核心要点速记
ECLIC 模式下,层级 Level 决定抢占,优先级 Priority 决定同级顺序,二者不可混淆
硬件仅自动保存 mepc、mcause 等少量 CSR,通用寄存器上下文必须软件保存
向量模式默认关中断不支持抢占,非向量模式原生支持抢占与尾链
Zephyr 默认使用非向量模式,经
_isr_wrapper软件分发;关键中断可使用IRQ_DIRECT_CONNECT开启向量模式降低延迟mtvec控制模式切换与异常 / 非向量入口,mtvt控制向量表基址,mtvt2控制非向量入口是否与异常分离
