嵌入式软件开发之: 复位和初始化
时候0x0~0x4000的地址空间空闲,不被程序引用,执行remap后把RAM引进。因为程序一直在0x10000起始的ROM空间里运行,remap对运行流程没有任何影响。
③ 通过在ROM里运行的程序,对RAM进行相应的代码和数据拷贝,完成应用程序运行的初始化。
图13.16显示了ROM和RAM重映射的第二种解决方案。
图13.16 ROM/RAM重映射(2)
该ROM与RAM地址重映射的方法可以应用于任何具有ROM/RAM重映射机制的平台,但是内存重映射的地址根据具体平台的不同而不同。
图13.16显示的地址重映射例子中,第一条指令实现从ROM临时地址(0x0地址)到实际ROM的跳转。然后,控制寄存器的重映射位,清除ROM的临时地址设置。该代码通常在系统复位后立即执行。重新映射必须在执行C库初始化代码前完成。
在具有MMU的系统中,可通过在系统启动时配置MMU来实现重映射。
下面的例子显示了在ARM的Integrator开发板上实现的ROM/RAM重映射过程。
; --- Integrator CM control reg
CM_ctl_reg EQU 0x1000000C ;定义CM控制寄存器地址
Remap_bit EQU 0x04 ;CM控制寄存器重映射掩码
ENTRY
;复位异常处理程序开始
; 执行跳转指令,转到实际的ROM执行
LDR pc, =Instruct_2
Instruct_2
; 设置CM控制寄存器的重映射位
LDR r1, =CM_ctl_reg
LDR r0, [r1]
ORR r0, r0, #Remap_bit
STR r0, [r1]
; 重映射后,RAM在0x0地址
; 将向量表从ROM拷贝到 RAM (由 __main函数完成)
13.5.3 局部存储器设置有关的考虑事项
许多ARM处理器内核具有片上存储器系统,如MMU或MPU。这些设备通常是在系统启动过程中进行设置并启用的。因此,带有局部存储器系统的内核的初始化序列需要特别地考虑。
在前面所述的代码启动的过程中,__main中C库初始化代码负责建立代码执行时的内存映像,在跳转到__main前,必须建立处理器内核的运行时存储器视图。这就是说,在复位处理程序中必须设置并启用MMU或MPU。
另外,在跳转到__main前(通常在MMU/MPU设置前),必须启用紧耦合存储器TCM(Tightly coupled Memory),因为在通常情况下都是采用分散加载方法将代码和数据装入TCM。当TCM启用后,用户不必存取由TCM屏蔽的存储器。
在跳转到__main前,如果启用了Cache,可能还会遇到Cache一致性的问题,__main中的函数将程序代码从其加载域拷贝到执行域,在此过程中将指令作为数据进行处理。这样,一些指令可能被放入数据Cache中,在执行这些指令时,由于找不到地址路径而产生错误。为了避免Cache一致性的问题,在C库初始化序列执行完成后再启用Cache。
13.5.4 栈指针初始化
在程序的初始化代码中,用户必须要为处理器用到的各种模式设置堆栈,也就是说,复位处理程序必须为应用程序所使用的任何执行模式的栈指针分配初始值。
下面的例子显示了如何在初始化代码中启用不同模式下的堆栈。
; 启用系统模式堆栈
LDR r2,INT_System_Stack ;将系统堆栈的全局变量放到r2中
STR sp,[r2] ;将系统堆栈指针存储到系统模式下的sp
; 启用系统堆栈限制 (为ARM编译器的堆栈检测做准备)
SUB r1,sp,#SYSTEM_STACK_SIZE ;跳转堆栈指针
BIC r1,r1,#0x03 ;4字节对齐
MOV r10,r1 ;将堆栈的限制放入r10寄存器(AAPCS规则)
LDR r2,INT_System_Limit ;得到堆栈限制全局变量地址
STR r1,[r2] ;将堆栈限制存入全局变量
; 切换到IRQ模式
MRS r0,CPSR ;得到当前的CPSR值
BIC r0,r0,#MODE_MASK ;清除模式位
ORR r1,r0,#IRQ_MODE ;设为IRQ模式
MSR CPSR_cxsf,r1 ;切换到IRQ模式
;启用IRQ模式堆栈
LDR sp,=INT_Irq_SP ;将IRQ模式堆栈指针放入sp_irq
; 切换到FIQ
ORR r1,r0,#FIQ_MODE ;设置FIQ模式位
MSR CPSR_cxsf,r1 ;切换到FIQ模式
; Set-up FIQ stack
LDR sp,=INT_Fiq_SP ;得到FIQ模式指针
; 切换到Abort模式
ORR r1,r0,#ABT_MODE ;设置Abort模式位
MSR CPSR_cxsf,r1 ;切换到ABT模式
; 启用Abort堆栈
LDR sp,=INT_Abort_SP
; 切换到未定义异常模式
ORR r1,r0,#UNDEF_MODE
MSR CPSR_cxsf,r1
;启用未定义指令模式堆栈
LDR sp,=INT_Undefined_SP
; 启用系统/用户堆栈
……
……
为了设置栈指针,进入每种模式(中断禁用)并为栈指针分配适合的值。要利用软件栈检查,也必须在此设置栈限制。
复位处理程序中设置的栈指针和栈限制值由C库初始化代码作为参数自动传递给__user_initial_stackheap()。因此,不允许__user_initial_stackheap()更改这些值。
下面的例子显示了如何实现__user_initial_stackheap(),该段代码可以和上面的堆栈指针设置程序配合使用。
IMPORT heap_base
EXPORT __user_init
- 基于DSP的导弹仿真器嵌入式组件设计(04-30)
- 为嵌入式软件建立统一软件系统框架的方法详介(05-23)
- 在VIM中实现对嵌入式软件的调试(08-06)
- 基于仿真的嵌入式软件白盒覆盖测试系统设计(08-26)
- 嵌入式软件运行剖面建模及测试用例生成(11-06)
- 嵌入式软件与硬件的集成测试过程研究(11-16)