一向在看2440的中止处理部分,不明白的真实太多了,百度到这篇文章,真实有听君一席话,胜养十年猪的感觉啊,下面上文章:
中止向量
b HandlerIRQ ;handler for IRQ interrupt
很天然,由于一切的单片机都是那样,中止向量一般放在最初,用过单片机的人都会很熟悉,那就不多说了。
反常服务程序
这儿不必中止(interrupt)而用反常(exception),终究中止仅仅反常的一种状况,
下面首要剖析的是“中止反常”说白了,便是咱们平常单片机里边用的中止!!!一切由器材引起的中止,例如TIMER中止,UART中止,外部中止等等,都有一个一致的进口,那便是中止反常 IRQ ! 然后从IRQ的服务函数里边分辨出,当时终究是什么中止,再跳转到相应的中止服务程序。这样看来,ARM比单片机要杂乱一些了,不过原理是不变的。
上面说的便是思路,跟着这个思路来接着剖析。
HandlerIRQ 很明显是一个标号,咱们找到了
HandlerIRQ HANDLER HandleIRQ
这儿是一个宏界说,咱们再找到这个宏,看他是怎样界说的:
MACRO
$HandlerLabel HANDLER $HandleLabel
$HandlerLabel
sub sp,sp,#4 ;decrement sp(to store jump address)
stmfd sp!,{r0} ;PUSH the work register to stack(lr does not push because it return to original
address)
ldr r0,=$HandleLabel ;load the address of HandleXXX to r0
ldr r0,[r0] ;load the contents(service routine start address) of HandleXXX
str r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stack
ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR)
MEND
用 HandlerIRQ 将这个宏打开之后得到的成果实践是这样的
HandlerIRQ
sub sp,sp,#4 ;decrement sp(to store jump address)
stmfd sp!,{r0} ;PUSH the work register to stack(lr does not push because it return to original
address)
ldr r0,=HandleIRQ ;load the address of HandleXXX to r0
ldr r0,[r0] ;load the contents(service routine start address) of HandleXXX
str r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stack
ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR)
至于详细的跳转原理下面再说,
好了,这样的话就简单看的多了,很明显, HandlerIRQ 仍是一个标号,IRQ反常向量便是跳转到这儿履行的,这儿大略看一下,应该是保存现场,然后跳转到真实的处理函数,那么很简单发现了这么一句 ldr r0,=HandleIRQ ,没错,咱们又找到了一个标号 HandleIRQ ,看来真实的处理函数应该是这个 HandleIRQ ,持续寻觅
AREA RamData, DATA, READWRITE
^ _ISR_STARTADDRESS ; _ISR_STARTADDRESS=0x33FF_FF00
HandleReset # 4
HandleUndef # 4
HandleSWI # 4
HandlePabort # 4
HandleDabort # 4
HandleReserved # 4
HandleIRQ # 4
最终咱们发现在这儿找到了 HandleIRQ ,^ 其实便是 MAP ,这段程序的意思是,从 _ISR_STARTADDRESS 开端,预留一个变量,每个变量一个标号,预留的空间为 4个字节,也便是 32BIT,其实这儿放的是真实的C写的处理函数的地址,说白了,便是函数指针 – – 这样做的话就很灵活了
接着,咱们需求装置IRQ处理句柄,说白了,便是设置处理函数的地址,让PC指针能够正确的跳转。
所以咱们在接着的找到装置句柄的句子
; Setup IRQ handler
ldr r0,=HandleIRQ ;This routine is needed
ldr r1,=IsrIRQ ;if there is not subs pc,lr,#4 at 0x18, 0x1c
str r1,[r0]
说白了便是将 IsrIRQ 的地址填到 HandleIRQ对应的地址里边,前面说了 HandleIRQ 放的是中止处理的函数的进口地址,咱们持续找 IsrIRQ
IsrIRQ
sub sp,sp,#4 ;reserved for PC
stmfd sp!,{r8-r9}
ldr r9,=INTOFFSET
ldr r9,[r9]
ldr r8,=HandleEINT0
add r8,r8,r9,lsl #2
ldr r8,[r8]
str r8,[sp,#8]
ldmfd sp!,{r8-r9,pc}
要了解这个代码,得先学学2440的中止体系了,INTOFFSET寄存的是当时中止的偏移号,依据偏移就知道当时是哪个中止源产生的中止。
留意了,咱们说的是中止,而不是反常,看看本来的表是啥样子的
^ _ISR_STARTADDRESS ; _ISR_STARTADDRESS=0x33FF_FF00
HandleReset # 4
HandleUndef # 4
HandleSWI # 4
HandlePabort # 4
HandleDabort # 4
HandleReserved # 4
HandleIRQ # 4
HandleFIQ # 4
HandleEINT0 # 4
HandleEINT1 # 4
HandleEINT2 # 4
HandleEINT3 # 4
…….
能够看到,前面几个是反常,从 HandleEINT0 便是 IRQ反常的向量寄存的当地了,这样就能够了解为什么上面 IsrIRQ 里边里边要履行那条指令
ldr r8,=HandleEINT0
add r8,r8,r9,lsl #2
道理很简单, HandleEINT0 便是一切IRQ中止向量表的进口,在这个地址上面,加上一个恰当的偏移量,INTOFFSET ,那么咱们知道现在,到底是哪个IRQ在请求中止了。
声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/news/guandian/254691.html