CH32V003的PFIC中断控制

发布时间 2023-08-23 00:54:31作者: fxzq

CH32V003芯片是以青稞V2为内核的处理器,青稞V2 微处理器内部设计了一个可编程快速中断控制器(Programmable Fast Interrupt Controller,PFIC)可管理异常在内的最多256个中断。其中前16 个固定为微处理器内部中断,其余为外部中断,即最大支持扩展240个外部中断。其主要特征如下:
1、240个外部中断,每个中断请求都有独立的触发和屏蔽控制位,有专用的状态位;
2、可编程中断优先级,支持2级嵌套;
3、特有快速中断进出机制,硬件自动压栈和恢复,最大硬件压栈深度2级;
4、特有免表(Vector Table Free,VTF)中断响应机制,2路可编程直达中断向量地址。

下面给出的是CH32V003的中断和异常向量表。

从上表中可以看到,CH32V003的PFIC一共编了38个中断号,其中16~38号的23个中断为外设中断,其余4个为内核中断。

以下是CH32V003中PFIC所涉及的寄存器,一共有22个。

下面就分别来进行讨论,先来看PFIC中断使能状态寄存器0(PFIC_ISR0),下面给出了它的全部位结构。

(1)第31~16位分别反映第31~16号中断的使能状态,值为1时表示当前中断已使能,值为0时表示未使能。这些位的复位值为全0。
(2)第15位为及其后的13、11~4、1、0均为保留位。
(3)第14位为第14号中断的使能状态,值为1时表示当前中断已使能,值为0时表示未使能。该位的复位值为0。
(4)第12位为第12号中断的使能状态,值为1时表示当前中断已使能,值为0时表示未使能。该位的复位值为0。
(5)第3、2位分别是第3、2号中断的使能状态,值为1时表示当前中断已使能,值为0时表示未使能。这两位的复位值为0。

这里需要注意一点,由于第3、2号中断(异常)默认就是使能的(它们不支持使能操作),所以PFIC_ISR0寄存器的复位值为0x0000000C。

从上面的讨论可以看出,PFIC_ISR0寄存器只反映了31号中断,还剩第32~38号中断没有反映到,所以还需要再加一个寄存器,即PFIC中断使能状态寄存器1(PFIC_ISR1),下面是它的全部位结构。

(1)第31~7位均为保留位。
(2)第6~0位分别反映第38~32号中断的使能状态,
值为1时表示当前中断已使能,值为0时表示未使能。这些位的复位值为全0。 

接下来看PFIC中断挂起状态寄存器0(PFIC_IPR0),下面给出了它的全部位结构。

(1)第31~16位分别反映第31~16号中断的挂起状态,值为1时表示当前中断挂起,值为0时表示未挂起。这些位的复位值为全0。
(2)第15位及其后的13、11~4、1、0均为保留位。
(3)第14位反映第14号中断的挂起状态,值为1时表示当前中断挂起,值为0时表示未挂起。该位的复位值为0。
(4)第12位反映第12号中断的挂起状态,值为1时表示当前中断挂起,值为0时表示未挂起。该位的复位值为0。
(5)第3、2位分别反映第3、2号中断的挂起状态,值为1时表示当前中断挂起,值为0时表示未挂起。这两位的复位值为0。

下面是PFIC中断挂起状态寄存器1(PFIC_IPR1)的全部位结构。

(1)第31~7位均为保留位。
(2)第6~0位(PENDSTA)分别反映第38~32号中断的挂起状态,值为1时表示当前中断挂起,值为0时表示未挂起。这些位的复位值为全0。 

接着来看PFIC中断优先级阈值配置寄存器(PFIC_ITHRESDR),下面给出了它的全部位结构。

(1)第31~8位均为保留位。
(2)第7~0位(THRESHOLD)为中断优先级阈值的设置值,其中第7、6两位为优先级阈值,第5~0位固定为0值,写无效。低于当前设置值的中断优先级值,挂起时不执行中断服务,该寄存器值为0 时表示阈值寄存器功能无效。这些位的复位值为全0。

