因此,我们设置MUXH的第4-0位为定时器1的中断选择码00010,其余位可以任意设置(在此可以填1)。转换为16进制后,设置如下:
- *( volatile unsigned int* )MUXH=0x7fff7fe2;
复制代码
MUXL可以不设置。
开启中断到IE10,使能全局中断:
- IER |= 0x00000402; // IE10=1
- CSR |= 0x00000001; // 全局中断使能
复制代码
以上就完成了中断参数的配置,中断启动并且可以进入了。下面是中断的处理过程。主要分为设计中断向量表和中断处理函数。
我们可以从DSP CCS的示例中复制一份向量表的雏形。例如\CCStudio_v3.1\tutorial\dsk6416\hello1\vectors.asm
将其拷贝到本工程目录下并加入工程中。
中断向量表包含了16个中断处理单元,每个单元限制必须是8条指令。如果不够8条,可以用nop填充,(但nop 4算1条语句),如果服务程序过多,那么可以制作专门的中断服务程序,此时此表只起到跳转作用,这样CPU就可以正确寻址找到正确的中断服务入口。
首先分析一下此文件。
文件开始定义了一个宏,用于处理未用到的中断。
- unused .macro id
- .global unused:id:
- unused:id:
- b unused:id: ; nested branches to block interrupts
- nop 4
- b unused:id:
- nop
- nop
- nop
- nop
- nop
复制代码
它的做法是让程序进入死循环,我认为这种做法未必最优,因此我建议使用直接返回的方式。返回到被中断地址,对于可屏蔽中断为b irp,因此将此宏部分替换成,注意一定要凑够8条。
- unused .macro id
- .global unused:id:
- unused:id:
- b irp
- nop
- nop
- nop
- nop
- nop
- nop
- nop
- .endm
这样,即使我们误开启了此中断,也会顺利返回。当然,如果我们确信的确没有开启,那么其内容是无意义的。
代码的正文部分用了一系列unused n来插入此宏,起到占地的作用。
由于NMI的返回与可屏蔽中断不同,它在向量表中位于RESET之下,即unused 1,我们将其删除,替换为
- NMI: b nrp
- nop
- nop
- nop
- nop
- nop
- nop
- nop
复制代码
为了实现定时器1中断的处理,我们将unused 10删除,替换为我们自己的中断跳转程序,如下:
- INT10:
- stw b0,*--b15
- mvkl _xint0_isr,b0
- mvkh _xint0_isr,b0
- b b0
- ldw *b15++,b0
- nop 3
- nop
- nop
复制代码
另外,需要和语句:
- .ref _c_int00 ; C entry point
复制代码
类似,添加处理程序的引用
- .ref _xint0_isr ; timer 1 interrupt handler
复制代码
由于中断向量表的位置需要特定指明,且应对齐到400H,在此文件中,已经定义了段名:
复制代码
因此我们需要将此.vector代码段挂载到专门的一段指定内存区域。
修改link.cmd 链接文件,加入INT区域,起点为0地址。其大小为400H,将原先的ISRAM起始点修改。并将SECTIONS中的.vector指向自己定义的内存区域。
- MEMORY
- {
- INT : origin = 0x00000000, len = 0x0000400
- ISRAM : origin = 0x00000400, len = 0x1000000
- }
- SECTIONS
- {
- .vectors > INT
- …
- }
复制代码
中断向量表设置、安装完毕。
最后,设计中断服务函数,在main.c中添加:
- interrupt void xint0_isr(void)
- {
- }
复制代码
注意,一定要标识interrupt关键字,用于产生中断返回语句b irp,同时,此函数的入口参数和出口参数应为void。如果需要更新变量,可以通过全局变量的方式。
另外,C语言函数名称与汇编相差一个“_”,请在设计中断向量表时注意添加。
经过上述步骤,整个定时器中断的制作过程就完成了。此时可以在interrupt void xint0_isr(void)上添加一个断点,运行后应该停在此处。如果进入失败,可以先在vector.asm的INT10:stw b0,*--b15一句上设置断点,如果没有进入此处,证明中断没有进来,可以检查是否在参数设置上出现了问题。
五、 外部中断设计
DSP6000系列提供了INT4-7四个中断输入管脚,因此可以通过此四个管脚的输入电平变化实现外部中断。对于电平变化的极性,分为高到低,低到高两种,因此,DSP采用寄存器EXTPOL来设置。EXTPOL只有低4位有效,分别代表INT4-7,对于每个位有:
复制代码
因此设置它即可完成极性变化。
下面,以设置外部端口INT7中断,并将其挂载到12号中断为例,简述实现过程:
将12号中断设置为外部中断7,即MUXH(4:0)=00111,此时MUXH设置为:
- *( volatile unsigned int* )MUXH=0x7fff7ce2;//0111 1100 1110 0010
- 将IER的第12位开启。
- IER |= 0x00001402; // IE10=1 IE12=1
- 对vectors.asm的unused 12替换为:
- INT12:
- stw b0,*--b15
- mvkl _extint7_isr,b0
- mvkh _extint7_isr,b0
- b b0
- ldw *b15++,b0
- nop 3
- nop
- nop
复制代码
并添加引用
复制代码
在main.c中加入服务函数:
- interrupt void extint7_isr(void)
- {
- }
复制代码
在硬件上,对INT7/GPIO7管脚产生一个低->高的信号,则可以触发出中断。
若改变此极性,可以设置EXTPOL第四位为1:
- *( volatile unsigned int* )EXTPOL|= 0x00000008;
复制代码
此时,一个高->低的信号可以产生中断。
需要注意的是,如果你对GPIO进行过初始化,一定要保证GPEN的中断引脚相应位为1。如全部使能:
- *(volatile unsigned int* )GPEN = 0x000000F0;
复制代码
六、 MCBSP串口接收中断设计
在实际应用过程中,经常需要通过中断接收串口数据。在此假设添加MCBSP0接收中断到11号。
首先,将MCBSP0别名添加到global.h文件。
设置MCBSP0参数并启用,其初始化函数为:
- void MCBSP0_Init(void)
- {
- *( volatile unsigned int* )McBSP0_SPCR = 0x00000000;
- *( volatile unsigned int* )McBSP0_SRGR = 0x200000FF;
- *( volatile unsigned int* )McBSP0_PCR = 0x00000800;
- *( volatile unsigned int* )McBSP0_XCR = 0x000100A0;
- *( volatile unsigned int* )McBSP0_RCR = 0x000100A0;
- *( volatile unsigned int* )McBSP0_MCR = 0x00000000;
- *( volatile unsigned int* )McBSP0_SPCR |= 0x00C10001;
- }
复制代码
并在main函数中调用。
开启中断11:
- IER |= 0x00001C02; // IE10=1 IE11=1 IE12=1
复制代码
并将MUXH(9:5)=01101,综合以上三个中断,此时MUXH为:
- *( volatile unsigned int* )MUXH=0x7fff1da2;//0001 1101 1010 0010
复制代码
当然,如果只考虑现在的中断,MUXH可以设置为:
- *( volatile unsigned int* )MUXH=0x7fff7dbf;//0111 1101 1011 1111
|