中断的原理具体可以参考:TMS320C64x/C64x+ DSP CPU and Instruction Set Reference Guide第五章内容。
6437有优先级从高到低三种类型的中断:RESET NMI 可屏蔽中断(INT4-INT15)
对于我们一般使用INT4-15比较多,实现的步骤:
1 首先是把中断向量表定位到某一内存段中,我们可以在cmd文件中配置中断向量表的内存映射
MEMORY
{
VECS:
o = 0x10800000
l = 0x00000400
MEMTEST: o = 0x10800400
l = 0x00000200
IRAM: o = 0x10800600
l = 0x0001FA00
DDR2: o = 0x80000000
l = 0x10000000
}
SECTIONS
{
.bss >
IRAM
.cinit >
IRAM
.cio >
IRAM
.const >
IRAM
.data >
IRAM
.far >
IRAM
.stack >
IRAM
.switch >
IRAM
.sysmem >
IRAM
.text >
IRAM
.vecs
> VECS
.ddr2 >
DDR2
}
2 .vecs.asm
* Copyright (C) 2003 Texas Instruments Incorporated
* All Rights Reserved
*
*
*---------vecs_timer1.asm---------
*
* Assembly file to set up interrupt service table (IST)
*
*------------------------------------------------------------------------------
* Global symbols defined here and exported out of this file
*然后建立一个.asm文件,用以配置中断向量表中的中断向量,我们需要声明一些全局变量,以便其他源文件可以引用这些变量或者引用其他*源文件的变量,如:
*------------------------------------------------------------------------------
.global _vectors
.global _c_int00
.global _vector1
.global _vector2
.global _vector3
.global _vector4
.global _vector5
.global _vector6
.global _vector7
.global _vector8
.global _vector9
.global _vector10
.global _vector11
.global _vector12
.global _vector13
.global _extint14_isr ; Hookup the c_int14 ISR in main()
.global _vector15
*------------------------------------------------------------------------------
* Global symbols referenced in this file but defined somewhere else.
* Remember that your interrupt service routines need to be referenced here.
*因为引用了rts的_c_int00中断(实际_c_int00在其他文档中定义),即RESET中断,因此需要引入这个符号:
*------------------------------------------------------------------------------
.ref _c_int00
.ref _extint7_isr ; external interrupt INT 7 handler
.ref _extint8_isr ; external interrupt INT 8 handler
.ref _extint14_isr ; external interrupt INT 14 handler
*------------------------------------------------------------------------------
* This is a macro that instantiates one entry in the interrupt service table.
*为了把中断服务例程的地址,即中断向量插入到中断向量表中,可以定义一个宏:
*------------------------------------------------------------------------------
VEC_ENTRY .macro addr
STW B0,*--B15 ;把B0内容保存到*B15,然后指针变量后移,相当于压栈
MVKL addr,B0 ;传入参数的地址给B0
MVKH addr,B0
B B0 ;程序跳转到B0指向的地址
LDW *B15++,B0 ;把之前保存的B0恢复;相当于pop
NOP 2
NOP
NOP
.endm
*------------------------------------------------------------------------------
* This is a dummy interrupt service routine used to initialize the IST.
*为了初始化中断向量表中的中断向量,可以定义一个虚拟的中断向量:
*------------------------------------------------------------------------------
_vec_dummy:
B B3
NOP 5
*------------------------------------------------------------------------------
* This is the actual interrupt service table (IST). It is properly aligned and
* is located in the subsection .text:vecs. This means if you don't explicitly
* specify this section in your linker command file, it will default and link
* into the .text section. Remember to set the ISTP register to point to this
* table.
*配置中断向量表 上面定义的宏起作用了,这里中断向量的名字,比如_c_int00,_extint14_isr相当于函数入口地址
*不同的在于C编译器会自动吧c_int00当做_c_int00来处理,这样地址就插入中断向量表中了。
*------------------------------------------------------------------------------
.sect ".vectors"
;.align 1024
_vectors:
_vector0: VEC_ENTRY _c_int00 ;RESET
_vector1: VEC_ENTRY _vec_dummy ;NMI
_vector2: VEC_ENTRY _vec_dummy ;RSVD
_vector3: VEC_ENTRY _vec_dummy
_vector4: VEC_ENTRY _vec_dummy
_vector5: VEC_ENTRY _vec_dummy
_vector6: VEC_ENTRY _vec_dummy
_vector7: VEC_ENTRY _extint7_isr
_vector8: VEC_ENTRY _extint8_isr
_vector9: VEC_ENTRY _vec_dummy
_vector10: VEC_ENTRY _vec_dummy
_vector11: VEC_ENTRY _vec_dummy
_vector12: VEC_ENTRY _vec_dummy
_vector13: VEC_ENTRY _vec_dummy
_vector14: VEC_ENTRY _extint14_isr ; Hookup the c_int14 ISR in main()
_vector15: VEC_ENTRY _vec_dummy
*------------------------------------------------------------------------------
3.在C程序中指定定义的中断向量表,并且启用CPU中断功能
在C程序中,用CSL的IRQ模块来设置中断比较方便,在设置之前,需要外部链接上面的asm程序的中断向量表符号:
extern far void vectors();//之所以为vectors,因为C编译器编译后自动改名其为_vectors
引用了中断向量表之后,就可以设置中断了:
IRQ_setVecs(vectors); //指向asm中定义的中断向量表
IRQ_nmiEnable();
IRQ_globalEnable();
IRQ_map(IRQ_EVT_EDMAINT, 8);
//映射事件到指定的物理中断号
IRQ_reset(IRQ_EVT_EDMAINT);
4 定义中断相关寄存器必不可少,一般放在头文件中,具体的地址可以参考相关的手册,定义寄存器的方法如下,例如:
#define PARAMENTRY0 (0x01c04000) //确定基地址
#define OPT *((volatile unsigned int *)(PARAMENTRY0 + 0x00)) //确定寄存器地址
5 关中断
cpu的中断寄存器参考:TMS320C64x/C64x+ DSP CPU and Instruction Set Reference Guide 5.1.3 Summary of Interrupt Control Registers ,具体内容参考:2.7 Control Register File
CSR=0x100; /* disable all interrupts */
IER=1; /* disable all interrupts except NMI */
ICR=0xffff; /* clear all pending interrupts */
ISTP = 0x10800400;
6 建立事件与中断的关联
Megamodule Interrupt Controller实际上是6437的一个外设(6437的外设可以参考:TMS320DM643x DMP Peripherals Overview),提供了一个中断分类的功能,让dsp的中断可以支持高达128个事件,它的寄存器具体参见:TMS320C64x+ DSP Megamodule Reference Guide 7.5节
具体的事件可参考:TMS320DM643x DMP Peripherals Overview:7.3 C64x+ Megamodule Events。更详细的关于一些芯片级的事件可以参考各个处理器的数据手册,如dm6437参考:TMS320DM6437 Digital Media Processor 6.8 Interrupts Table 6-21. DM6437 DSP System Event Mapping
/*
INTC_EVTCLR0 = 0xFFFFFFFF;
INTC_EVTCLR1 = 0xFFFFFFFF;
INTC_EVTCLR2 = 0xFFFFFFFF;
INTC_EVTCLR3 = 0xFFFFFFFF;
// INTC_EVTFLAG1=0x00000000;
INTC_EVTMASK3 = 0xFFFFFFFF;
INTC_EVTMASK2 = 0xFFFFFFFF;
INTC_EVTMASK1 = 0xFFFFFFFF;
INTC_EVTMASK0 = 0xFFFFFFEF;
INTC_EVTSET1 = 0x00000004;*/
// INTC_INTMUX1 = 0x18000000; //CPUINT7 //24 VPSS-CCDC0
// INTC_INTMUX2 = 0x00000024; //CPUINT8 //34 EDMA3CC_GINT
INTC_INTMUX2 = 0x00000018; //CPUINT8 //24 VPSS-CCDC0
INTC_INTMUX3 = 0x00040000; //CPUINT14 //4 TINTL0
7 开中断
IER |= 0x00000102; //enable 7 8 14
// ISR = 0x00000100;
CSR =0x01 ; /* enable all interrupts*/
8 初始化完成后,只需在主程序中加入对应的中断服务程序,如
interrupt void extint8_isr(void)
{
....
}