打印

ARM系统编程

[复制链接]
楼主: xinzha
手机看帖
扫描二维码
随时随地手机跟帖
61
zh5202| | 2012-11-1 11:43 | 只看该作者 回帖奖励 |倒序浏览
强烈感谢楼主,**多写点,新人们期待中

使用特权

评论回复
62
freeny| | 2012-11-2 10:12 | 只看该作者
好东西,得支持~~

使用特权

评论回复
63
xinzha|  楼主 | 2012-11-4 22:21 | 只看该作者
之后几天一直在于GCC做斗争,以后可能要长期使用这种编译器了,所以即使我再不喜欢它,也要开始了解了。
GCC对MIPS的编译做了一些特殊的处理,有一些专门为MIPS的编译选项,这在GNU的官方网站上都可以查得到,我在这里简单说明一下,虽然不是ARM,但是日后会和ARM做比较。
在对MIPS的编译中,不能简单地使用-fpic来达到位置无关的目的,最重要的一个开关是-mabicalls(使能System V r4调用格式),使用了这个开关,并且再搭配上-mshare或者-fpic才能达到位置无关的目的,而在链接时是否使用位置无关选项并不重要,即使选择了静态链接,依然能够给出位置无关代码。
还有一点需要注意的是如果你的工程是类似于bootloader这样的汇编代码和c代码混编的工程,就一定要注意处理好汇编与c代码间调用的接口,在SVr4针对MIPS的寄存器调用规则中,t9寄存器保存当前函数的地址,这一点要切记切记。所以在汇编代码跳往c代码之前,要把t9设置好,最好用如下格式的跳转:
la t9, start
jalr t9
也一定要注意在这两句之前,要把gp寄存器的值设为你动态加载时image的首地址,la t9,start这句话会分解为几句汇编代码,利用gp寄存器的值查找GOT的位置。同时也要注意更新GOT的值,因为编译完的结果都只是相对于0地址的值,你要把这个值更新为你动态加载后的地址。这些内容不只是MIPS相关,所有系统的动态加载都会使用差不多的方法,而ARM的编译器在处理这些问题的时候还是稍微聪明点,小范围内跳转都是直接使用相对偏移跳转,不会借助于GOT,MIPS的专业编译器没有使用过。

使用特权

评论回复
64
xinzha|  楼主 | 2012-11-5 22:37 | 只看该作者
今天在公司的邮件中,几个大牛关于如何设计中断控制器有了争论,所以觉得关于中断的话题,还是有必要再多说点,毕竟这对于系统的性能和稳定性至关重要。
RISC架构中,包括ARM和MIPS,一般情况下采用的清中断机制是软件手动清理中断标志,而不是像早期CISC架构中所采用的响应中断后硬件自动清理的方法,至于CISC现在用什么机制,已经完全没有概念了。所以在写ARM或者MIPS的中断处理程序时,一定要注意在退出中断前清理中断标志位,否则就会在退出后再马上回来,形成一个死循环。
在ARM的中断相应流程中,一旦kernel开始响应一个中断,就会自动将CPSR中的I位置位,也就是说此时不会再响应其他中断,此时没有中断嵌套一说,除非软件在ISR中主动将I位清零,但是由于ARM多种模式机制的一个问题,在某种极限情况下会导致简单嵌套处理无**常工作,如果想实现嵌套需要写很多额外的处理代码。请注意,这里的ARM不包括M系列,完全不一样的机制。
ARM公司提供了VIC模块,就是vectored interrupt controller,向量中断控制器,一定程度上实现了中断优先级处理。其机制是每种中断初始化的时候会将自己这个中断的ISR地址通知VIC模块,当有中断产生时,VIC模块会取此时有中断产生的最高优先级中断的ISR地址填到一个寄存器中,在异常级别的中断处理只需要简单的一句话LDR PC, #Vector_ISR,直接将这个寄存器的内容写入到pc就实现了ISR的调用,既实现了优先级管理又加快了中断响应速度。但是要注意,即使实现了VIC,如果不做特殊处理,依然没有中断嵌套,也就是当你响应中断时,即使有更高优先级中断进来,也要等你的ISR执行完再说。
ARM核心中断响应的伪代码大致如下,这是我从软件人员的角度总结的,真正的ic设计是并行的,在判断中断状态时是把所有中断线或在一起连接到异常级别的中断线:
if(I bit in cleared)
{
    if(0 != interrupt status)
    {
        assert interrupt line to invoke exception.
    }
}
至于中断采取沿中断还是电平中断跟软件人员关系不大,一般情况下硬件人员更喜欢采用电平方式,因为电平方式就不存在中断采不到的问题了。

