+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

看到不错的文章。不要加入收藏夹,想着以后有时间再看。由于非常有可能你以后再也不会看它们了。

想写总结的文章。不要想着等到以后有时间了再总结,由于非常有可能你以后更没有时间总结它们了。

——送给自己

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

要想知道一个程序的作用。最好的办法是分析程序的源代码。这一方法对了解u-boot的功能也适用,因此。我们首先看u-boot的源代码结构,然后依据源代码结构总结出u-boot的主要特性。

最后,依据配置、编译的过程,简单分析u-boot。

(一)

以u-boot-1.1.6为例分析文件夹结构例如以下:

1、平台相关的或开发板相关的文件夹:board、cpu、lib_i386类似

2、通用函数的文件夹:include、lib_generic、common

3、通用的设备驱动程序:disk、drivers、dtt、fs、nand_spl、net、post、rtc

4、u-boot工具、演示样例程序、文档:doc、example、tools

u-boot顶层文件夹说明

文件夹 特性 解释说明
board 开发板相关 相应不同配置的电路板(即使CPU同样),比方smdk2410等
cpu 平台相关 相应不同的CPU,如arm920t、i386等。
lib_i386 平台相关 某一架构下通用的文件
include 通用函数 头文件和开发板配置文件,开发板的配置文件都放在include/configs文件夹下
lib_generic 通用函数 须要通用的库函数。比方printf等
common 通用函数 通用函数,多是对下一层驱动程序的进一步封装
disk 通用设备驱动程序 硬盘接口程序
drivers 通用设备驱动程序

各类详细设备的驱动程序
dtt 通用设备驱动程序

数字温度測量或者传感器的驱动
fs 通用设备驱动程序

文件系统
nand_spl 通用设备驱动程序

u-boot一般从ROM、NORFLASH等设备启动。如今開始支持NAND Flash启动
net 通用设备驱动程序

各种网络协议
post 通用设备驱动程序

上电自检程序
rtc 通用设备驱动程序

实时时钟的驱动
doc 文档 开发、使用文档
example 演示样例程序 一些測试程序。能够使用u-boot下载后执行
tools 工具 制作S-Record、u-boot格式映像的工具,如mkimage

从上表中u-boot文件夹的分析能够看出u-boot的一些特性:支持多种嵌入式操作系统内核,如Linux、Vxworks等;支持多个处理器系列。如PowerPC、ARM、x86等;丰富的设备驱动源代码,如串口、SDRAM、Flash、以太网等;支持NFS挂载、RAMDISK形式的根文件系统、从Flash中引导压缩或非压缩系统内核;支持目标板环境变量多种存储方式。如Flash等。CRC32校验、上电自检功能等。



u-boot中各文件夹间也是层次结构的,这有助于在移植过程中为我们须要改动哪些文件提供信息。由下图能够知道。仅仅需改动board、cpu、lib_xxx文件夹下的文件。就可以完毕移植过程。假设想要加入其它的命令等,则须要改动其它文件。

lib_generic    common
post    net    fs   disk
dtt      nand_spl   rtc   drivers
board   cpu  lib_xxx



(二)配置

上一篇的u-boot概述中配置u-boot时使用了命令:make 100ask24x0_config命令。

运行该命令时运行Makefile中的例如以下一行规则:

100ask24x0_config	:	unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t 100ask24x0 NULL s3c24x0

该规则解释为:

100ask24x0_config	:	unconfig
mkconfig 100ask24x0 arm arm920t 100ask24x0 NULL s3c24x0

因此配置过程。我们能够分析根文件夹下的mkconfig文件。从而了解配置过程,做了哪些工作。逐行分析例如以下:

#!/bin/sh -e

