中断和异常虽说本身不是一种指令,但却是处理器指令集架构中非常重要的一环。
一、中断和异常概述
1.1 中断概述
中断机制,即处理器核在顺序执行程序指令流的过程中突然被别的请求打断而中止执行当前的程序,转而去处理别的事情,待其处理完了别的事情,然后重新回到之前程序中断的点继续执行之前的程序指令流,要点如下。
- 打断处理器执行程序指令流的“别的请求”便称之为中断请求,“别的请求”的来源称之为中断源。中断源通常来自于外围硬件设备。
- 处理器转而去处理“别的事情”便称之为中断服务程序。
- 中断处理是一种正常的机制,而非一种错误情形。处理器收到中断请求之后,需要保存当前程序的现场,简称为保存现场。等到处理完中断服务程序后,处理器需要恢复之前的现场,从而继续执行之前被打断的程序,简称为“恢复现场”。
- 可能存在多个中断源同时向处理器发起请求的情形。因此需要对这些中断源进行仲裁,从而选择哪个中断源被优先处理。此种情况称为“中断仲裁”,同时可以给不同的中断分配优先级以便于仲裁,因此中断存在着“中断优先级”的概念。
- 还有一种可能是处理器已经在处理器某个中断过程中(执行该中断的ISR中),此时还有一个优先级更高的新中断请求到来,此时处理器该如何是好呢?有如下两种可能。
第一种可能是处理器并不响应新的中断,而是继续执行当前正在处理的中断服务程序,待到彻底完成之后才响应新的中断请求,这种称为处理器“不支持中断嵌套”。
第二种可能是处理器中止当前的中断服务程序,转而开始响应新的中断,并执行其“中断服务程序”如此便形成了中断嵌套(即前一个中断还没响应完,又开始响应新的中断),并且嵌套的层次可以有很多层。
注意:假设新来的中断请求的优先级比正在处理的中断优先级低(或者相同),则不管处理器是否能支持“中断嵌套”,都不应该响应这个新的中断请求,处理器必须完成当前的中断服务程序之后才考虑响应新的中断请求(因为新的中断请求的优先级并不比当前正在处理的中断优先级高)。
1.2 异常概述
异常机制,即处理器核在顺序执行程序指令流的过程中突然遇到了异常的事情而中止执行当前的程序,转而去处理该异常,其要点如下。
- 处理器遇到的“异常的事情”称为异常。异常与中断最大区别在于中断往往是一种外因,而异常是由处理器内部事件或程序执行中的事件引起的,比如本身硬件故障,程序故障,或者执行特殊的系统服务指令而引起的,简而言之是一种内因。
- 与中断服务程序类似,处理器也会进入异常服务处理程序。
- 与中断类似,可能存在多个异常同时发生的情形,因此异常也有优先级,并且也可能发生多重异常的嵌套。
1.3 广义上的异常
如上一节所述,中断和异常最大的区别是起因内外有别。除此之外,从本质上来讲,中断和异常对于处理器而言基本上是一个概念。中断和异常发生时,处理器将暂停当前正在执行的程序,转而执行中断和异常处理程序;返回时,处理器恢复执行之前被暂停的程序。
因此中断和异常的划分是一种狭义的划分。从广义上来讲,中断和异常都被认为是一种广义上的异常。处理器广义上的异常,通常只分为同步异常和异步异常。
1、同步异常
同步异常是指由于执行程序指令流或者试图执行程序指令流而造成的异常。这种异常的原因能够被精确定位于某一条执行的指令。同步异常的另外一个通俗的表象便是,无论程序在同样的环境下执行多少遍,每一次都能精确地重现出来。
比如,程序流中有一条非法的指令,那么处理器执行到该非法指令便会产生非法指令异常,能被精确地定位于这一条非法指令,并且能够被反复重现。
2、异步异常
异步异常是指那些产生原因不能够被精确定位于某条指令的异常。异步异常的另外一个通俗的表象便是,程序在同样的环境下执行很多遍,每一次发生异常的指令PC都可能会不一样。
最常见的异步异常是“外部中断”。外部中断的发生是由外围设备驱动的,一方面外部中断的发生带有偶然性,另一方面中断请求抵达于处理器核之时,处理器的程序指令流执行到具体的哪一条指令更带有偶然性。因此一次中断的到来可能会巧遇到某一条“正在执行的不幸指令”,而该指令便成了“背锅侠”。在它的指令PC所在之处,程序便可停止执行,并转而响应中断去执行中断服务程序。但是当程序重复执行时,却很难会出现同一条指令反复“背锅”的精确情形。
对于异步异常,根据其响应异常后的处理器状态,又可以分为两种。
(1)精确异步异常:指响应异常后的处理器状态能够精确反映为某一条指令的边界,即某一条指令执行完之后的处理器状态。
(2)非精确异步异常:指响应异常后的处理器状态无法精确反映为某一条指令的边界,即可能是某一条指令执行了一半然后被打断的结果,或者是其他模糊的状态。
常见的典型同步异常和异步异常如表所示。
典型异常 | |
同步异常 |
假如外设模块的地址区间往往是不可能存放指令代码的,因此其属性是“不可执行”,并且还是读敏感的。如果某条指令的PC位于外设区间,则会造成取指令错误。这种错误能够精确的定位到是哪一条指令PC造成的。 |
假如有的地址区间的属性是只读或者只写的,假设Load或者Store指令以错误的方式访问了地址区间(假如写了只读的区间),这种错误方式能够被存储器保护单元MPU或者存储器管理单元MMU及时探测出来,则能够精确地定位到是哪一条Load或Store指令访存造成的。 MPU和MMU是分别对地址进行保护和管理的硬件单元 |
|
处理器指令集架构往往规定指令存放在存储器中的地址必须是对齐的,假如16位长的指令往往要求其PC值必须是16位对齐的。假设该指令的PC值不对齐,则会造成取指令不对齐错误。这种错误能够精确的定位到哪一条指令PC造成的。 |
|
处理器如果对指令进行译码发现这是一条非法的指令(比如不存在的指令编码),则会造成非法指令错误。这种错误能够精确的定位到哪一条指令PC造成的。 |
|
处理器指令集架构往往会定义若干条调试指令,比如断点(EBREAK)指令。当执行到该指令时处理器便会发生异常进入异常服务程序。该指令往往用于调试器使用,比如设置断点。这种错误能够精确的定位到哪一条指令PC造成的。 |
|
精确异步异常 |
外部中断是最常见的精确异步异常。 |
非精确异步异常 |
读写存储器出错是另外一种最常见的非精确异步异常,由于访问存储器(简称访存)需要一定的时间,处理器往往不可能坐等该访问结束(否则性能会很差),而是会继续执行后续的指令。等到访存结果从目标存储器返回来之后,发现出现了访存错误并汇报异常,但是处理器此时可能已经执行到了后续的某条指令,难以精确定位。并且存储器访问的时间延迟也具有偶然性,无法被精确地重现。 这种异步异常的另外一个常见实例便是写操作将数据写入缓存行(Cache Line)中,然后该缓存行经过很久才被替换出来,写回外部存储器,但是写回外部存储器返回结果出错。此时处理器可能已经执行过了后续成百上千条指令,到底是哪一条指令当时写的地址的缓存早已是前朝旧事,更不要说复现了。 |
二、RISC-V异常处理机制
RISC-V的架构不仅可以有机器模式的工作模式,还可以有用户模式,监督模式等工作模式。在不同的模式下均可以产生异常,并且有的模式也可响应中断。
RISC-V要求机器模式是必须具备的模式,其他的模式均是可选而非必选的模式。本章仅介绍基于机器模式的异常处理机制。
2.1 进入异常
进入异常时,RISC-V架构规定的硬件行为可以简述如下。
(1)停止执行当前程序流,转而从CSR寄存器mtvec定义的PC地址开始执行。
(2)进入异常不仅会让处理器跳转到上述的PC地址开始执行,还会让硬件同时更新其他几个CSR寄存器,分别是以下4个寄存器。
- 机器模式异常原因寄存器mcause(Machine Cause Register)
- 机器模式异常PC寄存器mepc(Machine Exception Program Counter)
- 机器模式异常值寄存器mtval(Machine Trap Value Register)
- 机器模式状态寄存器mstatus(Machine Status Register)
1、从mtvec定义的PC地址开始执行
RISC-V架构规定,在处理器的程序执行过程中,一旦遇到异常发生,则终止当前的程序流,处理器被强行跳转到一个新的PC地址。该过程在RISC-V的架构中定义为“陷阱(trap)”,字母含义为“跳入陷阱”,更加准确的意译为“进入异常”。
RISC-V处理器Trap后跳入的PC地址由一个叫做机器模式异常入口的基地址寄存器mtvec(Machine Trap-Vector Base-Address Register)的CSR寄存器指定,要点如下。
(1)mtvec寄存器是一个可读可写的CSR寄存器,因此软件可以编程更改其中的值。
(2)mtvec寄存器的详细格式如下图所示,其中低2位是MODE域,高30位是BASE域
- 假设MODE的值为0,则所有的异常响应时处理器均跳转到BASE值指示的PC地址。
- 假设MODE的值为1,则狭义的异常发生时,处理器跳转到BASE值指示的PC地址:狭义的中断发生时,处理器跳转到BASE+4*CAUSE值指示的PC地址。CAUSE的值表示中断对应的异常编号(Exception Code),如下图,比如机器计时器中断(Machine Timer Interrupt)的异常编号为7,则其跳转地址为BASE+4*7=BASE+28=BASE+0x1c。
2、更新CSR寄存器mcause
RISC-V架构规定,在进入异常时,机器模式异常原因寄存器mcause(Machine Cause Register)被同时更新,以反映当前的异常种类,软件可以通过读此寄存器查询造成异常的具体原因。
mcause寄存器详细格式如下图,其中最高1位为Interrupt域,低31位为异常编号域。此两个域的组合表示值如上图,用于指示RISC-V架构定义的12种中断类型和16种异常类型。
3、更新CSR寄存器mepc
RISC-V架构定义异常返回地址由机器模式异常PC寄存器mepc(Machine Exception Program Counter)保存。在进入异常时,硬件将自动更新mepc寄存器的值为当前遇到异常的指令PC值(即当前程序的停止执行点)。该寄存器将作为异常的返回地址,在异常结束之后,能够使用它保存的PC值回到之前被停止执行的程序点。
(1)值得注意的是,虽然mepc寄存器会在异常发生时自动被硬件更新,但是mepc寄存器本身也是一个可读可写的寄存器,因此软件也可以直接写该寄存器以修改其值。
(2)对于狭义的中断和狭义的异常而言,RISC-V架构定义其返回地址(更新的mepc值)有些细微差别。
- 出现中断时,中断返回地址mepc的值被更新为下一条尚未执行的指令。
- 出现异常时,中断返回地址mepc的值被更新为当前发生异常的指令PC。注意:如果异常由ecall和ebreak产生,由于mepc的值被更新为ecall或ebreak指令自己的PC。因此在异常返回时,如果直接使用mepc保存的PC值作为返回地址,则会再次跳回ecall或者ebreak指令,从而造成死循环(执行ecall或者ebreak指令导致重新进入异常)。正确的做法是在异常处理程序中软件改变mepc指向下一条指令,由于现在ecall/ebreak,因此改写设定mepc=mepc+4即可。
4、更新CSR寄存器mtval
RISC-V架构规定,在进入异常时,硬件将自动更新机器模式异常值寄存器mtval(Macheine Trap Value Register),以反映引起当前异常的存储器访问地址或者指令编码。
- 如果是由存储器访问造成的异常,比如遭遇硬件断点,取指令,存储器读写造成的异常,则将存储器访问的地址更新到mtval寄存器中。
- 如果是由非法指令造成的异常,则将该指令的指令编码更新到mtval寄存器中。
注意:mtval寄存器又名mbadaddr寄存器。在某些早期版本的RISC-V编译器中仅识别mbadaddr名称。
5、更新CSR寄存器mstatus
RISC-V架构规定,在进入异常时,硬件将自动更新机器模式状态寄存器mstatus(Machine Status Register)的某些域。
(1)mstatus寄存器的详细格式如下,其中MIE域表示在Machine Mode下中断全局使能
- 当该MIE域的值为1时,表示Machine Mode下所有中断的全局打开。
- 当该MIE域的值为0时,表示Machine Mode下所有中断的全局关闭。
(2)RISC-V架构规定,异常发生时有如下情况。
- MPIE域的值被更新为异常发生前MIE域的值。MPIE域的作用是在异常结束之后,能够使用MPIE的值恢复出异常发生之前的MIE值。
- MIE的值则被更新成为0(意味着进入中断异常服务程序后中断被全局关闭,所有的中断都将被屏蔽不响应)。
- MPP的值被更新为异常发生前的模式。MPP域的作用是在异常结束之后,能够使用MPP的值恢复出异常发生之前的工作模式。对于只支持机器模式的处理器核,则MPP的值永远为二进制值11。
2.2 退出异常
当程序完成异常处理之后,最终需要从异常服务程序中退出,并返回主程序。RISC-V架构定义了一组专门的退出异常指令(Trap-Return Instructions),包括MRET,SRET和URET。其中MRET指令是必备的,而SRET和URET指令仅在支持监督模式和用户模式的处理器中使用。
在机器模式下退出异常时,软件必须使用MRET指令。RISC-V架构规定,处理器执行MRET指令后的硬件行为如下。
- 停止执行当前程序流,转而从CSR寄存器mepc定义的PC地址开始执行
- 执行MRET指令不仅会让处理器跳转到上述的PC地址开始执行,还会让硬件同时更新CSR寄存器机器模式状态寄存器mstatus。
1、从mepc定义的PC地址开始执行
在进入异常时,mepc寄存器被同时更新,以反映当时遇到异常的指令的PC值。同时这个机制,意味着MRET指令执行后处理器回到了当时遇到异常的指令的PC地址,从而可以继续执行之前被中止的程序流。
2、更新CSR寄存器mstatus
RISC-V架构规定,在执行MRET指令后,硬件将自动更新机器模式状态寄存器mstatus的某些域。
RISC-V结构规定,执行MRET指令退出异常时有如下情况。
- mstatus寄存器MIE域的值被更新为当前MPIE的值。
- mstatus寄存器MPIE域的值则被更新为1。
在进入异常时,MPIE的值曾经被更新为异常发生前的MIE值。而MRET指令执行后,再次将MIE域的值更新为MPIE的值。通过这个机制,则意味着MRET指令执行后,处理器的MIE值被恢复成异常发生之前的值(假设之前的MIE值为1,则意味着中断被重新全局打开)。
2.3 异常服务程序
当处理器进入异常后,即开始从mtvec寄存器定义的PC地址执行新的程序。该程序通常为异常服务程序,并且程序还可以通过查询mcause中的异常编号决定进一步跳转到更具体的异常服务程序。比如当程序查询mcause中的值为0x2,则得知该异常是非法指令错误引起的,因此可以进一步跳转到非法指令错误异常服务子程序中去。
注意:由于RISC-V架构规定的进入异常和退出异常机制中没有硬件自动恢复和保存上下文的操作,因此需要软件明确的使用指令进行上下文的保存和恢复
三、RISC-V架构中断定义
3.1 中断类型
RISC-V架构定义的中断类型分为4种。
- 外部中断
- 计时器中断
- 软件中断
- 调试中断
1、外部中断
RISC-V架构定义的外部中断要点如下。
(1)外部中断是指来自于处理器核外部的中断,比如外部设备UART,GPIO等产生的中断。
(2)RISC-V架构在机器模式,监督模式和用户模式下均有对应的外部中断。
(3)机器模式外部中断的屏蔽由CSR寄存器mie中的MEIE域控制,等待标志则反映在CSR寄存器mip中的MEIP域。
(4)机器模式外部中断可以作为处理器核的一个单比特输入信号,假设处理器需要支持很多个外部中断源,RISC-V架构定义了一个平台级别中断控制器(Platform Level Interrupt Controlle,PLIC)可用于多个外部中断源的优先级仲裁和派发。
- PLIC可以将多个外部中断源仲裁为一个单比特的中断信号送入处理器核,处理器核收到中断进入异常服务程序后,可以通过读PLIC的相关寄存器查看中断源的编号和信息。
- 处理器核在处理完相应的中断服务程序后,可以通过写PLIC的相关寄存器和具体的外部中断源的寄存器,从而清楚中断源(假设中断来源为GPIO,则可通过GPIO模块的中断相关寄存器清除该中断)。
(5)虽然RISC-V架构只明确定义了一个机器模式外部中断,同时明确定义可通过PLIC在外部管理众多的外部中断源将其仲裁成为一根机器模式外部中断信号传递给处理器核。但是RISC-V架构也预留了大量的空间供用户扩展其他外部中断类型,如以下三种。
- CSR寄存器mie和mip的高20位可以用于扩展控制其他的自定义中断类型。
- 用户甚至可以自定义若干组新的mie<n>和mip<n>寄存器以支持更多自定义中断类型。
- CSR寄存器mcause的中断异常编号域为12及以上的值,均可以用于其他自定义中断的异常编号。因此理论上通过扩展,RISC-V架构可以支持无数根自定义的外部中断信号直接输入给处理器核。
2、计时器中断
RISC-V架构定义的计时器中断要点如下。
(1)计时器中断是指来自计时器的中断。
(2)RISC-V架构在机器模式,监督模式核用户模式下均有对应的计时器中断。
(3)机器模式计时器中断的屏蔽由mie寄存器中的MTIE域控制,等待标志则反映在mip寄存器中的MTIP域。
(4)RISC-V架构定义了系统平台中必须有一个计时器,并给该计时器定义了两个64位宽的寄存器mtime和mtimecmp。mtime寄存器用于反映当前计时器的计数值,mtimecmp用于设置计时器的比较值。当mtime中的计数值大于或者等于mtimecmp中设置的比较值时,计数器便会产生计时器中断。计时器中断会一直拉高,直到软件重新写mtimecmp寄存器的值,使得其比较值大于mtime中的值,从而将计时器中断清除。
- 值得注意的是,RISC-V架构并没有定义mtime寄存器和mtimecmp寄存器为CSR寄存器,而是定义其为存储器地址映射的系统寄存器,具体的存储器映射地址RISC-V架构并没有规定,而是交由SoC系统集成者实现。
- 另一点值得注意的是,RISC-V架构定义mtime定时器为实时计时器,系统必须以一种恒定的频率作为计时器的时钟。该恒定的时钟频率必须为低速的电源常开的时钟,低速是为了省电,常开是为了提供准确的计时。
3、软件中断
RISC-V架构定义的软件中断要点如下。
(1)软件中断是指来自软件自己触发的中断。
(2)RISC-V架构在机器模式,监督模式核用户模式下均有对应的软件中断。
(3)机器模式软件中断的屏蔽由mie寄存器中的MSIE域控制,等待标志则反映在mip寄存器中的MSIP域。
(4)RISC-V架构定义的机器模式软件中断可以通过软件写1至msip寄存器来触发
- 注意:此msip寄存器和mip寄存器中的MSIP域命名不可混淆。且RISC-V架构并没有定义msip寄存器为CSR寄存器,而是定义其为存储器地址映射的系统存储器,具体的存储器映射地址RISC-V架构并没有规定,而是交由SoC系统集成者实现。
(5)当软件写1至msip寄存器触发了软件中断之后,CSR寄存器mip中的MSIP域便会置高,反映其等待状态。软件可通过写0至msip寄存器来清除该软件中断。
4、调试中断
除了上述3种中断之外,还有一种特殊的中断——调试中断(Debug Interrupt)。此中断专用于实现调试器(Debugger)。
3.2 中断屏蔽
RISC-V架构的狭义上的异常是不可以被屏蔽的,也就是说一旦发生狭义上的异常,处理器一定会停止当前操作转而处理异常。但是狭义上的中断则可以被屏蔽掉,RISC-V定义了CSR寄存器机器模式中断使能寄存器mie(Machine Interrupt Enable Registers)可以用于控制中断的屏蔽。
(1)mie寄存器的详细格式如下图所示,其中每一个比特域用于控制单个单独的中断使能。
- MEIE域控制机器模式下外部中断的屏蔽。
- MTIE域控制机器模式下计时器中断的屏蔽。
- MSIE域控制机器模式下软件中断的屏蔽。
(2)软件可以通过写mie寄存器种的值达到屏蔽某些中断的效果。假设MTIE域为被设置成0,则意味着将计时器中断屏蔽,处理器将无法相应计时器中断。
(3)如果处理器只实现了机器模式。则监督模式和用户模式对应的中断使能位(SEIE,UEIE,STIE,UTIE,SSIE和USIE)无任何意义。
注意:除了对3种中断的分别屏蔽,通过mstatus寄存器种的MIE域还可以全局关闭所有中断。
3.3 中断等待
RISC-V架构定义了CSR寄存器机器模式中断等待寄存器mip(Machine Interrupt Pending Registers)可以用于查询中断的等待状态。
(1)mip寄存器的详细格式如下图所示,其中的每一个域用于反映每个单独的中断等待状态(Pending)
- MEIP域反映机器模式下的外部中断的等待状态。
- MTIP域反映机器模式下的计时器中断的等待状态。
- MSIP域反映机器模式下的软件中断的等待状态。
(2)如果处理器只实现了机器模式,则mip寄存器中监督模式和用于模式对应的中断等待状态位(SEIP,UEIP,STIP,UTIP,SSIP,USIP)无任何意义。
(3)软件可以通过读mip寄存器中的值达到查询中断状态的效果。
- 如果MTIP域的值为1,则表示当前有计时器中断正在等待。注意:即便mie寄存器中的MTIE域的值为0(被屏蔽),如果计时器中断到来,则MTIP域仍然能够显示为1。
- MSIP和MEIP与MTIP同理。
(4)MEIP/MTIP/MSIP域的属性均为只读,软件无法直接写这些域改变其值。只有这些中断的源头被清除后将中断源撤销, MEIP/MTIP/MSIP域的值才能相应地归零。比如MEIP对应的外部中断需要程序进入中断服务程序后配置外部中断源,将其中断撤销。MTIP和MSIP同理。
3.4 中断优先级与仲裁
对于RISC-V而言,分为如下三种情况。
(1)如果3种中断同时发生,其相应的优先级顺序如下,mcause寄存器中将按此优先级顺序选择更新异常编号的值。
- 外部中断优先级最高
- 软件中断其次
- 计时器中断再次
(2)调试中断比较特殊,只有调试器(Debugger)介入调试时才发生,正常情形下不会发生,因此在此不予讨论。
(3)由于外部中断来自PLIC,而PLIC可以管理数量众多的外部中断源,多个外部中断源之间的优先级和仲裁可通过配置PLIC的寄存器进行管理。
3.5 中断嵌套
曾经提到多个中断理论上可能存在着中断嵌套的情况。而对于RISC-V架构而言,
- 进入异常之后,mstatus寄存器中的MIE域将会被硬件自动更新成为0(意味着中断被全局关闭,从而无法响应新的中断)。
- 退出中断后,MIE域才被硬件自动恢复成中断发生之前的值,(通过MPIE域得到),从而再次全局打开中断。
由上可见,一旦响应中断进入异常模式后,中断被全局关闭再也无法响应新的中断,因此RISC-V架构定义的硬件机制默认无法支持硬件中断嵌套行为。
如果一定要支持中断嵌套,需要使用软件的方式达到中断嵌套的目的,从理论上来讲,可采用如下方法。
(1)在进入异常之后,软件通过查询mcause寄存器确认这是响应中断造成的异常,并跳入相应的中断服务程序中。在这期间,由于mstatus寄存器中的MIE域被硬件自动更新成为0,因此新的中断都不会被响应。
(2)待程序跳入中断服务程序中后,软件可以强行改写mstatus寄存器的值,而将MIE域的值改为1,意味着将中断再次全局打开。从此时起,处理器能够再次响应中断。但是在强行打开MIE域之前,需要注意如下事项。
- 假设软件希望屏蔽比其优先级低的中断,而仅允许优先级比它高的新来打断当前中断,那么软件需要通过配置mie寄存器中的MEIE/MTIE/MSIE域,来有选择地屏蔽不同类型的中断。
- 对于PLIC管理的众多外部中断而言,由于其优先级受PLIC控制,假设软件希望屏蔽比其优先级低的中断,而仅允许优先级比它高的新来中断打断当前中断,那么软件需要通过配置PLIC阈值寄存器的方式来有选择地屏蔽不同类型的中断。
(3)在中断嵌套的过程中,软件还需要注意保存上下文至存储器堆栈中,或者从存储器堆栈中将上下文恢复(与函数嵌套同理)。
(4)在中断嵌套的过程中,软件还需要注意将mepc寄存器,以及为了实现软件中断嵌套被修改的其他CSR寄存器的值保存至存储器堆栈中,或者从存储器堆栈中恢复(函数嵌套同理)
除此之外,RISC-V架构也允许用户实现自定义的中断控制器实现硬件中断嵌套功能。
3.6 总结比较
对ARM的Cortex-M系列或者Cortex-A系列比较熟悉的读者,可能会了解Cortex-M系列定义的嵌套向量中断控制器(NVIC)和Cortex-A系列定义的通用中断控制器(GIC)。这两种中断控制器都非常强大,但也非常复杂。相比而言,RISC-V架构中断和异常机制则要简单得多,这同样反映了RISC-V架构力图简化硬件的设计哲学。
四、RISC-V架构异常相关CSR寄存器
将RISC-V架构中所有中断和异常相关的寄存器加以总结,如下表所示。
类型 | 名称 | 全称 | 描述 |
CSR | mtvec | 机器模式异常入口基地址寄存器(Machine Trap-Vector Base-Address Register) | 定义进入异常的程序PC地址 |
mcause | 机器模式异常原因寄存器(Machine Cause Register) | 反映进入异常的原因 | |
mtval (mbadaddr) |
机器模式异常值寄存器(Machine Trap Value Register) | 反映进入异常的信息 | |
mepc | 机器模式异常PC寄存器(Machine Exception Program Counter) | 用于保存异常的返回地址 | |
mstatus | 机器模式状态寄存器(Machine Status Register) | mstatus寄存器中的MIE域和MPIE域用于反映中断全局使能 | |
mie | 机器模式中断使能寄存器(Machine Interrupt Enable Pending Registers) | 用于控制不同类型中断的局部使能 | |
mip | 机器模式中断等待寄存器(Machine Interrupt Pending Registers) | 反映不同类型中断的等待状态 | |
Memory Address Mapped |
mtime | 机器模式计时器寄存器(Machine-mode timer register) | 反映计时器的值 |
mtimecmp | 机器模式计时器比较值寄存器(Machine-mode timer compare register) | 配置计时器的比较值 | |
msip | 机器模式软件中断等待寄存器(Machine-mode Software Interrupt Pending Register) | 用以产生或者清除软件中断 | |
PLIC | 链接“” |