- 论坛徽章:
- 3
|
继续:
3.3 初始化堆栈
ARM处理器有7种工作模式,每种模式都有独立的堆栈指针寄存器(SP),并定义相应地址。改变状态寄存器(CPSR)的状态位,可使处理器切换到不同模式,然后给SP赋值,就实现了堆栈的初始化。需注意的是:不要切换到用户模式进行本模式的堆栈设置,因为进入该模式后就不能修改CPSR回到别的模式了,会影响程序的顺利执行[3]。初始化堆栈的代码如下所示:(以2个不同的SP寄存器SP_IRQ、SP_FIQ为例)
InitStacks: mrs r0,cpsr ;CPSR=》R0
bic r0,r0,#MODEMASK|NOINT ;屏蔽模式位和中断
orr r1,r0,#IRQMODE|NOINT ;MODEMASK =0x1f, NOINT = 0x80
msr cpsr_cxsf,r1 ;转到IRQ模式
ldr sp,=IRQStack ;设置SP_irq
orr r1,r0,#FIQMODE
msr cpsr_cxsf,r1 ;转到FIQ模式
ldr sp,=FIQStack
3.4 C例程全局变量初始化
全局变量的初始化,就是完成从ROM到RAM的数据传输和内容清零。可执行程序的映像结构由RO段、RW段和ZI段三部分组成,分别为只读数据段、可写数据段和堆栈段。其中RO段在Flash和RAM里都可运行;而RW和ZI段是必须转移到RAM中去的。尽管RAM的运行速度比Flash快的多,但由于RO段比较小,拷贝到RAM也需要时间,还要程序跳转,一比较两者的启动时间差不多,最终我们选择让RO段在Flash中运行。
开发工具中的链接器(Linker)提供了一定的机制来帮助我们完成这部分工作,其中|Image$$ZI$$ Base|,|Image$$ZI$$Limit|,|Image$$RW$$Base|,|Image$$RO$$Limit|是由链接器定义输出的。主要是输出段的起始和终止定位信息,具体程序实现如下:
startram : LDR a1,=|Image$$ZI$$Base| ;ZI段在RAM里面的起始地址
MOV a3,#0 ;寄存器清0
LDR a2,=|Image$$ZI$$Limit| ;ZI段在RAM里面的结束地址
CMP a1,a2
BEQ move_data
clear_loop : STR a3,[a1],#4 ;清一个字为0, a1 += 4
CMP a1,a2
BNE clear_loop
move_data LDR a1,=|Image$$RW$$Base| ;RW段在RAM中的起始地址
LDR a2,=|Image$$RO$$Limit| ;RW段在ROM中的起始地址
LDR a3,=|Image$$ZI$$Base| ;RW段在RAM中的结束地址
CMP a1,a3
BEQ goto_main
move_loop : LDR a4,[a2],#4
STR a4,[a1],#4 ;拷贝一个字,a1 += 4, a2 += 4
CMP a1,a3
BNE move_loop
goto_main : BL Main |
|