# Script to create header files and links to configure
# U-Boot for a specific board.
#
# Parameters: Target Architecture CPU Board [VENDOR] [SOC]
#
# (C) 2002-2006 DENX Software Engineering, Wolfgang Denk <wd@denx.de>
# APPEND=no # Default: Create new config file
BOARD_NAME="" # Name to print in make output mkconfig 100ask24x0 arm arm920t smdk2410 NULL s3c24x0
$0 $1 $2 $3 $4 $5 $6 while [ $# -gt 0 ] ; do <span style="color:#ff6666;">/*$ # :保存程序命令行參数的数目*/</span>
case "$1" in
--) shift ; break ;;
-a) shift ; APPEND=yes ;;
-n) shift ; BOARD_NAME="${1%%_config}" ; shift ;;
*) break ;;
esac
done [ "${BOARD_NAME}" ] || BOARD_NAME="$1" <span style="color:#ff6666;">/*由于上面定义了BOARD_NAME="",所以该句得到结果为BOARD_NAME=100ask24x0*/
</span>
[ $# -lt 4 ] && exit 1
[ $# -gt 6 ] && exit 1 <span style="color:#ff6666;">/*$#是參数的个数。此处$#=6。所以这两句都不会运行到exit 1语句*/</span> echo "Configuring for ${BOARD_NAME} board..."
<span style="color:#ff6666;">/*此句便是运行make 100ask24x0_config时显示的那条语句:Configuring for 100ask24x0 board...*/</span>
#
# Create link to architecture specific headers
#
<span style="color:#ff6666;">/*查看Makefile可知。
*OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
*SRCTREE := $(CURDIR)
*所以if语句不运行,而是运行以下的else语句
*/</span>
if [ "$SRCTREE" != "$OBJTREE" ] ; then
mkdir -p ${OBJTREE}/include
mkdir -p ${OBJTREE}/include2
cd ${OBJTREE}/include2
rm -f asm
ln -s ${SRCTREE}/include/asm-$2 asm
LNPREFIX="../../include2/asm/"
cd ../include
rm -rf asm-$2
rm -f asm
mkdir asm-$2
ln -s asm-$2 asm
else
cd ./include
rm -f asm
ln -s asm-$2 asm <span style="color:#ff6666;">/*删除asm文件。然后再次建立asm文件,并令它链接向asm-$2文件夹。即asm-arm文件夹*/</span>
fi rm -f asm-$2/arch <span style="color:#ff6666;">/*删除asm-$2/arch文件,即asm-arm/arch文件*/</span> if [ -z "$6" -o "$6" = "NULL" ] ; then <span style="color:#ff6666;">/* -z string表示string为null $6也不是NULL,因此运行else分支*/</span>
ln -s ${LNPREFIX}arch-$3 asm-$2/arch
else
ln -s ${LNPREFIX}arch-$6 asm-$2/arch <span style="color:#ff6666;">/*由于LNPREFIX为空,该句为ln -s arch-s3c24x0 asm-arm/arch*/</span>
fi if [ "$2" = "arm" ] ; then
rm -f asm-$2/proc
ln -s ${LNPREFIX}proc-armv asm-$2/proc <span style="color:#ff6666;">/*又一次建立asm-arm/proc文件。并让它链接向proc-armv文件夹*/</span>
fi #
# Create include file for Make
#
<span style="color:#ff6666;">/*
*创建config.mk文件
*ARCH = arm
*CPU = arm920t
*BOARD= smdk2410
*SOC = s3c24x0
*/</span>
echo "ARCH = $2" > config.mk
echo "CPU = $3" >> config.mk
echo "BOARD = $4" >> config.mk [ "$5" ] && [ "$5" != "NULL" ] && echo "VENDOR = $5" >> config.mk [ "$6" ] && [ "$6" != "NULL" ] && echo "SOC = $6" >> config.mk #
# Create board specific header file
#
<span style="color:#ff6666;">/*创建config.h文件*/</span>
if [ "$APPEND" = "yes" ] # Append to existing config file
then
echo >> config.h
else
> config.h # Create new config file
fi
echo "/* Automatically generated - do not edit */" >>config.h
echo "#include <configs/$1.h>" >>config.h exit 0

总结配置的作用有以下4点:

1、开发板名称BOARD_NAME等于$1

2、创建到平台/开发板相关的头文件的链接。例如以下所看到的

	ln -s asm-$2 asm
ln -s arch-$6 asm-$2/arch
ln -s proc-armv asm-$2/proc

3、创建顶层Makefile包括的文件include/config.mk

4、创建开发板相关的头文件include/config.h

(三)编译、链接

既然在编译之前必须经过上面的配置过程,那么配置过程一定为编译过程提供了某些东西。否则的话,我们直接编译就能够了。那么。上面配置过程生成的文件、改动的地方是怎样在编译过程中体现的呢。

事实上,这在Makefile文件里有所体现。

如:

include $(OBJTREE)/include/config.mk  <span style="color:#ff6666;">//包括了配置过程中宏生成的include/config.mk文件</span>
export ARCH CPU BOARD VENDOR SOC
include $(TOPDIR)/config.mk <span style="color:#ff6666;">//包括了配置过程中生成的顶层的config.mk文件</span>

配置完毕后,运行make命令就可以链接。运行make。我们运行的是Makefile里的make all语句,它的命令例如以下:

ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND)

all:		$(ALL)

$(obj)u-boot.hex:	$(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@ $(obj)u-boot.srec: $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O srec $< $@ $(obj)u-boot.bin: $(obj)u-boot
$(OBJCOPY) ${OBJCFLAGS} -O binary $< $@ $(obj)u-boot.img: $(obj)u-boot.bin
./tools/mkimage -A $(ARCH) -T firmware -C none \
-a $(TEXT_BASE) -e 0 \
-n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | \
sed -e 's/"[ ]*$$/ for $(BOARD) board"/') \
-d $< $@ $(obj)u-boot.dis: $(obj)u-boot
$(OBJDUMP) -d $< > $@ $(obj)u-boot: depend version $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT)
<span style="color:#ff6666;">UNDEF_SYM=`$(OBJDUMP) -x $(LIBS) |sed -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \
--start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \
-Map u-boot.map -o u-boot

从执行结果反看Makefile的执行:

UNDEF_SYM=</span>`arm-linux-objdump -x lib_generic/libgeneric.a board/100ask24x0/lib100ask24x0.a cpu/arm920t/libarm920t.a cpu/arm920t/s3c24x0/libs3c24x0.a lib_arm/libarm.a fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a net/libnet.a disk/libdisk.a rtc/librtc.a dtt/libdtt.a drivers/libdrivers.a drivers/nand/libnand.a drivers/nand_legacy/libnand_legacy.a drivers/usb/libusb.a drivers/sk98lin/libsk98lin.a common/libcommon.a |sed  -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
cd /work/system/u-boot-1.1.6</span> && arm-linux-ld -Bstatic -T /work/system/u-boot-1.1.6/board/100ask24x0/u-boot.lds -Ttext 0x33F80000  $UNDEF_SYM cpu/arm920t/start.o \
<span style="color:#ff6666;">--start-group</span> lib_generic/libgeneric.a board/100ask24x0/lib100ask24x0.a cpu/arm920t/libarm920t.a cpu/arm920t/s3c24x0/libs3c24x0.a lib_arm/libarm.a fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a net/libnet.a disk/libdisk.a rtc/librtc.a dtt/libdtt.a drivers/libdrivers.a drivers/nand/libnand.a drivers/nand_legacy/libnand_legacy.a drivers/usb/libusb.a drivers/sk98lin/libsk98lin.a common/libcommon.a --end-group -L /work/tools/gcc-3.4.5-glibc-2.3.6/lib/gcc/arm-linux/3.4.5 -lgcc \
<span style="color:#ff6666;">-Map u-boot.map -o u-boot

