中断的关闭与开放
开放MC56F8257中某个模块中断,通常需要开放总中断及模块中断来实现。这两部分缺一不可,并且开放总中断在前,开放模块中断在后。同理,关闭MC56F8257中某个模块中断,需要关闭总中断及模块中断来实现,先关闭模块中断,再关闭总中断;如果允许中断嵌套情况,不需关闭总中断。
开放MC56F8257总中断,通过清中断控制寄存器(INTC_CTRL)的INT_DIS位;关闭总中断,需置该位即可,具体代码如下:
#define EnableInterrupt() INTC_CTRL&=~INTC_CTRL_INT_DIS_MASK
#define DisableInterrupt() INTC_CTRL|=INTC_CTRL_INT_DIS_MASK
开放或关闭模块中断,需设置模块内部的控制寄存器的相应位。如开放QSCI模块的接收中断0,需置位QSCI控制寄存器1(QSCIx_CTRL1)中的RFIE位;关闭该中断,清RFIE位即可,具体代码如下:
#define EnableQSCIReInt(0) QSCI_C1(0)|=(QSCI1_CTRL1_RFIE_MASK)
#define DisableQSCIReInt(0) QSCI_C1(0)&=(QSCI1_CTRL1_RFIE_MASK)
中断优先级的设置
DSP56800E内核支持5级中断:LP、0、1、2和3,其优先级别依次升高。最低优先级LP只能由系统SWILP指令产生;0~2优先级用户可以编程设置,主要用于外设和外部中断请求;级别3是最高优先级且不可屏蔽。
具体设置某个中断源的中断优先级,可通过设置中断优先级寄存器(INTC_IPR0~INTC_IPR7)中的相应位。如设置QSCI中断优先级,通过设置中断优先级寄存器(INTC_IPR2)中的QSCI0_RCV位实现,该位具体含义见表1所示。
从表1看出,QSCI中断可配置三个不同级别,即优先级0、1和2。如果用户不配置QSCI中断的优先级,系统复位时,自动分配其优先级为0;但是复位后,紧接着初始化QSCI模块,其优先级由0级变为2级。
设置中断屏蔽
通过设置DSP56800E内核中的状态寄存器SR的I0、I1位,实现屏蔽不同级别优先级中断,具体设置如表2所示。
屏蔽某个优先级中断,可通过使能中断优先级相应的优先级中断来实现。例如,屏蔽优先级0中断,可通过使能优先级1,2,3中断实现,具体代码如下:
#define EnInt(1) {asm(bfset #0x0100,SR); asm(bfclr #0x0200,SR);}
另外,也可以同时屏蔽2个以上级别中断,如屏蔽优先级0,1,2中断,通过使能优先级3中断实现,具体代码如下:
#define EnInt(3) {asm(bfset #0x0300,SR);}
在设置中断屏蔽时,应注意的是主函数的屏蔽中断优先级代码与中断服务程序的相应代码应保证所需的中断不被屏蔽。
中断矢量表的定义
MC56F8257的67个中断源,其矢量号从0到66 [9]。每个中断源的中断服务程序首地址放入中断矢量表中。当有中断请求时,CPU通过中断矢量号在中断矢量表中找到其中断服务程序的首地址,根据这个首地址找到中断服务程序,进行中断处理。
中断矢量表在FLSAH中的位置由向量基地址寄存器(VBA)决定。向量基地址寄存器VBA[12:0]为21位中断矢量表首地址的高13位,低8位自动补0。具体到某个模块中断服务程序首地址在中断矢量表中的位置,由向量基地址寄存器(VBA)及控制寄存器(INTC_CTRL)的VAB位决定;向量基地址寄存器VBA[12:0]为其在中断矢量表地址[20:0]的高13位[20:8],控制寄存器(INTC_CTRL)的VAB位为其地址的[7:1],低位补0。
系统复位后,VBA的复位值为0x0000,系统进入复位中断(矢量号为0),相应的起始地址在0x00 0000处,这个过程系统自动完成。如果开放某个模块中断,需要将该模块中断服务程序的首地址加载到中断矢量表中的相应位置。具体过程如下:首先建立中断矢量表;没有开放的模块中断,在表中对应位置放入空函数的首地址(通过JSR isrDummy实现);开放的模块中断,在表中对应位置放入中断服务程序的首地址,通常中断服务程序由函数实现,在这里通过放入具体函数首地址实现,如开放QSCI0的接收中断(矢量号为32),其中断服务函数为isrSCI0_Recv,即可通过在矢量表中加入JSR isrSCI0_Recv代码实现,具体如下:
volatile asm void _vect(void);
#pragma define_section interrupt_vectors "interrupt_vectors.text" RX
#pragma section interrupt_vectors begin
volatile asm void _vect(void)
{
JSR init_MC56F824x_5x_ISR_HW_RESET /* Interrupt no. 0 (Used) - ivINT_Reset */
JSR isrDummy /* Interrupt no. 1 (Used) - ivINT_COPReset */
JSR isrDummy /* Interrupt no. 2 (Unused) - ivINT_Illegal_Instruction */
JSR isrSCI0_Recv /* Interrupt no. 32 (Used) - ivINT_QSCI0_RxFull */
JSR isrDummy /* Interrupt no. 65 (Unused) - ivINT_GPIO_A */
JSR isrDummy /* Interrupt no. 66 (Unused) - ivINT_LP */
}
#pragma section interrupt_vectors end
其中, isrDummy的函数形式如下:
void isrDummy(void)
{
}
该函数首地址用来充当未开放模块中断的中断服务程序的首地址,加载到中断矢量表中。