在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
芯片精品文章合集(500篇!) 创芯人才网--重磅上线啦!
查看: 2242|回复: 0

[原创] 关于C语言中DSP5402中断向量表的配置问题

[复制链接]
发表于 2008-12-21 10:56:34 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
本帖最后由 cjsb37 于 2013-4-29 08:58 编辑

hotpower 发表于 2008-12-21 10:23 DSP 技术 ←返回版面

楼主: 关于C语言中DSP5402中断向量表的配置问题

在MCU/ARM/DSP中,都有1个启动过程,这里主要设计复位及中断的入口问题。
所以它们基本都有启动文件的支持,使程序上电后自动进入正确的程序位置及地址。
复位及中断的入口具有多个间隔固定的程序空间,它们可以是单独的跳转地址
及函数指针,如ARM的中断向量表。也可是一块小的固定程序空间,如51的n*8+3和DSP5402的4字。
DSP5402和51略有不同,它在硬件复位时bootloader将中断向量表映射到ROM的0xFF80处。

但我们实际运行时,中断入口是允许改变的,而且每个程序的中断地址和个数都是不同的。

故需要动态地改变中断向量表。

DSP5402在硬件复位时中断向量表存在SREGs.PMST.IPTR中,步进(大小)0x80.

SREGs.PMST.IPTR初始化为0b11111111 1,故中断向量表在0xff80处。
我喜欢将其动态映射到0x0080处,因为寄存器在0x00~0x5f,0x60~0x7f处。
这样连续,RAM程序可从0x100开始装载。

所以我们要做至少2方面的工作:
1.修改SREGs.PMST.IPTR
//设置0x0080为中断向量表首址,在第2个128页内。
    SREGs.PMST.Regs = (0x01 << PMST_IPTR) | (1 << PMST_MP_MC) | (1 << PMST_OVLY);

2.初始化中断向量表
在C语言的启动文件中,我们只需将中断向量表看成普通数组即可,因为CCS具有地址绝对定位功能。
这样我们就可以很方便地将中断向量表绝对定位到我们需要定位的位置。

在CCS中想绝对定位,必须修改CMD文件。
例如:
MEMORY  
{
/*(R读 W写 X运行 I初始化)*/
    PAGE 0: /* Program Space */
        MMRS    (RWIX) : o=000000h l=000060h /* Memory-mapped registers  */
        SCRATCH (RW  ) : o=000060h l=000020h /* scratch-pad DARAM        */
        VECT    (RWIX) : o=000080h l=000080h /* Interrupt Vector Table   */
        IPROG   (RW  ) : o=000100h l=001f00h /* On-Chip DARAM            */
    PAGE 1: /* Data Space */
        /* declaration for DARAM already made in PAGE 0                 */
        /*支持对SREGs在watch窗口中有效查看*/
        IMMRS   (RWIX) : o=000000h l=000060h /* Memory-mapped registers  */
        ISCRATCH(RW  ) : o=000060h l=000020h /* scratch-pad DARAM        */
        /*支持对中断向量表的正确定位及改写*/
        IVECT   (RWIX) : o=000080h l=000080h /* Interrupt Vector Table   */
        IDATA   (RW  ) : o=002000h l=002000h /* On-Chip DARAM            */
        EDATA   (RW  ) : o=008000h l=008000h
}

SECTIONS
{
    /*支持对中断向量表的正确定位及改写*/
    .vectors    : > IVECT   PAGE 1 /* interrupt vector table            */
    /*支持对SREGs在watch窗口中有效查看*/
    .registers  : > IMMRS   PAGE 1 /*                                   */
    .text       : > IPROG   PAGE 0 /* User code                         */
    .cinit      : > IPROG   PAGE 0 /* initialization tables             */
    .pinit      : > IPROG   PAGE 0 /* initialization functions          */
    .switch     : > IPROG   PAGE 0 /* for C-switch tables               */

    /* Normally, data would go to DMEM0, but OVLY=1 so put data in      */
    /* PMEM0 to keep loader from overwriting program with data.         */
    .sysmem     : > IDATA   PAGE 1 /*fill = 0DEADh*/ /* dynamic heap        */
    .stack      : > IDATA   PAGE 1 /*fill = 0BEEFh*/ /* system stack        */
    .const      : > IDATA   PAGE 1 /* C constant tables                 */
    .cio        : > IDATA   PAGE 1 /* C-IO Buffer                       */
    .bss        : > IDATA   PAGE 1 /* global & static vars              */
    .data       : > IDATA   PAGE 1 /* asm data area                     */
    .flash      : > EDATA   PAGE 1 /**/
}

这里将VECT移入了PAGE 1,为不破坏以前的“规矩”,特将VECT重起名IVECT.
实际VECT以无用。

