掌桥专利:专业的专利平台
掌桥专利
首页

一种基于RISC-V的中断控制系统及方法

文献发布时间:2023-06-19 10:24:22


一种基于RISC-V的中断控制系统及方法

技术领域

本发明涉及内核中断处理技术领域,特别涉及一种基于RISC-V的中断控制系统及方法。

背景技术

RISC-V是一种开源指令集架构,使用BSD License开源协议,具有简洁性、可扩展性、易编程/编译/链接等特点,其目标是成为指令集架构中的Linux,与ARM相庭抗礼。在国家的助推下,芯片自主创新研发已是大势所趋,RISC-V架构也已经得到行业的积极实践和探索。但是现有的RISC-V中断控制器方案普遍存在中断响应速度慢、无法支持嵌套中断或繁琐操作、大量上下文保存恢复指令等缺点,如图1中右边一列为现有的RISC-V中断响应流程图,图中A1,A2为编译器添加的prologue/epilogue;图中B1,B2为程序中由程序员添加内容,为了支持嵌套中断;图中C为程序中由程序员完成的中断处理内容;图中H3,H4为硬件内部行为,不由指令控制;其中请求、响应、程序跳转为硬件内部行为,上下文压栈、中断处理、上下文恢复与中断返回通过软件告知硬件具体行为,此处我们称为软件行为。

标准的RISC-V platform-levelinterruptcontroller(PLIC)是一种集中式中断管理系统,每种特权模式仅提供单独的外部中断信号(meip/seip/ueip)给内核。对于嵌入式领域的单核心、小系统来说,集中式的外部中断管理带来许多缺点。如无法在相同特权模式的外部中断之间发生中断的嵌套(嵌入式领域RISC-V单片机,往往只有机器模式中断,意味着仅有PLIC的小型单核RISC-V系统无法完成对外部中断的嵌套管理,在某些嵌入式应用领域,可能无法完成某些特定功能);

RISC-V Core-Local Interrupt Controller(CLIC)draft为解决PLIC嵌套管理上的缺陷而制定的Core-Local中断控制器,能解决嵌套问题,但是软件操作繁琐,中断处理缓慢,无法实现中断嵌套的真实目的。

额外的,现有RISC-V的standardcallingconvention,规定函数在用通用寄存器之前把通用寄存器的值保存在栈上,函数结束之前需要把通用寄存器的值恢复原始值。通用寄存器包括Callee-save和Caller-save两组寄存器,对于A(Caller)调用B(Callee),Caller-save类型由Caller进行保护,Callee-save类型由Callee进行保护,通用的编译工具会在中断服务函数之前加入prologue,用于保存16组Caller-save寄存器,同时在退出时加入epilogue,用于恢复16组Caller-save寄存器,prologue/epilogue共同负责了函数中保存/恢复硬件寄存器值的堆栈平衡。对于普通的函数而言,加入prologue/epilogue是必要的也是合理的,但是中断服务函数中加入大量的prologue/epilogue,会导致中断无法得到快速响应,甚至在某些实时性的领域还会带来软件开发困难、工作效率低下等缺点。

发明内容

发明目的:为了解决现有技术中存在的RISC-V架构处理器中断响应速度慢、程序开发难度大等问题,本发明提供一种基于RISC-V中断控制系统。

本发明的另一目的是提供一种基于RISC-V中断控制方法。

技术方案:一种基于RISC-V的中断控制方法,包括普通中断控制,所述普通中断控制包括以下步骤:

(a1)处理器接收第一中断请求并响应,停止执行原程序流;

(a2)硬件保存现场,所述硬件保存现场包括:快速中断控制器将Caller-save类型通用寄存器中的内容存储至硬件存储区内;硬件保存现场的同时处理器跳转程序至第一中断入口;

(a3)处理器处理第一中断事件;

(a4)第一中断事件处理完成后,通过中断返回指令返回至原程序断点处继续执行原程序流;同时硬件恢复现场,所述硬件恢复现场包括:快速中断控制器将硬件存储区内存储的内容存回Caller-save类型通用寄存器。

进一步地,步骤(a2)和步骤(a4)中所述硬件存储区包括第一类存储区和第二类存储区,所述第一类存储区用于存储控制和状态寄存器组的内容,所述第二类存储区用于存储Caller-save类型通用寄存器中的内容;所述第一类存储区包括至少第二级子存储区,第二类存储区包括至少第一级子存储区和第二级子存储区。

进一步地,步骤(a2)中硬件保存现场指:将开始进入第一中断前的Caller-save类型通用寄存器中的内容存储至第二类存储区中的第一级子存储区内;

