锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

bootloader 详细介绍

时间:2023-05-12 04:07:00 温度传感器型号86x86mm

Bootloader

对于计算机系统来说,从启动到启动操作系统需要一个指导过程。Linux系统也离不开引导程序,称为引导程序Bootloader。

6.1.1 Bootloader介绍

Bootloader是操作系统运行前执行的小程序。通过这个小程序,我们可以初始化硬件设备,建立内存空间的映射表,从而建立适当的系统软硬件环境,为最终调用操作系统核心做好准备。

嵌入式系统,Bootloader是基于特定硬件平台来实现的。因此,几乎不可能为所有的嵌入式系统建立一个通用的Bootloader,不同的处理器结构不同Bootloader。Bootloader不但依赖于CPU系统结构取决于嵌入式系统板级设备的配置。对于两个不同的嵌入式板,即使它们使用相同的处理器,它们也希望运行在一个板上Bootloader程序也能运行在另一块板子上,一般也都需要修改Bootloader的源程序。

反过来,大多数Bootloader仍然具有很多共性,某些Bootloader嵌入式系统也可以支持多种系统结构。U-Boot就同时支持PowerPC、ARM、MIPS和X86等系统结构支持数百块板。通常,它们可以自动从存储介质开始,引导操作系统开始,其中大多数可以支持串口和以太网接口。

本章将是各种各样的Bootloader总结分类,分析它们的共同特征。U-Boot例如,详细讨论Bootloader设计与实现。

6.1.2 Bootloader的启动

Linux系统是通过Bootloader引导启动。一上电,就要执行Bootloader初始化系统。可以通过第四章Linux回顾启动过程框图。

所有系统加电或复位后CPU它将从处理器设计决定的地址开始。X高地址端有86个复位向量,ARM处理器从地址0复位x取第一条指令。嵌入式系统的开发板应该放在板上ROM或Flash这个地址必须映射。Bootloader相应地存储程序Flash位置。系统加电后,CPU它将首先执行。

主机和目标机之间通常有串口,Bootloader该软件通常通过串口输入输出。例如:输出错误或执行结果信息到串口终端,从串口终端读取用户控制命令等。

Bootloader启动过程通常是多阶段的,可以提供复杂的功能和良好的可移植性。例如:从Flash启动的Bootloader大部分是两个阶段的启动过程。从后面开始。U-Boot这一特征可以详细分析。

大多数Bootloader它们都包括两种不同的操作模式:本地加载模式和远程下载模式。这两种操作模式之间的只对开发人员有意义,即使用不同的启动模式。从最终用户的角度来看,Bootloader其功能是加载操作系统,没有所谓的本地加载模式和远程下载模式的区别。

因为Bootloader主要功能是引导操作系统启动,所以我们详细讨论了各种启动方法的特点。

1.网络启动模式

这样,开发板就不需要配置大的存储介质,这有点类似于无盘工作站。但在使用这种启动方法之前,需要使用它Bootloader安装在板上EPROM或者Flash中。Bootloader远程下载Linux内核图像或文件系统。第四章介绍的交叉开发环境是通过网络启动建立的。这种方法对嵌入式系统的开发非常重要。

使用这种方法也有先决条件,即目标板有串口、以太网接口或其他连接方式。串口通常可以作为控制台下载内核图像和RAMDISK文件系统。串口通信传输速率过低,不适合挂接NFS文件系统。因此,以太网接口已成为一种通用的互连设备,一般开发板可配备10个M以太网接口。

对于PDA对于手持设备,以太网RJ-45接口更大,USB特别是接口USB迷你接口尺寸很小。对于开发的嵌入式系统,可以使用USB接口虚拟成以太网接口来通讯。这种方式在开发主机和开发板两端都需要驱动程序。

此外,还应在服务器上配置相关网络服务。Bootloader一般使用下载文件TFTP网络协议也可以通过DHCP动态配置模式IP地址。

DHCP/BOOTP服务为Bootloader分配IP在支持网络传输功能之前,配置网络参数。Bootloader网络参数可以直接设置,不用DHCP。

TFTP服务为Bootloader客户提供文件下载功能,将内核图像和其他文件放在/tftpboot目录下Bootloader通过简单TFTP协议远程下载内核图像到内存。

