RISC-V入门(5)- 中断
本文最后更新于:3 个月前
中断分类
- 本地(Local)中断
- 软中断software interrupt
- 定时器中断timer interrupt
- 全局(Global)中断
- 外部中断externel interrupt
RISC-V 中断编程中涉及的寄存器
| 寄存器 | 用途说明 |
|---|---|
| mie (Machine Interrupt Enable) |
用于进一步控制(打开和关闭)software interrupt/timer interrupt/external interrupt |
| mip (Machine Interrupt Pending) |
它列出目前已发生等待处理的中断。 |
mie(Machine Interrupt Enable)

打开(1)或者关闭(0)M/S/U 模式下对应的 External/Timer/Software 中断。
mip(Machine Interrupt Pending)

获取当前 M/S/U 模式下对应的 External/Timer/Software 中断是否发生。
中断处理流程
中断处理
- 把
mstatus的MIE值复制到MPIE中,清除mstatus中的 MIE 标志位,效果是中断被禁止。 - 当前的
PC的下一条指令地址被复制到mepc中,同时PC被设置为mtvec。注意如果我们设置mtvec.MODE = vetcored,PC =mtvec.BASE + 4 × exception-code。 - 根据
interrupt的种类设置mcause,并根据需要为mtval设置附加信息。 - 将
trap发生之前的权限模式保存在mstatus的MPP域中,再把hart权限模式更改为M。
退出中断
以在 M 模式下执行 mret 指令为例,会执行如下操作:
- 当前 Hart 的权限级别 = mstatus.MPP; mstatus.MPP= U(如果 hart 不支持 U 则为 M)
- mstatus.MIE = mstatus.MPIE; mstatus.MPIE = 1
- pc = mepc
PLIC(Platform-Level Interrupt Controller)
HART只能处理一个中断,PLIC相当于一个控制中心,它通过中断类型,优先级等等来选出一个需要处理的中断。协调多个中断,服务一个HART。
1 | |
- Interrupt Source ID 范围:1 ~ 53(0x35)
- 0 预留不用
PLIC本身也是一个外设,RISC-V 规范规定,PLIC 的寄存器编址采用内存映射(memory map)方式。每个寄存器的宽度为32-bit。
具体寄存器编址采用 base + offset 的格式,且 base 由各个特定platform 自己定义。针对 QEMU-virt,其 PLIC 的设计参考了FU540-C000,base 为 0x0c000000。
1 | |
PLIC 编程接口 - 寄存器
Priority
功能:设置某一路中断源的优先级
内存映射地址:BASE + (interrupt-id) * 4
- 每个
PLIC中断源对应一个寄存器,用于配置该中断源的优先级。 QEMU-virt支持 7 个优先级。 0 表示对该中断源禁用中断。其余优先级,1 最低,7 最高。- 如果两个中断源优先级相同,则根据中断源的 ID 值进一步区分优先级,ID 值越小的优先级越高。
Pending
功能:用于指示某一路中断源是否发生
内存映射地址:BASE + 0x1000 + ((interrupt-id) / 32) * 4
- 每个
PLIC包含 2 个 32 位的Pending寄存器,因为总共有54个中断源,每一个bit对应一个中断源,如果为 1 表示该中断源上发生了中断(进入Pending状态),有待hart处理,否则表示该中断源上当前无中断发生。 Pending寄存器中断的Pending状态可以通过claim方式清除。- 第一个
Pending寄存器的第 0 位对应不存在的 0 号中断源,其值永远为 0。
Enable
功能:针对某个 hart 开启或者关闭某一路中断源
内存映射地址:BASE + 0x2000 + (hart) * 0x80
- 每个
Hart有 2 个Enable寄存器 (Enable1和Enable2)用于针对该Hart启动或者关闭某路中断源。 - 每个中断源对应
Enable寄存器的一个bit,其中Enable1负责控制 1 ~ 31 号中断源;Enable2负责控制32 ~ 53号中断源。 将对应的bit位设置为 1 表示使能该中断源,否则表示关闭该中断源。
Threshold
功能:针对某个 hart 设置中断源优先级的阈值
内存映射地址:BASE + 0x200000 + (hart) * 0x1000
- 每个
Hart有 1 个Threshold寄存器用于设置中断优先级的阈值。 - 所有小于或者等于(<=)该阈值的中断源即使发生了也会被
PLIC丢弃。特别地,当阈值为 0 时允许所有中断源上发生的中断;当阈值为 7 时丢弃所有中断源上发生的中断。
Claim/Complete
功能:如下
内存映射地址:BASE + 0x200004 + (hart) * 0x1000
Claim和Complete是同一个寄存器,每个Hart一个。- 对该寄存器执行读操作称之为
Claim,即获取当前发生的最高优先级的中断源ID。Claim成功后会清除对应的Pending位。 - 对该寄存器执行写操作称之为
Complete。所谓Complete指的是通知PLIC对该路中断的处理已经结束。
1 | |
CLINT (Core Local INTerruptor)
定时器中断,属于本地中断的一种,由芯片内部CLINT设备产生的中断。
- RISC-V 规范规定,CLINT 的寄存器编址采用内存映射(memory map)方式。
- 具体寄存器编址采用
base + offset的格式,且base由各个特定platform自己定义。针对QEMU-virt,其 CLINT 的设计参考了SFIVE,base为0x2000000。
CLINT 编程接口 - 寄存器 (Timer 部分)
mtime
功能:real-time 计数器(counter)
内存映射地址:BASE + 0xbff8
- 由晶振产生,系统全局唯一,在
RV32和RV64上都是 64-bit。系统必须保证该计数器的值始终按照一个固定的频率递增。 - 上电复位时,硬件负责将
mtime的值恢复为 0。
mtimecmp
功能:定时器比较寄存器
内存映射地址:BASE + 0x4000 + (hart) * 8)
每个
hart一个mtimecmp寄存器,64-bit。上电复位时,系统不负责设置 mt`imecmp 的初值。
当
mtime >= mtimecmp时,CLINT会产生一个timer中断。如果要使能该中断需要保证全局中断打开并且mie.MTIE标志位置1。当
timer中断发生时,hart会设置mip.MTIP,程序可以在mtimecmp中写入新的值清除mip.MTIP。
时钟节拍tick
- 操作系统中最小的时间单位;
Tick的单位(周期)由硬件定时器的周期决定
(通常为 1 ~ 100ms);Tick周期越小,也就是1s内产生的中断越多,系统的精度越高,但开销越大。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!