步骤(a4)中硬件恢复现场指:将第二类存储区中的第一级子存储区的内容存回Caller-save类型通用寄存器。

进一步地,步骤(a3)中,还包括嵌套中断,所述嵌套中断包括以下步骤:

(c1)当处理器正在处理第一中断事件过程中,接收第二中断请求并响应,停止处理第一中断事件;

(c2)处理器跳转程序至第二中断入口;同时更新控制和状态寄存器组的值,并将开始处理第二中断事件之前的Caller-save类型通用寄存器的内容存储至第二类存储区的第二级子存储区内,和/或将控制和状态寄存器组中的内容存储至第一类存储区的第二级子存储区内;

(c3)处理器处理第二中断事件;

(c4)待第二中断事件处理完成后,返回继续处理第一中断事件;同时将第二类存储区的第二级子存储区的内容存回Caller-save类型通用寄存器,和/或将第一类存储区的第二级子存储区的内容存回控制和状态寄存器组。

进一步地,设第一类存储区的子存储区为第二级子存储区至第m级子存储区,设第二类存储区的子存储区为第一级子存储区至第n级子存储区,m>n;

当处理器正在处理第n级中断事件过程中,发成第n+1级嵌套中断时,执行以下步骤:

(n1)接收第n+1中断请求并响应,停止处理第n中断事件;

(n2)处理器跳转程序至第n+1中断入口,同时将开始处理第n+1中断事件之前的控制和状态寄存器组中的内容存储至第一类存储区的第n+1级子存储区内,再将开始处理第n+1中断事件之前的Caller-save类型通用寄存器中的内容通过软件进行保护,不对第二类存储区进行访问;

(n3)处理器处理第n+1中断事件;

(n4)待第n+1中断事件处理完成后,通过软件恢复Caller-save类型通用寄存器中的内容,再返回继续处理第n中断事件,同时将第n+1级子存储区的内容存回控制和状态寄存器组。

进一步地,步骤(n2)通过设置硬件存储区增强控制位HS_ENHANCE为1实现;

增加可编程快速中断控制寄存器,所述可编程快速中断寄存器包括硬件存储区增强控制位;

当HS_ENHANCE为1时,在发生第n+1级中断时,程序跳转的同时将开始处理第n+1中断事件之前的控制和状态寄存器组中的内容存储至第一类存储区的第n+1级子存储区内,且不进行第二类存储区的访问,然后将开始处理第n+1中断事件之前的Caller-save类型通用寄存器内容由软件进行保护;并在中断处理完成后,软件恢复Caller-save类型通用寄存器的内容,再返回继续处理第n中断事件,同时将第一类存储区的第n+1级子存储区的内容存回控制和状态寄存器组;

当HS_ENHANCE为0时,屏蔽中断,不会发生第n+1级中断。

进一步地,所述步骤(c2)更新控制和状态寄存器组的值的方法包括:控制和状态寄存器组中包含机器模式状态寄存器,机器模式状态寄存器包含中断使能位MIE,当MIE=1时,保持中断使能;当MIE=0时,屏蔽中断;

当中断响应过程中有以下任一情况发生时,将MIE置为0,否则置为1:

当嵌套中断关闭或不存在第一类存储区时;

当嵌套中断打开但第一类存储区已满时;

当第二类存储区已满且HS_ENHANCE=0时。

进一步地,还包括任务切换中断,所述任务切换中断包括以下步骤:

(b1)任务调度器在任务就续表中查找最高优先级的就绪任务,确定即将切换的新任务;

(b2)保存原任务上下文至原任务堆栈空间;

(b3)屏蔽所有中断;中断屏蔽后,从新任务堆栈空间中弹出上下文内容,通过中断返回指令返回至新任务的断点处继续执行,解除屏蔽中断。

进一步地,步骤(b3)中屏蔽所有中断的方法为:增加可编程快速中断控制寄存器,所述可编程快速中断寄存器包括硬件存储区临时关闭控制位HS_OFF_T,HS_OFF_T为1时,屏蔽所有中断,并且在退出中断时不执行硬件存储区的弹出操作。

一种基于RISC-V的中断控制系统,包括处理器、快速中断控制器、Caller-save类型通用寄存器,还包括硬件存储区,所述硬件存储区用于在中断响应时存储中断处理之前所述Caller-save类型通用寄存器的值;所述快速中断控制器用于将Caller-save类型通用寄存器的值存入硬件存储区,或者将硬件存储区的内容存入Caller-save类型通用寄存器。

