基于AT91RM9200的U-Boot启动分析和移植

发布时间:2024-11-12

本文采用U-Boot构建嵌入式系统的引导加载程序,在对U-Boot的启动工作机理进行了简略分析后,针对基于AT91RM9200的目标板对U-Boot作了具体的修改和移植。应用结果表明,移植后的U-Boot在目标板上运行良好,可成功引导Linux内核。

基于AT91RM9200的U-Boot启动分析和移植

周庆松,史小军

东南大学电子科学与工程学院,南京 (210096)

E-mail:摘 要:本文采用U-Boot构建嵌入式系统的引导加载程序,在对U-Boot的启动工作机理进

行了简略分析后,针对基于AT91RM9200的目标板对U-Boot作了具体的修改和移植。应用结

果表明,移植后的U-Boot在目标板上运行良好,可成功引导Linux内核。

关键词:U-Boot;移植;内核;AT91RM9200;嵌入式系统

1.引言

Bootloader代码是芯片复位后进入操作系统之前执行的一段代码,主要用于完成由硬件启

动到操作系统启动的过渡[1]。一般,Bootloader基于特定硬件平台实现,不但依赖于CPU的体

系结构,而且依赖于嵌入式系统板级设备的配置,因此需要修改源码来适合具体的嵌入式板

级设备。

本文基于AT91RM9200的嵌入式目标板和U-Boot源码资源,分析了U-Boot的启动过程,介

绍了U-Boot的移植方法和具体操作,最后讲述如何引导内核启动。

2.U-Boot简介

U-Boot,全称Universal Boot Loader,是遵循GPL条款的开放源码项目。他支持PowerPC、

ARM、X86、MIPS等体系结构的上百种开发板;并且支持多种嵌入式操作系统内核,如Linux、

NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS;具有较高的可靠性和稳定性,已经成为功

能最多、灵活性最强并且开发最积极的开放源码Bootloader。作为通用的BootLoader,U-Boot

可以方便的移植到其他硬件平台上[2]。

U-Boot移植一般都是针对嵌入式目标板的硬件资源,主要是CPU、FLASH 和SDRAM等情

况,以尽可能一致的原则,在U-Boot源码中,找到一个与目标板为同一个或同一系列处理器

的目标板模板,在此基础上再针对具体开发板对程序作相应的修改,比如不同型号存储芯片

的初始化等。这里笔者选用U-Boot 1.1.2版本,该版本支持基于at91rm9200的处理器配置,并

提供了一个目标板模板,即U-Boot源码下的board/at91rm9200dk模板。

3.U-Boot启动分析

在具体移植之前,先来了解一下U-Boot启动过程。U-Boot启动过程可以分成3个阶段[3]。

(1) 在Flash中运行汇编程序,进行基本硬件初始化,并将Flash中的启动代码复制到SDRAM中,

同时创造环境准备运行C程序;

汇编程序start.s是U-Boot启动后执行的第一个程序,它位于cpu/at91rm9200中,链接脚本

board/at91rm920dk/u-boot.lds决定U-Boot的入口函数位于该程序中。上电后,处理器首先执行

该程序,具体工作流程如图1所示。

(2) 跳转到SDRAM中执行,对硬件进行初始化,并向显示终端输出启动信息;

start_armboot是U-Boot执行的第一个C语言函数,它位于lib_arm/board.c中,主要完成

系统初始化工作,进入主循环,处理用户输入的命令。 具体工作流程如图2所示。

全局变量结构体gd主要用来保存开发板信息、终端存在标志位、环境变量结构体起始地

本文采用U-Boot构建嵌入式系统的引导加载程序,在对U-Boot的启动工作机理进行了简略分析后,针对基于AT91RM9200的目标板对U-Boot作了具体的修改和移植。应用结果表明,移植后的U-Boot在目标板上运行良好,可成功引导Linux内核。

址、环境变量校验标志位、frame buffer 基地址等。它是指向gd_t结构体的指针,gd_t结构体

定义在include\asm-asm\global_data.h中。

硬件初始化中执行函数及各函数作用如下所示:

board_init:基本的板级相关配置,主要包括:设置处理器类型和启动参数地址;

interrupt_init:中断处理初始化,主要对TC控制器作相应设置。

env_init:设置环境变量,初始化环境;

init_baudrate:指定串口的波特率;

serial_init:串口初始化设置;选择通讯端口,设置串口波特率和工作方式;

console_init_f:设置gd->have_console=1,表示可以使用串口通讯控制台;

display_banner:在控制台输出 U-Boot信息;

dram_init:设置SDRAM的起始地址和大小;

