打印

DSP中断设置简明教程 (2)

[复制链接]
1689|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Jasmines|  楼主 | 2017-11-15 10:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
DSP中断设置简明教程 (2)


  这样,即使我们误开启了此中断,也会顺利返回。当然,如果我们确信的确没有开启,那么其内容是无意义的。
        代码的正文部分用了一系列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种中断。

相关帖子

沙发
smilingangel| | 2017-11-15 19:45 | 只看该作者
对于电平变化的极性,分为高到低,低到高两种,,这个细节要注意区分的

使用特权

评论回复
板凳
comeon201208| | 2017-11-15 20:37 | 只看该作者
在程序设计中,采用宏设计的还是比较合理的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

745

主题

1077

帖子

10

粉丝