进一步地,还包括控制和状态寄存器组,所述硬件存储区用于在嵌套中断响应时存储嵌套中断处理之前所述控制和状态寄存器和/或Caller-save类型通用寄存器的值;所述快速中断控制器用于将控制和状态寄存器和/或Caller-save类型通用寄存器的值存入硬件存储区,或者将硬件存储区的内容存入控制和状态寄存器和/或Caller-save类型通用寄存器。

进一步地,所述硬件存储区包括第一类存储区和第二类存储区,所述第一类存储区用于存储控制和状态寄存器组的内容,所述第二类存储区用于存储Caller-save类型通用寄存器中的内容;所述第一类存储区包括至少第二级子存储区,第二类存储区包括至少第一级子存储区和第二级子存储区。

进一步地,所述硬件存储区采用触发器、锁存器、RAM类型存储介质中的一种或多种。

进一步地,所述控制和状态寄存器组包括可编程快速中断向量表模式寄存器,可编程快速中断向量表模式寄存器包含模式位MODE,MODE=1时,向量表中存放绝对地址,MODE=0时,向量表中存放跳转指令。

进一步地,所述控制和状态寄存器组还包括可编程快速中断控制寄存器,所述可编程快速中断控制寄存器包括硬件存储区临时关闭控制位HS_OFF_T;

当HS_OFF_T=1时,打开屏蔽中断以及在中断退出时不进行硬件存储区的恢复Caller-save类型通用寄存器的操作,同时中断退出指令将HS_OFF_T清0;

当HS_OFF_T=0时,不对中断使能产生任何作用。

进一步地,所述控制和状态寄存器组还包括可编程快速中断控制寄存器,所述可编程快速中断控制寄存器包括硬件存储区增强控制位HS_ENHANCE;

当HS_ENHANCE=1时,第一类存储区未满且第二类存储区已满,在中断响应时,将Caller-save类型通用寄存器内容通过软件进行保护,将控制和状态寄存器组的内容存入第一类存储区,且在中断退出时,通过软件将Caller-save类型通用寄存器内容恢复,将第一类存储区的内容存回控制和状态寄存器组;

当HS_ENHANCE=0时,第一类存储区与第二类存储区均未满,在中断响应时,将Caller-save类型通用寄存器内容存入第二类存储区,将控制和状态寄存器组的内容存入第一类存储区,且在中断退出时,将第二类存储区的内容存回Caller-save类型通用寄存器,将第一类存储区的内容存回控制和状态寄存器组,第二类存储区满时,中断被屏蔽。

进一步地,所述控制和状态寄存器组还包括机器模式状态寄存器,所述机器模式状态寄存器包括中断使能位MIE;当MIE=1时,保持中断使能;当MIE=0时,屏蔽中断;

当有以下任一情况发生时,将MIE置为0,否则置为1:

当嵌套中断关闭或不存在第一类存储区时;

当嵌套中断打开但第一类存储区已满时;

当第二类存储区已满且HS_ENHANCE=0时。

有益效果:本发明提供一种基于RISC-V中断控制系统及方法,与现有技术相比,该系统具有硬件存储区、快速中断控制器、快速中断入口、多种中断寻址方式,不仅解决了RISC-V中断控制器响应慢、控制繁琐、大量上下文保存指令的缺点,同时在嵌入式OS系统中保证优化功能的完整、有效性。实时嵌套,可完成高优先级任务的快速抢占。同时基于优化的中断响应流程,可有效解决中断全局关闭过程中同时出现非精确中断造成的程序异常,避免多余软件操作。该方法可大大提高RISC-V架构处理器的中断处理速度,简化程序开发难度,扩展RISC-V为核心单片机的应用领域,尤其在嵌入式应用领域,该RISC-V中断控制系统及方法具有显著表现。

附图说明

图1为现有的标准中断响应流程与本实施例的基于RISC-V中断控制方法流程对比图;

图2为本实施例的基于RISC-V的中断控制系统的结构框图。

具体实施方式

下面结合附图和具体实施例对本发明做进一步解释说明。

如图2所示,基于RISC-V的中断控制系统,包括处理器CPU、快速中断控制器、控制和状态寄存器组(CSRs)、通用寄存器、硬件存储区,所述硬件存储区用于在中断响应时存储中断处理之前所述控制和状态寄存器组和/或Caller-save类型通用寄存器的值;所述快速中断控制器除了接收外部中断源、进行中断的使能、优先级、阈值等条件的判断、发送中断请求给处理器外,还用于将控制和状态寄存器组和/或Caller-save类型通用寄存器的值存入硬件存储区,或者将硬件存储区的内容存入控制和状态寄存器组和/或Caller-save类型通用寄存器。

