打印

请教:keil for arm中如何实现中断操作

[复制链接]
4068|2
手机看帖
扫描二维码
随时随地手机跟帖
沙发
wowow| | 2007-4-21 04:46 | 只看该作者

在arm目录里搜带"__irq"的c代码

在arm目录里搜带"__irq"的c代码,然后打开相应的project看看。如:
D:KeilARMRV30BoardsSamsungS3C44001Hello

要点:
1.在启动文件里设置中断向量,比如s3c44b0x.s里有一段:
                IF      VIM_SETUP <> 0

                MACRO
$IRQ_Vector     IRQ_Vec $Num, $HandlerName
$IRQ_Vector     IF      (VIM_CFG:AND:(1:SHL:$Num)) <> 0
                IMPORT  $HandlerName
                LDR PC, =$HandlerName
                ELSE
                B       .
                ENDIF 
                MEND

                IRQ_Vec 25, HandlerEINT0
                IRQ_Vec 24, HandlerEINT1
                IRQ_Vec 23, HandlerEINT2
                IRQ_Vec 22, HandlerEINT3
                IRQ_Vec 21, HandlerINT4567
                IRQ_Vec 20, HandlerTICK
                B       .
                B       .
                IRQ_Vec 19, HandlerZDMA0
                IRQ_Vec 18, HandlerZDMA1
                IRQ_Vec 17, HandlerBDMA0 
                IRQ_Vec 16, HandlerBDMA1 
                IRQ_Vec 15, HandlerWDT 
                IRQ_Vec 14, HandlerUERR01 
                B       .
                B       .
                IRQ_Vec 13, HandlerTIMER0
                IRQ_Vec 12, HandlerTIMER1 
                IRQ_Vec 11, HandlerTIMER2 
                IRQ_Vec 10, HandlerTIMER3 
                IRQ_Vec 9,  HandlerTIMER4 
                IRQ_Vec 8,  HandlerTIMER5
                .................

                ENDIF

如果要用HandlerTIMER5,将VIM_SETUP设为1,VIM_CFG中与TIMER5相关的bit置1。这样在中断向量表中在TIMER5中断位置会生成一句:
     LDR PC, =HandlerTIMER5
其中HandlerTIMER5为中断服务程序的函数地址

2。在C程序中为中断5写服务程序:
__irq void HandlerTIMER5 (void) {           /* Timer 5 Interrupt Handler */

  timeval++;                                /* Increment Time Tick  */
  pIC->I_ISPC = INT_TIMER5;                 /* Clear Interrupt Flag */
}

函数定义前加上__irq,函数名与启动文件中的一致。

3。在scatter文件中将中断向量表放到0地址,这个不用解释了吧?

4。如果你调试时程序加载到ram,最后程序是烧到flash中的,如果arm不支持remap(如s3c44b0x),那么用仿真器在ram中程序时发生中断,会到flash中找中断向量表,因此flash中的向量表要与ram程序的中断向量表一致。解决至少有两种,这里介绍中断调用比软件快的一种。启动文件仍然如上,因此只要保证HandlerTIMER5函数的地址在flash中运行与仿真器加载到ram中运行一样。步骤:
a.给中断服务程序的程序段起个名字,加上#pragma arm section编译指令:
#pragma arm section code = "ISR_TIMER5"
__irq void HandlerTIMER5(void)
{
    if(RefreshBatt!=0)RefreshBatt--;
    rI_ISPC |= (1<<8);
}
#pragma arm section code //表示恢复原来的程序段名
b.两个运行版本本给ISR_TIMER5段分配相同的地址,如:
ISR_SECT  0x0C1F0000 
{
       isr.o (ISR_TIMER5, +first)
}
这样就保证了HandlerTIMER5在两个运行版本中的地址是一样的,中断向量表当然也是一样的了。

如果有多个中断服务程序,最老实的办法是每个服务程序命名一个段,然后在scatter文件中分配地址。如果你能确认编译参数和链接循序是一样的,产生代码位置也是一样,分配到同一个段中也行,不过总有点隐患。

另外一个方案里改启动文件,思路是中断服务地址在程序运行时存到一个地址中,而中断服务程序先跳到一个取地址的小代码里。这样的好处是中断服务程序的地址随意,但增加了调用中断的时间。因为不仅要多跳转一次,而且取地址要用到寄存器又得压栈。因此个人倾向于前一种方案。

使用特权

评论回复
板凳
tdwmcu|  楼主 | 2007-4-21 22:26 | 只看该作者

非常感谢楼上相助,我好好研究一下

使用特权

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

本版积分规则

31

主题

136

帖子

1

粉丝