Chinaunix首页 | 论坛 | 博客
  • 博客访问: 866153
  • 博文数量: 190
  • 博客积分: 7021
  • 博客等级: 少将
  • 技术积分: 1752
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-17 19:26
文章分类

全部博文(190)

文章存档

2014年(9)

2011年(32)

2010年(149)

我的朋友

分类: 嵌入式

2010-05-19 17:30:23

    接触ARM,嵌入式也有1年多的时间,期间因为各种原因有一些断断续续,但是从未放弃。今天就来对ARM处理器进行一下总结,可能会比较乱,知识的跳跃也会比较大,但都是我根据自己的总结,有的是我以前记载在笔记本上的,有的则是我写在google notebook里面的东西。因为水平有限,可能还有会错误,欢迎指正!

计算机体系结构:
冯.诺依曼体系结构:我们将数据和指令都存储在一个存储器中的计算机称为冯.诺依曼机
哈佛体系结构:为数据和程序提供了各自独立的存储器,程序计数器只指向程序存储器而不指向数据存储器
而ARM7使用的是冯.诺依曼体系结构,ARM9使用的是哈佛体系结构

ARM的数据总线:
总线:用于在其间不同部件之间进行通讯
AHB:连接高性能的片内外设接口
APB:连接较慢的片内外设接口连接
第三种总线用于连接片内外外设,这条外部总线需要一个特殊的桥,用于和AHB总线

流水线技术:
在ARM处理器中使用了流水线技术,3级的ARM7,5级的ARM9,还有更新的就是7级流水线的,在ARM体系中采用了相对简单的流水线技术,这样就简化了芯片结构。在这里我只是提到了流水线技术,真正要讲流水线我的水平还不够,如果有兴趣的可以去看看《深入理解计算机系统》那本经典教材,特别推荐,对计算机系统的硬件的理解和软件的编写都有很好的提升作用,一个特别好的朋友推荐给我的,在这里感谢(orangeprince),是一头大牛!

ARM处理器工作模式和工作状态,寄存器
我们结合CPSR程序状态寄存器。最后5位绝对了处理器的工作模式M[4:0]
1,用户模式(usr)[10000]:ARM处理器正常的程序执行状态
2,快速中断模式(fiq)[10001]:用于高速数据传输或通道处理
3,外部中断模式(irq)[10010]:用于通用的中断处理
4,管理模式(svc)[10011]:操作系统使用的保护模式
5,中止模式(abt)[10111]:当数据或指令预取终止时进入该模式,用于虚拟存储及存储保护
6,未定义指令模式(und)[11011]:当未定义的指令执行时进入该模式,用于支持硬件协处理器的软件仿真
7,系统模式(sys)[11111]:运行具有特权模式的操作系统任务

ARM的工作状态有两种:32位的ARM状态,16位的Thum状态

ARM微处理器共有37个32位寄存器,其中31个位通用寄存器,6个为状态寄存器
寄存器R13在ARM指令中常用作堆栈指针,由于处理器的每种工作模式都有自己的R13,在用户应用程序额的初始化部分,一般都要初始化每种模式下的R13

R14也称作子程序连接寄存器或连接寄存器LR,当执行BL子程序调用指令时,R14中得到R15(程序计数器PC)的备份

CPSR的低八位称为控制位,(I,F,T和M[4:0])
(1)中断禁止位
中断禁止位包括I,F,用来禁止或允许IRQ, FIQ两类中断,等于1时表示禁止,等于0是表示允许中断
(2)T标识位
T标志用来标识/设置处理器的工作状态,1表示为Thumb状态,0表示ARM状态
(3)M[4:0]
参考上面的说明

ARM存储简介:
存储格式:
1,大端格式:字数据的高字节存储在低地址中,而子数据的低字节则存储在高地址中。
2,小端格式:低地址存放的是字数据的低字节,高地址存放的是字数据的高字节。