display_dram_config:在控制台输出 SDRAM信息;

flash_init:设置FLASH芯片ID号、每个扇区起始地址等信息,将信息送到相应的结构

体中;对FLASH中U-BOOT和环境变量存储扇区做软件写保护;

display_flash_config (size):在上位机终端输出FLASH大小。

图1 start.s函数执行流程 图2 start_armboot函数执行流程

(3) 将内核映像和根文件系统映像从flash拷贝到SDRAM中,为内核设置启动参数,进入内

核的入口函数。

U-Boot作为Bootloader,具备多种引导内核启动的方式。常用bootm命令引导内核映像

启动。使用bootm命令时,需要首先使用U-Boot自带的mkimage命令,将内核映像文件转换

成U-Boot格式映像。即在内核的前头加上64byte的信息帧头,供建立tag之用。

本文采用U-Boot构建嵌入式系统的引导加载程序,在对U-Boot的启动工作机理进行了简略分析后,针对基于AT91RM9200的目标板对U-Boot作了具体的修改和移植。应用结果表明,移植后的U-Boot在目标板上运行良好,可成功引导Linux内核。

bootm命令调用do_bootm函数。这个函数专门用来引导各种操作系统映像,可以支持引

导Linux、vxWorks、QNX等操作系统。具体完成的工作有:

① 保存内核引导地址;

② 分析内核帧头;

③ 复制内核映像到SDRAM中;

④ 调用do_bootm_linux()函数。

do_bootm_linux()函数是专门引导Linux映像的函数,它还可以处理ramdisk文件系统的映

像。具体完成的工作有:

① 检查是否有根文件系统映像文件。我们这里只用bootm命令引导内核映像;

② 将要传递给Linux的参数存放到标记列表中。内核将会从此处接收参数,完成参数传递;

③ 调用 Linux 内核。系统采用下列代码来进入内核函数:

theKernel = (void (*)(int, int))ntohl(hdr->ih_ep);

theKernel (0, bd->bi_arch_number, bd->bi_boot_params);

hdr是image_header_t类型的结构体,结构体定义位于include/image.h中;hdr->ih_ep指

向内核的第一条指令地址。第一行代码将theKernel函数指向内核首地址处;第二行代码调用

theKernel()函数,并通过r0、r1、r2将机器编号和参数链表物理地址传递给内核。

4.U-Boot修改与移植

4.1 嵌入式目标板介绍

本目标板以at91rm9200作为微处理器,板上存储系统包括NOR Flash、NAND Flash、

SDRAM等;外围支持设备有JTAG、串口、USB接口、 网络接口、SD Card 接口及显示接

口等。目标板硬件架构如图3所示;主要硬件资源如表1所示。

图3 嵌入式目标板硬件架构图

表1 嵌入式目标板主要硬件资源 硬件 型号 描述

8M Byte

32M Byte

64M Byte(2片)主频180MHz NOR Flash SST39VF6401BNAND Flash K9F5608U0D 网络芯片

本文采用U-Boot构建嵌入式系统的引导加载程序,在对U-Boot的启动工作机理进行了简略分析后,针对基于AT91RM9200的目标板对U-Boot作了具体的修改和移植。应用结果表明,移植后的U-Boot在目标板上运行良好,可成功引导Linux内核。

4.2 U-boot源码修改

根据目标板的配置,主要考虑修改以下U-Boot源码文件:

① include/configs/AT91RM9200dk.h。该头文件包含了SDRAM的一些设置和定义;

② board/AT91RM9200dk/flash.c。该程序完成的功能包括Flash初始化、打印Flash信息、Flah

擦除和Flash写入等操作。可在参考已有FLASH驱动的基础上,结合目标板FLASH数

据手册,进行适当修改;

③ include/flash.h。FLASH程序头文件,结合目标板修改FLASH型号和ID定义。

具体所作修改如下:

(1) include/configs/AT91RM9200dk.h中:

① 将 #undef CONFIG_BOOTBINFUNC 改为 #define CONFIG_BOOTBINFUNC

定义的目的是使能U-Boot中初始化SDRAM并拷贝自己到SDRAM中的相关代码。

② 修改SDRAM大小 #define PHYS_SDRAM_SIZE 0x4000000 /* 64 megs */

③ 修改FLASH大小和扇区数

#define PHYS_FLASH_SIZE 0x800000 /* 8 megs main flash */

#define CFG_MAX_FLASH_SECT 2048

④ 将 #define CFG_PROMPT "U-Boot> " 改为 #define CFG_PROMPT " zqs_1U-Boot> "

此处更改主要为了识别这是你修改后的U-Boot。

