3. RISC-V PLIC与CLINT中断控制器基础

在RISC-V系统中,中断控制器的架构与ARM Cortex-A系列有显著差异。ARM通常使用GIC(Generic Interrupt Controller),而RISC-V标准定义了两种核心中断控制单元:PLIC(Platform-Level Interrupt Controller)和CLINT(Core Local Interruptor)。理解这两者的分工与协作,是从ARM驱动移植到RISC-V的关键第一步。

核心概念:PLIC负责管理来自外设的全局中断(如UART、I2C、GPIO),而CLINT负责管理每个CPU核本地的定时器中断和软件中断(IPI)。两者共同构成了RISC-V的中断处理体系。

3.1 PLIC(平台级中断控制器)架构

PLIC是RISC-V系统中用于处理外部设备中断的控制器。它支持多个中断源,并将这些中断路由到多个HART(硬件线程,即CPU核心)。PLIC的主要职责包括中断采集、优先级裁决、中断分发和中断完成通知。

3.1.1 PLIC核心功能模块

  • 中断源(Interrupt Sources): 最多支持1023个外部中断源(编号1-1023,0保留)。
  • 中断网关(Interrupt Gateways): 每个中断源对应一个网关,负责检测中断信号边沿或电平,并维护挂起状态。
  • 优先级裁决器(Priority Arbiter): 为每个中断源分配优先级(通常0-7,0表示禁用)。
  • 中断目标(Interrupt Targets): 支持多个HART作为中断目标,每个HART可以独立设置中断使能和阈值。
  • 中断声明与完成(Claim & Complete): 软件通过读取claim寄存器获取当前最高优先级中断ID,处理完成后写入complete寄存器通知PLIC。
移植要点: ARM GIC使用中断号直接映射,而PLIC需要驱动通过claim/complete机制与硬件交互。在设备树中,PLIC节点通常使用"riscv,plic0"兼容字符串。

3.1.2 PLIC中断处理流程

  1. 外设产生中断信号,PLIC中断网关检测到事件并设置挂起位。
  2. 优先级裁决器在所有挂起的中断中选出优先级最高的中断。
  3. 如果该中断的优先级高于目标HART设置的阈值,PLIC向目标HART发送中断请求。
  4. HART的CSR寄存器mip.MEIP(机器模式外部中断挂起位)被置位。
  5. 软件进入中断服务程序,读取PLIC的claim寄存器获取中断ID。
  6. 处理完成后,软件将中断ID写入complete寄存器,PLIC清除挂起位并允许下一个中断。
PLIC中断处理流程架构图 外设中断源 中断网关 优先级裁决器 目标HART Claim/Complete 写complete 流程说明: 1. 外设触发中断 → 2. 网关捕获并设置挂起 → 3. 裁决器选出最高优先级中断 → 4. 发送到目标HART 5. 软件读取Claim获取中断ID → 6. 处理完成后写Complete释放中断线

3.2 CLINT(核心本地中断器)架构

CLINT是每个HART本地的中断控制器,负责管理两类核心本地中断:定时器中断(Timer Interrupt)和软件中断(Software Interrupt)。CLINT不处理外部设备中断,这些由PLIC负责。

3.2.1 CLINT核心寄存器

寄存器名称 偏移地址 宽度 描述
msip 0x0000 + 4*HART_ID 32位 软件中断挂起寄存器,写1触发IPI
mtimecmp 0x4000 + 8*HART_ID 64位 定时器比较寄存器,当mtime >= mtimecmp时触发定时器中断
mtime 0xBFF8 64位 全局实时计数器,所有HART共享
移植陷阱: ARM的Generic Timer使用CNTPCT和CNTP_CVAL寄存器,而RISC-V使用mtime和mtimecmp。在设备树中,CLINT节点通常使用"riscv,clint0"兼容字符串,且必须正确指定mtime和mtimecmp的偏移地址。

3.2.2 CLINT中断类型

  • 软件中断(MSI): 通过写msip寄存器触发,用于核间通信(IPI)。每个HART独立拥有一个msip寄存器。
  • 定时器中断(MTI): 基于mtime和mtimecmp的比较结果。当mtime值达到或超过mtimecmp时,触发定时器中断。
