ColdFire与ARM处理器中断响应分析

[复制链接]
 楼主| 阿南 发表于 2007-10-22 20:30 | 显示全部楼层 |阅读模式
**标题:<br />ColdFire与ARM处理器中断响应分析<br /><br />**简介:<br />对于任何一种处理器,中断都是非常重要的,它的响应速度,直接关系着程序的性能。另外用户程序出现跑飞形象,也大多都是由中断引起,在中断的处理过程当中执行非法指针操作引起。因此分析、熟悉处理器的中断响应执行过程,无论对其性能的了解,还是解决由中断引起的程序跑飞的调试,都是必须的。<br /><br />正文:<br />一.&nbsp;&nbsp;&nbsp;&nbsp;ARM处理器中断分析(以S3C2410的IRQ及timer0中断为例)<br />1.&nbsp;&nbsp;&nbsp;&nbsp;中断初始化过程<br />1&gt&nbsp;中断向量表起始地址定义<br />C文件中的宏定义:<br />#define&nbsp;_ISR_STARTADDRESS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0x33ffff00<br />汇编文件中的定义:<br />&nbsp;&nbsp;&nbsp;&nbsp;_ISR_STARTADDRESS&nbsp;&nbsp;&nbsp;&nbsp;EQU&nbsp;0x33ffff00<br />2&gt&nbsp;IRQ中断及具体外设中断源地址定义<br />C文件中的宏定义:<br />&nbsp;&nbsp;&nbsp;&nbsp;。。。。。。<br />#define&nbsp;pISR_IRQ&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(*(unsigned&nbsp;*)(_ISR_STARTADDRESS+0x18))<br />。。。。。。<br />#define&nbsp;pISR_TIMER0&nbsp;&nbsp;&nbsp;(*(unsigned&nbsp;*)(_ISR_STARTADDRESS+0x48))<br />。。。。。。。<br />汇编文件中的定义:<br />&nbsp;&nbsp;&nbsp;&nbsp;。。。。。。<br />pISR_IRQ&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;(_ISR_STARTADDRESS+0x18)<br />。。。。。。<br />pISR_TIMER0&nbsp;&nbsp;&nbsp;EQU&nbsp;&nbsp;(_ISR_STARTADDRESS+0x48)<br />。。。。。。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AREA&nbsp;RamData,&nbsp;DATA,&nbsp;READWRITE<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;^&nbsp;&nbsp;&nbsp;_ISR_STARTADDRESS<br />。。。。。。<br />HandleIRQ&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//注:位于_ISR_STARTADDRESS+0x18处<br />。。。。。。<br />HandleTIMER0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;&nbsp;&nbsp;4<br />。。。。。。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;END<br />3&gt&nbsp;相关的子程序段<br />内核中断都要用到的宏定义:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MACRO<br />$HandlerLabel&nbsp;HANDLER&nbsp;$HandleLabel<br /><br />$HandlerLabel<br />&nbsp;&nbsp;&nbsp;&nbsp;sub&nbsp;&nbsp;&nbsp;&nbsp;sp,sp,#4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;decrement&nbsp;sp(to&nbsp;store&nbsp;jump&nbsp;address)<br />&nbsp;&nbsp;&nbsp;&nbsp;stmfd&nbsp;&nbsp;&nbsp;&nbsp;sp!,{r0}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;PUSH&nbsp;the&nbsp;work&nbsp;register&nbsp;to&nbsp;stack(lr&nbsp;does't&nbsp;push&nbsp;because&nbsp;it&nbsp;return&nbsp;to&nbsp;original&nbsp;address)<br />&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r0,=$HandleLabel;load&nbsp;the&nbsp;address&nbsp;of&nbsp;HandleXXX&nbsp;to&nbsp;r0<br />&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r0,[r0]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;load&nbsp;the&nbsp;contents(service&nbsp;routine&nbsp;start&nbsp;address)&nbsp;of&nbsp;HandleXXX<br />&nbsp;&nbsp;&nbsp;&nbsp;str&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r0,[sp,#4]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;store&nbsp;the&nbsp;contents(ISR)&nbsp;of&nbsp;HandleXXX&nbsp;to&nbsp;stack<br />&nbsp;&nbsp;&nbsp;&nbsp;ldmfd&nbsp;&nbsp;&nbsp;sp!,{r0,pc}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;POP&nbsp;the&nbsp;work&nbsp;register&nbsp;and&nbsp;pc(jump&nbsp;to&nbsp;ISR)<br />&nbsp;&nbsp;&nbsp;&nbsp;MEND<br /><br />IRQ中断处理程序断:<br />IsrIRQ&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;sub&nbsp;&nbsp;&nbsp;&nbsp;sp,sp,#4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;reserved&nbsp;for&nbsp;PC<br />&nbsp;&nbsp;&nbsp;&nbsp;stmfd&nbsp;&nbsp;&nbsp;&nbsp;sp!,{r8-r9}&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;r9,=INTOFFSET<br />&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;r9,[r9]<br />&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;r8,=HandleEINT0<br />&nbsp;&nbsp;&nbsp;&nbsp;add&nbsp;&nbsp;&nbsp;&nbsp;r8,r8,r9,lsl&nbsp;#2<br />&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;r8,[r8]<br />&nbsp;&nbsp;&nbsp;&nbsp;str&nbsp;&nbsp;&nbsp;&nbsp;r8,[sp,#8]<br />&nbsp;&nbsp;&nbsp;&nbsp;ldmfd&nbsp;&nbsp;&nbsp;&nbsp;sp!,{r8-r9,pc}<br />4&gt&nbsp;系统启动时的初始化过程<br />ResetHandler<br />&nbsp;&nbsp;&nbsp;&nbsp;//系统复位后,从这开始执行<br />&nbsp;&nbsp;&nbsp;&nbsp;。。。。。。<br />&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;r0,=HandleIRQ&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;r1,=IsrIRQ&nbsp;//将IRQ中断处理程序IsrIRQ入口地址保存在向量表HandleIRQ位置<br />&nbsp;&nbsp;&nbsp;&nbsp;str&nbsp;&nbsp;&nbsp;&nbsp;r1,[r0]<br />&nbsp;&nbsp;&nbsp;&nbsp;。。。。。。<br />pISR_TIMER0&nbsp;=&nbsp;(int)Timer0Done;//该语句为C语言,在应用程序中初始化<br />//将定时器0的中断处理程序地址保存在向量表该中断源位置<br />2.&nbsp;&nbsp;&nbsp;&nbsp;中断响应过程<br />当产生timer0中断请求时,PC指向IRQ中断入口(地址:0x00000018)处,执行跳转指令(b&nbsp;&nbsp;&nbsp;&nbsp;HandlerIRQ)到宏定义(HandlerIRQ&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HANDLER&nbsp;HandleIRQ)处,即相当于如下程序:<br />HandlerLabel<br />&nbsp;&nbsp;&nbsp;&nbsp;sub&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sp,sp,#4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;stmfd&nbsp;&nbsp;&nbsp;&nbsp;sp!,{r0}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r0,=HandleIRQ<br />&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r0,[r0]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;str&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r0,[sp,#4]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;ldmfd&nbsp;&nbsp;&nbsp;&nbsp;sp!,{r0,pc}<br />执行这段程序后,PC将指向存放在中断向量表HandleIRQ处的IsrIRQ程序,如下:<br />IsrIRQ&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;sub&nbsp;&nbsp;&nbsp;&nbsp;sp,sp,#4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;reserved&nbsp;for&nbsp;PC<br />&nbsp;&nbsp;&nbsp;&nbsp;stmfd&nbsp;&nbsp;&nbsp;&nbsp;sp!,{r8-r9}&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;r9,=INTOFFSET&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;r9,[r9]<br />&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;r8,=HandleEINT0<br />&nbsp;&nbsp;&nbsp;&nbsp;add&nbsp;&nbsp;&nbsp;&nbsp;r8,r8,r9,lsl&nbsp;#2<br />&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;r8,[r8]<br />&nbsp;&nbsp;&nbsp;&nbsp;str&nbsp;&nbsp;&nbsp;&nbsp;r8,[sp,#8]<br />&nbsp;&nbsp;&nbsp;&nbsp;ldmfd&nbsp;&nbsp;&nbsp;&nbsp;sp!,{r8-r9,pc}&nbsp;<br />上述的INTOFFSET为中断偏移寄存器,该值保存了请求挂起的中断源的偏移值(每个中断源都对应一个唯一值,参考S3C2410&nbsp;datasheet的P14-16页表格,如timer0的偏移值为10),指示是哪个中断源产生请求处理,例如timer0产生中断请求,则该值就为10。由于EINT0的偏移值为0,而中断向量表是根据偏移值排列的,故上述的程序将向量表的HandlerEINT0再加上INTOFFSET值,查表得到pISR_TIMER0位置处的timer0中断处理程序Timer0Done的地址,所以执行这段程序后PC指向了Timer0Done,也就是用户最终的中断处理程序。<br />二.&nbsp;&nbsp;&nbsp;&nbsp;ColdFire中断分析(以MCF52235的EPORT0的IRQ4为例)<br />1.&nbsp;&nbsp;&nbsp;&nbsp;中断向量表初始化<br />1&gt&nbsp;&nbsp;&nbsp;&nbsp;中断函数定义<br />__interrupt__&nbsp;void<br />irq4_handler(void)<br />{<br />。。。。。。<br />}<br />2&gt&nbsp;&nbsp;&nbsp;&nbsp;向量表定义<br />/*<br />&nbsp;*&nbsp;Exception&nbsp;Vector&nbsp;Table<br />&nbsp;*/<br />VECTOR_TABLE:<br />_VECTOR_TABLE:<br />INITSP:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.long&nbsp;&nbsp;&nbsp;&nbsp;___SP_INIT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Initial&nbsp;SP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />INITPC:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.long&nbsp;&nbsp;&nbsp;&nbsp;0x00000400&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Initial&nbsp;PC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />vector02:&nbsp;&nbsp;&nbsp;&nbsp;.long&nbsp;&nbsp;&nbsp;&nbsp;_asm_exception_handler&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Access&nbsp;Error&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />。。。。。。<br />vector44:&nbsp;&nbsp;&nbsp;&nbsp;.long&nbsp;&nbsp;&nbsp;&nbsp;_irq4_handler&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//64+4(IRQ4的中断源号)=0x44<br />。。。。。。<br />vectorFF:&nbsp;&nbsp;&nbsp;&nbsp;.long&nbsp;&nbsp;&nbsp;&nbsp;_irq_handler<br />3&gt&nbsp;&nbsp;&nbsp;&nbsp;系统启动时的对中断向量表的初始化<br />&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Copy&nbsp;the&nbsp;vector&nbsp;table&nbsp;to&nbsp;RAM&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(__VECTOR_RAM&nbsp;!=&nbsp;VECTOR_TABLE)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(n&nbsp;=&nbsp;0;&nbsp;n&nbsp;&lt&nbsp;256;&nbsp;n++)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__VECTOR_RAM[n]&nbsp;=&nbsp;VECTOR_TABLE[n];<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;mcf5xxx_wr_vbr((uint32)__VECTOR_RAM);//将向量表地址写入内核向量寄存器<br /><br />2.&nbsp;&nbsp;&nbsp;&nbsp;中断响应过程<br />当IRQ4中断源产生中断时,PC将直接指向中断向量表的IRQ4处的服务程序地址:irq_handler。注:由于接触ColdFire也不是很久,所以不一定正确,还请熟悉ColdFire的朋友指证。不过我在单步仿真的情况下,触发IRQ4时,观察PC值确时是如此的。<br />三.&nbsp;&nbsp;&nbsp;&nbsp;总结<br />由上述分析,ColdFire处理器很像8位单片机(如:51系列等)那样,一个中断源占用一个中断入口,只是该中断入口是跟随内核的VBR值的不同,而可以不同。当产生某个中断源请求时,PC直接指向该中断源的处理程序。相比之下,ARM的中断响应处理要复杂些,无论是哪个中断源请求,都必须先进入IRQ(假设中断源被设成IRQ模式)的中断入口,再根据具体中断源的偏移寄存器INTOFFSET值,找到最终中断源的处理程序。<br />
 楼主| 阿南 发表于 2007-10-22 20:36 | 显示全部楼层

有没有兄弟要一起学MOTO单片机的?

欢迎访问:
LPcfANS 发表于 2007-10-24 10:55 | 显示全部楼层

明年开始....

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

本版积分规则

5786

主题

10224

帖子

463

粉丝
快速回复 在线客服 返回列表 返回顶部