这个 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
华为旗舰新机成明“星”,这一通信技术“闪”耀A股
大温差TEC模块 TEC制冷片 半导体制冷片
ADI推出适合3G和4G移动终端使用的功率管理器件
TDK推屏蔽型SMT功率电感器 博通展示100G/通道光学PAM-4 DSP PHY
通过大脑植入芯片 恢复盲人的视力将有可能成为现实
基于单片机2440test中断向量处理方案
不同继电器开关电路
LiMPO4基础教材
商业航天发展进入快车道 技术创新赋能卫星测试
宽带自组网电台的多普勒频偏估计及补偿能力
AIOps工具在IT领域具有广阔的应用前景
IR为混合动力汽车和电动车推出600V车用IGBT
人工智能算法分析数据 可以更好地预测玉米产量
IPhone13最新配置和价格曝光
什么是热气流式MEMS加速度传感器
传感器在健康可穿戴设备中的发展趋势
宁夏联通Cloud VR完成上线,带给用户沉浸式体验
科创板首批过会名单出炉 为何半导体材料企业安集科技能入选?
什么是磷酸铁锂电池?
日常生活中-使用电池应注意的事项