中断是计算机架构中的一个重要机制。
一般来说,CPU/Core的工作过程就是不断地“取指令、解释指令、执行指令”。
当芯片上电(power on)或者重启(reset)时,会从某个地址(由规范指定或芯片设计厂家自定)取第1条指令,然后就不断地“取指令、解释指令、执行指令”。
光这个过程难以让CPU/Core及时响应外部事件或内部异常进行处理,因此引入了中断机制。
大致地说,当异常(Exception)/中断(Interrupt)事件发生时,CPU/Core可以暂停当前指令流的执行,转而从另一个入口(中断服务程序)开始执行另一个指令流直到遇到“中断返回”指令,然后返回原指令流断点处执行,这个过程称为“中断处理过程”。相关概念和实现都归属于“中断”机制。
就我接触的教材看,基本中断原理和概念写得最详细的是马潮老师的“基于AVR的单片嵌入式系统原理与实践应用”,大家可以找来看看。看完再去看ARM的教材会清晰一些(ARM的机制更复杂)。
这两个术语在不同教材和规范中的含义和包含关系略有不同。
异常(狭义)是指计算机系统(软件或硬件)运行过程中出现的不该出现的事件。CPU/Core需要针对该事件进行相应的处理。常见异常包括存储器读写出错、除以零、访问了不允许访问的地址单元等。
中断(狭义)是指正常的外部事件或内部事件(软中断)出现了,需要CPU/Core及时响应进行相应的处理。
异常(广义)包含异常(狭义)和中断(狭义)。
在术语上,似乎没有“中断(广义)”包含“异常(狭义)”。但是在行文上,由于异常事件的处理过程跟中断的处理过程基本一样,有时往往也笼统称为中断和中断处理过程。
以下内容主要针对中断处理开展介绍。
中断源就是可以引发中断的来源。
一个芯片可以支持许多个中断源。但是一般来说一个CPU/Core同时只能执行一路指令流(一个中断服务程序或异常服务程序)。
于是各种表述中“中断请求信号”可能会出现两个概念,一个是中断源产生的中断事件信号,另一个是CPU/Core的中断触发信号。
由多个中断源同时产生的多路中断事件信号中选出一路生成送往一个CPU/Core的中断触发信号,属于中断管理的内容。往往由一个或多个模块实现。
(注意:芯片中可以有多个CPU/Core)
处理某个中断事件的程序(指令流)称为中断服务程序。
一个中断服务程序可以服务一个中断事件,也可以服务多个中断事件(由芯片设计者决定)。
中断服务程序的第一条指令的地址称为中断入口。
各个中断服务程序及异常服务程序的入口往往放在一起,称为中断矢量表。
不同的芯片,中断矢量表里面每个地址单元的内容(中断矢量)可以是一条跳转指令(第一条指令本身),或者是第一条指令的地址。
CPU/Core可以配置一个中断源产生的中断事件信号是否能够触发中断,称为中断禁止/中断允许。
芯片中一般会设置一个中断允许寄存器(Mask),其中对每个中断源设置一个中断允许比特位。该位比特值为1则为允许。往往会设置另外一个中断事件信号寄存器(Pending),同样的中断源对应比特位值为1表示有请求。因为将这两个寄存器的值按位与,结果为1的位置就是允许中断的中断源,因此将这样的中断允许机制称为中断掩码(Mask)(值为0就把请求信号给掩掉了)。
芯片中一般会设置另外一个全局中断允许比特,置0则所有中断请求都不会响应。
当同时出现多个允许中断的中断请求信号时,CPU/Core跳转到对应哪一个中断源的中断服务程序执行呢?这里就可以有多种算法了。
首先是各种中断请求中是否有不同的等级,术语为“中断优先级”。优先级高的先服务。
其次是同一等级中按什么顺序提供服务。这里可以有不同策略。
假如有区分中断优先级,那么当CPU/Core已经在执行一个事件的中断/异常服务程序时,是否允许进一步中断,转而执行高优先级的中断服务程序呢?
假如允许的话,该机制称为中断嵌套。中断嵌套往往有层数限制。
大多教材把中断处理过程划分为“中断响应”、“中断处理”、“中断返回”三个部分。
有的教材把中断源产生事件信号、经中断掩码和中断允许判断及优先级判断等过程产生中断请求信号的过程称为“中断请求”,作为“中断响应”前面的部分,则过程划分为四个部分。有的则纳入中断响应中。有的不把中断请求算入中断处理过程。
从CPU/Core看,“中断响应”从送入CPU/Core的中断请求信号有效时开始。
CPU/Core要中断当前指令流的执行,跳转到相应的中断服务程序入口。相应的工作包括:
粗糙地说,断点就是当前指令流断开的位置。
对于单级流水线(即无流水线)的CPU/Core来说,往往会执行完当前指令再跳转。那么断点就是下一条指令的地址。下一条指令的地址可能是当前指令地址加指令长度,也可能是一个新地址(遇到跳转指令)
对于多级流水线以及其它高性能CPU/Core架构(多发射、硬件多线程等),问题就复杂了,我也不懂。
断点保存动作由硬件完成。
当前指令流执行过程中会用到通用寄存器和一些系统寄存器,这些寄存器的内容就称为现场。
因为新的指令流也可能会用到这些寄存器,从而把它们的内容冲掉。因此在执行新的指令流时需要先保存下来,在中断返回时再恢复。这个过程称为保护现场。
现场数据的保存往往用到堆栈,保存在RAM中。因此会耗费一定的时间。
保护现场的工作一般由软件完成。有的芯片提供硬件方式的现场保护和现场恢复,速度会快。
关全局中断(可选) 为了避免中断嵌套,执行中断服务程序的过程中需要关全局中断。这个动作一般由软件实现,也有的芯片是由硬件自动实现。
跳转
计算入口地址,然后跳转。
中断处理就是中断服务程序的内容,由应用决定。
当硬件没有负责现场保护时,中断服务程序的开头要进行现场保护,返回前要进行现场恢复。
一般指令集中会有一条专门的中断返回指令(有的没有,比如ARM(直接修改PC值))。
中断服务程序的最后一条指令是中断返回指令。
假如现场保护和现场恢复由硬件实现的话,则执行中断返回指令时先恢复现场。
有的芯片会自动开全局中断。
然后返回断点处继续执行原来的指令流。
术语在RISC-V的基本规范文档的“1.3 Exceptions, Traps, and Interrupts”。
这里多了个术语“Trap”,可以先不管它。
基本规范和特权规范中定义了若干系统寄存器,称为控制与状态寄存器(Control and Status Register)。以及规定了存取CSR的相关指令。
注:以下只介绍特权模式为机器模式(machine mode)下的相关内容。
其中一个CSR寄存器名为mtvec的,负责保存中断/异常矢量表入口。另一个CSR名为mcause的保存中断/异常原因。
(3.1.12 Machine Trap-Vector Base-Address Register (mtvec))
(3.1.20 Machine Cause Register (mcause))
mtvec的比特[1:0]区分两种模式,一种是所有中断/异常的入口都是mtvec,另一种是入口为mtvec+mcause(大致的,细节看规范)。
地址为mtvec或mtvec+mcause的地址单元中保存的是指令(中断服务程序的第一条指令)。
断点由硬件自动保存在名为mepc的CSR中。(3.1.19 Machine Exception Program Counter (mepc))
分别在名为mip和mie的寄存器中。(3.1.14 Machine Interrupt Registers (mip and mie))
机器模式的中断/异常返回指令为mret。
规范没有要求。由软件实现。
特权规范中专门有一章介绍平台层次中断控制器的功能、结构和规范“Platform-Level Interrupt Controller(PLIC)”。
所谓“Platform-Level”,是指这个模块(中断控制器)是面向多个CPU/Core,不是CPU/Core内部的中断/异常管理模块。
里面介绍了中断源、中断请求、中断允许等概念。
其内容很多,这里不详述。(后面的实现没用到)
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。