使用特权

评论回复
65
188585901| | 2012-11-6 07:39 | 只看该作者
刘明,我来看你了。

使用特权

评论回复
66
xinzha|  楼主 | 2012-11-6 23:37 | 只看该作者
在RISC体系中,进入中断后的现场保护一般是由软件来完成的,如果是C代码,编译器就会替你决定将哪些寄存器入栈,而如果你的中断处理函数是汇编级别的,那就要处理哪些寄存器需要保护了,而且由于中断的执行非常频繁,你要是把所有寄存器都入栈将会是一个比较大的开销,正好合适是最好的。有人可能要说,不管入栈多少个寄存器,我只需要一条stm就行了,很快的,这只是个错觉,stm指令的执行还是一个个内存单元的写操作,入栈多少个寄存器,总线上就会有多少个针对内存单元的写操作(对于DRAM搭建的系统来说,这可是很慢的),当然stm有可能是burst写,比你多条指令写还是快一点的。
cpu在响应中断时,会将中断产生时的PC写入终端模式下的lr寄存器,并由硬件自动将cpsr中的中断使能关闭,寄存器组切换到中断模式,寄存器组的切换中最重要的是sp的切换,在某种模式下就会使用当前模式的栈指针,所以要在bootloader或者bsp中初始化所有必要的模式的sp寄存器。
下面讲解一些为什么arm实现中断嵌套会比较麻烦,我们首先描述一下一般情况下其他架构怎么做。
1、中断产生,ISR开始服务中断
2、此时有更高级别中断产生,将当前ISR必要信息入栈,响应更高级别中断
3、高优先级中断处理完毕,将低优先级中断信息恢复,继续处理低优先级中断。
而由于arm架构的特殊问题,导致在某种极端情况下,这种处理方式会出现致命错误,请看如下描述:
1、中断int0产生,ISR0开始服务中断
2、修改crpsr,使能中断,使之可以中断嵌套
3、ISR0运行到某处进行一个函数调用func0,由于此时在中断模式下,所以在函数调用的时候会将函数调用的返回值填入到中断模式下的lr寄存器。
4、在执行bl或者blx的瞬间,另外一个中断int1产生,此时int1中断会等待bl或者blx执行完毕,也就是被调用函数连一句都没有被执行到时就抢走cpu,进入ISR1,而此时硬件会自从将lr值修改为子函数中的地址。
5、于是问题产生了,ISR0中调用func0的返回地址lr在保存之前就被中断isr1给覆盖了,这导致func0中记录下来的lr是个错误的地址,程序因此也就会乱套。

这从根本上来说是arm在设计时的一个瑕疵,mips用了一个非常聪明的设计解决了这个问题,而arm不知道出于什么原因这么多年来始终没有修改这个问题,而只是用一种比较繁琐的方式去规避这个问题,明天继续讲mips的解决手段和arm的规避方法。

使用特权