大多数引导程序都能支持网络启动。BIOS的PXE(Preboot Execution Environment)功能是网络启动模式;U-Boot还支持网络启动功能。

2.磁盘启动模式

传统的Linux系统运行在台式机或者服务器上,这些计算机一般都使用BIOS使用磁盘作为存储介质进行指导。BIOS设置菜单,检测处理器、内存、硬盘等设备BIOS从软盘、光盘或硬盘开始。也就是说,BIOS操作系统不直接引导。所以在硬盘的主导区域,还需要一个Bootloader。这个Bootloader操作系统可以从磁盘文件系统中引导。

Linux传统上是通过LILO(LInux LOader)引导后来又出现了GNU的软件GRUB(GRand Unified Bootloader)。这2种Bootloader广泛应用在X86的Linux系统上。你的开发主机可能就使用了其中一种,熟悉它们有助于配置多种系统引导功能。

LILO软件工程是由Werner Almesberger专门为指导而创建Linux开发LILO的维护者是John Coffman,下载站点的最新版本:http://lilo.go.dyndns.org。LILO例如,有详细的文档LILO手册和参考手册附在套件中。此外,它还可以LDP的“LILO mini-HOWTO”中找到LILO使用指南。

GRUB是GNU计划的主要bootloader。GRUB最初是由Erich Boleyn为GNU Mach操作系统编写的指导程序。后来有了Gordon Matzigkeit和Okuji Yoshinori接替Erich继续维护和开发工作GRUB。GRUB的网站http://www.gnu.org/software/grub/上面有套件使用的说明文件,称为《GRUB manual》。GRUB能够使用TFTP和BOOTP或者DHCP该功能通过网络启动,对系统开发过程非常有用。

除了传统的Linux除了系统上的引导程序外,还有一些其他的引导程序,也可以支持磁盘引导启动。LoadLin可以从DOS下启动Linux;还有ROLO、LinuxBIOS,U-Boot也支持这种功能。

3.Flash启动方式

大多数嵌入式系统都使用Flash存储介质。Flash有很多类型,包括NOR Flash、NAND Flash还有其他半导体盘。NOR Flash(即线性Flash)最常用的使用。

NOR Flash可可以支持随机访问,因此代码可以直接访问Flash上执行的。Bootloader一般存储Flash芯片上的。Linux内核映像和RAMDISK也可以存储Flash上。通常需要把Flash使用分区时,每个区域的大小应该是Flash擦去块大小的整数倍

Bootloader一般放在Flash根据处理器的复位向量设置底部或顶部。Bootloader入口位于处理器上电执行第一条指令的位置。

接下来,参数区的分配可以作为Bootloader参数保存区。

下一步是内核图像区。Bootloader引导Linux内核是从这个地方解压内核图像RAM然后跳转到内核图像入口执行。

然后是文件系统区。如果使用。Ramdisk需要文件系统Bootloader把它解压到RAM中。如果使用JFFS2.文件系统将直接连接到根文件系统。这两个文件系统将在第12章中详细解释。

最后,根据实际需要,可以区分一些数据区Flash考虑大小。

开发者定义了这些分区,Bootloader一般直接读写相应的偏移地址。Linux可配置内核空间MTD设备来访问Flash分区。但是,有的Bootloader还支持分区的功能,如:Redboot可以创建Flash分区表,内核MTD驱动可以分析redboot的分区表。

除了NOR Flash,还有NAND Flash、Compact Flash、DiskOnChip等。这些Flash芯片价格低,存储容量大。但这些芯片通常由专用控制器制成I/O访问方式,不能随机访问,所以指导方法跟进NOR Flash也有所不同。在这些芯片中,需要配置特殊的指导程序。通常,该指南程序的一段代码将整个指南程序复制到RAM中间运行,从而实现自启动,类似于从磁盘上启动。

6.1.3 Bootloader的种类

世界上有各种各样的嵌入式系统Bootloader,分类的方法有很多。除了根据不同的处理器系统结构进行划分外,还具有不同的功能复杂性。

首先,区分Bootloader”和“Monitor概念。严格来说,Bootloader只是指导设备并执行主程序的固件;Monitor还提供了更多的命令行接口,可以调试、阅读和写作内存、烧写Flash、配置环境变量等。Monitor在嵌入式系统开发过程中,可以提供良好的调试功能。开发完成后,完全设置为Bootloader所以习惯上大家都把它们统称为Bootloader。

