中断原理.docx
- 文档编号:30585723
- 上传时间:2023-08-18
- 格式:DOCX
- 页数:17
- 大小:695.69KB
中断原理.docx
《中断原理.docx》由会员分享,可在线阅读,更多相关《中断原理.docx(17页珍藏版)》请在冰豆网上搜索。
中断原理
ARM的中断发生时、pc指针跳转到相应的中断服务程序。
复位中断时、pc自动跳转到了服务程序。
但是IRQ中断过程中、pc指针的跳转经历了1次硬件自动跳转、3次软件跳转。
这里主要的内容是跟踪IRQ中断过程中pc的跳转。
当有中断源发出中断请求之后、该中断源的请求信息会被记录到源挂起寄存器SRCPEND寄存器。
当然、可能不止一个中断请求,只能先执行优先级最高的中断,也就是需要选出其中优先级最高的中断。
被记录的中断们经过仲裁器裁决(按照约定的仲裁规则),筛选出优先级最高的中断,他将被记录到中断挂起寄存器INTPND和偏移量寄存器INTOFFSET,这是即将被执行的中断。
此时、内核中的中断模块硬件会自动根据该中断的类型使pc跳转到一个与该中断对应的空间,从这个空间开始执行程序,这个特定空间就是该中断向量占据的空间,里面存储的是跳转到该中断服务程序的指令。
至此由硬件完成的记录、筛选和跳转过程结束、后面的由软件完成,(其中、IRQ中断包含很多个中断源、需要判别并转到响应的中断服务函数、这些由软件完成)。
中断模块预先设置了8个(种)中断,从0地址开始、即程序最开始的地方,共有32Byte空间被分配给他们,组成中断向量表,这个向量表空间的位置/地址固定不变。
但是在调试时、映像文件是放入SDRAM中,入口地址被指定为-entry0x30000000。
也就是映像文件被放入从0x30000000开始的空间、而不是0x0地址开始的空间。
调试时pc会指向入口地址、即0x3000000。
所以在有异常发生之前、必须将这些代码重映射到0地址、以恢复异常向量表。
因而在Main函数的第一条语句就是MMU_Init();:
中断向量表占据的这32B空间被分为8份,每个类型的中断占据4Byte,里面存储的是跳转到相应的中断服务程序的指令,8个向量空间内的指令为(从0地址开始依次为):
bResetHandler
bHandlerUndef
bHandlerSWI
bHandlerPabort
bHandlerDabort
b.;死循环指令(系统保留的空间)
bHandlerIRQ
bHandlerFIQ;2440init.s里面在第8个空间后面追加了第9个向量空间
发生某一中断时、pc跳转到这些空间中的某一个、从该处开始执行其中的跳转指令。
b是跳转指令、后面跟的是中断服务函数的函数名,也就是中断函数的入口地址。
比如发生FIQ中断时、pc自动跳转到第8个向量空间、执行bHandlerFIQ指令。
最常见的是复位中断:
上电时、触发ResetHandler中断、pc跳到0x0地址处(当然上电时pc本来就是指向0地址的)。
0x0地址处的指令为bResetHandler、也就是跳到复位中断服务程序ResetHandler,执行中断处理任务。
复位中断程序执行到最后、会进入Main函数执行。
同样、FIQ中断也可以这样、直接跳转到FIQ处理中断服务程序。
不过IRQ不是一个中断、是一类。
假如发生IRQ中的EINT3中断,就需要将他筛选出来,并跳转到EINT3的中断服务程序。
2440init.s中是这样实现的:
首先为IRQ的每一个中断分配一个4Byte的空间、构成一个IRQ中断向量表,类似异常向量表。
每一个4B空间中存储的不是一条跳转指令、而是相应的中断服务程序的入口地址。
这个表在2440init.s的最后、定义在DATA区:
AREARamData,DATA,READWRITE
^_ISR_STARTADDRESS;IRQ中断向量表起始地址
HandleReset#4;第1个4B空间
HandleUndef#4
HandleSWI#4
HandlePabort#4
HandleDabort#4
HandleReserved#4
HandleIRQ#4;存放IsrIRQ的入口
HandleFIQ#4
HandleEINT0#4;IRQ中断向量表的首地址是人为指定的
HandleEINT1#4
HandleEINT2#4
HandleEINT3#4
HandleEINT4_7#4
HandleEINT8_23#4
HandleCAM#4
HandleBATFLT#4
……
HandleADC#4
END
然后看在复位时执行的一小段指令:
;SetupIRQhandler
ldrr0,=HandleIRQ;HandleIRQ#4空间的地址
ldrr1,=IsrIRQ
strr1,[r0]
这里IsrIRQ是IRQ中断服务函数的入口地址、他被放入HandleIRQ,也就是IRQ的中断向量空间。
复位初始化结束后、我们追踪一下EINT3的跳转过程:
EINT3发生、并被INTPND和INTOFFSET记录、即将被执行。
pc自动跳转到8个异常向量表中的IRQ向量空间。
CPU即开始执行该空间的bHandlerIRQ指令跳转到指定为HandlerIRQ的地址空间,也就是标号为HandleIRQ处。
而HandlerIRQ处定义的是一段由宏展开后的指令:
HandlerIRQ
subsp,sp,#4;sp指针下降一个单元,sp1=sp0-4
stmfdsp!
{r0};r0的内容暂存在堆栈中,sp2=sp1-4=sp0-8,r0->[sp2],且sp=sp2
ldrr0,=HandleIRQ;注意这里是HandleIRQ、不是HandlerIRQ
ldrr0,[r0];将HandleIRQ地址处的值放入r0
strr0,[sp,#4];将HandleIRQ地址处的值放入堆栈,即将HandleIRQ中的
;内容存入SP1中,SP不变
ldmfdsp!
{r0,pc};恢复r0的内容,并将HandleIRQ的值放入pc中,先弹r0,再
;弹HandleIRQ
这段指令由宏HandlerIRQHANDLERHandleIRQ展开而得。
其功能是将HandleIRQ空间中的值放入pc中、HandleIRQ是在IRQ中断向量表中定义的一段向量空间。
而在初始化时、HandleIRQ空间中被写入了IsrIRQ函数的入口地址。
所以pc中的内容就是IrsIRQ的入口地址、从而跳转到IsrIRQ函数。
看看IsrIRQ:
IsrIRQ
subsp,sp,#4
stmfdsp!
{r8-r9}
ldrr9,=INTOFFSET;偏移量
ldrr9,[r9]
ldrr8,=HandleEINT0;ISR中断向量表的首地址
addr8,r8,r9,lsl#2;r8=r8+(r9*4)
ldrr8,[r8]
strr8,[sp,#8]
ldmfdsp!
{r8-r9,pc}
这个函数利用r8、r9完成的功能很简单、就是将IRQ中的某个中断的中断服务函数的入口地址放入pc中。
其中r8=r8+(r9*4)=IRQ向量表首地址+(偏移量*4)、这是INTOFFSET中记录的那个即将要被服务的中断的向量空间的地址、也就是EINT3所占据的向量空间。
EINT3发生、那么INTOFFSET的值是3、r8=IRQ首地址+3*4、就是IRQ向量表中EINT3中断所占据的空间的地址。
要’*4’是因为中断所占据的空间是4B大小、移动一个单元需要移动4B大小。
EINT3是第4个向量、地址是IRQ首地址(HandleEINT0)+12。
紧接着、这个中断向量空间中的值被放入r8、接着压入堆栈、再在出栈时将该值放入pc中。
这个值是中断服务函数Eint3Handler_ISR的入口地址、是我们在Main函数中写入的:
pISR_EINT3=(unsigned)Eint3Handler_ISR;
pISR_EINT3就是2440init.s中HandleEINT3,在2440addr.h中定义的:
#definepISR_EINT3(*(unsigned*)(_ISR_STARTADDRESS+0x2c))。
也就是说pc中的值就是EINT3的中断服务函数的入口地址,那么接下来就是跳转到EINT3的中断服务函数了。
最后用一个图表述这个过程:
最后解释一下8个空间:
HandleReset#4
HandleUndef#4
HandleSWI#4
HandlePabort#4
HandleDabort#4
HandleReserved#4
HandleIRQ#4
HandleFIQ#4
他们是在这个宏里面用到(上面响应IRQ时已经用到了HandleIRQ空间):
MACRO
$HandlerLabelHANDLER$HandleLabel
$HandlerLabel
subsp,sp,#4
stmfdsp!
{r0}
ldrr0,=$HandleLabel
ldrr0,[r0]
strr0,[sp,#4]
ldmfdsp!
{r0,pc}
MEND
2440init.s里面有6个中断用到了这个宏:
HandlerFIQHANDLERHandleFIQ
HandlerIRQHANDLERHandleIRQ
HandlerUndefHANDLERHandleUndef
HandlerSWIHANDLERHandleSWI
HandlerDabortHANDLERHandleDabort
HandlerPabortHANDLERHandlePabort
那什么时候调用到了这些宏呢,在这里:
ASSERT:
DEF:
ENDIAN_CHANGE
[ENDIAN_CHANGE
ASSERT:
DEF:
ENTRY_BUS_WIDTH
[ENTRY_BUS_WIDTH=32
bChangeBigEndian;DCD0xea000007
]
[ENTRY_BUS_WIDTH=16
andeqr14,r7,r0,lsl#20;DCD0x0007ea00
]
[ENTRY_BUS_WIDTH=8
streqr0,[r0,-r10,ror#1];DCD0x070000ea
]
|
bResetHandler
]
bHandlerUndef;handlerforUndefinedmode
bHandlerSWI;handlerforSWIinterrupt
bHandlerPabort;handlerforPAbort
bHandlerDabort;handlerforDAbort
b.;reserved
bHandlerIRQ;handlerforIRQinterrupt
bHandlerFIQ;handlerforFIQinterrupt
首先bResetHandler、直接跳转到ResetHandler标号处执行、这个标号没用使用到上面的宏:
;=======
;ENTRY
;=======
ResetHandler
……
8个空间中,分配给复位中断的空间HandlerReset没被使用到,他直接跳转到了中断服务函数。
HandleReserved空间也没使用。
另外6个空间在bHandlerXXX时被调用。
比如SWI中断时,pc首先自动跳转到0x08(SWI的中断向量空间)、执行bHandlerSWI。
pc跳转到HandlerSWI,HandlerSWI在这里:
HandlerSWIHANDLERHandleSWI
即(宏展开):
HandlerSWI--标号、就是函数名(函数入口)
subsp,sp,#4
stmfdsp!
{r0}
ldrr0,=HandleSWI
ldrr0,[r0]
strr0,[sp,#4]
ldmfdsp!
{r0,pc}
这里将HandleSWI空间中的内容放在了pc里面、那么HandleSWI空间里面当然就要存放SWI中断服务程序的地址了。
如此、pc就跳转到SWI的中断服务程序。
也就是说、这6个空间里面防止相应的中断服务程序的入口地址。
同样、响应FIQ时、将他的中断服务程序的地址放进HandleFIQ即可。
这里经历了一次硬件跳转和2次软件跳转、跳转之后做什么就要看之后执行的中断服务程序了:
进入异常时:
1、保存pc的值到lr(含偏移量、与指令状态和工作状态有关)
2、保存cpsr的值到spsr
3、改变cpsr的值以变更到需要的处理器工作模式
4、改变pc的值(为异常/中断向量表的地址)、以跳转到ISR
退出异常时:
1、从spsr恢复cpsr的值
2、清除中断标志
3、恢复pc(含偏移量)
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 中断 原理