1. RISC-V中断与异常概述

各位同学好,我是老李。做数字IC设计十几年了,从ARM、MIPS一路做到RISC-V。今天咱们聊聊中断和异常——这两个概念,说白了就是处理器应对突发事件的机制。

我记得刚入行那会儿,带我的师傅说了一句话,我一直记到现在:「没有中断的处理器,就像没有门铃的房子」。你想想看,CPU正在那吭哧吭哧算数据,外设想跟它说句话,还得等它忙完——这不耽误事吗?

中断与异常的基本概念

先理清两个概念。很多初学者容易搞混,我当年也犯过这毛病。

中断(Interrupt),是外部事件触发的。比如你按下键盘、网卡收到数据包、定时器溢出——这些都属于中断。它是异步的,CPU不知道它啥时候来。

异常(Exception),是CPU内部执行指令时出问题了。比如除零、访问非法地址、执行非法指令——这些属于异常。它是同步的,跟指令执行绑在一起。

核心区别一句话:中断是「外部找上门」,异常是「内部出了事」。

在RISC-V里,这两者统称为「陷阱(Trap)」。嗯,这个叫法挺形象的——CPU正常跑着跑着,突然掉坑里了。

RISC-V特权架构简介

说到中断和异常,就绕不开特权架构。RISC-V定义了三个特权级别:

级别 编码 名称 用途
U 00 用户模式 运行应用程序
S 01 监督模式 运行操作系统
M 11 机器模式 运行固件/监控程序

为什么要有特权级?说白了就是权限管理。用户程序不能随便改系统配置,操作系统不能随便动硬件寄存器——各司其职。

我在项目中遇到过一个问题:有个同事把M模式下的CSR寄存器在U模式下去读写,结果CPU直接跳异常了。查了半天才发现是特权级没搞对。所以啊,特权级的概念一定要刻在脑子里。

中断与异常在RISC-V中的角色

在RISC-V里,中断和异常的处理流程大致是这样的:

  1. 触发:中断信号来了,或者指令执行出错了
  2. 响应:CPU暂停当前工作,保存现场
  3. 处理:跳转到对应的处理程序
  4. 返回:处理完毕,恢复现场,继续干活

这里面有几个关键寄存器,我列一下:

  • mtvec:M模式下的陷阱向量基址寄存器,告诉CPU去哪找处理程序
  • mcause:记录陷阱原因,是中断还是异常,具体是哪种
  • mepc:保存发生陷阱时的PC值,返回时用
  • mstatus:状态寄存器,控制中断使能等

个人经验:我建议你在FPGA上调试时,先把mtvec配好。曾经有一次我忘了配这个寄存器,中断来了CPU直接跑飞——那叫一个惨。后来我习惯在初始化代码里第一件事就是配mtvec,形成肌肉记忆。

下面这张图是我自己画的,展示了RISC-V中断与异常处理的整体流程:

RISC-V中断与异常处理流程 CPU正常执行 有陷阱? 保存现场 mepc, mcause 跳转处理程序 mtvec → PC mret 返回 图例 正常执行 陷阱处理 返回恢复

注意:在FPGA实现中,中断响应延迟是个关键指标。我曾经在一个项目中,中断从触发到进入处理程序花了20多个时钟周期——这在实时控制场景下完全不可接受。后来优化了中断控制器和向量跳转逻辑,才压到10个周期以内。

中断类型与优先级

RISC-V把中断分成了三类:

  • 软件中断:由一个hart向另一个hart发送中断,常用于多核通信
  • 定时器中断:由定时器触发,用于操作系统的时间片调度
  • 外部中断:由外设触发,比如UART、GPIO、以太网等

优先级方面,RISC-V的规则很简单:异常优先级高于中断,M模式中断优先级高于S模式。具体到同一类中断,优先级由平台中断控制器(PLIC)来管理。

嗯,这里要提一句。RISC-V的中断优先级不像ARM那样有固定的硬件优先级。它把优先级管理交给了PLIC,给了设计者更大的灵活性。我在做FPGA实现时,就自己定制过PLIC的优先级策略——这在ARM上是很难做到的。

小结

中断和异常是RISC-V处理器的核心机制。理解它们,你才能写出靠谱的嵌入式软件和硬件设计。我个人觉得,学RISC-V最好的方法就是动手——在FPGA上搭一个最小系统,然后自己写中断处理程序,跑一跑,看看波形。纸上得来终觉浅,绝知此事要躬行。

好了,这一章就到这里。记住:中断是外部的敲门声,异常是内部的警报声。搞清楚了这两个,后面的内容就好办了。


公众号:蓝海资料掘金营,微信deep3321