您的位置 首页 电子

根据单片机2440test中断向量处理计划

基于单片机2440test中断向量处理方案-这里不用中断(interrupt)而用异常(exception),毕竟中断只是异常的一种情况,呵呵

下面主要分析的是“中断异常”说白了,就是我们平时单片机里面用的中断!!!所有有器件

引起的中断,例如TIMER中断,UART中断,外部中断等等,都有一个统一的入口,那就是中断

异常 IRQ ! 然后从IRQ的服务函数里面分辨出,当前究竟是什么中断,再跳转到相应的中断

服务程序。

这个 2440test里边的中止写的向量有些荫蔽,兜了很多个圈,也难怪这么难了解,下面

就对这个东西抽丝剥茧,看清楚这终究是一个怎样样的进程。

中止向量

bHandlerIRQ;handler for IRQ interrupt

很天然,由于一切的单片机都是那样,中止向量一般放在最初,用过单片机的人都会很熟悉

那就不多说了。

反常服务程序

这儿不必中止(interrupt)而用反常(excepTIon),终究中止仅仅反常的一种状况,呵呵

下面首要剖析的是“中止反常”说白了,便是咱们平常单片机里边用的中止!!!一切有器材

引起的中止,例如TIMER中止,UART中止,外部中止等等,都有一个一致的进口,那便是中止

反常 IRQ ! 然后从IRQ的服务函数里边分辨出,当时终究是什么中止,再跳转到相应的中止

服务程序。这样看来,ARM比单片机要杂乱一些了,不过原理是不变的。

上面说的便是思路,跟着这个思路来接着剖析。

HandlerIRQ 很明显是一个标号,咱们找到了

HandlerIRQ HANDLER HandleIRQ

这儿是一个宏界说,咱们再找到这个宏,看他是怎样界说的:

MACRO

$HandlerLabel HANDLER $HandleLabel

$HandlerLabel

subsp,sp,#4;decrement sp(to store jump address)

stmfdsp!,{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

subsp,sp,#4;decrement sp(to store jump address)

stmfdsp!,{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

ldrr0,=HandleIRQ ;This routine is needed

ldrr1,=IsrIRQ;if there is not ‘subs pc,lr,#4’ at 0x18, 0x1c

strr1,[r0]

说白了便是将 IsrIRQ 的地址填到 HandleIRQ对应的地址里边,前面说了 HandleIRQ 放的是中止处理的

函数的进口地址,咱们持续找 IsrIRQ

IsrIRQ

subsp,sp,#4 ;reserved for PC

stmfdsp!,{r8-r9}

ldrr9,=INTOFFSET

ldrr9,[r9];读入中止偏移码

ldrr8,=HandleEINT0;二级跳转表的首地址

addr8,r8,r9,lsl #2;R8=R8+R9X4得到相应的中止进口地址

ldrr8,[r8]

strr8,[sp,#8];中止进口地址送进SP(第一个代码留出的4字节空间)

ldmfdsp!,{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 里边里边要履行那条指令

ldrr8,=HandleEINT0

addr8,r8,r9,lsl #2

道理很简单, HandleEINT0 便是一切IRQ中止向量表的进口,在这个地址上面,加上一个恰当的偏移量,

INTOFFSET ,那么咱们知道现在,到底是哪个IRQ在请求中止了。

至于详细怎样跳转的?

首要,咱们说了,HandleEINT0 开端的一段内存里边,寄存的便是中止服务函数的函数指针,ARM的系统

的话,每个指针变量便是占4个字节,这儿就解说了,为什么这儿为每个标号分配了4个字节的空间,里边

放的便是函数指针!!!下面再看看怎样跳转,持续看 IsrIRQ 里边就完结了跳转了

strr8,[sp,#8]

ldmfdsp!,{r8-r9,pc}

其实最中心便是这两句了,先查找到当时中止服务程序的地址,将他放到 R8 里边,然后出栈,弹出给PC

那么PC很天然就跳到中止服务程序了。至于这儿的仓库问题又是一个十分扎手的,需求好好的参透ARM的

中止架构,需求了解的能够自己细心的阅览 《ARM系统结构与编程》里边说的很详细。咱们这儿的要点

是研讨怎样跳转。

最终,咱们看看在C代码中是怎样装置终端向量的,例如看 按键的外部中止,是怎样详细设置的,参看

/src/keyscan.c 里边的代码

很简单,里边只要3个函数

KeyScan_Test 是按键测验的主函数

Key_ISR 是按键中止服务函数

在 KeyScan_Test里边,咱们发现了有这么一句

pISR_EINT0 = pISR_EINT2 = pISR_EINT8_23 = (U32)Key_ISR;

能够了解否? Key_ISR便是上面说到的按键中止服务函数,函数的姓名,代表的便是函数的地址!!!!

将中止服务函数的地址,留意了,是地址,这是一个 U32型的变量。送到几个变量,咱们以pISR_EINT0

作为比如,检查头文件界说,在 2440addr.h 里边找到

// Interrupt vector

#define pISR_EINT0(*(unsigned *)(_ISR_STARTADDRESS+0x20))

_ISR_STARTADDRESS有没有似曾相识的感觉?没错,方才剖析的汇编代码里边就说到了

^ _ISR_STARTADDRESS; _ISR_STARTADDRESS=0x33FF_FF00

HandleReset # 4

HandleUndef # 4

。..。..

对,地址便是这儿,然后 _ISR_STARTADDRESS+0x20 便是越过前面的反常向量,进入IRQ中止向量的进口

所以说到尾

pISR_EINT0 = (U32)Key_ISR;

完结的操作便是,将 Key_ISR 的地址寄存到

HandleEINT0# 4

这个IRQ向量表里边!!!!

当按键中止产生的时分,产生IRQ反常中止

当时PC值-4 保存到LR_IRQ里边,然后履行

bHandlerIRQ

然后是履行

HandlerIRQ

sub

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qiche/dianzi/347121.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部