总结编译流程:

1、编译cpu/$(CPU)/start.S。

2、然后,对于平台/开发板相关的每一个文件夹、每一个通用文件夹都使用它们各自的Makefile生成对应的库。

3、将1、2步骤生成的.o、.a文件依照board/$(BOARDDIR)/config.mk文件里指定的代码段起始地址、board/$(BOARDDIR)/U-Boot.lds链接脚本进行链接。

4、第3步得到的ELF格式的U-Boot,后面Makefile还会将它转换为二进制格式S-Record格式。

(四)逐行分析链接文件

/*
* (C) Copyright 2002
* Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/ OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") <span style="color:#ff6666;">/*定义3种输出文件的格式(大小端)*/</span>
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
OUTPUT_ARCH(arm) <span style="color:#ff6666;">/*设置输出文件的machine architecture(体系结构)*/</span>
ENTRY(_start) <span style="color:#ff6666;">/*将符号_start的值设置成入口地址*/</span>
SECTIONS
{
. = 0x00000000; . = ALIGN(4);
.text :
{
cpu/arm920t/start.o (.text)
board/100ask24x0/boot_init.o (.text)
*(.text)
} <span style="color:#ff6666;">/*将start.o boot_init.o 以及除此之外的全部(*符号代表随意输入文件)
*输入文件的.text section 以4字节对齐的方式合并成一个.text section,
*该section的地址由定位器符号的值指定,即为0x00000000
*/</span> . = ALIGN(4);
.rodata : { *(.rodata) }
<span style="color:#ff6666;">/*将全部输入文件的仅仅读数据段.rodata section 以4字节对齐的方式
*合并成一个.rodata section,该section的地址为
*0x00000000+.text section的大小
*/</span>
. = ALIGN(4);
.data : { *(.data) }
<span style="color:#ff6666;">/*将全部输入文件的数据段.data section 以4字节对齐的方式
*合并成一个.data section,该section的地址为
*0x00000000+.text section的大小+.rodata section的大小
*/</span>
. = ALIGN(4);
.got : { *(.got) } . = .;
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .; . = ALIGN(4);
__bss_start = .;
.bss : { *(.bss) }
_end = .;
}



參考:韦东山《嵌入式Linux应用开发全然手冊》

    Linux下的lds链接脚本基础



















版权声明:本文博客原创文章,博客,未经同意,不得转载。

