收藏 分销(赏)

中断向量表配置.doc

上传人:pc****0 文档编号:6710159 上传时间:2024-12-20 格式:DOC 页数:14 大小:27.02KB 下载积分:10 金币
下载 相关 举报
中断向量表配置.doc_第1页
第1页 / 共14页
中断向量表配置.doc_第2页
第2页 / 共14页


点击查看更多>>
资源描述
DM6437  中断向量表配置 1. 编写中断服务例程  在.c源文件中编写ISR函数c_intXX,用于中断处理,如:  interrupt void c_intXX (void)  {            …;  }  注:对于硬件中断而言,XX = 00~15。  2.初始化中断向量表,并在内存段中的中断向量表中配置好对应的中断向量            首先是把中断向量表定位到某一内存段中,我们可以在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  }                     然后建立一个.asm文件,用以配置中断向量表中的中断向量,我们需要声明一些全局变量,以便其他源文件可以引用这些变量或者引用其他源文件的变量,如:     *-----------------------------------------------------------------* Global symbols defined here and exported out of this file  *--------------------------------------------------------------------   .global _vectors     .global _c_int00     .global _vector1                       .global _vector2       ;RSVD保留     .global _vector3       ;RSVD保留     .global _vector4     .global _vector5     .global _vector6     .global _vector7     .global _vector8     .global _vector9         .global _vector10     .global _vector11       .global _vector12       .global _vector13       .global _c_int14_vencint  ; Hookup the c_int14 ISR in main()     .global _vector15                      因为引用了rts的_c_int00中断,即RESET中断,因此需要引入这个符号:     .ref     _c_int00          为了把中断服务例程的地址,即中断向量插入到中断向量表中,可以定义一个宏:  VEC_ENTRY .macro addr         STW      B0,*--B15         MVKL     addr,B0         MVKH     addr,B0         B        B0         LDW      *B15++,B0         NOP      2         NOP           NOP    .endm                            为了初始化中断向量表中的中断向量,可以定义一个虚拟的中断向量:  _vec_dummy:       B       B3       NOP     5                   接下来就可以配置中断向量表了:  .sect “.vecs”  .align 1024  _vectors:  _vector0:      VEC_ENTRY _c_int00         ;RESET中断  _vector1:      VEC_ENTRY _vec_dummy ;NMI不可屏蔽中断  _vector2:      VEC_ENTRY _vec_dummy ;保留中断1  _vector3:      VEC_ENTRY _vec_dummy ;保留中断2  _vector4:      VEC_ENTRY _vec_dummy ;外部中断INT4  _vector5:      VEC_ENTRY _vec_dummy ;外部中断INT5  _vector6:      VEC_ENTRY _vec_dummy ;外部中断INT6  _vector7:      VEC_ENTRY _vec_dummy ;外部中断INT7  _vector8:      VEC_ENTRY _c_int08 ; EDMA控制器中断EDMAINT,对应于c_int08 ISR  _vector9:      VEC_ENTRY _vec_dummy;JTAGRTDX中断  _vector10:     VEC_ENTRY _vec_dummy;EMIF_SDRAM_Timer中断  _vector11:     VEC_ENTRY _vec_dummy;McBSP_0_Receive中断  _vector12:     VEC_ENTRY _vec_dummy;McBSP_1_Transmit中断  _vector13:     VEC_ENTRY _vec_dummy;Host_Port_Host_to_DSP中断  _vector14:     VEC_ENTRY _vec_dummy;Timer0中断  _vector15:     VEC_ENTRY _vec_dummy;Timer1中断  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.启动中断源,如venc中断  至此,中断服务例程c_int14_vencint  就可以为venc中断服务了,其它硬件中断向量的配置同理。 DSP中断设置简明教程   (2011-10-26 10:14) 分类: 未分类 一、 简述 本文介绍TMS320C6000系列中断设置的简明方法。通过示例定时器中断,MCBSP串口接收中断及外部中断这三种中断实现过程,介绍如何实现中断各个寄存器的配置,中断向量表书写以及中断服务函数。最后提供一个简要的示例程序可供大家下载使用。此示例在DSK6416的TI官方实验板上通过测试。由于定时器和串口工作模式较繁,因此对中断无关部分不做介绍。 二、 实现DSP中断需要做哪些通用工作 设置允许哪些非屏蔽中断 设置各个允许的非屏蔽中断的中断来源 设置开启总中断 设计中断向量表 将中断向量表通过cmd文件挂载到指令内存 提供中断处理函数 如果中断向量表首地址挂载的不是0地址,那么需要设置中断向量表地址寄存器 对于不同的中断源,需要做各个自己的工作,比如如果是外部中断,那么需要设置管脚极性,即由高->低产生中断抑或反之。 为了照顾知识较少的读者,下面将从一个新工程出发,引导大家建立一个中断示例程序。 如果您对建立工程很熟悉,可以跳过此步。 三、 建立新工程 1.点击 Project->New,设置Project Name为intexample,Project Type为Executable,Target选择您需要的器件,在此由于本人使用的是DSK6416评估板。因此选择TMS320C64XX。 2.添加标准库rts6400.lib,以便自动产生c_int00等函数。右击当前工程,选择“Add Files to Project”,选择库所在路径,一般为CCS安装自带,可参考本CCS3.1版本的路径地址:\CCStudio_v3.1\C6000\cgtools\lib\rts6400.lib 如果您使用的是其他器件类型,请在lib文件夹内选择其他器件库。 添加源文件,选择File->New->Source File,保存为main.c到工程路径下。 在此文件内书写主函数。 void main(void) {  while(1); } 最后通过如2步骤添加此文件到工程。 3.添加寄存器别名定义头文件。在本示例中,对需要用到的寄存器定义别名后,构成global.h文件,内容在后文逐步介绍。在此可以建立一个空文件,并在main.c中包括它。 #i nclude "global.h" 到此,一个DSP的新工程框架制作完毕。 4.添加cmd链接文件  为了实现链接时内存配置,我们需要提供一个cmd文件,为了方便,可以从官方的示例程序中拷贝一份,再加以修改。  在安装目录下D:\CCStudio_v3.1\tutorial\器件类型\hello1示例下,会找到一个hello1.cmd,  将其拷贝到本工程目录下,并将其改名为link.cmd,最后将其添加到工程中。  由于此文件没有声明stack和heap,会产生警告,如果动态数据较多也容易溢出。因此我们最好在此文件提供stack和heap的大小,其值可根据实际情况调整,修改后,此文件内容类似为: -stack 0x1000 -heap 0x1000 MEMORY {    ISRAM       : origin = 0x0,         len = 0x1000000 } SECTIONS {         .vectors > ISRAM         .text    > ISRAM         .bss     > ISRAM         .cinit   > ISRAM         .const   > ISRAM         .far     > ISRAM         .stack   > ISRAM         .cio     > ISRAM         .sysmem  > ISRAM } 至此,工程建立完毕,可以编译一遍,观察是否正常。 ---------------------------  intexample.pjt - Debug  --------------------------- [main.c] "D:\CCStudio_v3.1\C6000\cgtools\bin\cl6x" -g -fr"D:/intexample/Debug" -d"_DEBUG" -mv6400 -@"Debug.lkf" "main.c" [Linking...] "D:\CCStudio_v3.1\C6000\cgtools\bin\cl6x" -@"Debug.lkf" <Linking> Build Complete,   0 Errors, 0 Warnings, 0 Remarks. 四、 定时器中断设计 首先,我们先实现一个定时器中断,因为它不受外部影响,容易测试。 在global.h文件中,加入控制寄存器和中断寄存器别名定义,另外为了使用定时器1,也应对其别名进行定义: /*定义控制寄存器*/ extern cregister volatile unsigned int AMR;     /* Address Mode Register      */ extern cregister volatile unsigned int CSR;     /* Control Status Register    */ extern cregister volatile unsigned int IFR;     /* Interrupt Flag Register    */ extern cregister volatile unsigned int ISR;     /* Interrupt Set Register     */ extern cregister volatile unsigned int ICR;     /* Interrupt Clear Register   */ extern cregister volatile unsigned int IER;     /* Interrupt Enable Register  */ extern cregister volatile unsigned int ISTP;    /* Interrupt Service Tbl Ptr  */ extern cregister volatile unsigned int IRP;     /* Interrupt Return Pointer   */ extern cregister volatile unsigned int NRP;     /* Non-maskable Int Return Ptr*/ extern cregister volatile unsigned int IN;      /* General Purpose Input Reg  */ extern cregister volatile unsigned int OUT;     /* General Purpose Output Reg */ /* 定义中断选择寄存器 */ #define MUXH 0x019C0000 #define MUXL 0x019C0004 #define EXTPOL 0x019C0008 /*定义定时器1寄存器*/ #define CTL1 0x01980000     //Timer1 control register #define PRD1 0x01980004     //Timer1 period register #define CNT1 0x01980008     //Timer1 counter register 之后,在main函数中对定时器进行初始化,在此我们使用Timer1,参数初始化函数如下: void Timer1_Init(void) {  *( volatile unsigned int* )CTL1= 0x00000201;  //计数器功能设置  *( volatile unsigned int* )PRD1= 0x1000;   //计数器周期值  *( volatile unsigned int* )CTL1|= 0x000000C0;  //计数器清零,启动 } 并在主函数中调用它。 随后我们设置中断寄存器参数。 DSP支持1个RESET中断,1个NMI(不可屏蔽中断),12个可屏蔽中断(INT4-15),它们具有优先级顺序,INT4最高,INT15最低。每个中断号都可以设置任何中断来源。在此我们选择中断INT10,即开启中断10,并设置其中断来源为定时器1,即在MUXH或MUXL中指定位上填写中断来源选择码: 中断来源选择码定义如下:(此内容可以通过帮助中搜索INTSEL得到) INTSEL(Interrupt Selection Number Deion) 00000b DSPINT Host port host to DSP interrupt 00001b TINT0 Timer 0 interrupt 00010b TINT1 Timer 1 interrupt 00011b SD_INT EMIF SDRAM timer interrupt 00100b EXT_INT4 External interrupt 4 00101b EXT_INT5 External interrupt 5 00110b EXT_INT6 External interrupt 6 00111b EXT_INT7 External interrupt 7 01000b EDMA_INT EDMA channel (0-15) interrupt 01001-01011b  Reserved 01100b XINT0 McBSP0 transmit interrupt 01101b RINT0 McBSP0 receive interrupt 01110b XINT1 McBSP1 transmit interrupt 01111b RINT1 McBSP1 receive interrupt 10000-11111b  Reserved 从中得到定时器1的中断选择码为00010。 MUXH和MUXL的寄存器定义如下:(也可以通过帮助得到)   MUXH 位  中断来源 30-26 INTSEL15 25-21 INTSEL14 20-16 INTSEL13 14-10 INTSEL12 9-5  INTSEL11 4-0   INTSEL10 31,15位保留,填0   MUXL 位  中断来源 30-26 INTSEL9 25-21 INTSEL8 20-16 INTSEL7 14-10 INTSEL6 9-5  INTSEL5 4-0  INTSEL4 31,15位保留,填0 因此,我们设置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,在此文件中,已经定义了段名:         .sect ".vectors" 因此我们需要将此.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,对于每个位有: 0:低->高产生中断 1:高->低产生中断 因此设置它即可完成极性变化。 下面,以设置外部端口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 并添加引用 .ref _extint7_isr 在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 制作中断服务程序,将数据取出: interrupt void rint0_isr(void) {  int DotRev;  DotRev=*( volatile unsigned int *)McBSP0_DRR; } 修改vectors.asm,替换unused 11为: INT11:   stw b0,*--b15   mvkl _rint0_isr,b0   mvkh _rint0_isr,b0   b b0   ldw *b15++,b0   nop 3   nop   nop 添加引用:   .ref _rint0_isr   ; mcbsp 0 receive interrupt handler 这时,所有的任务完成了,可以通过设置断点观察一下接收的数值。 另外需要注意一定要在服务程序中将数据取出,否则会停止接到新的数据。 七、 其他话题 1.设置中断向量表起始位置 上文讨论的都是将中断向量表放置在0地址,如果需要放置到任意地址(以400H对齐),那么就需要提供向量表起始地址。 比如我们的终端向量位置:INT设置为: MEMORY {    INT         : origin = 0x00000400,  len = 0x0000400    ISRAM       : origin = 0x00000800,  len = 0x1000000 } 那么我们在初始化中断时,应设置:  ISTP=0x00000400; 2.查看现在的中断位图 可以查看中断标志寄存器IFR相应位(15:0)看是否有中断到达。   3.清除/设置原先的中断 如果需要清除原先的中断,可以通过对ICR寄存器相应位置位。如果希望人工触发中断,可以设置ISR寄存器相应位置位,它们将更新IFR位图。 比如,我们在定时器中断服务程序中,通过设置ISR的第12位,人工触发外部INT7的12号中断。 interrupt void xint0_isr(void) {  ISR=0x00001000; } 那么CPU将执行extint7_isr(void)处理此中断。 又比如,在上例的外部中断中,有时会出现刚一开机,没有发送信号就有中断进来的情况,那么怎样克服呢?可以通过ICR克服。对ICR置位可以清除可屏蔽中断。对应位有效。比如在设置中断初始化时清除所有原先的中断。那么可以加入语句:  ICR =0xffffffff; 4.DSP/BIOS下的中断设置 在DSP/BIOS管理下,我们不需要自己设定中断向量表,以及中断初始化等等,一切通过BIOS的图形化设置即可完成。 添加一个DSP/BIOS 选择File->New,在本测试下选择DSK6416,读者可根据自己实际需要选取。保存为Configuration1.cdb。 将其添加到工程。 如上例需求,选择HWI的10,11,12号中断,右键选择Properties分别填写如下参数: HWI_INT10  interrupt source=Timer_1  =_xint0_isr(注意下划线!) HWI_INT11 interrupt source=MCSP_0_Receive =_rint0_isr HWI_INT11 interrupt source=External_Pin_7  =_extint7_isr 在main函数中可以通过同样的方法启动中断。   IER |= 0x00001C02;   // IE10=1 IE11=1 IE12=1   CSR |= 0x00000001;   //全局中断使能 至此配置完毕。 5.中断进不来怎样检查? 首先检查是否设置IER相应位开启,CSR最低位置位,其次看看中断向量表地址是否设置正确。如果确认无误。在向量表中断应当进入的位置设定断点。运行看是否执行到断点。如果有,那么看看中断服务程序有没有执行到。如果中断只进来一次后就再也无法进入了,可以查看中断向量表是否能返回到原程序,如果不能返回,查看是否是8条语句。另外可以通过跟踪查看b irp语句是否被执行。如果可以正常返回到原程序,例如串口接收,看看是否没有取值导致阻塞。如果是这样需要将原先值取出才有新的中断。 6.中断若干寄存器的说明到哪里去找? 可以通过Help->Contents,搜索关键字的方法得到。也可以参考官方文档。 八、 附带程序 本教程以附件提供三个示例: 1. onlytimerint——仅包含了定时器的示例 2. int——包含了完整的3种中断 3. intbios——提供了DSP/BIOS下的此3种中断。
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:4009-655-100  投诉/维权电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服