APP下载

基于AT91SAM9263的嵌入式系统启动过程分析

2011-06-02中北大学姚文俊裴焕斗

电子世界 2011年10期
关键词:存储器内核代码

中北大学 姚文俊 裴焕斗

1.引言

随着计算机与通信技术的飞速发展,尤其是互联网的迅速普及,嵌入式的应用越来越广泛,嵌入式系统的微型化和专业化成为发展的新趋势。而在所有嵌入式系统中又由于嵌入式Linux具有源代码开放、易于移植、资源丰富、免费等优点而被广泛使用,并且将越来越流行。而在嵌入式硬件平台中又以ARM的应用最为广泛,其中Atmel公司的AT91SAM9263是一款性能优越、功能强大的ARM9处理器,且在工业控制上应用广泛。

嵌入式的开发过程包括硬件和软件两方面的开发,而其中软件开发又可以分为四个部分,即引导加载程序、Linux内核、文件系统和用户应用程序,而引导加载程序即启动代码是整个开发的第一步,也是非常关键的一步,会直接影响到后面几步的开发效率和系统的整体性能。所以对系统启动过程的了解和熟悉,是编写好高效启动代码的前提,也会为后续的开发提高效率。

2.AT91SAM9263上电启动过程

系统上电后,CPU首先会根据BMS引脚上的电平情况来选择启动存储器,如果BMS为1,选择启动的存储器是内部的ROM,如果BMS为O,选择启动的存储器是连接于外部总线接口片选O处的存储器,本文以从内部ROM启动为例来说明启动过程(BMS=1)。在选择为内部ROM启动后,系统会先运行一段固化在ROM中的boot代码,它会初始化处理器和一些必要的外设比如:调试部件串行端口(DBGU)和USB设备端口,然后依次检测SD卡、nandflash、dataflash等存储器的OxO地址处有没有符合bootstrap规范的启动程序,如果有则执行bootstrap代码,如果没有有效的bootstrap,则会接着执行SAM-BA,它会等待USB设备或DBUG串行端口上的事件发生。

当系统执行到检测合法的bootstrap存储位置时(以dataFlash启动为例)ARM芯片会读取与SPIO端口相连的dataflash的八个中断向量,看是否符合一定的规则,如果合适则将dataflash中所存储的启动代码下载到SRAM,然后经存储器的remap后,SRAM从映射前的Ox3OOOOO地址被映射到了OxO地址,从而bootstrap的代码已经出现在OxO的SRAM空间中,然后程序从此处开始执行去寻找一个有效的应用程序,此应用程序可以是跑裸机程序时的应用程序代码,也可以是一个二级的bootloader(本文是u-boot)。图2为存储器重映射图,

3.Bootloader简介

图2 存储器重映射

嵌入式系统的bootloader是系统上电后运行的第一个程序。它的作用如同PC机中的BIOS,是在操作系统运行之前的一段小程序。通过这段小程序系统可以初始化硬件设备,将系统的软硬件环境带到一个合适的状态,为调用操作系统做好准备。Bootloader的启动过程根据处理器的不同和具体的功用一般可以分为两种,一种是先运行小型的bootstrap来完成低级别的初始化,然后再调用如Uboot,RedBOOT等功能强大的引导程序进行全面的初始化、设置操作系统内核的加载地址和运行参数等等,这类的处理器以Atmel公司AT91SAM926x为代表。另外一种是直接使用Uboot等引导程序两步合成一步完成引导任务,这类处理器如samsung公司的s3c24xx系列等。Atmel公司的AT91SAM9263的bootloader采用第一种拥有两级的boot,分别是第一级的bootstrap和第二级的u-boot或者RedBOOT等等。所以系统上电后会首先运行bootstrap,然后引导u-boot,最后再把控制权交给u-boot,这样做的目的是可以提供更多更复杂的功能,而且具有更好的可移植性,提高开发效率。

图3 bootstrap工程组织结构图

图4 uboot整体工作流程

3.1 Bootstrap启动分析

Bootstrap被应用于AT91SAM9263微处理器的第一级启动代码,它的代码包括汇编和C语言两部分,主要工作就是一些硬件的初始化和将uboot的内容拷贝到外部的内存中,然后再跳转到存储uboot的内存地址执行uboot。对AT91SAM9263的bootstrap来说,编译完成后由于受到内部SRAM的大小限制代码长度必须小于4KB,然后烧写到dataflash中的OxO处。因此整个程序也比较短小,组织结构也比较清晰。图3为bootstrap工程组织结构图,

从图3可看出bootstrap结构清晰明了,其中crtO_gnu.s是系统的入口程序,完成的功能和uboot中cpu/arm926ejs下的start.s类似,主要执行设置ARM中断向量,将bootstrap代码从dataflash搬移到SRAM中,然后设置时钟,初始化数据段,bss段,最后跳转到main.c执行。