u-boot学习(两):u-boot简要分析的更多相关文章

  1. Spring Boot学习笔记---Spring Boot 基础及使用idea搭建项目

    最近一段时间一直在学习Spring Boot,刚进的一家公司也正好有用到这个技术.虽然一直在学习,但是还没有好好的总结,今天周末先简单总结一下基础知识,等有时间再慢慢学习总结吧. Spring Boo ...

  2. spring boot 学习(二)spring boot 框架整合 thymeleaf

    spring boot 框架整合 thymeleaf spring boot 的官方文档中建议开发者使用模板引擎,避免使用 JSP.因为若一定要使用 JSP 将无法使用. 注意:本文主要参考学习了大神 ...

  3. spring boot 学习(六)spring boot 各版本中使用 log4j2 记录日志

    spring boot 各版本中使用 log4j2 记录日志 前言 Spring Boot中默认日志工具是 logback,只不过我不太喜欢 logback.为了更好支持 spring boot 框架 ...

  4. Spring Boot学习笔记——Spring Boot与ActiveMQ的集成

    Spring Boot对JMS(Java Message Service,Java消息服务)也提供了自动配置的支持,其主要支持的JMS实现有ActiveMQ.Artemis等.这里以ActiveMQ为 ...

  5. Spring Boot学习笔记——Spring Boot与Redis的集成

    一.添加Redis缓存 1.添加Redis起步依赖 在pom.xml中添加Spring Boot支持Redis的依赖配置,具体如下: <dependency> <groupId> ...

  6. Spring Boot学习笔记——Spring Boot与MyBatis的集成(项目示例)

    1.准备数据库环境 # 创建数据库 CREATE DATABASE IF NOT EXISTS zifeiydb DEFAULT CHARSET utf8 COLLATE utf8_general_c ...

  7. Spring Boot学习 之 Spring Boot Actuator(一)

    Spring Boot版本:2.1.4.RELEASE 启用: spring-boot-actuator模块提供了一系列的用于监控的端点.最简单的开启这个功能的方法就是,在pom文件中添加如下的依赖. ...

  8. spring boot 学习10 定义springboot的两种方法

    使用spring boot的两种方法: A:继承spring-boot-starter-parent项目 这种方式很简单,只需要在POM里面添加parent父工程即可. B: 如果你不喜欢继承spri ...

  9. 转载:spring boot学习

    Spring Boot学习 Spring Boot是为了简化Spring应用的创建.运行.调试.部署等而出现的,使用它可以做到专注于Spring应用的开发,而无需过多关注XML的配置. 简单来说,它提 ...

随机推荐

  1. 给定一个set字符和一个正数k,找出所有该做set它可以由长度构成k该字符串集合 print-all-combinations-of-given-length

    // 给定一个set字符和一个正数k,找出所有该做set它可以由长度构成k该字符串集合 /* Input: set[] = {'a', 'b'}, k = 3 Output: aaa aab aba ...

  2. Linux环境Eclipse + Tomcat + MySQL 构造J2EE方法开发环境

    1. 版本号信息 (1)CentOS 6.4释64位置.uname -a 下面的示例演示显著样本: Linux localhost.localdomain 3.11.6 #1 SMP Sat Nov ...

  3. Android APK反编译详解(非常有用)

    如何学习最快呢?无疑是通过研究别人的源代码? 但是,获取别人的源代码,比较困难.本文,仅限于用于学习开发. 这段时间在学Android应用开发,在想既然是用Java开发的应该很好反编译从而得到源代码吧 ...

  4. PHP 闭包函数 function use 使用方法实例

    /** * @param string $hisStart * @param string $hisEnd * @param int $range * @param string $format * ...

  5. IT薪酬

    新加坡IT薪酬 2014-06-12 12:51 by 圣殿骑士, 8856 阅读, 37 评论, 收藏, 编辑 很多朋友发邮件或留言问我关于新加坡IT薪酬的问题,由于前段时间比较忙,所以没有及时一一 ...

  6. DDD Reference

    版权声明:本文博客原创文章.博客,未经同意,不得转载.

  7. 编写WCF服务时右击配置文件无“Edit WCF Configuration”(编辑 WCF 配置)远程的解决办法

    原文:编写WCF服务时右击配置文件无“Edit WCF Configuration”远程的解决办法 今天在看<WCF揭秘>书中看到作者提出可以在一个WCF Host应用程序的App.Con ...

  8. 如何让格斗游戏的横版过关(2) Cocos2d-x 2.0.4

    在第一章<如何使横版格戏>基础上.添加角色运动.碰撞.敌人.AI和音乐音效,原文<How To Make A Side-Scrolling Beat 'Em Up Game Like ...

  9. UI測试内容

    我们在实际工作其中,针对web应用程序,也就是常常所说的B/S系统,能够从例如以下方面来进行用户界面測试: 导航測试 导航描写叙述了用户在一个页面内操作的方式,在不同的用户接口控制之间,比如butto ...

  10. erlang R17新socket选项{active,N}

    erlang R17带来了新的socket选项{active,N} .与{active,once}连同应用层提供的流量控制.为什么会这样选择,{active,once}不能够有效地抑制了很多socke ...