对于硬件存储区,不限制其实现方式,所述硬件存储区可以采用触发器、锁存器、RAM等类型存储介质,应用范围广泛。

所述硬件存储区包括第一类存储区和第二类存储区,第一类存储区用于存储CSRs的内容,只有在嵌套中断时才需要保存,用于更好的支持嵌套中断,避免繁琐的中断屏蔽、保存CSRs、解除屏蔽等操作。第二类存储区用于存储Caller-save类型通用寄存器,用于快速处理中断,避免过多的prologue/epilogue操作造成中断处理慢的缺点。

第一类存储区为非必要,若只有第二类存储区,可用于无嵌套中断场景,或者使用现有的CLIC标准嵌套流程实现嵌套中断。

第一类存储区和第二类存储区均可以包括多级子存储区,不同的嵌套中断会将寄存器组的内容存储在不同级的子存储区内。但两者包含的子存储区级数可以不同,设第一类存储区的子存储区为第二级子存储区至第m级子存储区,设第二类存储区的子存储区为第一级子存储区至第n级子存储区,可有m>n。例如第二类存储区包括第一级子存储区、第二级子存储区、第三级子存储区,第一类存储区包括第二级子存储区和第三级子存储区(因为第一级中断无需第一类存储区存储,所以第一类存储区不存在第一级子存储区)。这样设计是因为存储Caller-save类型通用寄存器的内容较控制和状态寄存器组而言需要更大的空间,为了提高硬件存储区的利用率,设计第一类存储区的子存储区级数大于第二类存储区的子存储区级数。当发生嵌套中断的次数大于第二类存储区的子存储区级数时,Caller-save类型通用寄存器的内容可以按照现有技术的方式通过软件进行保护,以保证嵌套中断可以正常进行。

所述控制和状态寄存器组包括可编程快速中断(FPIC)向量表模式寄存器,可编程快速中断向量表模式寄存器包含模式位MODE,MODE=1时,向量表中存放32位绝对地址,MODE=0时,向量表中存放跳转指令。当存放绝对地址时,处理器根据响应的中断号相对此基地址进行偏移,从而进行中断服务函数的寻址工作。相比较现有技术的向量表中的多条非压缩的跳转指令,通过跳转指令跳转至中断服务函数入口,对于32位RISC-V而言,JAL指令寻址范围为±1M,而通过本实施例的绝对地址进行寻址,可以扩大寻址范围覆盖4G空间。

所述控制和状态寄存器组还包括可编程快速中断(FPIC)控制寄存器,所述可编程快速中断控制寄存器包括硬件存储区临时关闭控制位HS_OFF_T;

当HS_OFF_T=1时,打开屏蔽中断以及在中断退出时不进行硬件恢复现场;

当HS_OFF_T=0时,解除屏蔽中断,不对中断使能产生任何作用。

所述可编程快速中断控制寄存器还包括硬件存储区增强控制位HS_ENHANCE;

当HS_ENHANCE=1时,第一类存储区未满且第二类存储区已满,在中断响应时,将Caller-save类型通用寄存器内容通过软件进行保护,将控制和状态寄存器组的内容存入第一类存储区,且在中断退出时,通过软件将Caller-save类型通用寄存器内容恢复,将第一类存储区的内容存回控制和状态寄存器组的内容;

当HS_ENHANCE=0时,第一类存储区与第二类存储区均未满,在中断响应时,将Caller-save类型通用寄存器内容存入第二类存储区,将控制和状态寄存器组的内容存入第一类存储区,且在中断退出时,将第二类存储区的内容存回Caller-save类型通用寄存器,将第一类存储区的内容存回控制和状态寄存器组。

所述控制和状态寄存器组还包括机器模式状态寄存器,所述机器模式状态寄存器包括中断使能位MIE;当MIE=1时,保持中断使能;当MIE=0时,屏蔽中断;

当有以下任一情况发生时,将MIE置为0,否则置为1:

当嵌套中断关闭或不存在第一类存储区时;

当嵌套中断打开但第一类存储区已满时;

当第二类存储区已满且HS_ENHANCE=0时。

基于RISC-V的中断控制方法,包括普通中断控制和任务切换中断。

1、普通中断控制

如图1左列所示,普通中断控制包括以下步骤:

(a1)处理器接收第一中断请求并响应,停止执行原程序流;

(a2)硬件保存现场,所述硬件保存现场包括:快速中断控制器将Caller-save类型通用寄存器中的内容存储至硬件存储区内;硬件保存现场的同时处理器跳转程序至第一中断入口;

