一、Bootloader
对于计算机系统来说,从开机上电到操作系统启动需要一个引导过程。嵌入式Linux系统同样离不开引导程序,这个引导程序就叫作Bootloader。
1. 概念
Bootloader是在操作系统运行之前执行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射表,从而建立适当的系统软硬件环境,为最终调用操作系统内核做好准备。
对于嵌入式系统,Bootloader是基于特定硬件平台来实现的。因此,几乎不可能为所有的嵌入式系统建立一个通用的Bootloader,不同的处理器架构都有不同的Bootloader。
Bootloader不但依赖于CPU的体系结构,而且依赖于嵌入式系统板级设备的配置。对于2块不同的嵌入式板而言,即使它们使用同一种处理器,要想让运行在一块板子上的Bootloader程序也能运行在另一块板子上,一般也都需要修改Bootloader的源程序。
反过来,大部分Bootloader仍然具有很多共性,某些Bootloader也能够支持多种体系结构的嵌入式系统。
例如,U-Boot就同时支持PowerPC、ARM、MIPS和X86等体系结构,支持的板子有上百种。通常,它们都能够自动从存储介质上启动,都能够引导操作系统启动,并且大部分都可以支持串口和以太网接口。
2. 分类
嵌入式系统世界已经有各种各样的Bootloader,种类划分也有多种方式。除了按照处理器体系结构不同划分以外,还有功能复杂程度的不同。
目前,嵌入式系统中广泛应用的BootLoader有U-Boot、vivi、blob、ARMBoot、RedBoot等。
4.2.2 vivi
vivi是由韩国Mizi公司开发的一种BootLoader,专门针对ARM9处理器而设计,支持S3C2410x处理器。和所有的BootLoader一样,vivi有两种工作模式,即启动加载模式和下载模式。当vivi处于下载模式时,它为用户提供一个命令行接口,通过该接口可以使用vivi提供的一些命令。
4.2.3 Blob
Blob(BootLoader Object)是由Jan-Derk Bakker和Erik Mouw发布,专为StrongARM构架下的LART设计的BootLoader。
Blob支持SA1100的LART主板,但用户也可以自行修改移植。Blob也提供两种工作模式,在启动时处于正常的启动加载模式,但是它会延时10秒等待终端用户按下任意键而将Blob 切换到下载模式。如果在10秒内没有用户按键,则Blob继续启动Linux内核。
Blob功能比较齐全,代码较少,比较适合做修改移植,用来引导Liunx,目前大部分S3C44B0板都用Blob修改移植后来加载uCLinux。
4.2.4 ARMboot
ARMboot是一个ARM平台的开源固件项目,它严重依赖于PPCBoot。ARMboot支持的处理器构架有StrongARM,ARM720T,PXA250等,是为基于ARM或者StrongARM CPU的嵌入式系统所设计的。ARMboot的目标是成为通用的、容易使用和移植的引导程序,非常轻便地运用于新的平台上。
总得来说,ARMboot介于大、小型BootLoader之间,相对轻便,基本功能完备,缺点是缺乏后续支持。ARMboot发布的最后版本为ARMboot–1.1.0,2002年终止了ARMboot的维护。
4.2.5 RedBoot
RedBoot是标准的嵌入式调试和引导解决方案,是一个专门为嵌入式系统定制的引导工具,最初由Redhat开发,是嵌入式操作系统eCos的一个最小版本,是随eCos发布的一个BOOT方案,是一个开源项目。现在交由*软件组织FSF管理,遵循GPL。集BootLoader、调试、Flash烧写于一体。支持串口、网络下载、执行嵌入式应用程序。既可以用在产品的开发阶段(调试功能),也可以用在最终的产品上(Flash更新、网络启动)。
RedBoot支持的处理器构架有ARM、MIPS、PowerPC、x86等,是一个完善的嵌入式系统BootLoader。
对于每种体系结构,都有一系列开放源码Bootloader可以选用。
(1)X86
X86的工作站和服务器上一般使用LILO和GRUB。LILO是Linux发行版主流的Bootloader。不过Redhat Linux发行版已经使用了GRUB,GRUB比LILO有更有好的显示界面,使用配置也更加灵活方便。
在某些X86嵌入式单板机或者特殊设备上,会采用其他Bootloader,例如:ROLO。这些Bootloader可以取代BIOS的功能,能够从FLASH中直接引导Linux启动。现在ROLO支持的开发板已经并入U-Boot,所以U-Boot也可以支持X86平台。
(2)ARM
ARM处理器的芯片商很多,所以每种芯片的开发板都有自己的Bootloader。结果ARM bootloader也变得多种多样。最早有为ARM720处理器的开发板的固件,又有了armboot,StrongARM平台的blob,还有S3C2410处理器开发板上的vivi等。现在armboot已经并入了U-Boot,所以U-Boot也支持ARM/XSCALE平台。U-Boot已经成为ARM平台事实上的标准Bootloader。
(3)PowerPC
PowerPC平台的处理器有标准的Bootloader,就是ppcboot。PPCBOOT在合并armboot等之后,创建了U-Boot,成为各种体系结构开发板的通用引导程序。U-Boot仍然是PowerPC平台的主要Bootloader。
(4)MIPS
MIPS公司开发的YAMON是标准的Bootloader,也有许多MIPS芯片商为自己的开发板写了Bootloader。现在,U-Boot也已经支持MIPS平台。我们自主研究的cpu龙芯采用的是pmon。
(5)SH
SH平台的标准Bootloader是sh-boot。Redboot在这种平台上也很好用。
(6)M68K
M68K平台没有标准的Bootloader。Redboot能够支持m68k系列的系统。
值得说明的是Redboot,它几乎能够支持所有的体系结构,包括MIPS、SH、M68K等体系结构。Redboot是以eCos为基础,采用GPL许可的开源软件工程。现在由core eCos的开发人员维护。
二、uboot
ARM处理器的芯片商很多,所以每种芯片的开发板都有自己的Bootloader。结果ARM bootloader也变得多种多样。
最早有为ARM720处理器的开发板的固件,又有了armboot,StrongARM平台的blob,还有S3C2410处理器开发板上的vivi等。现在armboot已经并入了U-Boot,所以U-Boot也支持ARM/XSCALE平台。
U-Boot已经成为ARM平台事实上的标准Bootloader。
1. 概念
U-Boot,全称 Universal Boot Loader,是遵循GPL条款的从FADSROM、8xxROM、PPCBOOT逐步发展演化而来的开放源码项目,是一套在GNU通用公共许可证之下发布的*软件。
U-Boot 是一个主要用于嵌入式系统的引导加载程序,可以支持多种不同的计算机系统结构,包括PPC、ARM、AVR32、MIPS、x86、68k、Nios与MicroBlaze等诸多常用系列的处理器。
在操作系统方面,U-Boot不仅支持嵌入式Linux系统的引导,它还支持NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS, android嵌入式操作系统。目前支持的目标操作系统是OpenBSD, NetBSD, FreeBSD,4.4BSD, Linux, SVR4, Esix, Solaris, Irix, SCO, Dell, NCR, VxWorks, LynxOS, pSOS, QNX, RTEMS, ARTOS, android。
U-Boot项目的开发目标是支持尽可能多的嵌入式处理器和嵌入式操作系统。
2. uboot的特性
Uboot的特性:
- 开放源码;
- 支持多种嵌入式操作系统内核,如Linux、NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS, android;
- 支持多个处理器系列,如PowerPC、ARM、x86、MIPS;
- 较高的可靠性和稳定性;
- 高度灵活的功能设置,适合U-Boot调试、操作系统不同引导要求、产品发布等;
- 丰富的设备驱动源码,如串口、以太网、SDRAM、FLASH、LCD、NVRAM、EEPROM、RTC、键盘等;
- 较为丰富的开发调试文档与强大的网络技术支持;
3. 主要功能
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内核引导;
4. 工作模式
U-Boot的工作模式有启动加载模式和下载模式。
- 启动加载模式
启动加载模式是Bootloader的正常工作模式,嵌入式产品发布时,Bootloader必须工作在这种模式下,Bootloader将嵌入式操作系统从FLASH中加载到SDRAM中运行,整个过程是自动的。
- 下载模式
下载模式就是Bootloader通过某些通信手段将内核映像或根文件系统映像等从PC机中下载到目标板的FLASH中。用户可以利用Bootloader提供的一些命令接口来完成自己想要的操作。
开发人员可以使用各种命令,通过串口连接或网络连接等通信手段从主机(Host)下载文件(比如内核映像、文件系统映像),将它们直接放在内存运行或是烧入Flash类固态存储设备中。
板子与主机间传输文件时,可以使用串口的xmodem/ymodem/zmodem协议,还可以使用网络通过tftp、nfs协议来传输,以及USB下载等方法。
一般来说,嵌入式开发人员采用下载模式进行开发嵌入式系统。通常采用交叉网线将PC与目标开发板连接,通过TFTP服务器下载内核,用NFS服务器挂载文件系统。
5. uboot常用命令
- 获取命令
命令:help 或 ?
功能:查看当前U-boot版本中支持的所有命令。
- 环境变量命令
命令 | 含义 |
---|---|
bootdelay | 执行自动启动(bootcmd中的命令)的等候秒数 |
baudrate | 串口控制台的波特率 |
netmask | 以太网的网络掩码 |
ethaddr | 以太网的MAC地址 |
bootfile | 默认的下载文件名 |
bootargs | 传递给Linux内核的启动参数 |
printenv | 打印Uboot环境变量 |
setenv | 设置Uboot环境变量 |
ipaddr | 本地的IP地址 |
serverip | TFTP服务器端的IP地址 |
gateway | 以太网的网关 |
bootcmd | 自动启动时执行命令 |
bootargs | 传递给Linux内核的启动参数 |
bootm | 引导启动存储在内存中的程序映像。这些内存包括RAM和可以永久保存的Flash |
stdin | 标准输入设备,一般是串口 |
stdout | 标准输出,一般是串口,也可是LCD(VGA) |
stderr | 标准出错,一般是串口,也可是LCD(VGA) |
使用printenv命令可以打印出当前开发板的环境变量。
setenv envname value设置环境变量的值,如果没有value,则表示删除env环境变量
saveenv将修改的环境变量保存到固态存储器中。
bootcmd 自动启动执行命令,uboot开机后会自动倒计时,在倒计时结束前如果没有外部按键打断自动计时,uboot将自动执行bootcmd变量保存的命令。
- 串口传输命令
- loadb - load binary file over serial line (kermit mode)
- loadx - load binary file over serial line (xmodem mode)
- loady - load binary file over serial line (ymodem mode)
- 网络命令
uboot可以通过网络来传输文件到开发板,直接用交叉网线连接开发板和电脑,也可以用普通直连网线连接路由器。
ping hostname
网络不通的原因:
A、U-boot网卡驱动有问题
B、U-boot网络协议延时配置有问题
C、网络参数配置问题,比如IP等,Host和Target都有可能有问题。
如果网络连通,就可以通过tftp、NFS挂载开发板
nfs - boot p_w_picpath via network using NFS protocol tftpboot- boot p_w_picpath via network using TFTP protocol bootp - boot p_w_picpath via network using BOOTP/TFTP protocol
- NandFlash操作命令
nand info 显示可使用的Nand Flash
nand device [dev] 显示或设定当前使用的Nand Flash
nand read addr off sizeNand Flash 读取命令,从Nand的off偏移地址处读取size字节的数据到SDRAM的addr地址。
nand write addr off size Nand Flash烧写命令,将SDRAM的addr地址处的size字节的数据烧写到Nand的off偏移地址。
nand write[.yaffs[1]] addr off size 烧写yaffs 映像专用的命令,.yaffs1 for 512+16 NAND
nand erase [clean] [off size] Nand Flash檫除命令,擦除Nand Flash的 off 偏移地址处的size 字节的数据
nand bad 显示Nand Flash的坏块
nand dump[.oob] off 显示Nand Flash中的数据(16进制)
nand scrub 彻底擦除整块Nand Flash中的数据,包括OOB。可以擦除软件坏块标志。
nand markbad off 标示 Nand的 off 偏移地址处的块为坏块
- 内存、寄存器操作命令
nm 修改内存值 (指定地址)
格式: nm [.b, .w, .l] address
mm 修改内存值(地址自动加一)
格式: mm [.b, .w, .l] address
md 显示内存值
格式: md [.b, .w, .l] address [# of objects]
mw 用指定的数据填充内存
格式: mw [.b, .w, .l] address value [count]
cp 内存的拷贝(包括内存与Nor Flash间的数据拷贝)
格式:cp [.b, .w, .l] source target count
- USB操作命令
usb reset 初始化USB控制器
usb stop [f] 关闭USB控制器
usb tree 已连接的USB设备树
usb info [dev] 显示USB设备[dev]的信息
usb storage 显示已连接的USB存储设备
usb dev [dev] 显示和设置当前USB存储设备
usb part [dev] 显示USB存储设备[dev]的分区信息
usb read addr blk# cnt 读取USB存储设备数据
使用USB操作命令前必须确保USB设备连接好,usb reset,以初始化USB控制器,获取设备信息。
- SD/MMC操作命令
mmc init [dev] - 初始化MMC子系统
mmc device [dev] - 查看和设置当前设备
使用SD/MMC操作命令前必须确保SD/MMC设备连接好,mmc init,以初始化MMC 控制器,获取设备信息。
三、配置举例
本书并不涉及到Linux内核编译,下面配置信息仅作参考。
下面以tftp下载内核、网络挂载nfs文件系统为例。
1)配置ubuntu
ubuntu ip:192.168.6.186
nfs配置:
配置文件如下:
/etc/exports
配置信息如下:
11 /rootfs *(rw,sync,no_subtree_check,no_root_squash)
2)开发板设置
开发板ip:192.168.6.187
配置命令:
setenv ipaddr 192.168.6.187 ;板子的ip setenv serverip 192.168.6.186 ;虚拟机的ip setenv gatewayip 192.168.1.1 ;网关 saveenv ;保存配置
- 加载内核和设备树
setenv bootcmd tftp 41000000 uImage\;tftp 42000000 exynos4412-fs4412.dtb\;bootm 41000000 - 42000000
- bootcmd:uboot启动之后,首先先执行找到这个参数,执行后面的命令;
- tftp:从serverip 192.168.6.186的根目录下载文件uImage到地址41000000 ;
- uImage:内核镜像;
- exynos4412-origen.dtb:设备树文件;
- bootm 41000000 - 42000000 引导内核,并传入地址。
从tftp服务器下载内核镜像uImage到地址41000000,设备树文件exynos4412-fs4412.dtb到42000000,并通过命令bootm加载启动内核。
- 挂载nfs
setenv bootargs root=/dev/nfs nfsroot=192.168.6.186:/rootfs rw console=ttySAC2,115200 init=/linuxrc ip=192.168.6.187
挂载nfs文件系统,
- root=/dev/nfs
- nfsroot=192.168.6.186:/rootfs nfs服务器地址192.168.6.186,目录为/rootfs,
- rw 文件系统操作权限为可续写
- console=ttySAC2,115200 串口名称和波特率
- init=/linuxrc 内核启动后运行的进程为linuxrc
- ip=192.168.6.187 开发板地址
四、uboot源码简介
1. 下载源码
我们可以在下面这个网站上下载任一版本的uboot:
ftp://ftp.denx.de/pub/u-boot/ git://git.denx.de/u-boot.git http://git.denx.de/u-boot.git
2. 解压uboot源码
将uboot源码拷贝到ubuntu一下目录:/home/peng/uboot/
然后解压
tar jxvf u-boot-2013.01.tar.bz2
root@ubuntu:/home/peng/uboot/u-boot-2013.01# ls api boards.cfg COPYING doc examples include MAKEALL nand_spl README spl arch common CREDITS drivers fs lib Makefile net rules.mk test board config.mk disk dts helper.mk MAINTAINERS mkconfig post snapshot.commit tools
3. 目录介绍
u-boot目录结构各个版本之间都有差异,有的甚至差异非常大,读者在分析的时候要根据实际情况,不要教条。
uboot-2013主要目录如下:
表6.2 U-Boot的源码顶层主要目录说明
目 录 | 特 性 | 解 释 说 明 |
---|---|---|
arch | 平台依赖 | 与体系结构相关的代码 |
board | 平台依赖 | 根据不同开发板定制的代码,例如:RPXlite(mpc8xx)、smdk2410(arm920t)、sc520_cdp(x86) 等目录 |
cpu | 平台依赖 | 存放CPU相关的目录文件,例如:mpc8xx、ppc4xx、arm720t、arm920t、 xscale、i386等目录 |
lib | 通用 | 通用库文件 |
nand_spl | 通用 | NAND存储器相关代码 |
include | 通用 | 头文件和开发板配置文件,所有开发板的配置文件都在configs目录下 |
common | 通用 | 通用的代码,涵盖各个方面,以命令行处理为主 |
net | 通用 | 网络相关代码,小型的协议栈 |
fs | 通用 | 文件系统,支持嵌入式开发板常见的文件系统 |
post | 通用 | 存放上电自检程序 |
drivers | 通用 | 通用的设备驱动程序,比如i2c、spi、网卡、usb、video等驱动,每种类型的设备驱动占用一个子目录 |
disk | 通用 | 磁盘分区相关代码 |
examples | 应用例程 | 一些独立运行的应用程序的例子,例如helloworld |
tools | 工具 | 存放制作S-Record 或者 U-Boot格式的映像等工具,例如mkimage |
doc | 文档 | 开发使用文档,模块说明文档,均以README开头,后缀为对应的模块 |
4、移植工作涉及的目录情况
从uboot代码根目录,可以看出其已经非常庞大,功能也很丰富。
移植工作最主要的是看对应的处理器和开发板代码,2010.06版本以后处理器相关的代码集中在arch、board目录。(以前版本主要在cpu和board目录)
先看一下arch目录:
arch ├── arm ├── avr32 ├── blackfin ├── i386 ├── m68k ├── microblaze ├── mips ├── nios2 ├── powerpc ├── sh └── sparc
arch目录下每个子目录代表一个处理器类型,子目录名称就是处理器的类型名称。
我们移植的是arm的处理器,所以参考一下arch/arm目录:
arch/arm ├── cpu ├── dts ├── imx-common ├── include └── lib
arch/arm目录下有5个目录,其他的处理器目录下类似这个结构,但是会有差别,主要关注以下4个目录:
- cpu子目录对应一种处理器的不同产品型号或者系列;
- dts是设备树文件,uboot对设备的支持越来越好
- include子目录是处理器用到的头文件;
- lib目录对应用到处理器公用的代码。
下面看看cpu下的内容,arch/arm/cpu目录下的内容:
arch/arm/cpu ├── arm1136 ├── arm1176 ├── arm720t ├── arm920t ├── arm925t ├── arm926ejs ├── arm946es ├── arm_intcm ├── armv7 我们CPU架构 │ ├── am33xx │ ├── exynos 我们CPU的类型 │ ├── highbank │ ├── mx5 │ ├── mx6 │ ├── omap3 │ ├── omap4 │ ├── omap5 │ ├── omap-common │ ├── rmobile │ ├── s5pc1xx │ ├── s5p-common │ ├── socfpga │ ├── tegra20 │ ├── tegra-common │ ├── u8500 │ └── zynq ├── ixp ├── pxa ├── s3c44b0 ├── sa1100 ├── tegra20-common ├── tegra-common └── u-boot.lds 整个uboot代码入口点
exynos4412是armv7架构,对应的cpu类型是exynos;
u-boot.lds是ld链接器的脚本文件,这个文件描述了如何连接目标文件,ld程序会根据这个文件的指示按照需求把不同的目标文件连接在一起生成供烧写到开发板的程序,详细内容参考前面章节。
由于u-boot的各版本没有重大变化,各版本移植起来基本相同,也正因为如此,大多数版本均有人移植过,主要是arm体系结构的。