DSP中断机制的基本流程可以分为三步, 如下图所示. 一, 中断事件的产生和判断, 当判断为合法的中断事件时会将程序指针PC跳转到中断向量表的相应位置, 这都是由硬件自动完成的; 二, 按照中断向量表定义跳转到中断主服务程序, 实际上中断向量表中就是一条条的跳转(到中断主服务程序的)指令; 三, 执行中断服务程序, 用户将该中断中要处理的任务都放在中断服务程序中完成.
4.3.2.2 假中断
当一个中断被响应, 但没有外设将中断向量地址偏移量装入外设中断向量寄存器PIVR中, 为了保持中断系统的完整性, 0000H被装入PIVR, 这个中断称为假中断. 假中断产生的原因有两个:
◆ CPU执行一个软件中断指令INTR, 使用的参数为1~6;
◆ 外设发出了中断请求, 但其所对应的CPU的标志位在CPU应答之前已被清“0”.
这样CPU不知道装入哪一个外设中断向量地址偏移量到PIVR, 此时假中断向量就装入PIVR.
4.3.2.3 中断寄存器
CPU中断寄存器包括:
◆ 中断标志寄存器IFR;
◆ 中断屏蔽寄存器IMR.
中断标志寄存器用于识别和清除登记的中断. 读取IFR可以识别登记的中断而写IFR则将清除已登记的中断. 清除一个中断请求, 要向相应的IFR位写“1”, 而不是写“0”. IMR包括所有可屏蔽中断(INT1~INT6)的屏蔽位. 为了使能某中断, 应设置相应的IMR位为“1”, 而屏蔽某中断时只需将相应的位设为“0”.
外设中断寄存器包括:
◆ 外设中断向量寄存器PIVR;
◆ 外设中断请求寄存器PIRQR0/ PIRQR1/ PIRQR2;
◆ 外设中断响应寄存器PIACKR0/ PIACKR1/ PIACKR2. PIVR包含了最近一次被响应的外设中断的地址向量;
PIRQR0/ PIRQR1/ PIRQR2和PIACKR0/ PIACKR1/ PIACKR2都属于外设中断用来向CPU产生INT1~INT6中断请求的内部寄存器. 这些寄存器用于测试目的, 而非用户应用目的, 因此在编程中可以忽略.
4.3.2.4 中断程序构成
中断机制的实现应包含如下三个组成部分.
1) 中断数据段分配
由于DSP在响应一个中断事件后, 总会自动跳转到固定的程序存储器单元读取中断服务程序入口地址(如LF2407A的复位中断向量是在0x0000单元), 因此, 要想让DSP正确的找到相应的中断服务程序入口地址, 必须首先完成中断数据段分配的工作. 对于ASM语言工程或是C语言工程, 中断数据段的分配都在CMD文件中完成. 下面的CMD文件代码示例中, 分配了一个名为VECS的存储段(存储首地址为0h, 长度为40h), 并将.vectors代码段连接到该存储段. 其中.vectors代码段即是后面的中断向量表代码将要存放的区域.
MEMORY
{
PAGE0:
VECS: origin=0h, length=40h /*VECTOR*/
PROG: origin=40h, length=0FFC0h /*PROGRAM */
PAGE1:
MMRS: origin=0h, length=60h /*MMRS */
B2: origin=0060h, length=20h /*B2 BLOCK*/
B0: origin=0200h, length=100h /*B0 BLOCK*/
B1: origin=0300h, length=100h /*B1 BLOCK*/
DATA: origin=8000h, length=8000h /*XDM*/
}
SECTIONS
{
.vectors : {}>VECS PAGE0
.text : {}>PROG PAGE0
.cinit : {}>PROG PAGE0
.data : {}>DATA PAGE1
.stack : {}>DATA PAGE1
.bss : {}>DATA PAGE1
}
2) 中断向量表
中断向量表, 顾名思义就是与中断有关的一系列跳转指令(B指令)的列表, 这些跳转指令正如一系列的矢量箭头直指中断服务程序. 正如前面中断响应机制一节所述, 当中断事件发生、中断响应条件满足时, 硬件会自动将程序指针跳转到一段特定的程序空间(可以叫做中断向量空间)中特定的位置, 如果在此已预置了指向中断服务程序的跳转指令, 就可以实现整套中断服务机制.
C24x系列DSP中采用两级中断结构: 对应CPU中断(也称为主中断)的通用中断服务程序(GISR), 和对应外设中断的特定中断服务子程序(SISR). 中断响应后会根据中断向量表进入相应的通用中断服务程序, 然后再根据外设中断向量寄存器PIVR中产生的地址偏移量进入具体的外设中断向量服务程序.
从通用中断服务程序到特定中断服务程序的转移处理有两种方式: ①直接编写外设中断向量(或称子中断向量)表, 根据PIVR中产生的地址偏移值在子中断向量表完成跳转; ②直接判断PIVR中产生的地址偏移值选择进入某一特定中断服务程序.
采用外设中断向量表的中断转移处理程序段如下:
LDP #0E0H
LACC PIVR,1 ;读取某中断事件对应的偏移量地址并左移移位
ADD #PVECTORS ;加上外设矢量表基地址
BACC ;转移到相应的外设中断服务程序
直接判断PIVR的中断转移处理程序段如下:
LDP #0E0H
LACC PIVR ;读取某中断事件对应的偏移量地址
XOR #00NNH ;00NNH为某外设对应的偏移量地址
BCND SISRNN,EQ ;判断是否为该外设对应的偏移量地址,
;如果是就转移到相应的外设中断服务程序
对于C24x系列DSP而言, 无论是ASM语言工程或是C语言工程, 中断向量表都必须使用ASM指令(或者是行内汇编的C语言语句)来实现, 包括自定义段伪指令.sect和一系列的(使用B指令)跳转到中断服务程序的跳转语句. 如果涉及引用文件外部的函数, 还需要引用伪指令.ref. 中断向量表可以写为头文件(如vector.h)形式或汇编源文件(如vector.asm)形式. 下面是一个头文件形式、包含CPU中断合外设中断的中断向量表示例.
; vector.h
;定义主中断向量
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.ref _c_int0 ;函数声明
.ref GISR1
.ref GISR2
.ref GISR3
.ref GISR4
.ref GISR5
.ref GISR6
.sect ".vectors" ;定义主向量
RESET B _c_int0 ;地址0000H, 复位, 优先级1
INT1 B GISR1 ;地址0002H, INT1, 优先级4
INT2 B GISR2 ;地址0004H, INT2, 优先级5
INT3 B GISR3 ;地址0006H, INT3, 优先级6
INT4 B GISR4 ;地址0008H, INT4, Capture1,3
INT5 B GISR5 ;地址000AH, INT5, SCIRX,SCITX
INT6 B GISR6 ;地址000CH, INT6, 优先级9
RESERVED B _phantom ;地址000EH, 测试, 优先级10
SW_INT8 B _phantom ;地址0010H, 自定义软中断
SW_INT9 B _phantom ;地址0012H, 自定义软中断
SW_INT10 B _phantom ;地址0014H, 自定义软中断
SW_INT11 B _phantom ;地址0016H, 自定义软中断
SW_INT12 B _phantom ;地址0018H, 自定义软中断
SW_INT13 B _phantom ;地址001AH, 自定义软中断
SW_INT14 B _phantom ;地址001CH, 自定义软中断
SW_INT15 B _phantom ;地址001EH, 自定义软中断
SW_INT16 B _phantom ;地址0020H, 自定义软中断
TRAP B _phantom ;地址0022H, TRAP矢量
NMI B _phantom ;地址0024H, NMI, 优先级3
EMU_TRAP B _phantom ;地址0026H, 仿真Trap, 优先级2
SW_INT20 B _phantom ;地址0028H, 自定义软中断
SW_INT21 B _phantom ;地址002AH, 自定义软中断
SW_INT22 B _phantom ;地址002CH, 自定义软中断
SW_INT23 B _phantom ;地址002EH, 自定义软中断
SW_INT24 B _phantom ;地址0030H, 自定义软中断
SW_INT25 B _phantom ;地址0032H, 自定义软中断
SW_INT26 B _phantom ;地址0034H, 自定义软中断
SW_INT27 B _phantom ;地址0036H, 自定义软中断
SW_INT28 B _phantom ;地址0038H, 自定义软中断
SW_INT29 B _phantom ;地址003AH, 自定义软中断
SW_INT30 B _phantom ;地址003CH, 自定义软中断
SW_INT31 B _phantom ;地址003EH, 自定义软中断
;定义外设中断向量(INT2为例)
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.sect ".pvectors"
PVECTORS B _phantom ;地址0000H, 保留外设向量
B _phantom ;地址0001H, 保留外设向量
B _phantom ;地址0002H, 保留外设向量
B _phantom ;地址0003H, 保留外设向量
B _phantom ;地址0004H, 保留外设向量
B _phantom ;地址0005H, 保留外设向量
B _phantom ;地址0006H, 保留外设向量
B _phantom ;地址0007H, 保留外设向量
B _phantom ;地址0008H, 保留外设向量
B _phantom ;地址0009H, 保留外设向量
B _phantom ;地址000AH, 保留外设向量
B _phantom ;地址000BH, 保留外设向量
B _phantom ;地址000CH, 保留外设向量
B _phantom ;地址000DH, 保留外设向量
B _phantom ;地址000EH, 保留外设向量
B _phantom ;地址000FH, 保留外设向量
B _phantom ;地址0010H, 保留外设向量
B _phantom ;地址0011H, 保留外设向量
B _phantom ;地址0012H, 保留外设向量
B _phantom ;地址0013H, 保留外设向量
B _phantom ;地址0014H, 保留外设向量
B _phantom ;地址0015H, 保留外设向量
B _phantom ;地址0016H, 保留外设向量
B _phantom ;地址0017H, 保留外设向量
B _phantom ;地址0018H, 保留外设向量
B _phantom ;地址0019H, 保留外设向量
B _phantom ;地址001AH, 保留外设向量
B _phantom ;地址001BH, 保留外设向量
B _phantom ;地址001CH, 保留外设向量
B _phantom ;地址001DH, 保留外设向量
B _phantom ;地址001EH, 保留外设向量
B _phantom ;地址001FH, 保留外设向量
B _phantom ;地址0020H, 保留外设向量
B _phantom ;地址0021H, 比较1中断
B _phantom ;地址0022H, 比较2中断
B _phantom ;地址0023H, 比较3中断
B _phantom ;地址0024H, 比较4中断
B _phantom ;地址0025H, 比较5中断
B _phantom ;地址0026H, 比较6中断
B PHANTOM ;地址0027H, 定时器1周期中断
B SISR28 ;地址0028H, 定时器1比较中断
B SISR29 ;地址0029H, 定时器1下溢中断
B SISR2A ;地址002AH, 定时器1上溢中断
B _phantom ;地址002BH, 保留外设向量
B _phantom ;地址002CH, 保留外设向量
B _phantom ;地址002DH, 保留外设向量
B _phantom ;地址002EH, 保留外设向量
B _phantom ;地址002FH, 定时器3周期中断
B _phantom ;地址0030H, 定时器3比较中断
B _phantom ;地址0031H, 定时器3下溢中断
B _phantom ;地址0032H, 定时器3上溢中断
B _phantom ;地址0033H, 保留外设向量
B _phantom ;地址0034H, 保留外设向量
B _phantom ;地址0035H, 保留外设向量
B _phantom ;地址0036H, 保留外设向量
B _phantom ;地址0037H, 保留外设向量
B _phantom ;地址0038H, 保留外设向量
B _phantom ;地址0039H, 保留外设向量
B _phantom ;地址003AH, 保留外设向量
B _phantom ;地址003BH, 保留外设向量
B _phantom ;地址003CH, 保留外设向量
B _phantom ;地址003DH, 保留外设向量
B _phantom ;地址003EH, 保留外设向量
B _phantom ;地址003FH, 保留外设向量
B _phantom ;地址0040H, 保留外设向量
B _phantom ;地址0041H, 高优先级CAN错误中断
3) 中断服务程序中断服务程序完成具体中断事件的处理以及现场的保护和恢复等工作. 中断服务程序可由汇编语言或C语言来编写. 中断服务程序的标号(或函数名)应该与中断向量表(或子中断向量表)中的名称对应.