(a3)处理器处理第一中断事件;

(a4)第一中断事件处理完成后,通过中断返回指令(mret)返回至中断断点处继续执行原程序流;同时硬件恢复现场,所述硬件恢复现场包括:快速中断控制器将硬件存储区内存储的内容存回Caller-save类型通用寄存器,如图1中的H2行为。

以下以现有带C调用的中断服务函数为例与本实施例提供的方法进行对比:

现有带C调用的中断服务函数描述:

01 ##############################################

02 # RISC-V标准中断服务函数

03 ##############################################

04 void __attribute__((interrupt))

05 SysTick_Handler (void)

06 {

07 Regular_C_Call();

08 }

09

10 :

11 addi sp,sp,-64 # Create a frame on stack for full caller-save

12 sw ra,60(sp) # Save ra

13 sw t0,56(sp) # Save t0

14 sw t1,52(sp) # Save t1

15 sw t2,48(sp) # Save t2

16 sw a0,44(sp) # Save a0

17 sw a1,40(sp) # Save a1

18 sw a2,36(sp) # Save a2

19 sw a3,32(sp) # Save a3

20 sw a4,28(sp) # Save a4

21 sw a5,24(sp) # Save a5

22 sw a6,20(sp) # Save a6

23 sw a7,16(sp) # Save a7

24 sw t3,12(sp) # Save t3

25 sw t4,8(sp) # Save t4

26 sw t5,4(sp) # Save t5

27 sw t6,0(sp) # Save t6

28 jal Regular_C_Call # Nested regular c call

29 lw ra,60(sp) # Restore ra

30 lw t0,56(sp) # Restore t0

31 lw t1,52(sp) # Restore t1

32 lw t2,48(sp) # Restore t2

33 lw a0,44(sp) # Restore a0

34 lw a1,40(sp) # Restore a1

35 lw a2,36(sp) # Restore a2

36 lw a3,32(sp) # Restore a3

37 lw a4,28(sp) # Restore a4

38 lw a5,24(sp) # Restore a5

39 lw a6,20(sp) # Restore a6

40 lw a7,16(sp) # Restore a7

41 lw t3,12(sp) # Restore t3

42 lw t4,8(sp) # Restore t4

43 lw t5,4(sp) # Restore t5

44 lw t6,0(sp) # Restore t6

45 addi sp,sp,64 # Free stack frame

46 mret # Return from handler

47 #-----------------------------------------#

上文中,11-27行为上下文入栈行为,11行开辟一块栈空间用于保存Caller-save类型通用寄存器;12-27行将CPU内部寄存器压入栈空间;(11-27行,即标准编译器添加的prologue,用于保存16组Caller-save类型通用寄存器)28行调用中断服务函数,进行中断处理;29-45行将CPU内部寄存器从栈空间恢复并释放栈空间;46行使用mret指令退出中断恢复返回至中断的断点处继续程序运行(29-46行,即标准编译器添加的epilogue,用于恢复16组Caller-save类型通用寄存器)。

采用本专利的硬件存储区方案下的RISC-V中断响应流程包含请求、响应、硬保护现场以及程序跳转、中断处理、硬件恢复现场以及恢复程序流等步骤。其中请求、响应、硬压保护现场以及程序跳转为硬件内部行为,中断处理以及中断返回为软件告知硬件具体行为,此处我们称为软件行为。

采用本方法的中断服务函数描述:

01 ##############################################

02 # 硬件堆栈RISC-V标准服务函数

03 ##############################################

04 void __attribute__((interrupt("HW_STACK")))

05 SysTick_Handler (void)

06 {

07 Regular_C_Call();

08 }

09

10 :

11 jal Regular_C_Call # Nested regular c call

12 mret # Return from handler

13 #-----------------------------------------#

上文中,11行进行函数调用,进行中断处理;12行使用mret指令退出中断。

由以上对比可知,使用本实施例提供的方法,在中断处理之前节约17条指令(在典型的单发射流水线架构CPU中执行上述prologue至少需要17个周期,且大量占用存储器带宽,此时系统中的高速接口得不到总线权限,无法完成特定任务),中断处理结束至中断返回之间节约17条指令(在典型的单发射流水线架构CPU中执行上述epilogue至少需要17个周期,且大量占用存储器带宽)。分析指令可知,本实施例提出的方案具有节约代码空间、加速中断处理速度、释放存储器带宽提高单片机整体性能的优点。在嵌入式应用领域相比典型的RISC-V架构具有显著的优势,尤其在一些对中断响应速度、实时性高的场景,为产品的开发提供更优化的方案、更广阔的应用领域。