⑤ 添加 #define CFG_LONGHELP 1

该处定义的作用是在U-Boot下输入help命令时,可得到详细的命令解释。

(2) include/flash.h中:

① 添加 #define SST_ID_xF6401B 0x236D236D /* 39xF6401B ID (64M =

(3) board/AT91RM9200dk/flash.c中:

① 添加:OrgDef OrgSST39VF6401B[] = { {2048,4*1024},}; /* 2048 * 4 kBytes sectors */

② 屏蔽如下两行:

info->flash_id = ATM_MANUFACT & FLASH_VENDMASK;

printf ("Atmel: ");

在下面添加如下两行:

info->flash_id = SST_MANUFACT & FLASH_VENDMASK;

printf ("SST: ");

③ 在void flash_identification (flash_info_t * info)函数的最后添加:

else if ((device_code & FLASH_TYPEMASK) == (SST_ID_xF6401B &

FLASH_TYPEMASK)) {

info->flash_id |= SST_ID_xF6401B & FLASH_TYPEMASK; printf ("SST39VF6401B (64Mbit)\n");}

④ 在ulong flash_init (void)函数中添加:

else if ((flash_info[i].flash_id & FLASH_TYPEMASK) ==

(SST_ID_xF6401B & FLASH_TYPEMASK)) { /* SST39VF6401B Flash */

pOrgDef = OrgSST39VF6401B;

flash_nb_blocks = sizeof (OrgSST39VF6401B) / sizeof (OrgDef); }

⑤ 在 void flash_print_info (flash_info_t * info)函数中添加:

case (SST_MANUFACT & FLASH_VENDMASK):

printf ("SST: ");

break;

4M x 16 )*/

本文采用U-Boot构建嵌入式系统的引导加载程序,在对U-Boot的启动工作机理进行了简略分析后,针对基于AT91RM9200的目标板对U-Boot作了具体的修改和移植。应用结果表明,移植后的U-Boot在目标板上运行良好,可成功引导Linux内核。

⑥在 void flash_print_info (flash_info_t * info)函数中添加:

case (SST_ID_xF6401B & FLASH_TYPEMASK):

printf ("SST39VF6401B (64Mbit)\n");

break;

⑦ 在int flash_erase (flash_info_t * info, int s_first, int s_last)函数中,将以下几句用/* */屏蔽掉:

if ((info->flash_id & FLASH_VENDMASK) !=

(ATM_MANUFACT & FLASH_VENDMASK)) {

return ERR_UNKNOWN_FLASH_VENDOR;

}

并在下面添加如下几行:

if ((info->flash_id & FLASH_VENDMASK) !=

(STT_MANUFACT & FLASH_VENDMASK)) {

return ERR_UNKNOWN_FLASH_VENDOR;

}

至此,UBOOT源码文件修改完毕。

4.3 U-Boot编译与测试

U-Boot的源码通过GCC和Makefile组织编译。顶层目录下的Makefile设置开发板的定

义,递归地调用各级子目录下的Makefile,把编译过的程序链接成U-BOOT映像[2]。

这里上位机操作系统采用Redhat9.0,交叉工具链采用cross-2.95.3。GCC安装的路径为

/usr/loacal/arm/2.95.3,在环境变量PATH中添加相应路径,就可以直接使用arm-linux-gcc命令。

编译U-BOOT分两步,第一步配置,执行命令: make at91rm9200dk_config

第二步编译,执行命令: make

编译完成,生成3个映像文件system.map、u-boot、u-boot.bin,和1个符号表system.map,

一般u-boot.bin最为常用,直接按照二进制格式下载。

使用FLASH烧写程序将u-boot.bin烧进NOR FLASH中,目标板重新上电复位后,U-Boot

启动成功,在超级终端里会显示如下信息:

出现Warning的原因是还未设置环境变量。设置环境变量后执行saveenv命令即可去掉

Warning.

5.引导内核

U-Boot的最终目的是引导内核启动。上述仅仅启动了U-Boot,要引导内核启动还需要设

置环境变量、下载内核和根文件系统映像、执行引导内核启动命令。假设内核映像文件为

zImage,根文件系统映像文件为myramdisk.gz(生成方法略)。具体方法如下:

(1) 启动目标机,在U-BOOT中进行网络参数等环境变量设置

U-Boot> setenv ethaddr 12:34:56:78:90:aa

本文采用U-Boot构建嵌入式系统的引导加载程序,在对U-Boot的启动工作机理进行了简略分析后,针对基于AT91RM9200的目标板对U-Boot作了具体的修改和移植。应用结果表明,移植后的U-Boot在目标板上运行良好,可成功引导Linux内核。