接下来的PFIC中断配置寄存器(PFIC_CFGR)在CH32V003芯片(青稞V2)中没有作用,保留它仅起到兼容其他高版本内核(青稞V3及以上)的作用,在此就不作讨论了。

下面看PFIC中断全局状态寄存器(PFIC_GISR),以下给出了它的全部位结构。

(1)第31~10位均为保留位。
(2)第9位(GPENDSTA)反映当前是否有中断处于挂起状态,值为1时表示有,为0时表示没有。该位的复位值为0。
(3)第8位(GACTSTA)反映当前是否有中断被执行,值为1时表示有,为0时表示没有。该位的复位值为0。
(4)第7~0位(NESTSTA)反映当前中断嵌套状态,值为0x03时表示正处于第2级中断嵌套中,值为0x01时表示正处于第1中断中,为其他值时表示无中断发生,目前最大支持2级嵌套,硬件压栈深度最大为2级。这些位的复位值为全0。

接下来看PFIC的VTF中断ID配置寄存器(PFIC_VTFIDR),下面给出了它的全部位结构。

(1)第31~16位均为保留位。
(2)第15~8位(VTFID1)用于配置VTF中断1的中断编号,编号的值从0~255,在CH32V003中可对应0~38号中断。这些位的复位值为全0。
(3)第7~0位(VTFID0)用于配置VTF中断0的中断编号,编号的值从0~255,在CH32V003中可对应0~38号中断。这些位的复位值为全0。

接下来是PFIC的VTF中断0地址寄存器(PFIC_VTFADDRR0),下面给出了它的全部位结构。 

(1)第31~1位(ADDR0)为VTF中断0服务程序的入口地址。这些位的复位值为全0。
(2)第0位(VTFOEN)为VTF中断0的使能位,置1时使能VTF中断0通道,置0时禁止。该位的复位值为0。

这样的寄存器还有一个,即VTF中断1地址寄存器(PFIC_VTFADDRR1),下面给出了它的全部位结构。

(1)第31~1位(ADDR1)为VTF中断1服务程序的入口地址。这些位的复位值为全0。
(2)第0位(VTF1EN)为VTF中断1的使能位,置1时使能VTF中断1通道,置0时禁止。该位的复位值为0。

VTF(Vector Table Free)即免表中断响应机制,在CH32V003中设有2路可编程直达中断向量地址,相关内容在后面再作详细讨论。 

下面来看PFIC中断使能设置寄存器0(PFIC_IENR0),以下给出了它的全部位结构。

(1)第31~16位分别是第31~16号中断的使能位,置1时使能中断,置0时禁止中断。这些位的复位值为全0。
(2)第15位及其后的13、11~0均为保留位。
(3)第14位为第14号中断使能位,置1时使能中断,置0时禁止中断。该位的复位值为0。
(4)第12位为第12号中断使能位,置1时使能中断,置0时禁止中断。该位的复位值为0。
这里需要说明的是,第3、2号中断(异常)不支持使能操作,它们默认就是使能的,所以PFIC_IENR0寄存器不包含对它们的操作位。

下面是PFIC中断使能设置寄存器1(PFIC_IENR1)的全部位结构。

(1)第31~7位均为保留位。
(2)第6~0位分别为第38~32号中断的使能位,置1时使能中断,置0时禁止中断。这些位的复位值为全0。

接下来是PFIC中断使能清除寄存器0(PFIC_IRER0),下面给出了它的全部位结构。

(1)第31~16位分别是第31~16号中断的关闭位,置1时关闭中断,置0时无影响。这些位的复位值为全0。
(2)第15位及其后的13、11~0均为保留位。
(3)第14位为第14号中断关闭位,置1时关闭中断,置0时无影响。该位的复位值为0。
(4)第12位为第12号中断关闭位,置1时关闭中断,置0时无影响。该位的复位值为0。

下面是PFIC中断使能清除寄存器1(PFIC_IRER1)的全部位结构。