因为在现有的中断响应中,当GCC把C/C++语言中函数体翻译成汇编语言时,每个函数会用到某些通用寄存器。但是通用寄存器的个数是有限的,这就需要函数在用通用寄存器之前把通用寄存器的值保存在栈上,函数结束之前需要把通用寄存器的值恢复原始值。GCC在每个函数开头增加一个prologue,在每个函数的结尾处增加一个epilogue,prologue/epilogue就是负责函数中保存/恢复通用寄存器值的堆栈平衡。所以本方法需要增加定义一个属性,在中断响应后不按照现有技术的方法进行通用寄存器的保存和恢复,而采用定义的方法执行后续任务,具体方式为:进行中断的基本配置(如使能、阈值、优先级等),打开硬件存储区的存储功能,同时使用第4行所示的__attribute__((interrupt(“HW_STACK”)))为中断服务函数添加了新的属性。使用该属性,告知编译器不为此中断服务函数添加prologue/epilogue,否则编译器仍然会按照原有规则进行硬件寄存器的保存与恢复。

2、任务切换中断

对于普通中断与任务切换中断共存的系统,任务切换也需要通过中断实现。任务调度器的主要工作有两项,在任务就绪表中查找最高优先级的就绪任务、实现任务切换,其中任务的切换通常利用中断实现断点数据的切换。实现这种断点数据的切换,需要在中断中将原先任务的寄存器压入任务堆栈,再将新任务的任务堆栈的寄存器内容弹出到CPU寄存器中。本实施例提供的中断控制方法,不仅支持常规普通中断应用的上下文快速保存与恢复,同时在任务切换中断和普通外部中断共存的OS系统中,通过简单的配置,既可以实现普通中断快速上下文保存与恢复,也可以实现任务切换中断完成切换任务的目的。

所述任务切换中断包括以下步骤:

(b1)任务调度器在任务就续表中查找最高优先级的就绪任务,确定即将切换的新任务;

(b2)保存原任务上下文至原任务堆栈空间;

(b3)屏蔽所有中断,具体方法为:定义可编程快速中断(FPIC)控制寄存器,所述可编程快速中断控制寄存器包括硬件存储区临时关闭控制位HS_OFF_T,所述硬件存储区临时关闭控制位为1时,屏蔽所有中断,并且在退出中断时不执行第二类存储区的弹出操作的步骤。

中断屏蔽后,从新任务堆栈空间中弹出上下文内容,通过中断返回指令返回至新任务的断点处继续执行,新任务堆栈空间中弹出上下文后即可解除屏蔽中断:硬件自动清除HS_OFF_T。

进行中断的基本配置(如使能、阈值、优先级等),再打开硬件存储区的存储功能,使用__attribute__((interrupt(“HW_STACK”)))属性定义普通中断服务函数以及任务切换中断,在任务切换弹出新任务的寄存器内容之前配置HS_OFF_T为1,以此屏蔽所有中断,防止其他中断破坏新任务弹出的Caller-save类型通用寄存器,同时在当前中断退出时不会执行硬件恢复现场的功能,防止硬件出栈功能破坏新任务弹出的Caller-save类型通用寄存器。一旦弹出新任务的寄存器内容,便可以解除屏蔽中断。

3、嵌套中断

除了单中断外,本方法也支持嵌套中断。嵌套中断控制方法包括以下步骤:

(a1)处理器接收第一中断请求并响应,停止执行原程序流;

(a2)硬件保存现场,所述硬件保存现场包括:快速中断控制器将将开始进入第一中断前的Caller-save类型通用寄存器中的内容存储至第二类存储区的第一级子存储区内;硬件保存现场的同时处理器跳转程序至第一中断入口;

(a3)处理器处理第一中断事件;

(c1)当处理器正在处理第一中断事件过程中,接收第二中断请求并响应,停止处理第一中断事件;

(c2)处理器跳转程序至第二中断入口;同时更新控制和状态寄存器组的值(MEPC=p1(PC=p1,程序断点处),MCAUSE=中断编号,MSTATUS.MIE=1(保持中断使能),MSTATUS.MPIE=MSTATUS.MIE,MSTATUS.MPP=中断前特权模式),将开始处理第二中断事件之前的Caller-save类型通用寄存器中的内容存储至第二类存储区的第二子存储区内,和/或将开始处理第二中断事件之前的控制和状态寄存器组内容存储至第一类存储区的第二级子存储区内。

