首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

用ARM汇编语言编写系统启动程序

用ARM汇编语言编写系统启动程序

ARM汇编语言编写系统启动程序基于ARM内核的芯片多数为复杂的片上系统,这种复杂系统里的多数硬件模块都是可以配置的,需要由软件来设置其需要的工作状态。由于C语言具有模块性和可移植性的特点,大部分基于ARM的应用系统程序都采用C语言编写。但是当系统复位启动时,在进入C语言的main函数之前,需要有一段启动程序来完成对存储器配置、地址重映射和ARM芯片内部集成外围功能初始化等工作。这类工作直接面对处理器内核和硬件控制器进行编程,用C语言较难实现,因此一般采用汇编语言编写。
3.9.1  编写启动程序的一般规则ARM内核的处理器在复位后,从0x00000000地址处开始读取指令。实现启动最简单的方法是将应用程序放在映射空间地址为0ROM中。这样当执行第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
返回列表