标题:
用ARM汇编语言编写系统启动程序
[打印本页]
作者:
look_w
时间:
2017-9-24 15:53
标题:
用ARM汇编语言编写系统启动程序
用
ARM
汇编语言编写系统启动程序
基于
ARM
内核的芯片多数为复杂的片上系统,这种复杂系统里的多数硬件模块都是可以配置的,需要由软件来设置其需要的工作状态。由于
C
语言具有模块性和可移植性的特点,大部分基于
ARM
的应用系统程序都采用
C
语言编写。但是当系统复位启动时,在进入
C
语言的
main
函数之前,需要有一段启动程序来完成对存储器配置、地址重映射和
ARM
芯片内部集成外围功能初始化等工作。这类工作直接面对处理器内核和硬件控制器进行编程,用
C
语言较难实现,因此一般采用汇编语言编写。
3.9.1
编写启动程序的一般规则
ARM
内核的处理器在复位后,从
0x00000000
地址处开始读取指令。实现启动最简单的方法是将应用程序放在映射空间地址为
0
的
ROM
中。这样当执行第
1
条指令时,应用程序就从
0x00000000
处开始执行。但这种方法有很多缺点:
ROM
的存储宽度较小且速度较慢,会降低系统启动和处理器对异常处理的速度;异常向量表放在
ROM
中,程序将无法修改向量表,因此常将地址为
0
的空间映射成
RAM
,但
RAM
中的程序掉电无法保存,因此必须将
ROM
映射为
0
地址,以保证有效的复位向量,然后再使用重映射命令将
RAM
映射为
0
地址,
ROM
映射到其他地址空间,并将异常向量从
ROM
复制到
RAM
中。
编写启动程序应遵循以下一般规则:
1
. 设置入口指针
启动程序首先必须定义入口指针,而且整个应用程序只有一个入口指针,通常应用程序的入口地址为
0
。
2
. 设置异常向量
基于
ARM7TDMI
内核的处理器共支持
7
种异常,异常处理地址存放在地址
0
处的异常向量表中,共
8
×
4
字节的空间。异常向量表的内容参见
2.4.2
节。
异常向量表通常放在存储器底部,每个异常分配
4
个字节的空间。每个向量入口包含一条跳转指令或加载
PC
的指令,以执行适当的转移到具体的异常处理程序。如果
ROM
定位于
0
地址,则向量表由一系列固定的用以指向每个异常的指令组成;否则向量必须被动态初始化。可以在启动程序中添加一段代码,使其在运行时将向量表拷贝到
0
地址开始的存储器空间。对于没有使用的异常,使其指向一个只含返回指令的哑函数,以防止错误异常引起系统混乱。
3
. 初始化片内集成外围功能
由于
ARM
公司仅设计内核并出售给其它半导体厂商,不同的厂商购买内核授权后加入自己的外围功能,从而导致
ARM
核处理器芯片丰富多样,但也使得不同芯片的启动代码在这一部分差别很大。编写这一部分时应根据芯片和应用系统要求对它们进行合适的初始化。比较重要的操作一般有:外部总线接口的初始化、配置时钟锁相环、配置中断控制器、禁用看门狗电路等。
4
. 初始化存储系统
有些
ARM
核芯片可通过对寄存器编程来初始化系统存储器,而对于较复杂系统通常由存储管理单元
MMU
来管理内存空间。为正确运行应用程序,在初始化期间应将系统需要读写的数据和变量从
ROM
拷贝到
RAM
中;一些要求快速响应的程序,例如中断处理程序,也需要在
RAM
中运行;如果使用
Flash
,对
Flash
的擦除和写入操作也一定要在
RAM
中运行。
5
. 初始化堆栈寄存器
系统堆栈初始化取决于用户使用了哪些中断,以及系统需要处理哪些错误类型。一般来说管理模式堆栈必须初始化。如果使用
IRQ
中断,则
IRQ
堆栈必须初始化,并且必须在允许中断之前进行。如果使用
FIQ
中断,则
FIQ
堆栈也必须初始化,并且必须在允许中断之前进行。一般在简单的嵌入式系统中不使用中止状态堆栈和未定义指令堆栈,但为了调试方便还是将其初始化。如果系统使用
DRAM
或其它外设,还需要设置相关寄存器,以确定其刷新频率、数据总线宽度等信息。
6
. 改变处理器模式和状态
此时可以通过清除
CPSR
寄存器中的中断控制位来允许中断,这里是安全开启中断的最早地方。这个阶段处理器仍处于管理模式下。如果程序需要在用户模式下运行,可以在此处切换到用户模式并初始化用户模式堆栈指针。
7
. 跳转到
C
语言主程序
在从启动程序跳转到
C
语言程序的
main
函数之前,还需要初始化数据存储空间。通常是加入一段循环代码对数据存储空间清
0
。这样做的主要原因是
C
语言中没有初值的变量默认值均为
0
。已经初始化变量的初值必须从
ROM
中复制到
RAM
中,其它变量的初值必须为
0
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0