Nuclei N200系列中断机制详解
Nuclei N200系列中断介绍
中断概述
从CPU的角度看,中断(Interrupt)是处理器内核在顺序执行程序指令流的过程中突然被别的请求打断而中止执行当前的程序,转而去处理别的事情,待其处理完了别的事情,然后重新回到之前程序中断的点继续执行之前的程序指令流。
之前听过一个很巧妙地类比,如果一个人在等一条短信,可以有两种方式查看到短信。第一种就是不断的(间隔一定时间)去看手机有没有收到短信,如果收到了短信就查看短信内容;还有一种可以专心做别的事情,如果听到了手机提示音,就去看一下是不是有收到短信,再查看收到的短信发件人是不是你要等的信息发件人,如果都正确再去查看短信内容。类比到计算机中程序处理,第一种对应的是轮询方式,第二种是中断方式。
相比较轮询方式,中断方式有如下优点:
在介绍Nuclei N200系列中断之前,简单介绍一下Nuclei和N200系列内核:
Nuclei是国内首批基于RISC-V 开放指令集架构并率先实现产业化应用的企业。其开发的蜂鸟E203处理器是国内第一个完善的开源RISC-V处理器项目;N级别处理器是Nuclei商用的一个处理器内核(Processor Core)级别,其中N200系列性能可以对标ARM Cortex-M3内核。
如下介绍一下中断相关知识:
打断处理器执行的“别的请求”便称之为中断请求(Interrupt Request),“别的请求”的来源便称之为中断源(Interrupt Source),中断源通常来自于内核外部(外部中断源), 也可以来自于内核内部(内部中断源)。
处理器转而去处理的“别的事情”便称之为中断服务程序(Interrupt Service Routine,简称ISR)。
中断处理是一种正常的机制,而非一种错误情形。处理器收到中断请求之后,需要保存当前程序的现场,简称为“保存现场”。等到处理完中断服务程序后,处理器需要恢复之前的现场,从而继续执行之前被打断的程序,简称为“恢复现场”。
可能存在多个中断源同时向处理器发起请求的情形,需要对这些中断源进行仲裁,从而选择哪个中断源被优先处理。此种情况称为“中断仲裁”,同时可以给不同的中断分配级别和优先级以便于仲裁,因此中断存在着“中断级别”和“中断优先级”的概念。
CLIC模式和CLINT模式
CLINT模式
CLINT模式是复位后的默认模式,是一种简单的中断处理方案。CLINT模式依赖PLIC (Platform Level Interrupt Controller) ,是 RISC-V 标准特权架构规范的一部分。适用于支持 Linux 的应用程序或对称多处理器 (SMP) 应用程序。
CLIC模式
CLIC模式是一种相对复杂的中断处理方案。CLIC模式依赖于ECLIC(Platform Level Interrupt Controller) ,拥有快速中断处理能力,建议使用在实时或微控制器应用中。
Nuclei 处理器内核支持 "CLINT中断模式"和 “CLIC中断模式”。软件可通过写入寄存器MTVEC的最低有效位来设置不同的模式。一般N200系列内核中会配备CLIC中断模式,CLINT中断模式不会被实例化;可以通过寄存器MCFG_INFO查看是否支持CLINT模式和CLIC模式模式。
以下内容介绍CLIC(ECLIC)中断模式。
中断类型
N 级别处理器内核支持的中断类型如图所示
外部中断
外部中断是指来自于处理器核外部的中断。外部中断可供用户连接外部中断源,譬如外部设备UART、 GPIO 等产生的中断。
内部中断
N 级别处理器内核有两种内核私有的内部中断,分别为:
内部中断外部中断使用上无区别。
中断屏蔽
中断全局屏蔽
N 级别处理器内核的中断可以被全局屏蔽掉,寄存器MSTATUS的MIE域控制中断的全局使能
中断源单独屏蔽
ECLIC 为每个中断源分配了各自的中断使能寄存器,用户可以通过配置ECLIC中某个中断源的CLICINTIE寄存器来管理对应中断源的使能。
中断属性
ECLIC的每个中断源均可以设置电平触发或者边沿触发的属性。
当中断属性位电平触发时中断源的IP位会实时反应该中断源的电平值,所以对IP的写操作会被忽略,软件想要清除中断,需要在源头(中断源)上清除。
当中断属性位边沿触发时,ECLIC会检测中断源的边沿,当出现边沿跳动(上升沿/下降沿)时,中断触发,IP位被置高。软件可以通过写IP位的方式设置和清除IP位的值,需要注意的是,为了提高中断处理的效率,当中断被响应时(处理器执行ISR)时ECLIC会自动清除该中断的IP位,所以ISR中无需再清除IP。
中断模式
ECLIC 的每个中断源均可以设置成向量或者非向量处理。
如果被配置成为向量处理模式,则该中断被处理器内核响应后,处理器直接跳入该中断的向量入口(Vector Table Entry)存储的目标地址。
如果被配置成为非向量处理模式,则该中断被处理器内核响应后,处理器直接跳入所有中断共享的入口地址。共享的入口地址函数可以找到pending的中断进行处理,最终还是跳到向量入口(Vector Table Entry)存储的目标地址。
对于向量模式和非向量模式的处理上有较大的区别,向量模式在跳入中断服务程序之前,处理器并没有进行任何特殊的处理, 处理器内核在响应中断后,中断被全局关闭,从而无法响应新的中断,因此向量处理模式默认是不支持中断嵌套的,为了达到向量处理模式且又能够中断嵌套的效果需要在中断服务程序的开头处添加特殊的入栈操作。且向量模式需要_attribute_((interrupt))来修饰中断服务程序函数。
非向量模式通过共享的入口地址函数添加特殊的入栈操作可以实现中断嵌套,且无需_attribute_((interrupt))来修饰中断服务程序函数,其实都是在共享的入口地址函数中做了。
使用中推荐使用非向量模式,使用起来简单,使用共享的入口地址函数就可以实现中断嵌套。但如果你的中断函数特别简单,甚至是Leaf Function,且不会被打断(Level设置成最大)。那么在极端的情况下也无需_attribute_((interrupt))来修饰中断服务,无需在中断服务函数内添加特殊的入栈操作出栈操作。此时在理想的情况下约六个时钟周期中断服务函数就会被响应!!!
中断级别、优先级
当多个中断同时出现时,需要进行仲裁。对于 N 级别处理器内核处理器而言, ECLIC 统一管理所有的中断。 ECLIC 为每个中断源分配了各自的中断级别和优先级寄存器(CLICINTCTL),用户可以通过配置该寄存器来管理各个中断源的级别和优先级,当多个中断同时发生时, ECLIC 会仲裁出级别和优先级最高的中断
中断级别和中断优先级共同使用CLICINTCTL来决定。CLICINFO.CLICINTCTBITS用来指示CLICINTCTL中总有效比特数,CLICCFG用来指示 CLICINTCTL中表示LEVEL的比特数。MTH寄存器用来指示中断可以被送到Core的LEVEL。
中断仲裁
Level的数字越大表示中断级别越高,高级别的中断可以打断低级别的中断。多个中断同时等待时,LEVEL高的中断先被响应。
Priority的数字越大表示中断优先级越高,中断优先级不参与中断嵌套的判断(同Level的中断,高优先级不能打断低优先级),多个中断同时等待时,仲裁会先判断多个中断的Level和Priority。如果都一样,会先响应中断源序号小的中断。
中断向量表
中断向量表是指在存储器里面开辟的一段连续的地址空间,该地址空间的每个字(Word)用于存储ECLIC每个中断源对应的中断服务程序(Interrupt Service Routine, ISR)函数的 PC 地址 。
中断向量表的作用非常重要,当处理器响应某个中断源后,无论中断是向量处理模式还是非向量处理模式,硬件最终都将通过查询中断向量表中存储的 PC 地址跳转到其对应的中断服务程序函数中去
中断嵌套
处理器内核正在处理某个中断的过程中,可能有一个级别更高的新中断请求到来,处理器可以中止当前的中断服务程序,转而开始响应新的中断,并执行其“中断服务程序”,如此便形成了中断嵌套(即前一个中断还没响应完,又开始响应新的中断),并且嵌套的层次可以有很多层
注意:假设新来的中断请求的优先级比正在处理的中断级别低(或者相同),则处理器不应该响应这个新的中断请求,处理器必须完成当前的中断服务程序之后才考虑响应新的中断请求(因为新中断请求的级别并不比当前正在处理的中断级别高)。在N 级别处理器内核中,取决于中断是向量处理模式还是非向量处理模式,中断嵌套的支持方法会有所差异
作者:yyqqwwheart