接下来就是对中断向量进行初始化。
#pragma DATA_SECTION("vectors")//将中断向量绝对定位到0x80处
uVectorEntry g_pfnVectors[] = {
    ISR_Reset(),   //reset      0x0080 #0//软硬件复位nISR_REST
    ISR_Default(), //nmi        0x0084 #1//非屏蔽中断nISR_NMI
    ISR_Default(), //sint17     0x0088 #2//软件中断17   
    ISR_Default(), //sint18     0x008c #3//软件中断18
    ISR_Default(), //sint19     0x0090 #4//软件中断19
    ISR_Default(), //sint20     0x0094 #5//软件中断20
    ISR_Default(), //sint21     0x0098 #6//软件中断21
    ISR_Default(), //sint22     0x009c #7//软件中断22
    ISR_Default(), //sint23     0x00a0 #8//软件中断23
    ISR_Default(), //sint24     0x00a4 #9//软件中断24
    ISR_Default(), //sint25     0x00a8 #10//软件中断25
    ISR_Default(), //sint26     0x00ac #11//软件中断26
    ISR_Default(), //sint27     0x00b0 #12//软件中断27
    ISR_Default(), //sint28     0x00b4 #13//软件中断28
    ISR_Default(), //sint29     0x00b8 #14//软件中断29
    ISR_Default(), //sint30     0x00bc #15//软件中断30
    ISR(Eint0Isr), //int0       0x00c0 #16//外部中断0
    ISR(Eint1Isr), //int1       0x00c4 #17//外部中断1
    ISR(Eint2Isr), //int2       0x00c8 #18//外部中断2
    ISR(Timer0Isr),//tint       0x00cc #19//定时器中断0
    ISR(McBSPIsr), //rint0      0x00d0 #20//McBSP0接收中断
    ISR_Default(), //xint0      0x00d4 #21//McBSP0发送中断
    ISR_Default(), //rint1      0x00d8 #22//McBSP1接收中断
    ISR(Timer1Isr),//xint1      0x00dc #23//定时器中断1
    ISR(Eint3Isr), //int3       0x00e0 #24//外部中断3
    ISR_Default(), //hpint      0x00e4 #25//HPI中断
    ISR_Default(), //           0x00e8 #26//软件中断10
    ISR_Default(), //           0x00ec #27//软件中断11
    ISR_Default(), //           0x00f0 #28//软件中断12
    ISR_Default(), //           0x00f4 #29//软件中断13
    ISR_Default(), //           0x00f8 #30//保留0
    ISR_Default(), //           0x00fc #31//保留1
};

其中宏实际是“嵌入汇编”:
#define ISR_Reset() {DSPCODE_BD, (pfnVectorEntry)c_int00, DSPCODE_SP_200L, DSPCODE_SP_200H}
#define ISR_Return() {DSPCODE_RETE, (pfnVectorEntry)DSPCODE_NOP, DSPCODE_NOP, DSPCODE_NOP}
#define ISR_Default() {DSPCODE_BD, (pfnVectorEntry)DefaultIsr, DSPCODE_NOP, DSPCODE_NOP}
#define ISR(addr) {DSPCODE_BD, (pfnVectorEntry)addr, DSPCODE_NOP, DSPCODE_NOP}
//注意:宏ISR_Load()调用前应该关闭中断,装载后再开放中断
#define ISR_Load(nISR, addr) {g_pfnVectors[nISR].Isr = (pfnVectorEntry)addr;}
//注意:宏ISR_UnLoad()调用前应该关闭中断,卸载后再开放中断
#define ISR_UnLoad(nISR) {g_pfnVectors[nISR].Isr = (pfnVectorEntry)DefaultIsr;}

这里的汇编代码用枚举来替代:
enum DspCodeEnum_Enum
{
    DSPCODE_BD       = (TI_IREG)0xf273u,//等效BD address指令
    DSPCODE_B       = (TI_IREG)0xf073u,,//等效B address指令
    DSPCODE_RETE    = (TI_IREG)0xf4fbu,,//等效rete指令
    DSPCODE_NOP     = (TI_IREG)0xf495u,//等效nop指令
    DSPCODE_SP_200L = (TI_IREG)0x7718u,//STM #200,SP
    DSPCODE_SP_200H = (TI_IREG)0x00c8u//STM #200,SP
};

例如ISR(Timer0Isr),它表示在19#中断向量nISR_TINT0的位置0xcc处为Timer0Isr的入口。

为了编写Timer0Isr,我们还要进行2方面的工作:
1.初始化定时器,设置100MHz时10mS中断的时间常数
void TimerObj::Timer0Init(void)
{
    SREGs.TIMER0.TCR.Bits.TSS = 1;//关闭定时器0
    SREGs.TIMER0.TCR.Bits.TDDR = 16 - 1;//16分频
    SREGs.TIMER0.PRD = 62500 - 1;//设置定时周期(PRD->TIM)
    SREGs.TIMER0.TIM = 62500 - 1;//设置定时计数器
    SREGs.TIMER0.TCR.Bits.TSS = 0;//启动定时器0
    SREGs.IMR.Bits.TINT0 = 1;//允许TINT0中断(62500*16=10mS)
}

2.编制定时器中断服务程序
extern "C" interrupt void Timer0Isr(void)
{//每10mS中断1次
static unsigned int Count = 0;
    Count ++;
    if (Count > 50)//16*62500*50=0.5S
    {//Led工作灯XF半秒翻转1次,注意XF的变化不是改写ST1而是改写SP(1)
        SREGs.SP.Ptr[1] ^= (1 << ST1_XF);//改写SP(1)
        Count = 0;
    }
    SREGs.IFR.Bits.TINT0 = 1;//清除定时器0中断标志
}

到此,完整的关于C语言中DSP5402中断向量表的配置问题及实现过程叙述完毕

菜农HotPower@126.com

下载C5402CFG.H(完全增强版)及应用演示包

签名:
●█〓██▄▄▄▄▄▄ ●●●●●●→ ''''╭WWWW╮
▄▅██████▅▄▃▂ 传播非典灌水四方 ( ●_●)
███天█马█行█空████ '''',,,;,;,;'''/▇\''
◥⊙▲⊙▲⊙▲⊙▲⊙▲⊙▲◤ 群魔乱舞见阳光/MMMM\
工程师的收藏夹

菜农的农家博客








您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /1 下一条


小黑屋| 手机版| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-11-14 15:45 , Processed in 0.019128 second(s), 8 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表