表6.1列出了Linux开放源代码指导程序及其支持的系统结构。表中给出X86 ARM PowerPC常用的系统结构引导程序,并注明每个引导程序是否Monitor”。

表6.1                     开放源码的Linux 引导程序

 

Bootloader

Monitor

描    述

x86

ARM

PowerPC

LILO

Linux磁盘引导程序

GRUB

GNU的LILO替代程序

Loadlin

从DOS引导Linux

ROLO

从ROM引导Linux而不需要BIOS

Etherboot

通过以太网卡启动Linux系统的固件

LinuxBIOS

完全替代BUIS的Linux引导程序

BLOB

LART等硬件平台的引导程序

U-boot

通用引导程序

RedBoot

基于eCos的引导程序

 

对于每种体系结构,都有一系列开放源码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平台。

(5)SH

SH平台的标准Bootloader是sh-boot。Redboot在这种平台上也很好用。

(6)M68K

M68K平台没有标准的Bootloader。Redboot能够支持m68k系列的系统。

值得说明的是Redboot,它几乎能够支持所有的体系结构,包括MIPS、SH、M68K等体系结构。Redboot是以eCos为基础,采用GPL许可的开源软件工程。现在由core eCos的开发人员维护,源码下载网站是http://www.ecoscentric.com/snapshots。Redboot的文档也相当完善,有详细的使用手册《RedBoot User’s Guide》。
 

6.2.1  U-Boot工程简介

最早,DENX软件工程中心的Wolfgang Denk基于8xxrom的源码创建了PPCBOOT工程,并且不断添加处理器的支持。后来,Sysgo Gmbh把ppcboot移植到ARM平台上,创建了ARMboot工程。然后以ppcboot工程和armboot工程为基础,创建了U-Boot工程。

现在U-Boot已经能够支持PowerPC、ARM、X86、MIPS体系结构的上百种开发板,已经成为功能最多、灵活性最强并且开发最积极的开放源码Bootloader。目前仍然由DENX的Wolfgang Denk维护。

U-Boot的源码包可以从sourceforge网站下载,还可以订阅该网站活跃的U-Boot Users邮件论坛,这个邮件论坛对于U-Boot的开发和使用都很有帮助。

U-Boot软件包下载网站:http://sourceforge.net/project/u-boot。

U-Boot邮件列表网站:http://lists.sourceforge.net/lists/listinfo/u-boot-users/。

DENX相关的网站:http://www.denx.de/re/DPLG.html。
 

6.2.2  U-Boot源码结构

从网站上下载得到U-Boot源码包,例如:U-Boot-1.1.2.tar.bz2

解压就可以得到全部U-Boot源程序。在顶层目录下有18个子目录,分别存放和管理不同的源程序。这些目录中所要存放的文件有其规则,可以分为3类。

· 第1类目录与处理器体系结构或者开发板硬件直接相关;

· 第2类目录是一些通用的函数或者驱动程序;

· 第3类目录是U-Boot的应用程序、工具或者文档。

表6.2列出了U-Boot顶层目录下各级目录存放原则。

表6.2                                                  U-Boot的源码顶层目录说明

 

目    录

特    性

解 释 说 明

board

平台依赖

存放电路板相关的目录文件,例如:RPXlite(mpc8xx)、smdk2410(arm920t)、sc520_cdp(x86) 等目录

cpu

平台依赖

存放CPU相关的目录文件,例如:mpc8xx、ppc4xx、arm720t、arm920t、 xscale、i386等目录

lib_ppc

平台依赖

存放对PowerPC体系结构通用的文件,主要用于实现PowerPC平台通用的函数

目    录

特    性

解 释 说 明

lib_arm

平台依赖

存放对ARM体系结构通用的文件,主要用于实现ARM平台通用的函数

lib_i386

平台依赖

存放对X86体系结构通用的文件,主要用于实现X86平台通用的函数

include

通用

头文件和开发板配置文件,所有开发板的配置文件都在configs目录下

common

通用

通用的多功能函数实现

lib_generic

通用

通用库函数的实现

Net

通用

存放网络的程序

Fs

通用

存放文件系统的程序

Post

通用

存放上电自检程序

drivers

通用

通用的设备驱动程序,主要有以太网接口的驱动

