Chinaunix首页 | 论坛 | 博客
  • 博客访问: 460428
  • 博文数量: 62
  • 博客积分: 1742
  • 博客等级: 中尉
  • 技术积分: 859
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-06 00:13
个人简介

这是一句很长很长而且又很啰嗦并且很无聊的废话...

文章分类

全部博文(62)

文章存档

2013年(1)

2012年(13)

2011年(48)

分类: LINUX

2011-07-28 16:54:10

----------------------------------------------------------------------------------------------------------------
RISC架构的指令是定长指令(ARM状态4字节,Thumb状态2字节)
CISC架构外部寄存器是独立的IO地址空间,端口映射.而RISC架构外部寄存器是统一内存地址编址.
ARM是使用哈佛架构的,即是数据总线和指令总线是分开的,这样做的好处是指令数据和存储数据的
缓冲不会重叠,因为它们都有各自片内高速缓冲(icache和dcache),使得指令的多级流水线的实现.
----------------------------------------------------------------------------------------------------------------
LDR伪指令
例如 LDR Rd,=const
当const满足八位图要求,则编译成
MOV Rd,#const
否则
LDR Rd,[PC,#Offset]
......
Limits
DD const
----------------------------------------------------------------------------------------------------------------
B/BL跳转指令

if L == 1 then
LR = address of the instruction after the branch instruction
PC = PC + (SignExtend_30(signed_immed_24) << 2)
--------------------------------------------------------------
上面的24位跳转地址立即数的计算方法是:将指令中的24位带符号的补码立即数(signed_immed_24)扩展为32位(扩展其符号位),
将此32位数左移两位,得到的值加到PC寄存器中,即得到目标的跳转地址.如果跳转地址不满足以上的计算方法转换为24位有符号
立即数,那么编译器会通过LDR或LDR加BX间接地跳转(直接赋予PC寄存器绝对跳转地址立即数).例如:跳转地址立即数0xFFFF8880
和0xFFFF8881,它们俩都按照如下操作后,(假设当前PC寄存器的值为8)->((const-0x8)/0x2/0x2)&0xFFFFFF->value,现在计算的
结果为value,然后将value按24位跳转地址立即数的计算方法计算,得出的结果可见,0xFFFF8880是可以还原的,0xFFFF8881却不可
以,对于0xFFFF8881这样的不对齐立即数,编译器会通过LDR或LDR加BX间接地跳转.
PS:一般不能被上面的地址算法压缩的地址立即数为奇数地址,是不对齐的地址.
----------------------------------------------------------------------------------------------------------------
ARM内存操作L/S

LDM/STM Rd!,{Rn-Rn,Rn}^
-----------------------
IA
start_address = Rn
if W == 1 then
Rn = Rn + (Number_Of_Set_Bits_In(register_list) * 4)
-----------------------------------------------------
IB
start_address = Rn + 4
if W == 1 then
Rn = Rn + (Number_Of_Set_Bits_In(register_list) * 4)
-----------------------------------------------------
DA
start_address = Rn - (Number_Of_Set_Bits_In(register_list) * 4) + 4
if W == 1 then
Rn = Rn - (Number_Of_Set_Bits_In(register_list) * 4)
-------------------------------------------------------------------
DB
start_address = Rn - (Number_Of_Set_Bits_In(register_list) * 4)
if W == 1 then
Rn = Rn - (Number_Of_Set_Bits_In(register_list) * 4)
--------------------------------------------------------------
LDM
address = start_address
for i = 0 to 14
if register_list[i] == 1 then
Ri = Memory[address,4]
address = address + 4
-------------------------------
STM
address = start_address
for i = 0 to 15
if register_list[i] == 1 then
Memory[address,4] = Ri
address = address + 4
-------------------------------
另外,^条件码在LDM指令中会因寄存器列表中有无包含PC寄存器所表现的意义将有所不同.如果寄存器列表中无包含PC寄存
器,那么寄存器列表中的所有寄存器均为USER模式下对应的寄存器,也就是说以Rd为首地址开始所访问的内存数据将存放到
USER模式下指定的寄存器,在手册上的指令集中为LDM(2).如果寄存器列表中有包含PC寄存器,那么寄存器列表中的寄存器对
应的还是当前模式下的寄存器,但是它会将SPSR_mod的值赋给CPSR实现状态返回,所以它适用于异常返回并且环境恢复.在手
册上的指令集中为LDM(3).因此,在执行有加^条件码的LDM指令时,当前模式都必须为特权模式,否则将发生不可预知的结果.
^条件码对于STM指令来说,同样是要求着它需要在特权模式下执行,而寄存器列表中的寄存器均为USER模式下对应的寄存器,
而且寄存器列表中是不能包含PC寄存器的,这跟LDM(2)很相似.这很适合模式切换时的参数压栈.

LDR/STR
-------
LDR/STR Rd,[, #+/-];Rn的值加上有符号数偏移量offset_12(满足八位图)的结果作为首地址,把这块内存的数据装载进Rd寄存器.或者把Rd的值放进这块内存里.
----------------------------------
LDR/STR Rd,[, +/-];把Rn和Rm的值相加作为首地址,把这块内存的数据装载进Rd寄存器.或者把Rd的值放进这块内存里.
--------------------------
LDR/STR Rd,[, +/-, #];将Rm的值经过移位或旋转(LSL,LSR,ASR,ROR,RRX,shift_imm为5位数)得到结果加上Rn的值作为首地址,把这块内存的数据装载进Rd寄存器.或者把Rd的值放进这块内存里.
------------------------------------------------
LDR/STR Rd,[, #+/-]!;与第一个操作一样,但是Rn的值加上符号数偏移量offset_12(满足八位图)的结果不仅作为首地址,而且还会赋值给Rn.
-----------------------------------
LDR/STR Rd,[, +/-]!;与第二个操作一样,但是Rn和Rm的值相加的结果不仅作为首地址,而且还会赋值给Rn.
---------------------------
LDR/STR Rd,[, +/-, #]!;与第三个操作一样,但是Rm的值经过移位或旋转(LSL,LSR,ASR,ROR,RRX,shift_imm为5位数)得到值加上Rn的结果不仅作为首地址,而且还会赋值给Rn.
-------------------------------------------------
LDR/STR Rd,[], #+/-;首先把Rn的值作为首地址,把这块内存的数据装载进Rd寄存器.或者把Rd的值放进这块内存里.之后Rn就等于Rn加有符号数偏移量offset_12(满足八位图)的结果.
----------------------------------
LDR/STR Rd,[], +/-;首先把Rn的值作为首地址,把这块内存的数据装载进Rd寄存器.或者把Rd的值放进这块内存里.之后Rn就等于Rn加Rm的结果.
--------------------------
LDR/STR Rd,[], +/-, #;首先把Rn的值作为首地址,把这块内存的数据装载进Rd寄存器.或者把Rd的值放进这块内存里.之后Rn就等于Rn加Rm移位或旋转(LSL,LSR,ASR,ROR,RRX,shift_imm为5位数)的值的结果.

----------------------------------------------------------------------------------------------------------------
UART

FIFO模式
(0x50000020)UTXH0->UTXH1->UTXH2->UTXHn->TXDATAn(移位发送)->8位发送完毕后将(0x50000010)UTRSTAT0[1]置位为1
非FIFO模式
(0x50000020)UTXH0->TXDATAn(移位发送)->8位发送完毕后将(0x50000010)UTRSTAT0[1]置位为1
两种模式区别在于缓冲寄存器的使用数量,FIFO用了16个,非FIFO只用一个,但他们的传递顺序是一致的
----------------------------------------------------------------------------------------------------------------
ARM的7种中断流程分析

复位中断:
当处理器检测到复位输入引脚有信号,ARM处理器将立即停止执行当前指令(流水线的执行级过后).将复位输入位清除后,就把外部中断和快速中断屏蔽,并且设置当前处理为ARM状态和SVC模式,最后把PC寄存器的值设置为0x00000000地址,如果是
高向量配置的话则为0xFFFF0000进入复位中断例程.

数据访问终止中断:
如果数据访问指令的目标地址不存在,或者该地址不允许当前指令访问,存储系统将发出一个访问中止异常信号,流水线的执行级过后,便把外部中断屏蔽,并且设置当前处理为ARM状态和ABT模式,接着就跳到访问中止中断例程.确定中止原因后,用下列指令从中止模式返回,即SUBS PC,R14,#8恢复PC(从R14_abt)和CPSR(从SPSR_abt),并返回重新执行中止的指令.若中止的指令不需要重新执行,则用SUBS PC,R14,#4指令返回.

快速中断:
通过处理器上的FIQ输入引脚,由外部产生FIQ中断.FIQ是设计为支持的数据传输或通道处理,并有足够的FIQ模式下自己独立的寄存器(R8_fiq-R1414_fiq,SPSR_fiq),因此,可以最大限度地减少上下文切换的开销.当CPSR中的F位被置位时(设置为1),禁用快速中断.否则,屏蔽外部中断和快速中断,设置当前处理为ARM状态和FIQ模式,最后进入快速中断例程.例外,如果要开启或禁用快速中断,只能在特权模式下(除了USER模式都是特权模式).中断发生时R14_fiq保存着取址级指令地址的值,所以要返回正常流程的下一条指令,使用SUBS PC, R14,#4即可.

外部中断:
通过处理器上的IRQ输入引脚,由外部产生IRQ中断.它优先级比快速中断低,而且如果有一个快速中断发生时,处理器将会自动屏蔽外部中断,但是,外部中断发生时,它只能屏蔽自己,并不能屏蔽快速中断.接着屏蔽外部中断,设置当前处理为ARM状态和IRQ模式,最后进入外部中断例程.例外,如果要开启或禁用外部中断,只能在特权模式下(除了USER模式都是特权模式).中断发生时R14_irq保存着取址级指令地址的值,所以要返回正常流程的下一条指令,使用SUBS PC, R14,#4即可.

指令预取终止中断:
当指令预取访问存储器失败时,存储器系统向ARM处理器发出存储器中止(abort)信号,预取的指令被记为无效,但只有当处理器试图执行无效指令时,指令预取中止异常才会发生,如果指令未被执行,例如在指令流水线中发生了跳转,则预取指令中止不会发生.在ARMv5及以上版本中,执行BKPT指令也会产生预取中止异常.当试图执行一条中止指令时,将屏蔽外部中断,设置当前处理为ARM状态和ABT模式,最后进入指令预取终止中断例程.中断处理例程过后程序要返回到该有问题的指令处,重新读取并执行该指令,而不是返回到发生异常的指令的下一条指令处.指令预取中止异常是由当前执行的指令自身产生的,当异常产生时,PC指向当前指令后面的第二条指令(对于ARM指令,它指向当前指令地址加8个字节的位置,对于Thumb指令,它指向当前指令地址加4个字节的位置),异常模式下的寄存器R14将保存当前指令的下一条指令地址(对于ARM指令来说是PC-4),返回操作可以通SUBS PC,R14,#4指令完成返回.

未定义指令中断:
当ARM处理器执行协处理器指令时,它必须等待任一外部协处理器应答后,才能真正执行这条指令,此时若没有协处理器回应,则产生未定义指令异常.如果尝试执行未定义的指令,也会产生未定义指令异常.当产生异常后,处理器自动屏蔽外部中断,设置当前处理为ARM状态和UND模式,最后进入未定义指令中断例程.在发生该异常时R14_und保存的是未定义指令后的下一条指令的地址,所以,返回操作使用MOVS PC,R14指令即可.

软中断:
SWI是进入SVC模式下请求特定功能子程序的一个指令.当处理器执行该指令时,处理器将自动屏蔽外部中断,设置当前处理为ARM状态和SVC模式.并且把当前CPSR保存到SPSR_svc中,最后进入软中断例程.为了能实现根据指令中immed_24操作数的不同,跳转到不同的处理程序,所以我们往往需要在SWI异常处理子程序中去获得immed_24操作数的实际内容.又因执行SWI指令时,R14_svc保存的是SWI指令后的下一条指令的地址(译码级),因此获得该操作数内容是在中断例程中使用LDR R0,[LR,#-4];BIC R0,R0,#0xFF000000;两条指令即可.最后返回操作可以使用MOVS PC,R14指令.
----------------------------------------------------------------------------------------------------------------
ARM中断实现及优先级

if 复位 then
R14_svc = UNPREDICTABLE value
SPSR_svc = UNPREDICTABLE value
CPSR[4:0] = 0b10011 /* Enter Supervisor mode */
CPSR[5] = 0 /* Execute in ARM state */
CPSR[6] = 1 /* Disable fast interrupts */
CPSR[7] = 1 /* Disable normal interrupts */
CPSR[8] = 1 /* Disable Imprecise Aborts (v6 only) */
CPSR[9] = CP15_reg1_EEbit /* Endianness on exception entry */
if high vectors configured then
PC = 0xFFFF0000
else
PC = 0x00000000
elseif 数据访问终止 then
R14_abt = address of the aborted instruction + 8
SPSR_abt = CPSR
CPSR[4:0] = 0b10111 /* Enter Abort mode */
CPSR[5] = 0 /* Execute in ARM state */
        /* CPSR[6] is unchanged */
CPSR[7] = 1 /* Disable normal interrupts */
CPSR[8] = 1 /* Disable Imprecise Data Aborts (v6 only) */
CPSR[9] = CP15_reg1_EEbit /* Endianness on exception entry */
if high vectors configured then
PC = 0xFFFF0010
else
PC = 0x00000010
------
/* To return use:SUBS PC,R14,#8 or SUBS PC,R14,#4(does not need to be re-executed)
elseif 快速中断 then
if CPSR[6] == 0 then
R14_fiq = address of next instruction to be executed + 4
SPSR_fiq = CPSR
CPSR[4:0] = 0b10001 /* Enter FIQ mode */
CPSR[5] = 0 /* Execute in ARM state */
CPSR[6] = 1 /* Disable fast interrupts */
CPSR[7] = 1 /* Disable normal interrupts */
CPSR[8] = 1 /* Disable Imprecise Data Aborts (v6 only) */
CPSR[9] = CP15_reg1_EEbit /* Endianness on exception entry */
if VE==0 then
if high vectors configured then
PC = 0xFFFF001C
else
PC = 0x0000001C
else
PC = IMPLEMENTATION DEFINED /* see page A2-26 */
------
/* To return use:SUBS PC, R14,#4 */
elseif 外部中断 then
if CPSR[7] == 0 then
R14_irq = address of next instruction to be executed + 4
SPSR_irq = CPSR
CPSR[4:0] = 0b10010 /* Enter IRQ mode */
CPSR[5] = 0 /* Execute in ARM state */
           /* CPSR[6] is unchanged */
CPSR[7] = 1 /* Disable normal interrupts 
CPSR[8] = 1 /* Disable Imprecise Data Aborts (v6 only) */
CPSR[9] = CP15_reg1_EEbit /* Endianness on exception entry */
if VE==0 then
if high vectors configured then
PC = 0xFFFF0018
else
PC = 0x00000018
else
PC = IMPLEMENTATION DEFINED /* see page A2-26 */
------
/* To return use:SUBS PC,R14,#4 */
elseif 指令预取终止 then
R14_abt = address of the aborted instruction + 4
SPSR_abt = CPSR
CPSR[4:0] = 0b10111 /* Enter Abort mode */
CPSR[5] = 0 /* Execute in ARM state */
           /* CPSR[6] is unchanged */
CPSR[7] = 1 /* Disable normal interrupts */
CPSR[8] = 1 /* Disable Imprecise Data Aborts (v6 only) */
CPSR[9] = CP15_reg1_EEbit /* Endianness on exception entry */
if high vectors configured then
PC = 0xFFFF000C
else
PC = 0x0000000C
------
/* To return use:SUBS PC,R14,#4 */
elseif 未定义指令 then
R14_und = address of next instruction after the Undefined instruction
SPSR_und = CPSR
CPSR[4:0] = 0b11011 /* Enter Undefined Instruction mode */
CPSR[5] = 0 /* Execute in ARM state */
        /* CPSR[6] is unchanged */
CPSR[7] = 1 /* Disable normal interrupts */
        /* CPSR[8] is unchanged */
CPSR[9] = CP15_reg1_EEbit /* Endianness on exception entry */
if high vectors configured then
PC = 0xFFFF0004
else
PC = 0x00000004
------
/* To return use:MOVS PC,R14 */
elseif 软中断 then
R14_svc = address of next instruction after the SWI instruction
SPSR_svc = CPSR
CPSR[4:0] = 0b10011 /* Enter Supervisor mode */
CPSR[5] = 0 /* Execute in ARM state */
           /* CPSR[6] is unchanged */
CPSR[7] = 1 /* Disable normal interrupts */
           /* CPSR[8] is unchanged */
CPSR[9] = CP15_reg1_EEbit /* Endianness on exception entry */
if high vectors configured then
PC = 0xFFFF0008
else
PC = 0x00000008
------
/* To return use:MOVS PC,R14 */
----------------------------------------------------------------------------------------------------------------
S条件码

在ARM指令集中,一部分指令执行码是可加S条件码的.但是,S条件码在不同的情况下会导致指令执行不同的操作.
在ARM手册上大部分可加S条件码的指令的伪代码都会有下面的一段:
------------------------------
if S == 1 and Rd == R15 then
if CurrentModeHasSPSR() then
CPSR = SPSR
else
UNPREDICTABLE
else if S == 1 then
N Flag = ...
Z Flag = ...
C Flag = ...
V Flag = ...
------------------------------
可见,凡是加S条件码的指令执行中,如果目的操作数是PC寄存器,并且当前模式为特权模式,那么指令的主体功能执
行完后,将会把SPSR_mod赋给CPSR,以达到恢复全局状态寄存器的目的.但是,当前模式为用户模式或者系统模式(没
有SPSR_mod寄存器)的话,指令的执行将会发生不可预知的结果.如果目的操作数不是PC寄存器的话,那么指令主体
功能执行完后将影响CPSR的对应标志位.
所以,一般从中断返回,可以使用:
MOVS pc,r14
或者
SUBS pc,r14,#4
或者
SUBS pc,r14,#8
或者返回并恢复用到寄存器
LDMFD r13!,{rBENGIN-rEND,pc}^
----------------------------------------------------------------------------------------------------------------
直接或者间接地修改PC寄存器而发生跳转时,会使ARM内核清空流水线,然后需要耗费一定的时钟周期重新填充流水线
ARM10使用分支预测技术,通过预测可能的分支并在指令执行前装载新的分支地址,从而减小了清空流水线的影响
----------------------------------------------------------------------------------------------------------------
GPIO分为多组,具体要看芯片.每组有控制寄存器,一般为GPxCON,它控制着对应该组的数据寄存器GPxDAT的每一位(引
脚)为输出或输入,或其他特定功能信号端口.例如2410里的GPxDAT寄存器是32位,因此一组里最多能有32个GPIO端口(
GPx0~GPx31).一般要使用GPIO端口时首先通过设置该组GPIO端口的控制寄存器GPxCON使能要使用的IO端口.
----------------------------------------------------------------------------------------------------------------
2410:
总线控制器地址拆分
[27:0]是128M的地址
[31:28]是片选地址

Nand控制器地址拆分
[7:0]决定半页起始地址
[8]决定是上半页还是下半页
[25:9]决定哪一页
----------------------------------------------------------------------------------------------------------------
ADR/ADRL伪指令

ADR ,
如果label是在当前ADR指令前面(地址小于当前ADR指令地址)的话,将会被编译器转译成:
ADD , PC, #
否则:
SUB , PC, #
而且,label的地址与ADR指令的地址的距离不能超过+/-4096个字节(具体要看对齐方式).
由上可见,ADR伪指令的功能主要是根据当前PC的地址加上或减去一定的偏移值,得到相对
的目的地址.

ADRL跟ADR的功能是一样的,只是根据不同的对齐方式,label的取址范围更大,一般可以去
到+/-256K.如上条件,编译器会编译成2条指令来实现:
ADD , PC, #
ADD , , #
SUB , PC, #
SUB , , #

总的来说,ADR伪指令跟LDR伪指令区别在于,同样是源目的地址label,LDR是以绝对地址立
即数加载到目的寄存器,而ADR则是用当前PC值加上或减去相对偏移值的方式加载到目的
寄存器中.
----------------------------------------------------------------------------------------------------------------
以后陆续记录点滴......
阅读(2388) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~