U-Boot> setenv ipaddr 192.168.0.11

U-Boot> setenv serverip 192.168.250

U-Boot> setenv netmask 255.255.255.0

U-Boot> setenv bootargs root=/dev/ram rw initrd=0x21200000,6000000

ramdisk_size=15360 console=ttyS0,115200 mem=64M

U-Boot> setenv bootcmd cp.b 10300000 21200000 300000\; bootm 10100000 U-Boot> saveenv

这里网络环境变量设置的目的是为了能够使用TFTP协议;bootargs用来定义传递给Linux

内核的命令行参数;Bootcmd定义自动启动时执行的命令;bootm 10100000表示从10100000

处引导内核程序。

(2) 给内核映像加帧头[4]

在上位机LINUX环境下,将U-Boot\tools\mkimage.exe COPY 到 \bin目录下;输入如下命令:

[root@localhost tftpboot]#mkimage -n 'linux-2.6.19' -A arm -O linux -T kernel -C none -a

0x20008000 -e 0x20008000 -d zImage zImage.img

这里zImage为原始内核映像文件名;zImage.img为生成的加过帧头的内核映像名。

(3) 加载内核和根文件系统映像到Flash中

加载zImage.img到0x10100000,加载myramdisk.gz到0x10300000。

至此,我们将UBOOT 、内核、根文件系统都下载到Flash中了,并且设置了环境变量。

重启目标板,等待延时时间结束自动进入本地装载模式,即可引导内核启动。

上面讲的是将内核和根文件系统固化到Flash中的情况,即使用本地加载模式,当以嵌入

式产品发布的时候,BootLoader必须工作在这种模式下。但我们实际在初期调试的时候,可

以在下载操作模式下直接用TFTP命令将这些映像文件下载到SDRAM中,然后用bootm命令

从SDRAM中引导。此时在给内核映像加帧头的时候要注意,bootm xxxx 指定的地址xxxx是

否与mkImage命令处的 -a指定的加载地址相同。如果不同,mkImage命令的写法和上面介绍

的一致。如果相同,在使用mkImage命令时,-e参数后的入口地址要比-a参数后的存储地址

推后64byte。

6.结论

U-Boot是一个功能强大的Bootloader开源软件,它支持上百种开发板和多种嵌人式操作系

统,可方便地移植到各种硬件平台上。目前,笔者移植的U-Boot已成功运行在目标板上,并

在此基础上成功地加载了Linux内核和根文件系统,为后续的驱动和应用开发奠定了基础。对

于不同的CPU和开发板,U-Boot的启动原理和移植步骤大致相同。希望本文能对学习U-Boot

的朋友有所帮助。

参考文献

[1]

[2]

[3]

[4]

张进,姜威.U-Boot的启动流程及移植[J],国外电子元器件,2005,5,11~14。 孙纪坤,张小泉.《嵌入式Linux系统开发技术详解-基于ARM》[M],北京:人民邮电出版社,2006.8。 焦玉全,黄乡生,鲍玉军.U-Boot在S3C2410上的移植[J],电子设计应用,2006,3,126~128。 Karim Yagbmour.《构建嵌入式LINUX系统》[M],北京:中国电力出版社,2004.12。

本文采用U-Boot构建嵌入式系统的引导加载程序,在对U-Boot的启动工作机理进行了简略分析后,针对基于AT91RM9200的目标板对U-Boot作了具体的修改和移植。应用结果表明,移植后的U-Boot在目标板上运行良好,可成功引导Linux内核。

Start analysis and porting of U-Boot based on AT91RM9200

board

Zhou Qingsong,Shi Xiaojun

Dept. of Electronic Science and Engineering,Southeast University,Nanjing (210096)

Abstract

This paper develops a bootloader for embedded system with the U-Boot. After analyzing the booting mechanism of U-Boot, the modification and porting in an embedded system board based on

AT91RM9200 are done in detail. The application shows that U-Boot runs well and can lead Linux kernel successfully.

Keywords:U-Boot,porting,kernel,AT91RM9200,embedded system

作者简介:

周庆松,1980,男,硕士研究生;

史小军,1952,男,教授,硕士生导师。

基于AT91RM9200的U-Boot启动分析和移植.doc 将本文的Word文档下载到电脑

    精彩图片

    热门精选

    大家正在看

    × 游客快捷下载通道(下载后可以自由复制和排版)

    限时特价:7 元/份 原价:20元

    支付方式:

    开通VIP包月会员 特价:29元/月

    注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
    微信:fanwen365 QQ:370150219