评论回复
67
xinzha|  楼主 | 2012-11-7 22:55 | 只看该作者
在MIPS中,对于这个问题的处理实际上非常简单,就是如果异常发生在跳转指令执行的时候,那么在处理完异常返回之后会重新执行一遍这个跳转指令,也就是说如果异常发生在跳转指令上,那么跳转指令就被抛弃了,看似效率低,而正是由于这个简单的重新执行,避免了寄存器被复写的问题。为什么这种设计就会防止上面那种问题的发生呢?我们可以模拟一下这个流程:
1、中断int0产生,ISR0开始服务中断
2、ISR中使能中断,使之可以中断嵌套
3、ISR0运行到某处进行一个函数调用func0,对于arm来说,由于此时在中断模式下,所以在函数调用的时候会将函数调用的返回值填入到中断模式下的lr寄存器。而对于mips来说,没有模式一说,都是使用通用寄存器,所以会将返回地址填入ra。
4、在执行bl或者blx的瞬间,另外一个中断int1产生,此时int1中断会等待跳转指令执行完毕,也就是被调用函数连一句都没有被执行到时就抢走cpu,进入ISR1,而此时硬件会自动将lr值修改为ISR0中跳转语句+8的位置。对于MIPS来说就是将ra值修改。
5、对于ARM来说,ISR0中调用func0的返回地址lr在保存之前就被中断isr1给覆盖了,程序因此也就会乱套。而对于MIPS来说则完全没有问题,因为架构保证在跳转语句执行时发生异常的话,跳转语句就还要被执行一遍,从根本上消除了这个问题。

ARM对这个问题的一种规避方法如下流程:
1. 中断响应进入ISR0
2. 在ISR0切换到SYS模式,然后再使能中断
3. 在SYS模式下执行相应处理
4. 关闭中断,回到中断模式,退出中断,恢复现场
这样的话,即使发生了嵌套,也只能当ISR0执行在SYS模式下时嵌套,由于此时ISR0使用的是SYS模式下的lr寄存器,而响应INT1时cpu自动更新的是INT模式的lr寄存器,不会导致lr寄存器内容的混乱。这个地方相当绕,如果有疑问可以提出来讨论,我所讲述的也只是我自己的理解。

使用特权

评论回复
68
xiangchli| | 2012-11-9 13:42 | 只看该作者
cool

使用特权

评论回复
69
1189594| | 2012-11-16 10:21 | 只看该作者
MARK

使用特权

评论回复
70
YJH眼睛| | 2012-11-16 11:13 | 只看该作者
非常好,还没接触ARM哦。。

使用特权

评论回复
71
hbicecream| | 2012-11-16 11:52 | 只看该作者
ARM中断保护大多数是汇编写的,而且会由中断状态切换到正常状态,处理handle函数,然后在回到中断状态,再恢复现场之后退出

使用特权

评论回复
72
inurl| | 2012-12-7 13:01 | 只看该作者
xinzha 发表于 2012-11-5 22:37
今天在公司的邮件中,几个大牛关于如何设计中断控制器有了争论,所以觉得关于中断的话题,还是有必要再多说 ...

感脚你说的功能, 编译器和IDE已经将它处理了 ,提供了适合人类操作的使用方式了

使用特权

评论回复
73
inurl| | 2012-12-7 13:05 | 只看该作者
xinzha 发表于 2012-11-6 23:37
在RISC体系中,进入中断后的现场保护一般是由软件来完成的,如果是C代码,编译器就会替你决定将哪些寄存器 ...

你说的保存lr功能,修改CPSR的I位,应该是软件控制的吧?由IRQ_HANDLER汇编实现的 ?
  好像和ARM MIPS架构没什么关系吧?

使用特权

评论回复
74
refee| | 2012-12-8 16:21 | 只看该作者
楼主V5 顶起来 :victory:

使用特权

评论回复
75
sing0126| | 2012-12-9 01:02 | 只看该作者
ding

使用特权

评论回复
76
yfyuan2008| | 2012-12-10 22:06 | 只看该作者
v5,顶了,学习

使用特权

评论回复
77
bd7qwmcu| | 2012-12-12 10:21 | 只看该作者
顶楼主,,谢谢

使用特权

评论回复
78
不能不吹| | 2012-12-15 16:15 | 只看该作者
观摩

使用特权

评论回复
79
ai1314小林| | 2012-12-16 18:18 | 只看该作者
时刻关注LZ的更新······顶······

使用特权

评论回复
80
mingyanren| | 2013-1-9 19:52 | 只看该作者
大牛

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则