U-BOOT全线移植分析(转)

本文详细介绍了Bootloader移植的重要性,特别是针对U-Boot在嵌入式系统中的应用。内容涵盖U-Boot的源代码结构、基本功能、启动模式以及与主机的通信协议。此外,还分析了U-Boot的启动流程,包括两个阶段:位置无关的Stage1和Stage2。文章强调了正确设置启动参数和内存地址对启动成功的关键作用,并提供了U-Boot命令和环境变量的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

U-BOOT全线移植分析系列之一

――――BOOTLOADER介绍

Sailor_forever sailing_9806@163.com 转载请注明

http://blog.youkuaiyun.com/sailor_8318/archive/2008/08/04/2768049.aspx

【摘要】本节介绍了bootloader的基本概念。首先分析了为什么要针对特定的CPU和开发板移植bootloader的必要性。然后介绍了两种如何在裸板中烧写bootloader的方法以及如何确定烧写地址。其次介绍了产品发布的启动加载模式和开发使用的下载模式(更新内核文件系统及bootloader自身)。最后介绍了bootloader的两个通用启动阶段的流程及代码特性和运行位置。

【关键词】bootloader,烧写,复位地址,固化loader,启动加载,stage1,位置无关

bootloader介绍

1.1 Bootloader移植的必要性

Bootloader是与系统硬件环境高度相关的初始化软件,它担负着初始化硬件和引导操作系统的双重责任。一些ARM平台可以共用同一种Bootloader,但是总的说来,每一个特定系统的Bootloader都会有所不同。Bootloader广泛用于有操作系统的手持终端设备、智能家电及机顶盒等嵌入式设备上,它负责完成硬件初始化、操作系统引导和系统配制等。Bootloader移植是在特定硬件平台上操作系统移植至关重要的一步。

1.2 BootLoader所支持的CPU和嵌入式系统板

每种不同的CPU体系结构都有不同的BootLoader。有些BootLoader也支持多种体系结构的CPU,比如U-BOOT就同时支持ARM、MIPS、POWERPC等体系结构。除了依赖于CPU的体系结构外,BootLoader实际上也依赖于具体的嵌入式板级设备的配置。也就是说,对于两块不同的嵌入式板而言,即使它们是基于同一种CPU而构建的,要想让运行在一块板子上的BootLoader程序也能运行在另一块板子上,通常也都需要修改BootLoader的源程序。

1.3. Boot Loader的烧录和存储

系统加电或复位后,所有的CPU通常都从某个由CPU制造商预先安排的地址上取指令。比如,at91rm9200的CPU在复位时通常都从地址0x00000000取它的第一条指令。而MPC8260高端启动则时从0xfff00000开始取指。这个地址依据特定的CPU而定。通常片外启动时,基于CPU构建的嵌入式系统通常都有某种类型的固态存储设备(EEPROM或FLASH等,at91rm9200是0x10000000)被映射到这个预先安排的地址上。因此在系统加电后,CPU将首先执行Boot Loader程序。

那么bootloader最初是怎么烧写到flash中的呢?对于一个裸板怎么让它跑起来呢?有两种方式:

² 通过片内固化的loader加载bootloader:通常某些CPU内部ROM中固化了一段程序可以用于最初的程序下载,如AT91RM9200。这时下载的程序是在内部RAM中运行的,大小有一定限制,然后由这段程序继续交互下载真正要烧写到flash中的程序,将其保存在外部RAM中,最终烧写到flash中。

² 通过JTAG或者仿真器下载:通常这些烧录工具可以直接操作flash,对其进行编程烧录。需要专门的工具。这种情况多用于那些没有固化loader的CPU,如三星系列。

上图是一个同时装有Boot Loader、内核的启动参数、内核映像和根文件系统映像的固态存储设备的典型空间分配结构图。上述顺序是可变的,但bootloader首地址一定要在CPU复位取指的地址上。

1.4 Boot Loader的操作模式(Operation Mode)

主机和目标机之间一般通过串口建立连接,BootLoader软件在执行时通常会通过串口来进行数据传输,如输出打印信息到串口,从串口读取用户控制字符。

大多数Boot Loader都包含两种不同的操作模式:启动加载模式和下载模式,这种区别仅对于开发人员才有意义。从最终用户的角度看,BootLoader的作用就是用来加载操作系统,而并不存在所谓的启动加载模式与下载工作模式的区别。

² 启动加载(Boot loading)模式:这种模式也称为自主模式bootstrap。也即Boot Loader将存储在目标板Flash中的内核和文件系统的镜像装载到SDRAM中,整个过程无需用户的介入。这种模式是BootLoader的正常工作模式,因此在嵌入式产品发布的时候,BootLoader显然必须工作在这种模式下。

