打印

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

[复制链接]
881|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Jasmines|  楼主 | 2017-11-14 14:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
DSP, TE, ST, TI, se
DSP中断设置简明教程


一、 简述
        本文介绍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

复制代码
   

相关帖子

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

本版积分规则

745

主题

1077

帖子

10

粉丝