当第一类存储区和第二类存储区均未存满时,不管是CSRs还是Caller-save类型通用寄存器都可以正常存储在硬件存储区内,但是若第一类存储区存满(甚至是一开始就没有设置第一类存储区),CSRs的值可以按照现有标准嵌套中断方式通过软件进行保护,中断退出前出栈即可,此时MSTATUS.MIE在进入中断服务函数前被清0,用于屏蔽中断;若第二类存储区存满(即前文所述的m>n),嵌套中断发生第n+1次,则CSRs可正常存储,Caller-save类型通用寄存器的值按照现有标准中断方式通过软件进行保护(程序员自行保护),不对第二类存储区做任何操作,防止第二类存储区溢出导致内容破坏,该步骤通过定义可编程快速中断寄存器中的硬件存储区增强控制位HS_ENHANCE实现,当HS_ENHANCE=1时,即执行上述步骤,嵌套可以更多,但是对程序员要求更高,需要采用下面三种途径按照现有标准嵌套中断方式进行压栈避免上下文被破坏:1. n+1级中断使用汇编语言进行处理;2. n+1级中断不进行c调用; 3. n+1级中断attribute__的时候不添加新属性(第n+1级的中断可以由系统中存在的中断优先级进行判断,仅有优先级大于n的中断可能发生在第n+1级中断中,优先级小于等于n的中断仅有可能发生在第1至第n级中断中)。HS_ENHANCE=0时,硬件的MIE会在第二类存储区满时被自动关闭,此时若来一个优先级更高的中断,中断控制器不会发送此中断请求至CPU,当CPU的硬件存储区满足要求时,该中断请求才能被CPU响应。

上述MSTATUS为机器模式状态寄存器,其中的MIE为机器模式状态寄存器中的中断使能位,本实施例定义的嵌套中断在中断响应时保持MIE为1,不会屏蔽中断;

(c3)处理器处理第二中断事件;

(c4)待第二中断事件处理完成后,返回继续处理第一中断事件;同时将第二类存储区的第二级子存储区的内容存回Caller-save类型通用寄存器,和/或将第一类存储区的第二级子存储区的内容存回控制和状态寄存器组。

(a4)第一中断事件处理完成后,通过中断返回指令(mret)返回至中断断点处继续执行原程序流;同时硬件恢复现场,所述硬件恢复现场包括:快速中断控制器将第二类存储区的第二级子存储区的内容存回Caller-save类型通用寄存器。

以下将现有的标准CLIC嵌套中断与本实施例提供的嵌套中断进行对比:

标准CLIC嵌套中断的中断服务函数描述:

01 ##############################################

02 # 标准CLIC嵌套中断流程

03 ##############################################

04 /*------------------------------------------------------------------

05 Small ISR to poke device to clear interrupt

06 and increment in-memory COUNTER.

07-------------------------------------------------------------------*/

08 void __attribute__ ((interrupt))

09 SysTick_Handler (void)

10 {

11 extern volatile int INTERRUPT_FLAG;

12 extern volatile int COUNTER;

13 INTERRUPT_FLAG = 0;

14 __atomic_fetch_add (&COUNTER, 1, __ATOMIC_RELAXED);

15 }

16

17 :

18 #----- interrupts disabled on entry ---#

19 addi sp, sp, -framesize # create a frame on stack.

20 sw a0, offset(sp) # save working register.

21 csrr a0, mcause # read cause.

22 sw a1, offset(sp) # save working register.

23 csrr a1, mepc # read epc.

24 csrrsi x0, mstatus, mie # enable interrupts.

25 #----- interrupts enabled ---------#

26 sw a0, offset(sp) # save cause on stack.

27 sw x0, INTERRUPT_FLAG, a0 # clear interrupt flag.

28 sw a1, offset(sp) # save epc on stack.

29 la a0, COUNTER # get COUNTER address.

30 li a1, 1

31 amoadd.w x0, (a0), a1 # increment COUNTER in memory.

32 lw a1, offset(sp) # restore epc

33 lw a0, offset(sp) # restore cause

34 csrrci x0, mstatus, mie # disable interrupts.

35 #----- interrupts disabled ---------#

36 csrw mepc, a1 # put epc back.

37 lw a1, offset(sp) # restore a1.

38 csrw mcause, a0 # put cause back.

39 lw a0, offset(sp) # restore a0.

40 addi sp, sp, framesize # free stack frame.

41 mret # return from handler.

42 #------------------------------------#