² 下载Downloading模式:在这种模式下,目标机上的BootLoader将通过串口连接或网络连接等通信手段从宿主机Host下载文件,比如下载内核映像和根文件系统映像等。从主机下载的文件通常首先被BootLoader保存到目标机的RAM中,然后再被BootLoader写到目标机上的FLASH类固态存储设备中。BootLoader的这种模式通常在第一次安装内核与根文件系统时被使用;此外,以后的系统更新(bootloader自身也可以这样更新)也会使用Boot Loader的这种工作模式。工作于这种模式下的BootLoader通常都会向它的终端用户提供一些简单的命令行接口。

像U-BOOT等这样功能强大的BootLoader通常同时支持这两种工作模式,而且允许用户在这两种工作模式之间进行切换。比如,U-BOOT在启动时处于正常的启动加载模式,但是它会延时几秒(在配置文件中可以设定)等待终端用户按下任意键而将其切换到下载模式(相当于bios下按del键可进入系统配置界面一样,设置从光盘启动可进行重装),如果在给定时间内没有用户按键,则U-BOOT继续启动,进行正常的启动加载。

1.5 Bootloader与主机之间进行文件传输所用的通信设备及协议

最常见的情况就是,目标机上的BootLoader通过串口与主机之间进行文件传输,传输协议通常是kermit / xmodem / ymodem协议中的一种。但是,串口传输的速度是有限的,因此如果该Bootloader对目标板的网卡支持良好,还可以通过以太网连接并借助TFTP (Trivial File Transfer Protocol)协议来下载文件是个更好的选择。此时,主机方所用的软件也要考虑,比如,在通过以太网连接和TFTP协议来下载文件时,主机方必须有一个软件用来提供TFTP服务,如Windows平台上的tftpd.exe等或Linux下面的tftp服务器。

1.6 Bootloader的通用执行流程

从操作系统的角度看,Bootloader的总目标就是正确地调用内核来执行。另外,由于Bootloader的实现依赖于 CPU的体系结构,因此大多数Bootloader都分为stagel和stage2两大部分。依赖于CPU体系结构的代码,比如设备初始化代码等,通常都放在stagel中,而且通常都用汇编语言来实现,以达到短小精悍和高效的目的。而stage2则通常用C语言来实现,这样可以实现更复杂的功能,而且代码会具有更好的可读性和可移植性。

Bootloader的stagel为位置无关代码,通常在FLASH中运行。所有的指令为相对寻址,可以在任何位置运行。通常包括以下步骤(以执行的先后顺序):

Ø 硬件设备初始化(配置SDRAM存储控制器及IO),中断初始化;

Ø 为加载Bootloader的stage2准备RAM空间(这个地址由链接脚本指定,为运行域地址,通常为RAM的高端地址),测试内存空间是否有效;

Ø 拷贝Bootloader的stage2到RAM空间中;

Ø 设置好堆栈;

Ø 跳转到stage2的C入口点。

Bootloader的stage2通常被拷贝到RAM中运行,这样可以提高运行速度。通常包括以下步骤(以执行的先后顺序):

Ø 初始化本阶段要使用到的硬件设备;

Ø 检测系统内存映射(memory map);

Ø 没有用户干预时将kernel映像和根文件系统映像从flash读到RAM空间中;

Ø 为内核设置启动参数;

Ø 调用内核。

U-BOOT全线移植分析系列之二

――U-boot基础

Sailor_forever sailing_9806@163.com 转载请注明

http://blog.youkuaiyun.com/sailor_8318/archive/2008/08/04/2768049.aspx

【摘要】本节介绍了U-boot的基本概念。首先介绍了U-boot源代码的目录结构,并给出了一个实例。接着简单介绍了U-boot支持的基本功能、常见命令和环境变量。最后详细分析了U-boot启动的两个阶段,重点介绍了加载拷贝代码至RAM中的过程。

【关键词】bootloader,U-boot,环境变量, stage1,位置无关,代码搬移

U-boot基础

现在为Linux开放源代码Bootloader有很多,blob、 redboot及U-BOOT等,其中U-BOOT是目前用来开发嵌入式系统引导代码使用最为广泛的Bootloader。它支持POWERPC、ARM、MIPS和 X86等处理器,支持嵌入式操作系统有Linux、Vxworks及NetBSD等。

2.1 U-boot源代码目录结构

|-- board 平台依赖,存放电路板相关的目录文件

|-- common 通用多功能函数的实现

|-- cpu 平台依赖,存放cpu相关的目录文件

|-- disk 通用。硬盘接口程序

|-- doc 文档

