修订历史
版本号 | 修订日期 | 修订的章节 | 修订的内容 |
---|---|---|---|
1.0 | 2020/03/17 | N/A | 初始版本 |
N级别内核用户将通过本文,快速掌握该内核中断应用开发的必要知识点。包括:内核中断机制、CORE TIMER和ECLIC介绍、芯来软件平台NSP应用介绍、嵌入式软件中断应用开发实例解析等。
中断应用,是N级别内核应用中的重点和难点。本文将结合嵌入式软件应用开发实例,着重讲解,N级别内核的中断使用方法。通过对例程解析,使用户在最短的时间内,熟练掌握N级别内核中断的应用开发。
为了使用户能对以上介绍的中断应用实例,进行快速启动和实践操作。本文将基于芯来科技推出的RV-STAR开发板,介绍通过芯来软件平台NSP进行应用实例的调试运行流程。
Nuclei N级别处理器内核(简称N级别内核)主要面向低功耗高性能的嵌入式场景而设计,非常适合于替代传统的8位/16位内核或者ARM Cortex-M/R系列内核应用于IoT、低功耗或者其他实时控制场景。
N级别内核遵循标准的RISC-V指令集标准。
详情请参见《Nuclei_N级别指令架构手册》第1.1节和第1.2节,了解其详情。
RISC-V的架构中定义了一些控制和状态寄存器(Control and Status Register,CSR),用于配置或记录一些运行的状态。CSR寄存器是处理器核内部的寄存器,使用其专有的12位地址编码空间。详情请参见《Nuclei_N级别指令架构手册》第1.3节了解其详情。
N级别内核支持三个特权模式(Privilege Modes):
机器模式(Machine Mode)是必须的模式。
监督模式(Supervisor Mode)是可配置的模式。
用户模式(User Mode)是可配置的模式。
机器模式包含四种机器子模式(Machine Sub-Mode)。其特权模式划分,如图 2-1所示:
详情请参见《Nuclei_N级别指令架构手册》第2.2节了解详情。
中断(Interrupt)机制,即处理器内核在顺序执行程序指令流的过程中突然被别的请求打断而中止执行当前的程序,转而去处理别的事情,待其处理完了别的事情,然后重新回到之前程序中断的点继续执行之前的程序指令流。
详情请参见《Nuclei_N级别指令架构手册》第5章了解其详情。
通过软件的不同配置,N级别处理器内核支持“默认中断模式”和“ECLIC中断模式”,推荐使用“ECLIC中断模式”,本文仅对“ECLIC中断模式”进行介绍。
N级别处理器内核实现了一个“改进型内核中断控制器(Enhanced Core Local Interrupt Controller,ECLIC)”,可用于多个中断源的管理。N级别处理器内核中的所有类型(除了调试中断之外)的中断都由ECLIC统一进行管理,有关ECLIC的详情请参见《Nuclei_N级别指令架构手册》第6.2节了解其详情。
N级别处理器内核支持的中断类型如图 3‑1中所示。
N级别内核的中断可以被屏蔽掉, CSR寄存器mstatus的MIE域控制中断的全局使能。
对于不同的中断类型而言,ECLIC统一管理外部中断、软件中断以及计时器中断。ECLIC为每个中断源分配各自的中断使能寄存器,用户可以通过配置ECLIC寄存器来管理各个中断源的屏蔽。
同时,用户可以通过配置ECLIC寄存器来管理各个中断源的屏蔽,达到使能或屏蔽某一个对应的中断。详情请参见《Nuclei_N级别指令架构手册》第5.4节了解其详情。
当多个中断同时出现时,需要进行仲裁。对于N级别内核处理器而言,ECLIC统一管理所有的中断。ECLIC为每个中断源分配了各自的中断级别和优先级寄存器,用户可以通过配置ECLIC寄存器来管理各个中断源的级别和优先级,当多个中断同时发生时,ECLIC会仲裁出级别和优先级最高的中断,如图
3-2中所示。详情请参见《Nuclei_N级别指令架构手册》第6.2.9节了解其详情。
在下文讲解的vectored_interrupt实例中,将定时器中断1(SoC TIMER1)、定时器中断2(SoC TIMER2)、用户按键外部中断的中断源级别,分别设置为级别1、级别2和级别3。当多个中断并发时,经过仲裁后,内核将优先响应优先级别为3的中断,即用户按键外部中断。
图3-3和图3-4分别介绍归纳了进入和退出中断模式的相关操作,详情请参见《Nuclei_N级别指令架构手册》第5章了解其详情。
如图 3‑5中所示,中断向量表是指在存储器里面开辟的一段连续的地址空间,该地址空间的每个字(Word)用于存储ECLIC每个中断源对应的中断服务程序(Interrupt Service Routine,ISR)函数的PC地址。
中断向量表的起始地址由CSR寄存器mtvt指定,通常可以将mtvt寄存器设置为整个代码段的起始位置。
中断向量表的作用非常重要,当处理器响应某个中断源后,无论中断是向量处理模式还是非向量处理模式,硬件最终都将通过查询中断向量表中存储的PC地址跳转到其对应的中断服务程序函数中去,请参见《Nuclei_N级别指令架构手册》第5.13节了解更多详细介绍。
RISC-V架构的处理器在进入和退出中断处理模式时没有硬件自动保存和恢复上下文(通用寄存器)的操作,因此需要软件明确地使用(汇编语言编写的)指令进行上下文的保存和恢复。根据中断是向量处理模式还是非向量处理模式,上下文的保存和恢复涉及到的内容会有所差异,请参见《Nuclei_N级别指令架构手册》第5.13节了解更多详细介绍。
中断响应延迟的概念通常是指,从“外部中断源拉高”到“处理器真正开始执行该中断源对应的中断服务程序(Interrupt Service Routine,ISR)中的第一条指令”所消耗的指令周期数。因此,中断响应延迟通常会包含如下几个方面的周期开销:
处理器内核响应中断后进行跳转的开销
处理器内核保存上下文所花费的周期开销
处理器内核跳转到中断服务程序(Interrupt Service Routine,ISR)中去的开销。
取决于中断是向量处理模式还是非向量处理模式,中断响应延迟会有所差异,请参见《Nuclei_N级别指令架构手册》第5.13节了解更多详细介绍。
处理器内核正在处理某个中断的过程中,可能有一个级别更高的新中断请求到来,处理器可以中止当前的中断服务程序,转而开始响应新的中断,并执行其“中断服务程序”,如此便形成了中断嵌套(即前一个中断还没响应完,又开始响应新的中断),并且嵌套的层次可以有很多层。请参见《Nuclei_N级别指令架构手册》第5.11节了解更多详细介绍。
处理器内核正在处理某个中断的过程中,可能有新中断请求到来,但是“新中断的级别”低于或者等于“当前正在处理的中断级别”,因此,新中断不能够打断当前正在处理的中断(因此不会形成嵌套)。
当处理器完成当前中断之后,理论上需要恢复上下文,然后退出中断回到主应用程序,然后重新响应新的中断,响应新的中断又需要再次保存上下文。因此,存在着一次背靠背的“恢复上下文”和“保存上下文”操作,如果将此背靠背的“恢复上下文”和“保存上下文”省略掉,则称之为“中断咬尾”,如图 3‑6中所示,显而易见,中断咬尾可以加快多个中断的背靠背处理速度。
在N级别处理器内核中,只有非向量处理模式才支持中断咬尾,请参见《Nuclei_N级别指令架构手册》第5.13.1.3节了解更多详细介绍。
ECLIC的每个中断源均可以设置成向量或者非向量处理(通过寄存器clicintattr[i]的shv域),向量处理模式和非向量处理模式二者有较大的差别,分别介绍如下。
如果被配置成为非向量处理模式,则该中断被处理器内核响应后,处理器会直接跳入到所有非向量中断共享的入口地址,该入口地址可以通过软件进行设置。
在进入所有非向量中断共享的入口地址之后,处理器会开始执行一段共有的软件代码,如图 3‑7中所示的例子。
由于非向量处理模式时处理器在跳到中断服务程序之前需要先执行一段共有的软件代码进行上下文的保存,因此,从中断源拉高到处理器开始执行中断服务程序中的第一条指令,需要经历以下几个方面的时钟周期开销:
处理器内核响应中断后进行跳转的开销。理想情况下约4个时钟周期。
处理器内核保存CSR寄存器mepc、mcause、msubm入堆栈的开销。
处理器内核保存上下文所花费的周期开销。如果是RV32E的架构,则需要保存8个通用寄存器,如果是RV32I的架构,则需要保存16个通用寄存器。
处理器内核跳转到中断服务程序(Interrupt Service
Routine,ISR)中去的开销。理想情况下约需要5个时钟周期。
如上文所述,非向量处理模式总是能够支持中断嵌套,如图 3‑8中所示的示例:假设中断源30、31、32这三个中断源先后到来,且“中断源32的级别” > “中断源31的级别”> “中断源30的级别”,那么后来的中断便会打断之前正在处理的中断形成中断嵌套。
对于非向量处理模式的中断而言,由于在跳入和退出中断服务程序之前,处理器要进行上下文的保存和恢复,因此进行“中断咬尾”能够节省显著的时间(节省一次背靠背的保存上下文和恢复上下文)。
如果被配置成为向量处理模式,则该中断被处理器内核响应后,处理器会直接跳入该中断的向量入口(Vector Table Entry)存储的目标地址,即该中断源的中断服务程序(Interrupt Service Routine,ISR),如图 3‑10中所示的例子。
向量处理模式具有如下特点:
向量处理模式时处理器会直接跳到中断服务程序,并没有进行上下文的保存,因此,中断响应延迟非常之短,从中断源拉高到处理器开始执行中断服务程序中的第一条指令,基本上只需要硬件进行查表和跳转的时间开销,理想情况下约6个时钟周期。
对于向量处理模式的中断服务程序函数,一定要使用特殊的attribute((interrupt))来修饰中断服务程序函数。
向量处理模式时,由于在跳入中断服务程序之前,处理器并没有进行上下文的保存,因此,理论上中断服务程序函数本身不能够进行子函数的调用(即,必须是Leaf
Function)。
向量处理模式时,由于在跳入中断服务程序之前,处理器并没有进行任何特殊的处理,且由于处理器内核在响应中断后,mstatus寄存器中的MIE域将会被硬件自动更新成为0(意味着中断被全局关闭,从而无法响应新的中断)。因此向量处理模式默认是不支持中断嵌套的,为了达到向量处理模式且又能够中断嵌套的效果,如图 3‑11中所示,需要在中断服务程序的开头处添加特殊的入栈操作:
首先保存CSR寄存器mepc、mcause、msubm入堆栈。保存这几个CSR寄存器是为了保证后续的中断嵌套能够功能正确,因为新的中断响应会重新覆盖mepc、mcause、msubm的值,因此需要将它们先保存入堆栈。
重新打开中断的全局使能,即,设置mstatus寄存器的MIE域为1。打开中断全局使能后,新的中断便可以被响应,从而达到中断嵌套的效果。
在中断服务程序的结尾处同样需要添加对应的恢复上下文出栈操作。并且在CSR寄存器mepc、mcause、msubm出堆栈之前,需要将中断全局使能再次关闭,以保证mepc、mcause、msubm恢复操作的原子性(不被新的中断所打断)。
如上文所述,向量处理模式的中断经过特殊处理也可以支持中断嵌套,如图 3‑12中所示的示例:假设中断源30、31、32这三个中断源先后到来,且“中断源32的级别”> “中断源31的级别”> “中断源30的级别”,那么后来的中断便会打断之前正在处理的中断形成中断嵌套。
对于向量处理模式的中断而言,由于在跳入中断服务程序之前,处理器并没有进行上下文的保存,因此进行“中断咬尾”的意义不大,因此,向量处理模式的中断,没有“中断咬尾”处理能力。
当用户程序需要最快速的响应中断处理请求,且中断服务程序函数本身没有进行子函数的调用(即,必须是Leaf Function)时,选择使用向量处理模式。
其他情况一律使用非向量处理模式。
计时器单元(Timer Unit,CORE TIMER),在N级别内核中主要用于产生计时器中断(Timer Interrupt)和软件中断(Software Interrupt)。详情请参见《Nuclei_N级别指令架构手册》第6.1节了解其详情。
N级别内核支持在RISC-V标准CLIC基础上优化而来的“改进型内核中断控制器(Enhanced Core Local Interrupt Controller,ECLIC)”,用于管理所有的中断源。详情请参见《Nuclei_N级别指令架构手册》第6.2节了解其详情。
ECLIC单元生成一根中断线,发送给处理器内核(作为中断目标),其关系结构如图4-1所示。
在下文解析的vectored_interrupt实例中,将详细讲解计时器单元(CORE TIMER)、定时器中断(SoC TIMER)和外部中断。
其中,计时器单元(CORE TIMER)用于实现延时函数功能;定时器1(SoC TIMER1)和定时器2(SoC TIMER2)用于产生2个周期性外部向量中断;用户按键,用于产生1个外部非向量中断。(用户按键中断级别高于计时器1&2的中断级别。)
芯来软件平台NSP(Nuclei Software Platform)包括:
Nuclei微控制器软件接口标准(NMSIS:Nuclei Microcontroller Software Interface Standard)。
Nuclei处理器内核的软件开发包(Nuclei SDK: Nuclei Software Development Kit )。
Nuclei SDK是专为基于芯来科技Nuclei处理器内核的SoC开发的软件开发包。Nuclei SDK以NMSIS为基础进行开发,提供NMSIS上的所有功能,包括NMSIS-Core,NMSIS-NN,NMSIS-DSP。Nuclei SDK提供裸机(Bare-metal)以及实时操作系统(FreeRTOS,μC/OS-II)开发环境。
请参阅芯来科技官网在线文档页面(https://doc.nucleisys.com/nuclei_sdk)
《Nuclei-SDK’s documentation》了解其详情。
NMSIS是为芯来科技RISC-V处理器定义的厂商无关的硬件抽象层,定义了通用工具接口并提供持续的处理器设备支持,以及简洁的处理器和外设的软件访问接口API。采用NMSIS框架,可以大幅提升应用软件的复用性,缩短RISC-V微处理器开发者的学习时间,缩短基于芯来内核IP的新产品的上市时间。
请参阅芯来科技官网在线文档页面(https://doc.nucleisys.com/nmsis)
《NMSIS’s documentation》了解其详情。
Nuclei Board Labs,由Nuclei Board Labs软件包及RV-STAR开发板组成。
Nuclei Board Labs是基于Nuclei SDK开发的适配RV-STAR开发板的实验教程,提供手把手的实验手册,方便RV-STAR开发板使用者入门以及教学使用。通过实验教程将有助于开发者更好的理解和使用Nuclei SDK以及了解NMSIS标准。
关于Nuclei Board Labs,请参阅芯来科技官网在线文档页面(https://doc.nucleisys.com/nuclei_board_labs)了解其详情。
RV-STAR是一款基于GD32VF103 MCU的RISC-V评估开发板。GD32VF103系列器件是基于Nuclei Bumblebee处理器的32位通用微控制器。
关于GD32VF103 MCU芯片的相关内容,请参阅RISCV-MCU网站下载页面下载《GD32VF103 RISC-V 32-bit MCU Datasheet》和《GD32VF103 RISC-V 32-bit MCU用户手册》。
Bumblebee内核是由芯来科技(Nuclei System Technology)联合兆易创新(Gigadevice)针对其面向IoT或其他超低功耗场景的通用MCU产品定制的一款商用 RISC-V 处理器内核,专用于型号为 GD32VF103的MCU产品。
关于芯来RV-STAR开发板,请参阅芯来科技官网页面https://www.nucleisys.com/developboard.php了解其详情。
SEGGER Embedded Studio(以下简称SES)是SEGGER公司推出的一款嵌入式开发的集成开发环境,具有开发与编译界面专业,调试功能强大(配备知名的J-Link仿真器),非商业使用免费,跨平台兼容和配置灵活等特点。
有关SES的详细安装步骤,以及如何为其设置Nuclei配套的工具链,请参阅芯来科技官网下载页面( http://www.nucleisys.com/download.php )下载《Nuclei_SES_IDE_Installation.pdf》。
下文中的移植实例解析将使用SES为IDE,介绍在RV-STAR开发板上进行嵌入式软件的开发。
关于使用SES进行基于RV-STAR的快速开发详细信息,详情请参见《SES for RV-STAR快速上手手册》。
vectored_interrupt程序是一个完整的示例程序,它使用到了SoC系统中的外设,调用了中断服务程序等。
该程序中断设置如下:
设置一个用户按键中断,作为一个ECLIC的外部中断,配置为优先级别3的非向量中断。
设置TIMER定时器2(SoC
TIMER2),使其周期性的产生定时器中断。配置为优先级别2的向量中断,且不支持中断嵌套。
设置TIMER定时器1(SoC
TIMER1),使其周期性的产生定时器中断。配置为优先级别1的向量中断,且支持中断嵌套。
(注意:本实例仅用于展示向量和非向量中断处理模式的使用方法。为了在RV-STAR开发板上体现直观的中断响应和嵌套效果,在SoC
TIMER1和SoC
TIMER2两个向量中断处理函数中,均存在子函数调用。当用户在实际开发场景中,需要追求最快速高效的中断响应处理性能时,请确保向量中断模式的处理函数中不存在子函数调用,必须是Leaf
Function)
基于RV-STAR开发板,演示效果如下图8-1所示:
用户可以通过GitHub链接,获取本文实例的工程源码。
用户可以直接调用该函数完成ECLIC的初始化配置工作,其中包括:
第一步:将中断配置为向量或非向量中断处理模式;
第二步:配置中断的触发模式;
第三步:配置中断的级别和优先级;
第四步:设置中断处理函数的入口地址;
第五步:使能该中断。
在本实例中,用户按键中断被设置为非向量中断处理模式:
该中断为非向量处理模式,则该中断被处理器内核响应后,处理器会直接跳入到所有非向量中断共享的入口地址。
在本实例中,TIMER定时器2(SoC TIMER2)中断被设置为向量中断处理模式,且不支持中断嵌套:
在NMSIS库中,定义了“INTERRUPT”,即上文中介绍的,需要使用“attribute__((interrupt))”对向量中断模式的处理函数进行修饰,以使编译器可以识别该中断处理函数为向量中断的处理函数。
由于该向量中断的处理函数中,存在子函数调用,那么编译器会进行判断,自动的插入一段代码进行上下文的保存。注意:这种情况下虽然保证了功能的正确性,但是由于保存上下文造成的开销,又会事实上还是增大中断的响应延迟(与非向量模式相当)并且造成代码尺寸(Code
Size)的膨胀。因此,在实践中,如果使用向量处理模式,那么不推荐在向量处理模式的中断服务程序函数中调用其他的子函数。
该中断为向量处理模式,则该中断被处理器内核响应后,处理器会直接跳入到该向量中断处理函数的入口地址。
在本实例中,TIMER定时器1(SoC TIMER1)中断被设置为向量中断处理模式,且支持中断嵌套:
该中断为向量模式(需要支持嵌套),且存在子函数调用,编译器会进行判断,自动的插入一段代码进行上下文的保存。
同时,向量处理模式时,由于在跳入中断服务程序之前,处理器并没有进行任何特殊的处理,且由于处理器内核在响应中断后,mstatus寄存器中的MIE域将会被硬件自动更新成为0(意味着中断被全局关闭,从而无法响应新的中断)。因此向量处理模式默认是不支持中断嵌套的,为了达到向量处理模式且又能够中断嵌套的效果,用户需要加入以下步骤使其支持向量中断嵌套:
该中断为向量处理模式,则该中断被处理器内核响应后,处理器会直接跳入到该向量中断处理函数的入口地址。
N级别处理器内核包含CORE TIMER,主要用于产生计时器中断(Timer Interrupt)和软件中断(Software Interrupt)。
详情请参见:https://doc.nucleisys.com/nuclei_spec/isa/timer.html
N级别处理器内核包含的ECLIC,用于管理所有的中断源。
详情请参见:https://doc.nucleisys.com/nuclei_spec/isa/eclic.html
https://doc.nucleisys.com/nuclei_spec/isa/interrupt.html
异常(Exception)机制,即处理器核在顺序执行程序指令流的过程中突然遇到了异常的事情而中止执行当前的程序,转而去处理该异常。
详情请参见:https://doc.nucleisys.com/nuclei_spec/isa/exception.html
NMI(Non-Maskable Interrupt)是处理器内核的一根特殊的输入信号,往往用于指示系统层面的紧急错误(譬如外部的硬件故障等)。在遇到NMI之后,处理器内核应该立即中止执行当前的程序,转而去处理该NMI错误。
详情请参见:https://doc.nucleisys.com/nuclei_spec/isa/nmi.html
Nuclei ISA标准规范,是为用户准备的Nuclei RISC-V ISA文档,包括完备的Nuclei RISC-V特性文档和完备的Nuclei Processor Core Unit文档。通过标准规范的文档学习,开发者可快速了解Nuclei RISC-V处理器特性,并用于研发项目中。
详情请参见:https://doc.nucleisys.com/nuclei_spec/
Nuclei SDK是专为基于芯来科技Nuclei处理器内核的SoC开发的软件开发包。Nuclei SDK以NMSIS为基础进行开发,提供NMSIS上的所有功能,包括NMSIS-Core,NMSIS-NN,NMSIS-DSP。Nuclei SDK提供裸机(Bare-metal)以及实时操作系统(FreeRTOS,μC/OS-II)开发环境。
详情请参见:https://doc.nucleisys.com/nuclei_sdk
NMSIS是为芯来科技RISC-V处理器定义的厂商无关的硬件抽象层,定义了通用工具接口并提供持续的处理器设备支持,以及简洁的处理器和外设的软件访问接口API。采用NMSIS框架,可以大幅提升应用软件的复用性,缩短RISC-V微处理器开发者的学习时间,缩短基于芯来内核IP的新产品的上市时间。
详情请参见:https://doc.nucleisys.com/nmsis
配合Nuclei SDK及RV-STAR开发板的配套实验教程(Nuclei Board Labs),方便开发者快速上手及应用。