如上文,标准CLIC中断控制器采用软件方式完成中断的嵌套功能,19-24行处于中断屏蔽状态,将mepc、mcause保存在a0、a1中(如果不屏蔽中断,a0、a1的存在被高优先级中断破坏的可能),26-34行处于可被抢占状态(中断全局使能打开),在此阶段软件完成了定义的INTERRUPT_FLAG清零以及COUNTER++的操作。36-41行处于中断屏蔽状态,将mepc、mcause从a0、a1中恢复(如果不屏蔽中断,a0、a1的存在被高优先级中断破坏的可能),41行退出中断。此外,上述中断关闭/打开,mepc、mcause保存恢复在现有工具链中并没有实现,因此中断服务函数中的操作无法通过编译器完成对寄存器的保护,需程序员自行采用汇编代码进行编程,大大增加了程序开发的难度。

本实施例提供的嵌套中断的服务函数描述:

01 ##############################################

02 # 标准FPIC嵌套中断流程(硬件GPR堆栈关闭状态)

03 ##############################################

04 /* -------------------------------------------

05 Small ISR to poke device to clear interrupt

06 and increment in-memory counter.

07 --------------------------------------------*/

08 void __attribute__ ((interrupt))

09 SysTick_Handler (void)

10 {

11 extern volatile int INTERRUPT_FLAG;

12 extern volatile int COUNTER;

13 INTERRUPT_FLAG = 0;

14 __atomic_fetch_add (&COUNTER, 1, __ATOMIC_RELAXED);

15 }

16

17 :

18 #----- interrupts enabled ---#

19 addi sp, sp, -framesize # create a frame on stack.

20 sw a0, offset(sp) # save working register.

21 sw a1, offset(sp) # save working register

22 sw x0, INTERRUPT_FLAG, a0 # clear interrupt flag.

23 la a0, COUNTER # get counter address.

24 li a1, 1

25 amoadd.w x0, (a0), a1 # increment counter in memory.

26 lw a1, offset(sp) # restore epc

27 lw a0, offset(sp) # restore cause

28 addi sp, sp, framesize # free stack frame.

29 mret # return from handler.

30 #------------------------------------#

由以上对比可知,现有方法中,硬件在响应中断的同时将MIE清零(图1中的H3硬件行为中将MIE清零),根据MIE描述此时所有机器模式中断被屏蔽,在典型的嵌入式RISC-V单片机中,往往外部中断均定义为机器模式中断,意味着当有一个中断响应之后,硬件屏蔽了所有其余外部中断。而本实施例定义的嵌套中断在中断响应时保持MIE为1(图1中的H1硬件行为),因此不会屏蔽中断,在中断请求、响应、处理、退出的全程均处于可被抢占状态,进入中断函数后无需软件保存mepc、mcause、关闭/打开中断使能等操作。完全兼容现有工具链,符合RISC-V易编程/易链接等设计目标,中断服务函数完全可以采用C代码书写,而不用担心上下文破坏的情形出现。

当外部中断源送入快速中断控制器中时,快速中断控制器进行中断的使能、优先级、阈值等条件判断,经过仲裁后发送中断请求至CPU,CPU准备就绪之后返回中断响应至快速中断控制器中,与此同时,告知RISC-V CSRs模块进行相关mstatus、mepc、mcause等寄存器的更新,并根据csrs.fpic_cr1的相关控制位的配置,条件性的将GPRs里的16组Caller-save类型通用寄存器存入硬件存储区,与此同时,CPU并发进行中断入口的寻址指令的预取等操作。根据描述,CPU响应中断请求至硬件运行中断处理函数(即上文的Regular_C_Call函数行为)的延迟取决于中断入口的寻址和硬件保持CPU寄存器周期数的最大值。该值将大大小于现有技术的软件保存寄存器的时间(因为11-27行中存在16条存储器访问指令,硬件进行寻址和保存指令的形式并发处理必定会更快,同时硬件存储区独立带宽,CPU紧耦合,不占用外部存储器带宽,进一步加快,同时硬件存储区不限制其实现方式,可采用更快的寄存器或者锁存器,或者高带宽RAM等灵活的行为,根据实际MCU外部控制电路、存储器选型等因素作灵活的变动,采用锁存器和寄存器方式构建的硬件堆栈区可在单周期完成CPU寄存器保存恢复操作)。硬件存储区保存中断上下文的方案需要保持16组GPRs,嵌套中断功能需要保存至少mstatus、mepc、mcause寄存器,两者可分开使用,也可以混合使用。当CPU执行mret中断返回指令进行中断退出时,快速中断控制器将硬件存储区的内容存回CPU寄存器。

相关技术
  • 一种基于RISC-V的中断控制系统及方法
  • 用于RISC-V架构的快速中断控制系统及方法
技术分类

06120112533778