(1)第31~7位均为保留位。
(2)第6~0位分别为第38~32号中断的关闭位,置1时关闭中断,置0时无影响。这些位的复位值为全0。

接下来看PFIC中断挂起设置寄存器0(PFIC_IPSR0),下面给出了它的全部位结构。 

(1)第31~16位分别是第31~16号中断的挂起设置位,置1时挂起中断,置0时无影响。这些位的复位值为全0。
(2)第15位及其后的13、11~4、1、0均为保留位。
(3)第14位为第14号中断的挂起设置位,置1时挂起中断,置0时无影响。该位的复位值为0。
(4)第12位为第12号中断的挂起设置位,置1时挂起中断,置0时无影响。该位的复位值为0。
(5)第3、2位分别是第3、2号中断的挂起设置位,置1时挂起中断,置0时无影响。这两位的复位值为0。

下面是PFIC中断挂起设置寄存器1(PFIC_IPSR1)的全部位结构。

(1)第31~7位均为保留位。
(2)第6~0位分别是第38~32号中断的挂起设置位,置1时挂起中断,置0时无影响。这些位的复位值为全0。

接下来看PFIC中断挂起清除寄存器0(PFIC_IPRR0),下面给出了它的全部位结构。

(1)第31~16位分别是第31~16号中断的挂起状态清除位,置1时挂起状态被清除,置0时无影响。这些位的复位值为全0。
(2)第15位及其后的13、11~4、1、0均为保留位。
(3)第14位为第14号中断的挂起状态清除位,置1时挂起状态被清除,置0时无影响。该位的复位值为0。
(4)第12位为第12号中断的挂起状态清除位,置1时挂起状态被清除,置0时无影响。该位的复位值为0。
(5)第3、2位分别是第3、2号中断的挂起状态清除位,置1时挂起状态被清除,置0时无影响。这两位的复位值为0。

下面是PFIC中断挂起清除寄存器1(PFIC_IPRR1)的全部位结构。  

(1)第31~7位均为保留位。
(2)第6~0位分别是第38~32号中断的挂起状态清除位,置1时挂起状态被清除,置0时无影响。这些位的复位值为全0。

接下来是PFIC中断激活状态寄存器0(PFIC_IACTR0),下面给出了它的全部位结构。

(1)第31~16位分别反映第31~16号中断的执行状态,值为1时表示当前中断执行中,值为0时表示没有中断执行。这些位的复位值为全0。
(2)第15位及其后的13、11~4、1、0均为保留位。
(3)第14位为第14号中断的执行状态,值为1时表示当前中断执行中,值为0时表示没有中断执行。该位的复位值为0。
(4)第12位为第12号中断的执行状态,值为1时表示当前中断执行中,值为0时表示没有中断执行。该位的复位值为0。
(5)第3、2位分别是第3、2号中断的执行状态,值为1时表示当前中断执行中,值为0时表示没有中断执行。这两位的复位值为0。

下面是PFIC中断激活状态寄存器1(PFIC_IACTR1)的全部位结构。  

(1)第31~7位均为保留位。
(2)第6~0位分别是第38~32号中断的执行状态,值为1时表示当前中断执行中,值为0时表示没有中断执行。这些位的复位值为全0。

接下来看PFIC中断优先级配置寄存器(PFIC_IPRIORx),其中x=0-63,下面给出了它的全部位结构。

PFIC_IPRIORx寄存器有些特别,总共可以有64个这样的寄存器,分别为IPRIOR0~IPRIOR63。每个寄存器内部又分成4个8位的单元,每个单元对应一个中断编号,一共可以对应256个中断编号(在CH32V003中,最多只用了39个中断编号)。也即每个中断编号对应1个8位的单元,这8位就用来设置此编号中断的优先级别。但在CH32V003中,有效的只有高2位(第7、6位),低6位(第5~0位)全部保留为0(不能更改),因此,最多也只能设置4个优先级别。其中,最高位(第7位)还可以用来设置强占,具体情况到后面再进行详细讨论,这里就不赘述了。 