crt_gnu.s程序在系统启动时首先被执行。其中reset是程序入口点,程序将从此处开始执行,依次执行ARM中断向量设置,时钟频率设置,初始化数据段,bss段,最后跳转到main.c执行。在main.c函数中将执行硬件初始化(hw_init()),再从dataflash里面加载代码(load_df()),然后执行所加载的代码程序,最后通过return JUMP_ADDR返回到crt_gnu.s函数继续执行。其中bx rO语句就是跳转到main函数后返回的地址。下面的代码是bootstrap两个重要跳转语句,

最后程序跳转到Ox23FOOOOO处在sdram中继续运行uboot程序代码。

3.2 u-boot启动分析

以uboot作为系统的第二级启动程序,而uboot的启动又可分成stage1和stage2两个阶段。Stage1使用汇编语言编写,与CPU的体系结构密切相关,通常执行处理器和设备的初始化等。stage2使用C语言编写,通常进行的工作有外围器件的初始化(如Flash器件、网络设备等)、检测内存映射等,最后进入命令循环,等待接收串口发送来的uboot命令进行相应的操作。Stage1和stage2两阶段分别在cpu/arm926ejs/start.s和lib_arm/board.c文件中实现。图4为uboot两个阶段工作的整体流程图。

3.2.1 stage1代码启动分析

当系统启动过程中由bootstrap跳转到uboot后,系统将由uboot控制引导启动,且首先会进入由汇编语言编写的第一阶段代码cpu/arm926ejs/start.s文件中执行,其入口标记代码为:

.globl _start

_start: b reset

程序首先会跳转到reset函数去执行,这个函数的主要任务是将CPU设为SVC32模式、关闭看门狗、屏蔽中断和设置时钟,最后跳转到cpu_init_crit函数去执行ARM处理器的初始化。cpu_init_crit函数主要的工作是刷新指令与数据缓冲,关闭MMU,再跳转到lowlevel_init函数处执行SDRAM的初始化。由于lowlevel_init函数的实现与具体的目标板有关,对于AT91SAM9263来说由于SDRAM的初始化已经在bootstrap中执行,所以此处不需要再执行此函数,程序会返回调用函数start.s继续执行。relocate是系统接下来执行的函数,它负责把uboot中stage2的代码从dataflash存储器拷贝到SDRAM中,程序标号copy_loop:的代码就是循环拷贝flash中的8个字节的数据到内存SDRAM,直到stage2的程序复制完毕。最后程序通过ldr pc, _start_armboot语句将程序指针寄存器设置为start_armboot函数的地址,跳转到stage2部分去执行。

3.2.2 stage2代码启动分析

当程序跳转到stage2部分后会首先进入start_armboot函数,它是一个C语言函数,位于lib_arm/board.c文件中。这个阶段的任务是进一步进行系统的初始化工作,包括dataflash、nandflash、串口、网卡等的初始化。在函数初始化配置完后,程序即进入for死循环执行main_loop函数。main_loop函数是一个与具体平台无关的函数,主要工作包括初始化启动次数限制机制、设置软件版本号、打印启动信息、解析命令等。main_loop在初始化完毕后,会设置延时等待用以确定目标板是进入下载操作模式还是装载镜像文件启动内核程序,此时程序会停在main_loop()函数的for死循环里不断调用readline函数,等待用户命令的输入,然后解析命令并执行相应的操作。

3.2.3 uboot命令引导linux Kernel的实现

Uboot中引导内核最常用的方法是bootm命令,当系统进入装载模式装载镜像文件来启动内核程序时,需要运行bootm命令。对于AT91SAM9263则需运行命令bootm Ox2OOO8OOO来进入do_bootm_linux函数调用内核启动函数。在启动函数中,下面两条语句非常关键:

其中(1)是将内核的入口地址Ox2OOO8 OOO赋给了thekernel,第二句是启动内核时给内核传入参数的三个变量,分别用通用寄存器rO,r1,r2传给内核,其中RO=O,R1=机器类型ID,R2=启动参数数据结构的首地址。这样linux kernel就可以被正常引导启动了。

4.总结

本文对基于AT91SAM9263的嵌入式Linux系统的启动过程进行了比较详细的分析,从系统上电到引导内核的过程都结合代码进行了说明。在嵌入式产品的开发过程中,启动代码的编写是开发的第一步,起着非常重要的作用。尤其是在嵌入式的应用越来越广泛,竞争越来越激烈的今天,好的启动程序会增加产品的竞争力。

[1]AT91SAM9263 datasheet:93-103.

[2]张晓林,崔迎炜.嵌入式系统设计与实践[M].北京:北京航空航天大学出版社,2006.

[3]韦东山编著.嵌入式Linux应用开发完全手册[M].人民邮电出版社,2008:240-248.

[4]弓雷等编著.ARM嵌入式Linux系统开发详解[M].清华大学出版社,2010.1:229-249.

猜你喜欢

存储器内核代码
强化『高新』内核 打造农业『硅谷』
静态随机存储器在轨自检算法
基于嵌入式Linux内核的自恢复设计
Linux内核mmap保护机制研究
创世代码
创世代码
创世代码
创世代码
微生物内核 生态型农资
存储器——安格尔(墨西哥)▲