CLINT核心架构与中断路径 mtime 全局64位计数器 HART 0 msip[0] mtimecmp[0] mip.MSIP / mip.MTIP HART 1 msip[1] mtimecmp[1] mip.MSIP / mip.MTIP CLINT中断触发条件: • 软件中断:写msip[HART_ID] = 1 → mip.MSIP置位 → 触发机器模式软件中断 • 定时器中断:mtime ≥ mtimecmp[HART_ID] → mip.MTIP置位 → 触发机器模式定时器中断 • 注意:mtime是全局计数器,所有HART共享;mtimecmp每个HART独立

3.3 中断优先级与委托机制

RISC-V定义了三种特权模式:机器模式(M-mode)、监管模式(S-mode)和用户模式(U-mode)。中断委托机制允许将某些中断从M-mode委托给S-mode处理,从而减少M-mode的负担并提高实时性。

3.3.1 中断优先级

PLIC支持两级优先级控制:

  • 中断源优先级: 每个中断源可配置0-7的优先级,0表示禁用该中断。
  • HART阈值: 每个HART可以设置一个优先级阈值,只有优先级高于阈值的中断才会被转发到该HART。
优先级裁决规则: 当多个中断同时挂起时,PLIC选择优先级最高的中断;如果优先级相同,则选择中断号最小的中断。这种确定性行为对驱动移植非常重要。

3.3.2 中断委托机制

中断委托通过mideleg(Machine Interrupt Delegation)CSR寄存器实现。该寄存器中的每一位对应一个中断类型,置位表示将该中断委托给S-mode处理。

中断类型 mideleg位 委托后CSR 典型用途
软件中断(SSI) 位1 sip.SSIP 核间通信(IPI)
定时器中断(STI) 位5 sip.STIP 操作系统调度时钟
外部中断(SEI) 位9 sip.SEIP 外设中断(通过PLIC)
中断委托机制示意图 M-mode 处理所有中断 mideleg 寄存器 决定哪些中断委托 S-mode 接收委托的中断 sie / sip 寄存器 处理外部/定时器/软件中断 委托(mideleg) 未委托(M-mode保留) 委托机制对驱动移植的影响: • ARM Linux通常运行在EL1(相当于S-mode),中断直接由内核处理 • RISC-V Linux需要确保mideleg正确配置,否则中断会陷入M-mode导致性能下降 • 设备树中通过"interrupts-extended"属性指定中断目标模式和HART

3.4 PLIC与CLINT在设备树中的描述

在设备树中,PLIC和CLINT作为独立节点存在,通过compatible属性和interrupt-controller属性标识。以下是典型设备树片段:

// CLINT节点
clint@2000000 {
    compatible = "riscv,clint0";
    reg = <0x00 0x2000000 0x00 0x10000>;
    interrupts-extended = <&cpu0 3 &cpu1 3>;
};

// PLIC节点
plic@c000000 {
    compatible = "riscv,plic0";
    reg = <0x00 0xc000000 0x00 0x4000000>;
    interrupts-extended = <&cpu0 11 &cpu1 11>;
    interrupt-controller;
    #interrupt-cells = <1>;
    riscv,ndev = <127>;
};
设备树关键属性说明:
• interrupts-extended:指定中断目标HART和中断号(CLINT使用3表示机器模式外部中断,PLIC使用11表示监管模式外部中断)
• riscv,ndev:PLIC支持的最大中断源数量(不包括0号中断)
• reg:控制器的内存映射地址和大小

3.5 中断控制器对比总结

特性 PLIC CLINT
管理中断类型 外部设备中断(UART、I2C等) 定时器中断、软件中断(IPI)
中断源数量 最多1023个 每个HART固定2个(定时器+软件)
优先级支持 支持(0-7级) 不支持(固定优先级)
中断目标 多HART,可配置路由 仅本地HART
Claim/Complete 需要 不需要
设备树兼容字符串 "riscv,plic0" "riscv,clint0"
ARM对应单元 GIC(中断分发器) Generic Timer + SGI
移植常见错误: 在将ARM驱动移植到RISC-V时,开发者常误以为PLIC等同于GIC而直接映射中断处理逻辑。实际上,PLIC的claim/complete机制、优先级阈值设置以及中断委托配置都需要在驱动初始化阶段显式处理,否则会导致中断丢失或系统挂起。