|-- drivers 通用的设备驱动程序,如以太网接口驱动

|-- dtt

|-- examples 应用例子

|-- fs 通用存放文件系统的程序

|-- include 头文件和开发板配置文件,所有开发板配置文件放在其configs里

|-- lib_arm 平台依赖,存放arm架构通用文件

|-- lib_generic 通用的库函数

|-- lib_i386 平台依赖,存放x86架构通用文件

|-- lib_m68k 平台依赖

|-- lib_microblaze 平台依赖

|-- lib_mips 平台依赖

|-- lib_nios 平台依赖

|-- lib_ppc平台依赖,存放ppc架构通用文件

|-- net 存放网络的程序

|-- post 存放上电自检程序

|-- rtc rtc的驱动程序

`-- tools 工具

详细实例:

² board:开发板相关的源码,不同的板子对应一个子目录,内部放着主板相关代码。 Board/at91rm9200dk/at91rm9200.c, config.mk, Makefile, flash.c ,u-boot.lds等都和具体开发板的硬件和地址分配有关。

² common:与体系结构无关的代码文件,实现了u-boot所有命令,其中内置了一个shell脚本解释器(hush.c, a prototype Bourne shell grammar parser), busybox中也使用了它。

² cpu:与cpu相关代码文件,其中的所有子目录都是以u-boot所支持的cpu命名。

cpu/at91rm9200/at45.c, at91rm9200_ether.c, cpu.c, interrupts.c serial.c, start.S, config.mk, Makefile等。其中:

cpu.c负责初始化CPU、设置指令Cache和数据Cache等;

interrupt.c负责设置系统的各种中断和异常,比如快速中断、开关中断、时钟中断、软件中断、预取中止和未定义指令等;

start.S负责u-boot启动时执行的第一个文件,它主要是设置系统堆栈和工作方式,为跳转到C程序入口点做准备;

at91rm9200_ether.c和serial.c很重要,这是系统能够下载资源的前提。

² disk:设备分区处理代码。

² doc:u-boot相关文档。

² drivers:u-boot所支持的设备驱动代码, 网卡、支持CFI的Flash、串口和USB总线等。

² fs: u-boot所支持文件系统访问存取代码, 如jffs2。

² include:u-boot head文件,主要是与各种硬件平台相关的头文件,如include/asm-arm/arch-at91rm9200/AT91RM9200.h(硬件寄存器名称及地址的定义), hardware.h (内存及flash地址以及IO物理地址和虚拟地址的定义),include/asm-arm/proc-armv(与具体的CPU无关,无需移植)。

² net:与网络有关的代码,BOOTP协议、TFTP协议、RARP协议代码实现. 无需移植。

² lib_arm:与arm体系相关的代码。

² tools:编译后会生成mkimage工具,用来对生成的raw bin文件加入u-boot特定的image_header.

2.2 U-Boot支持的主要功能

主要功能如下:

² 系统引导,支持NFS挂载、RAMDISK(压缩或非压缩)形式的根文件系统;

² 支持NFS挂载、从FLASH中引导压缩或非压缩系统内核;

² 基本辅助功能,强大的操作系统接口功能;可灵活设置、传递多个关键参数给操作系统,适合系统在不同开发阶段的调试要求与产品发布,尤对Linux支持最为强劲;

² 支持目标板环境参数多种存储方式,如FLASH、NVRAM、EEPROM;

² CRC32校验,可校验FLASH中内核、RAMDISK镜像文件是否完好;

² 设备驱动,串口、SDRAM、FLASH、以太网、LCD、NVRAM、EEPROM、键盘、USB、PCMCIA、PCI、RTC等驱动支持;

² 上电自检功能 SDRAM、FLASH大小自动检测;SDRAM故障检测;CPU型号;

² 特殊功能,XIP内核引导。

2.3 U-boot命令介绍及环境变量

² ?得到所有命令列表

² Help:help usb, 列出USB功能的使用说明

² ping:注意只能开发板PING别的机器(AT91RM9200不支持,需要进行配置)

² setenv: 设置环境变量

Ø setenv serverip 192.168.0.1

Ø setenv ipaddr 192.168.0.56

Ø setenv bootcmd ‘tftp 32000000 vmlinux; kgo 32000000’

² saveenv:保存环境变量。在设置好环境变量以后, 保存变量值

² tftp:tftp 32000000 vmlinux, 把server(IP=环境变量中设置的serverip)中/tftpboot/下的vmlinux通过TFTP读入到物理内存32000000处

² bootp- 通过网络用 BootP/TFTP 协议来启动映象

² tftpboot- 通过网络用 TFTP 协议、设置服务器和客户机的 IP 地址进行映象文件传送

² kgo: 起动没有压缩的linux内核,kgo 32000000(AT91RM9200不支持)

² bootm:起动UBOOT TOOLS制作的压缩LINUX内核, bootm 3200000

² protect: 对FLASH进行写保护或取消写保护,protect on 1:0-3(就是对第一块FLASH的0-3扇区进行保护),protect off 1:0-3取消写保护

² erase:删除FLASH的扇区, erase 1:0-2(就是对每一块FLASH的0-2扇区进行删除)

² cp: 在内存中复制内容, cp 32000000 0 40000(把内存中0x32000000开始的0x40000字节复制到0x0处)

² mw: 对RAM中的内容写操作, mw 32000000 ff 10000(把内存0x32000000开始的0x10000字节设为0xFF)

² md: 修改RAM中的内容, md 32000000(内存的起始地址)

² flinfo: 列出flash的信息

² loadb: 准备用KERMIT协议接收来自kermit或超级终端传送的文件。

² nfs: nfs 32000000 192.168.0.12:aa.txt,把192.168.0.12(LINUX 的NFS文件系统)中的NFS文件系统中的aa.txt 读入内存0x32000000处。

最常用的几个命令如下:

² go- 在地址 'addr' 处开始程序执行

² run- 运行一个环境变量所定义的命令

² bootm- 从内存中进行运行经过mkimage加工的程序映象

² loadb- 通过串口线(kermit mode) 来装载二进制文件

² printenv- 打印环境变量

² setenv- 设置环境变量

² saveenv保存环境变量到内存

² tftp-通过网络下载文件

² protect,erase,flash读写

下面是 U-BOOT 中的简单环境变量

² baudrate波特率

² bootdelay boot 延迟

² bootcmd Boot 命令

² bootargs Boot 参数,传递给内核

² bootfile 默认下载启动的内核映象

² ipaddr 客户机 IP 地址

² serverip 服务器地址

² loadaddr 装载地址

² ethaddr 网卡 MAC 地址

2.4 U-Boot的启动流程分析

和大多数的Bootloader一样,U-BOOT的启动分为两个阶段两个部分,依赖于CPU体系结构的代码主要放在stage1,且用汇编来实现,而stage2则通常用C语言来实现,这样可以实现复杂的功能,而且具有更好的可读性和可移植性。

下面分别分析一下这两个阶段的启动流程:

第一阶段:基本的硬件初始化,为第二阶段程序运行建立环境(cpu/ at91rm9200/start.s文件的代码部分):

××××××××××××××××××××××××××××

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")

OUTPUT_ARCH(arm)

ENTRY(_start) // 程序的入口在/cpu/××××/start.s中定义

SECTIONS

{

. = 0x00000000; // 程序链接的地址

. = ALIGN(4);

.text :

{

cpu/at91rm9200/start.o (.text)

*(.text)

}

. = ALIGN(4);

.rodata : { *(.rodata) }

. = ALIGN(4);

.data : { *(.data) }

. = ALIGN(4);

.got : { *(.got) }

__u_boot_cmd_start = .;

.u_boot_cmd : { *(.u_boot_cmd) }

__u_boot_cmd_end = .;

armboot_end_data = .; //代码段结束地址

. = ALIGN(4);

.bss : { *(.bss) }

armboot_end = .; //整个U-boot印象的结束地址

}

××××××××××××××××××××××××××××

在此需要定义程序入口,由于一个可执行的Image必须要有一个入口点,并且只能有一个全局入口,通常这个入口就在ROM (flash)的0x0地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本u-boot.lds来完成,该阶段需要依次完成的工作一般包括:

² CPU自身的初始化,它包括:CPU运行模式的设置(管理模式)、设置异常的入口地址和异常处理函数、运行时钟频率的设置等工作。

² 初始化GPIO和内存控制器。

² 为拷贝Stage2准备RAM空间。

² 进行自拷贝,将U-BOOT的Stage2拷贝到RAM中。

² 设置好堆栈。

² 跳转到Stage2的入口,从而转到RAM中执行,该工作是调用指令ldr pc, start armboot来完成的。

××××××××××××××××××××××××××

从1.1.2开始,u-boot有初始化SDRAM并拷贝自己到SDRAM运行的代码,而之前的版本就没有这个功能(详细查看下代码??的确如此,因此对于以前的版本TEXT_BASE没有起作用?实际测试下??)。board/ at91rm9200dk中config.mk文件(TEXT_BASE = 0x21f00000,32M RAM的设置,为第二阶段程序在RAM中的运行地址)用于设置程序编译连接的起始地址,在程序中要特别注意与地址相关指令的使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值