最后来看PFIC系统控制寄存器(PFIC_SCTLR),下面给出了它的全部位结构。

(1)第31位(SYSRST)是系统复位设置位,自动清零,置1时系统复位,置0时无影响。该位的复位值为0。
(2)第30~6位及其后的第0位均为保留位。
(3)第5位(SETEVENT)为事件设置位,可以唤醒WFE的情况。该位的复位值为0。
(4)第4位(SEVONPEND)为当发生事件或者中断挂起状态时,可以从WFE指令后唤醒系统,如果未执行WFE指令,将在下次执行该指令后立即唤醒系统,置1时启用的事件和所有中断(包括未使能中断)都能唤醒系统,置0时只有启用的事件和启用的中断可以唤
醒系统。该位的复位值为0。
(5)第3位(WFITOWFE)为将WFI指令当成WFE执行,置1时有效,置0时无效。该位的复位值为0。
(6)第2位(SLEEPDEEP)为控制系统的低功耗模式,置1时进入深度睡眠模式,置0时进入睡眠模式。该位的复位值为0。
(7)第1位(SLEEPONEXIT)为控制离开中断服务程序后系统的状态,置1时系统进入低功耗模式,置0时进入主程序。该位的复位值为0。

除了上述讨论的寄存器之外,在RISC-V架构中还定义了一些控制和状态寄存器(Control and Status Register,CSR),用于配置或标识或记录运行状态。CSR 寄存器属于内核内部的寄存器,使用专用的12 位地址空间。CH32V003芯片除了RISC-V定义的标准寄存器外,还增加了一些厂商自定义的寄存器,以下两个就是这样的寄存器。

先来看中断系统控制寄存器(INTSYSCR),其字节地址为0x804,下面给出了它的全部位结构。

(1)第31~2位均为保留位。
(2)第1位(INESTEN)为中断嵌套使能位,置1时使能中断嵌套,置0时关闭中断嵌套。该位的复位值为0。
(3)第0位(HWSTKEN)为硬件压栈使能位,置1时使能硬件压栈,置0时关闭硬件压栈。该位的复位值为0。

INTSYSCR寄存器的复位值虽然为关闭状态,但在MRS开发环境的启动文件startup_ch32v00x.S中,默认对它进行了使能的操作。在该文件中执行有如下的操作: 

li t0, 0x3
csrw 0x804, t0

以上汇编指令的意思就是把值0x3(即二进制的11)写入到0x804地址的寄存器中。也就是把INTSYSCR寄存器的低两位都置1了,启用了相应的功能。

接下来看异常入口基地址寄存器(MTVEC),下面给出了它的全部位结构。

(1)第31~2位为中断入口的基址。
(2)第1位(MODE1)为中断向量表识别模式位,置1时按绝对地址识别,支持全范围但必须跳转,置0时按跳转指令识别,有限范围且支持非跳指令。该位的复位值为0。
(3)第0位(MODE0)为中断(异常)入口地址模式选择位,置1时根据中断编号乘以4进行地址偏移,置0时使用统一入口地址。该位的复位值为0。

MTVEC寄存器的复位值虽然为0,但在MRSMRS开发环境的启动文件startup_ch32v00x.S中,默认对它进行了置1的操作。在该文件中执行有如下的操作: 

la t0, _start
ori t0, t0, 3
csrw mtvec, t0

上述汇编中的标号“_start”为第0号中断的入口地址,其值为0x00000000(见最前面给出的中断和异常向量表)。然后把它与值3(即二进制的11)进行“或”操作,再把结果写到MTVEC寄存器中。经过上述操作后,MTVEC寄存器中的高30位取得了中断入口基址,低两位则被置1,设置成了按绝对地址跳转,并且中断入口地址以4倍(因为芯片为32位,1个字等于4个字节)的方式进行分配。启动文件startup_ch32v00x.S的详细内容可参见前面“CH32V003在MRS中的初始化过程”一章部分。