Disk

通用

硬盘接口程序

Rtc

通用

RTC的驱动程序

Dtt

通用

数字温度测量器或者传感器的驱动

examples

应用例程

一些独立运行的应用程序的例子,例如helloworld

tools

工具

存放制作S-Record 或者 U-Boot格式的映像等工具,例如mkimage

Doc

文档

开发使用文档

 

U-Boot的源代码包含对几十种处理器、数百种开发板的支持。可是对于特定的开发板,配置编译过程只需要其中部分程序。这里具体以S3C2410 arm920t处理器为例,具体分析S3C2410处理器和开发板所依赖的程序,以及U-Boot的通用函数和工具。
 

6.2.3  U-Boot的编译

U-Boot的源码是通过GCC和Makefile组织编译的。顶层目录下的Makefile首先可以设置开发板的定义,然后递归地调用各级子目录下的Makefile,最后把编译过的程序链接成U-Boot映像。

1.顶层目录下的Makefile

它负责U-Boot整体配置编译。按照配置的顺序阅读其中关键的几行。

每一种开发板在Makefile都需要有板子配置的定义。例如smdk2410开发板的定义如下。

 

smdk2410_config :   unconfig

     @./mkconfig $(@:_config=) arm arm920t smdk2410 NULL s3c24x0

 

执行配置U-Boot的命令make smdk2410_config,通过./mkconfig脚本生成include/config.
mk的配置文件。文件内容正是根据Makefile对开发板的配置生成的。

 

ARCH   = arm

CPU    = arm920t

BOARD  = smdk2410

SOC    = s3c24x0

 

上面的include/config.mk文件定义了ARCH、CPU、BOARD、SOC这些变量。这样硬件平台依赖的目录文件可以根据这些定义来确定。SMDK2410平台相关目录如下。

board/smdk2410/

cpu/arm920t/

cpu/arm920t/s3c24x0/

lib_arm/

include/asm-arm/

include/configs/smdk2410.h

再回到顶层目录的Makefile文件开始的部分,其中下列几行包含了这些变量的定义。

 

# load ARCH, BOARD, and CPU configuration

include include/config.mk

export       ARCH CPU BOARD VENDOR SOC

 

Makefile的编译选项和规则在顶层目录的config.mk文件中定义。各种体系结构通用的规则直接在这个文件中定义。通过ARCH、CPU、BOARD、SOC等变量为不同硬件平台定义不同选项。不同体系结构的规则分别包含在ppc_config.mk、arm_config.mk、mips_config.mk等文件中。

顶层目录的Makefile中还要定义交叉编译器,以及编译U-Boot所依赖的目标文件。

 

ifeq ($(ARCH),arm)

CROSS_COMPILE = arm-linux-          //交叉编译器的前缀

#endif

export  CROSS_COMPILE

# U-Boot objects....order is important (i.e. start must be first)

OBJS  = cpu/$(CPU)/start.o                  //处理器相关的目标文件

LIBS  = lib_generic/libgeneric.a            //定义依赖的目录,每个目录下先把目标文件连接成*.a文件。

LIBS += board/$(BOARDDIR)/lib$(BOARD).a

LIBS += cpu/$(CPU)/lib$(CPU).a

ifdef SOC

LIBS += cpu/$(CPU)/$(SOC)/lib$(SOC).a

endif

LIBS += lib_$(ARCH)/lib$(ARCH).a

 

然后还有U-Boot映像编译的依赖关系。

 

ALL = u-boot.srec u-boot.bin System.map

all:        $(ALL)

u-boot.srec:    u-boot

            $(OBJCOPY) ${OBJCFLAGS} -O srec $< $@

u-boot.bin: u-boot

            $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@

……

