RISC-V PLIC 中断控制器:gateway、使能、优先级与 claim/complete
更新时间:2026-09-19。前置:中断与 DMA 入门、RISC-V CLINT 定时器。CLINT 管本地定时/软件中断,**PLIC(Platform-Level Interrupt Controller)**负责把成百上千个外部设备中断汇聚、仲裁后分发给各 hart。
本文要回答的问题
- 一个外部中断从引脚到 hart,经过 PLIC 哪些模块?
- pending、使能、优先级、阈值如何共同决定是否上报?
- claim 和 complete 两阶段握手为什么能避免丢中断?
- 电平/边沿中断、多核分发和优先级反转有哪些坑?
一、PLIC 数据通路
bash
设备中断源 1..N
│
┌─▼──────── 每源:gateway(锁存/中断控制) → pending 位
│ priority 寄存器(每源一个优先级)
│ 使能矩阵 enable[target][source]
└──────► 仲裁核心(按目标 hart 取最高优先级且>threshold 的待处理源)
│ 产生该 target 的外部中断线(EIP)
▼
hart 目标: threshold + 外部中断(MEIP/SEIP)
软件 claim(读 claim/complete 寄存器取 ID) → 服务 → complete(写 ID)核心要素:
- Gateway + pending:每源一个网关,把原始电平/脉冲转成统一的「待处理」状态并与 claim/complete 配合。pending 位为 1 表示有未被 claim 的中断;电平中断 pending 由引脚电平控制,边沿中断由事件锁存。
- 优先级(priority per source):0=从不中断,1 最低,数值越大优先级越高。
- target(hart×特权模式)使能:每个目标(如 M-mode hart0、S-mode hart0)一张 source 使能位表;同一源可使能给一个或多个目标。
- 阈值 threshold:目标设一个门槛,只有优先级严格大于 threshold 的中断才上报。
- 外部中断线:仲裁结果拉高该目标的 MEIP/SEIP(经 mie/sie 与 mstatus 使能)。
二、claim / complete 两阶段(关键)
PLIC 不像 NVIC 在进入 ISR 时硬件自动清 pending,而用显式寄存器握手:
bash
1. hart 收到外部中断入口
2. 读 claim/complete 寄存器(MMIO) → 返回「当前最高优先级待处理源 ID」
- 该源 pending 被清,其他同源源向被 gateway 屏蔽直到 complete
3. 软件按 ID 执行对应 ISR(清设备本身的中断源)
4. 向 claim/complete 写回同一 ID = complete
- gateway 解除屏蔽:若此时引脚仍有效(电平)会再次 pending这套「claim 取号、complete 归还」保证:服务期间同设备新中断不会重入踩踏;若中断在处理过程中再次到来,complete 后会重新上报,不丢。
三、电平 vs 边沿
- 电平中断(常用):设备保持中断线有效直到被清。正确顺序是在 ISR 里先清设备的中断原因(如读空 FIFO/写 W1C),再 complete PLIC;若先 complete 而设备仍拉着线,PLIC 会立刻再 pending(通常无害但可能多进一次)。
- 边沿中断:硬件锁存脉冲。若在 claim 前/处理期间来多个脉冲,gateway 模型一般会合并(至少不丢第一个),软件要在设备侧自己计数溢出事件,不能假设一脉冲一中断。
四、优先级仲裁与多核
- 多个 pending 同时有效时,仲裁器取使能给该目标、优先级最高且 >threshold 者;同优先级按源 ID 小者优先(确定性 tie-break)。
- 中断可路由到多 hart,但 claim 是「竞争消费」:一个 hart claim 走 ID 后其他 hart claim 到 0(无中断),天然做核间分发/负载均衡。
- 阈值可在临界区临时抬高来屏蔽低优先级(比逐个关使能轻量),但不替代自旋锁。
五、与中断聚合/软件流程配合
高吞吐设备(网卡队列)通常不应每事件中断,见 中断聚合;PLIC 负责「把一条 IRQ 线送给哪个核」,设备自身把多事件攒成一次。Linux 下 PLIC 对应 IRQ domain,smp_affinity 写使能矩阵做绑核。
六、常见的坑
- claim 后忘记 complete:该源被 gateway 永久屏蔽,设备「只中断一次」后静默。
- complete 写错 ID:应答了不存在/别的源,状态错乱甚至总线异常。
- 顺序反(电平中断):先 complete 后清设备源,立刻重入;应清设备原因再 complete。
- 没使能源/目标阈值太高:pending 有但 MEIP 不拉起,表现为「设备有中断标志却不进 ISR」。
- 读 claim 返回 0:把 0(无中断)当有效 ID 处理,索引越界;0 表示没有待处理。
- 优先级/反转问题:低优先级在 ISR 中未屏蔽高优先级、或共享资源导致的优先级反转需软件协议处理(PLIC 无硬件优先级继承)。
- 边沿脉冲丢失/合并误判:依赖一脉冲一中断,实际要查设备事件计数。
- 多核同使能但无亲和策略:中断随机落核,缓存/实时性差。
- MEIP 使能链漏一环:源使能 + target 使能 + mie.MEIE + mstatus.MIE 任一未开都不报。
- 上下文(M/S target)配错:S-mode OS 配了 M-mode 的使能/阈值寄存器,读不到。
- 唤醒配置缺失:低功耗下需把某源设为唤醒源并保证 PLIC 在常开域,见 低功耗模式。
相关与延伸
本地定时/软件中断见 CLINT;中断与 DMA 入门见 中断 DMA 入门;高吞吐设备配合见 中断聚合;寄存器访问见 AXI4-Lite 从机。
总结
PLIC 用「每源 gateway 锁存 pending + 每源优先级 + 每目标使能矩阵 + 每目标阈值」仲裁出最高优先级(同优先级 ID 小者)的外部中断拉起目标 hart 的 MEIP,软件再用 claim 读走中断 ID(硬件清 pending 并屏蔽同源)到清设备原因、complete 写回 ID 解除屏蔽的两阶段握手,保证服务期间不重入、complete 后若电平仍有效会重新上报而不丢;claim 返回 0 表示无中断——忘 complete、清设备源顺序反、使能链漏环和把 0 当有效 ID 是四大坑。