ARM微处理器的指令长度可以是32位的(ARM状态下),也可以是16位的(Thumb状态下)
ARM微处理器中支持字节(8位),半字(16位),字(32位)3中数据类型。其中字需要4字节对其(地址的低两位为0),半字需要2字节对齐(地址的最低位为0)

ARM指令
多寄存器寻址:
LDMIA R0!,{R1-R4}              ;R1<----[R0]
                               ;R2<----[R0+4]
                               ;R3<----[R0+8]
                               ;R4<----[R0+12]             

堆栈寻址:
STMFD入栈指令,相当于STMDB
STMFD SP!,{R2-R4}                            ;[SP-4]<---R4
                                             ;[SP-8]<---R3 
                                             ;[SP-12]<---R2   

LDMFD出栈指令,相当于LDMIA
LDMFD SP!,{R6-R8}                ;R6<----[SP]
                                 ;R7<----[SP+4]
                                 ;R8<----[SP+8]
                                   
 LDMIA / STMIA Increment After(先操作,后增加)
 LDMIB / STMIB Increment Before(先增加,后操作)
 LDMDA / STMDA Decrement After (先操作,后递减)
 LDMDB / STMDB Decrement Before(先递减,后操作)

STMFD (Push) 块存储Full Descending stack [STMDB]
LDMFD (Pop) 块装载Full Descending stack [LDMIA]
                                   
算术运算:
ADD
ADC
SUB
带借位的减法:SBC  R0,R1,R2            ;R0=R1-R2-!C
逆向减法指令:RSB  R0,R1,R2            ;R0=R2-R1
带借位的逆向减法指令:RSC  R0,R1,R2            ;R0=R2-R1-!C

逻辑运算指令:
AND:可以用来清零相应的位
ORR:可以用来置位相应的位
EOR:可以用来反转操作数1的某些位
BIC:可以用来清除相应的位
                            