u-boot:         depend $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT)

            UNDEF_SYM='$(OBJDUMP) -x $(LIBS) /

            |sed  -n -e 's/.*/(__u_boot_cmd_.*/)/-u/1/p'|sort|uniq`;/

            $(LD) $(LDFLAGS) $$UNDEF_SYM $(OBJS) /

                 --start-group $(LIBS) $(PLATFORM_LIBS) --end-group /

                 -Map u-boot.map -o u-boot

 

Makefile缺省的编译目标为all,包括u-boot.srec、u-boot.bin、System.map。u-boot.srec和u-boot.bin又依赖于U-Boot。U-Boot就是通过ld命令按照u-boot.map地址表把目标文件组装成u-boot。

其他Makefile内容就不再详细分析了,上述代码分析应该可以为阅读代码提供了一个线索。

2.开发板配置头文件

除了编译过程Makefile以外,还要在程序中为开发板定义配置选项或者参数。这个头文件是include/configs/.h。用相应的BOARD定义代替。

这个头文件中主要定义了两类变量。

一类是选项,前缀是CONFIG_,用来选择处理器、设备接口、命令、属性等。例如:

 

#define   CONFIG_ARM920T         1

#define   CONFIG_DRIVER_CS8900  1

 

另一类是参数,前缀是CFG_,用来定义总线频率、串口波特率、Flash地址等参数。例如:

 

#define     CFG_FLASH_BASE      0x00000000

#define CFG_PROMPT          "=>"

3.编译结果

根据对Makefile的分析,编译分为2步。第1步配置,例如:make smdk2410_config;第2步编译,执行make就可以了。

编译完成后,可以得到U-Boot各种格式的映像文件和符号表,如表6.3所示。

表6.3                                                  U-Boot编译生成的映像文件

 

文 件 名 称

说    明

文 件 名 称

说    明

System.map

U-Boot映像的符号表

u-boot.bin

U-Boot映像原始的二进制格式

u-boot

U-Boot映像的ELF格式

u-boot.srec

U-Boot映像的S-Record格式

 

U-Boot的3种映像格式都可以烧写到Flash中,但需要看加载器能否识别这些格式。一般u-boot.bin最为常用,直接按照二进制格式下载,并且按照绝对地址烧写到Flash中就可以了。U-Boot和u-boot.srec格式映像都自带定位信息。

4.U-Boot工具

在tools目录下还有些U-Boot的工具。这些工具有的也经常用到。表6.4说明了几种工具的用途。

表6.4                                                              U-Boot的工具

 

工 具 名 称

说    明

工 具 名 称

说    明

bmp_logo

制作标记的位图结构体

img2srec

转换SREC格式映像

envcrc

校验u-boot内部嵌入的环境变量

mkimage

转换U-Boot格式映像

gen_eth_addr

生成以太网接口MAC地址

updater

U-Boot自动更新升级工具

 

这些工具都有源代码,可以参考改写其他工具。其中mkimage是很常用的一个工具,Linux内核映像和ramdisk文件系统映像都可以转换成U-Boot的格式。
 

6.2.4  U-Boot的移植

U-Boot能够支持多种体系结构的处理器,支持的开发板也越来越多。因为Bootloader是完全依赖硬件平台的,所以在新电路板上需要移植U-Boot程序。

开始移植U-Boot之前,先要熟悉硬件电路板和处理器。确认U-Boot是否已经支持新开发板的处理器和I/O设备。假如U-Boot已经支持一块非常相似的电路板,那么移植的过程将非常简单。

移植U-Boot工作就是添加开发板硬件相关的文件、配置选项,然后配置编译。

开始移植之前,需要先分析一下U-Boot已经支持的开发板,比较出硬件配置最接近的开发板。选择的原则是,首先处理器相同,其次处理器体系结构相同,然后是以太网接口等外围接口。还要验证一下这个参考开发板的U-Boot,至少能够配置编译通过。

以S3C2410处理器的开发板为例,U-Boot-1.1.2版本已经支持SMDK2410开发板。我们可以基于SMDK2410移植,那么先把SMDK2410编译通过。

我们以S3C2410开发板fs2410为例说明。移植的过程参考SMDK2410开发板,SMDK2410在U-Boot-1.1.2中已经支持。

移植U-Boot的基本步骤如下。

(1)在顶层Makefile中为开发板添加新的配置选项,使用已有的配置项目为例。

 

smdk2410_config   :       unconfig

         @./mkconfig $(@:_config=) arm arm920t smdk2410 NULL s3c24x0

 

参考上面2行,添加下面2行。

 

fs2410_config   :       unconfig

     @./mkconfig $(@:_config=) arm arm920t fs2410 NULL s3c24x0

 

(2)创建一个新目录存放开发板相关的代码,并且添加文件。

board/fs2410/config.mk

board/fs2410/flash.c

board/fs2410/fs2410.c

board/fs2410/Makefile

board/fs2410/memsetup.S

board/fs2410/u-boot.lds

(3)为开发板添加新的配置文件

可以先复制参考开发板的配置文件,再修改。例如:

$cp include/configs/smdk2410.h  include/configs/fs2410.h

如果是为一颗新的CPU移植,还要创建一个新的目录存放CPU相关的代码。

(4)配置开发板

$ make fs2410_config

(5)编译U-Boot

执行make命令,编译成功可以得到U-Boot映像。有些错误是跟配置选项是有关系的,通常打开某些功能选项会带来一些错误,一开始可以尽量跟参考板配置相同。

(6)添加驱动或者功能选项

在能够编译通过的基础上,还要实现U-Boot的以太网接口、Flash擦写等功能。

对于FS2410开发板的以太网驱动和smdk2410完全相同,所以可以直接使用。CS8900驱动程序文件如下。

drivers/cs8900.c

drivers/cs8900.h

对于Flash的选择就麻烦多了,Flash芯片价格或者采购方面的因素都有影响。多数开发板大小、型号不都相同。所以还需要移植Flash的驱动。每种开发板目录下一般都有flash.c这个文件,需要根据具体的Flash类型修改。例如:

board/fs2410/flash.c

(7)调试U-Boot源代码,直到U-Boot在开发板上能够正常启动。

调试的过程可能是很艰难的,需要借助工具,并且有些问题可能困扰很长时间。
 

6.2.5 添加U-Boot命令

U-Boot的命令为用户提供了交互功能,并且已经实现了几十个常用的命令。如果开发板需要很特殊的操作,可以添加新的U-Boot命令。

U-Boot的每一个命令都是通过U_Boot_CMD宏定义的。这个宏在include/command.h头文件中定义,每一个命令定义一个cmd_tbl_t结构体。

 

#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) /

cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}

 

这样每一个U-Boot命令有一个结构体来描述。结构体包含的成员变量:命令名称、最大参数个数、重复数、命令执行函数、用法、帮助。

从控制台输入的命令是由common/command.c中的程序解释执行的。find_cmd()负责匹配输入的命令,从列表中找出对应的命令结构体。

基于U-Boot命令的基本框架,来分析一下简单的icache操作命令,就可以知道添加新命令的方法。

(1)定义CACHE命令。在include/cmd_confdefs.h中定义了所有U-Boot命令的标志位。

 

#define CFG_CMD_CACHE       0x00000010ULL   /* icache, dcache       */

 

如果有更多的命令,也要在这里添加定义。

(2)实现CACHE命令的操作函数。下面是common/cmd_cache.c文件中icache命令部分的代码。

 

#if (CONFIG_COMMANDS & CFG_CMD_CACHE)

static int on_off (const char *s)

{       //这个函数解析参数,判断是打开cache,还是关闭cache

        if (strcmp(s, "on") == 0) {  //参数为“on”

               return (1);

        } else if (strcmp(s, "off") == 0) {  //参数为“off”

               return (0);

    }

    return (-1);

}

 

int do_icache ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])

{     //对指令cache的操作函数

      switch (argc) {

      case 2:               /* 参数个数为1,则执行打开或者关闭指令cache操作 */

             switch (on_off(argv[1])) {

             case 0:     icache_disable();        //打开指令cache

                   break;

             case 1:     icache_enable ();        //关闭指令cache

                   break;

             }

            /* FALL TROUGH */

      case 1:           /* 参数个数为0,则获取指令cache状态*/ 

            printf ("Instruction Cache is %s/n",

                    icache_status() ? "ON" : "OFF");

            return 0;

      default:  //其他缺省情况下,打印命令使用说明

            printf ("Usage:/n%s/n", cmdtp->usage);

            return 1;

      }

      return 0;

}

……

U_Boot_CMD( //通过宏定义命令

    icache,   2,   1,     do_icache,  //命令为icache,命令执行函数为do_icache()

    "icache  - enable or disable instruction cache/n",   //帮助信息

    "[on, off]/n"

    "    - enable or disable instruction cache/n"

);

……

#endif

 

U-Boot的命令都是通过结构体__U_Boot_cmd_##name来描述的。根据U_Boot_CMD在include/command.h中的两行定义可以明白。

 

#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) /

cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs,

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章