比较指令:
CMP:比较指令,该指令实际上是进行一次减法运算,但不存储结果,只更改条件标识
CMN:反值比较指令,该指令实际上是将操作数Rn和操作说oprand相加,然后更改条件标识
TST:位测试指令(TST指令用于把一个寄存器Rn的内容和另一个操作数operand2按位                                  进行与运算,并根据运算结果更新CPSR中条件标志位的值)
TEQ:相等测试指令(TEQ指令用于把一个寄存器Rn的内容和另一个操作数operand2按                                      位进行异或运算,并根据运算结果更新CPSR中条件标志位的值。
                                    该指令通常用于比较操作数Rn和操作数Operand2是否相等

乘法指令:
MUL:32位乘法指令
MLA:32位乘加指令
SMULL:64位有符号数乘法指令    SMULL R0,R1,R2,R3        
                ;R0=(R2*R3)的低32位
                ;R1=(R2*R3)的高32位                             
SMLAL:64位有符号数乘加指令    SMLAL R0,R1,R2,R3        
                ;R0=(R2*R3)的低32位+R0
                ;R1=(R2*R3)的高32位+R1
UMULL:64位无符号数乘法指令
UMLAL:64位无符号数乘加指令

交换指令:
SWP:字数据交换指令
SWPB:字节数据交换指令
SWP R0,R1,[R2]         
;将R2所指向的存储器中的字数据加载到R0,同时将R1中的子数据存储到R2所指向的存储单元
SWPB R0,R1,[R2]     
;将R2所指向的存储器中的字节数据加载到R0中,R0的高24位清零,同时将R1的低8位数据存储到R2所指向的存储单元
当R0和R1为一个寄存器时(R1=R0),则可以互换R0与R2中的数据

分支指令:
B:分支指令
BL:带返回的分支指令,在跳转之前将PC的当前内容复制到R14(LR)中保存
BX:带状态切换的分支指令,BX Rm;Rm时一个表达目标地址的寄存器,当Rm中的最低位Rm【0】为1时,强制程序从ARM指令状态跳到Thumb指令状态。反之亦然。
BLX:带返回和状态切换的分支指令

程序状态寄存器访问指令
MRS Rd,psr     ;读状态寄存器的指令,Rd<----psr
MSR psr,Rd     ;写状态寄存器指令,psr<----Rd

软件中断指令:
SWI:软件中断指令,以便用户程序能调用操作系统的系统例程
当执行SWI调用时,ARM处理器将会实现下列操作:
1,把中断处的地址值(pc-4)复制到R14中,保留中断处地址
2,把CPSR复制到SWI模式的SPSR,保存状态寄存器
3,把状态寄存器的其他模式改变成管理模式
4,把中断向量0X00000008赋值给PC
5,禁止IRQ中断,使CPSR[7]=1

ARM协处理器:
    ARM微处理器可支持多达16个协处理器,用于各种协处理操作,在程序执行的过程中,每个协处理器只执行针对自身的协处理指令,忽略ARM处理器和其他协处理器的指令。
    ARM的协处理器指令主要用于ARM处理器初始化ARM协处理器的数据处理操作,以及在ARM处理器的寄存器和协处理器的寄存器之间传送数据,和在ARM协处理器的寄存器和存储器之间传送数据。ARM协处理器指令包括以下5条:
CDP:协处理器数据处理指令
LDC:协处理器数据加载指令
STC:协处理器数据存储指令
MCR:ARM处理器寄存器到协处理器寄存器的数据传送指令
MRC:协处理器寄存器到ARM处理器寄存器的数据传送指令

符号定义伪操作:
用于定义全局变量的GBLA(全局数字变量),GBLL(全局逻辑变量),GBLS(全局字符串变量).
用于定义局部变量的LCLA,LCLL,LCLS
用于对变量进行赋值的SETA,SETC,SETS
为通用寄存器列表定义名称的RLIST

数据定义伪操作:
DCB:分配一片连续的字节存储单元并初始化
DCD:分配一片连续的字存储单元并初始化
DCW:分配一片连续的半字存储单元并初始化

SPACE:分配一片连续的存储单元
用于分配一片连续的存储区域并初始化为0

FIELD:定义一个结构化的内存表的数据域,可以用#来代替
MAP:定义一个结构化的内存表首地址,可以用^来代替
FIELD和MAP伪操作配合使用来定义结构化的内存表。
MAP 0X100
A FIELD 4
B FIELD 4
S FIELD 16
LTORG:定义一个数据缓冲池的开始

EXPORT伪操作用于在程序中生命一个全局的标号,该标号可在其他的文件中引用。

ImPORT:伪操作用于通知编译器要使用的标号在其他的源文件中定义,但要在当前源文件中引用,而且无论当前源文件是否引用该标号,该标号均会被加入到当前源文件的符号表中

GET:伪操作作用于讲一个源文件包含到当前的源文件中,并将被包含的源文件在当前位置进行汇编处理

INCBIN:伪操作用于将一个目标文件或数据文件包含到当前的源文件中,被包含的文件不做任何变动地存放在当前文件中。

异常中断编程:
ARM的异常中断:复位,未定义指令,软件中断,指令预取中止,数据中止,中断请求(IRQ),快速中断请求(FIQ)

快速请求(IRQ):IRQ属于正常的的中断请求,可通过对处理器的nIRQ引脚输入低电平产生,IRQ的优先级低于FIQ,当程序执行进入FIQ异常时,IRQ可能被屏蔽
若将CPSR的 I 位置位1,则会禁止IRQ中断,若将CPSR的I位清零,处理器会在指令执行完之前检查IRQ的输入

快速中断请求(FIQ)
FIQ和IRQ中断处理机制:
FIQ异常中断位快读异常中断,它比IRQ异常中断优先级高,主要表现在下面两个方面:
1,当FIQ和IRQ异常中断同时产生时,CPU先处理FIQ异常中断
2,在FIQ异常中断处理程序中IRQ异常中断被禁止

ARM异常中断的处理过程:
1,保存处理器当前状态,中断屏蔽位以及各种条件标志位
SUB LR,LR,#4                    ;保存中断的返回地址
STMFD SP!, {LR}
MRS R14, SPSR                ;保存状态寄存器,及其他工作寄存器
STMFD SP!, {R12,R14}

2,设置当前程序状态寄存器CPSR中相应的位
    2.1,改变处理器状态进入ARM状态
    2.2,改变处理器模式进入相应的异常模式
    2.3,设置中断禁止位禁止相应中断
不管一场发生在ARM还是Thumb状态下,处理器都将自动进入ARM状态,如果此时处理器处于Thumb状态,则当异常向量地址加载入PC时,处理器自动切换到ARM状态,设置CPSR中的位,使得处理器进入相应的执行模式
典型的代码:
MRS R14,CPSR
BIC R14,R14,#0X9F
ORR R14,R14,#0X1F
MSR CPSR_c, R14

3,保存返回地址
将下一条指令的地址存入LR寄存器中,以便程序在处理一场返回是能从正确的位置重新开始执行。
典型代码:
STMFD SP!, {R0-R3,LR}
4,执行中断处理程序
强制PC从相关的异常向量地址去下一条指令执行从而跳转到相应的异常处理程序处
典型代码:
BL C_irq_handler

异常中断的返回:
1,恢复通用寄存器中的值,通用寄存器的恢复采用一般的堆栈操作指令
2,恢复状态寄存器的值,恢复被中断程序的的处理器状态,将SPSR_mode寄存器内容复制到当前程序状态寄存器CPSR中
3,修改PC的值
其中后两条可以采用:
MOVS PC, LR

SUBS PC, LR,#4
LDMFD sp!, {pc}^
在特权模式下,“S”和“^”的作用就是使指令在执行时,同时完成从SPSR到CPSR中的复制,达到恢复状态寄存器的作用

中断后的返回指令
未定义指令:     MOV PC, R14_und
软件中断:       MOV PC, R14_svc
取值中断:       SUBS PC, R14_abt,#4 
数据中止:       SUBS PC,R14_abt,#8
IRQ:            SUBS PC,R14_irq,#4
FIQ:            SUBS PC,R14_fiq,#4

指令的条件执行:
当处理器工作在ARM状态是,几乎所有的指令都根据CPSR中条件码的状态和指令的条件域有条件地执行,下面给出条件码:
我们注意到条件标志位位于CPSR状态寄存器中,下面给出CPSR寄存器的说明:
(图片截于刘洪涛,讲师的讲课稿)

结合以上两个图,我们对于ARM中条件执行也就有了很好的认识了!
现在我们来分析一个简单的软件中断的例子:
SWI异常中断处理程序:

下面是完成它的步骤(在存储寄存器 r0-r12 之后):

  1. 它从 r14 中减去 4 来获得 SWI 指令的地址。
  2. 把这个指令装载到一个寄存器。
  3. 清除这个指令的高端 8 位,去掉了 OpCode 而只剩下的 SWI 编号。
  4. 使用这个值来找到要被执行的代码的例程的地址(使用查找表等)。
  5. 恢复寄存器 r0-r12。
  6. 使处理器离开超级用户模式。
  7. 跳转到这个例程的地址。
T_bit EQU 0x20

SWI_Handler
STMFD  sp!, {r0-r3,r12,lr} 
MOV    r1, sp
;寄存器压栈,设置堆栈指针
MRS    r0, spsr
STMFD  sp!, {r0}
;取出 spsr 并压栈保存
;TST指令用于把一个寄存器Rn与oprand2进行与操作,并根据结果更新状态寄存器CPSR
TST    r0, #T_bit
LDRNEH r0, [lr,#-2]    ;H的后缀表示是半字操作,因为Thumb是                        ;16位的
BICNE  r0, r0, #0xff00
LDREQ  r0, [lr,#-4] 
BICEQ  r0, r0, #0xff000000
;测试状态
; r0 now contains SWI number
; r1 now contains pointer to parameters on stack

BL     C_SWI_Handler

LDMFD  sp!, {r1}
MSR    spsr_csxf, r1
LDMFD  sp!, {r0-r3,r12,pc}^
恢复寄存器并返回
阅读(7014) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~