Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1176733
  • 博文数量: 573
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 66
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-28 16:21
文章分类

全部博文(573)

文章存档

2018年(3)

2016年(48)

2015年(522)

分类: 嵌入式

2015-12-09 14:41:55

本文基于u-boot-1.3.4,开发板fs2410,交叉编译工具路径/usr/local/arm/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/bin

make fs2410_config
make all
简单的两条命令就可以编译完成。下面开始分析其详细过程,curdir为u-boot顶层目录
/////////////////
执行make fs2410_config的时候,顶层Makefile中有相对应的一个目标叫fs2410_config,所以会执行该目标的命令行:
@$(MKCONFIG) $(@:_config=) arm arm920t fs2410 NULL s3c24x0
MKCONFIG := $(SRCTREE)/mkconfig  顶层目录下的mkconfig shell脚本
$(@:_config=)就是将fs2410_config中的_config去掉变成fs2410
所以,实际上该命令就变成了:
./mkconfig fs2410 arm arm920t fs2410 NULL s3c24x0
$1=fs2410 $2=arm $3=arm920t $4=fs2410 $5=NULL $6=s3c24x0

********************./mkconfig文件分析******************************
从该文件的文件头中的英文说明可以看出,给该文件传递的参数的意义是什么?分别是
Target  Architecture     CPU     Board      [VENDOR]    [SOC]
fs2410    arm          arm920t   fs2410      NULL      s3c24x0

while [ $# -gt 0 ] ; do
 case "$1" in
 --) shift ; break ;;
 -a) shift ; APPEND=yes ;;
 -n) shift ; BOARD_NAME="${1%%_config}" ; shift ;;
 *)  break ;;
 esac
done
$#为shell中的一个特殊变量,代表传入参数的个数,-gt是大于的意思,该行的意思是“当传入参数个数大于0时”进入循环
case "$1" in接着下面的几行意思表示,判断第一个参数中是否有-- -a -n参数,我们传入的参数都没有这些,所以他们根本没机会执行到

[ "${BOARD_NAME}" ] || BOARD_NAME="$1"
有或的意思,如果||前的[]中不为NULL,那么||后面的就屏蔽了,很不幸,这里||前面部分却为NULL,所以BOARD_NAME=fs2410(第一个参数的值)

[ $# -lt 4 ] && exit 1
[ $# -gt 6 ] && exit 1
参数个数正确性判断

echo "Configuring for ${BOARD_NAME} board..."
打印  Configuring for fs2410 board...

接下来判断"$SRCTREE" != "$OBJTREE"是否成立,显然不成立(参考顶层Makefile),所以略过没必要的行,如下:
if [ "$SRCTREE" != "$OBJTREE" ] ; then
 ...
else
 cd ./include
 rm -f asm
 ln -s asm-$2 asm
fi
else分支中先进入inlcude目录,然后删除上一次编译时配置生成的asm文件,最后生成链接文件asm指向asm-arm

rm -f asm-$2/arch
删除include/asm-arm/arch链接文件

if [ -z "$6" -o "$6" = "NULL" ] ; then 
 ln -s ${LNPREFIX}arch-$3 asm-$2/arch
else
 ln -s ${LNPREFIX}arch-$6 asm-$2/arch
fi
如果$6参数字符串长度为0或者为NULL,那么条件成立,但是实际上条件不成立,$6=s3c2410,所以生成一个链接文件asm-arm/arch--->arch-s3c24x0

if [ "$2" = "arm" ] ; then
 rm -f asm-$2/proc
 ln -s ${LNPREFIX}proc-armv asm-$2/proc
fi
创建链接文件asm-arm/proc--->proc-armv

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  #存在第6个参数并且不为NULL
在include目录中创建config.mk文件,内容如下:
ARCH = arm
CPU  = arm920t
BOARD= fs2410
SOC  = s3c24x0


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 " >>config.h
在include目录中创建头文件config.h,内容为:
/* Automatically generated - do not edit */
#include

exit 0

总结:
1. 打印  Configuring for fs2410 board...
2. 在include目录下创建3个链接文件    Create link to architecture specific headers
 ./include 
  asm--->asm-arm
 ./include/asm-arm
  arch--->arch-s3c24x0
  proc--->proc-armv
3. 在include目录中创建config.mk文件 Create include file for Make
 ARCH = arm
 CPU  = arm920t
 BOARD= fs2410
 SOC  = s3c24x0
4. 创建板级特殊头文件config.h   Create board specific header file
 /* Automatically generated - do not edit */
 #include
****************************************************************************************************

///////////////////////////
执行make all,从顶层的Makefile开始
U_BOOT_VERSION = 1.3.1
VERSION_FILE = ./include/version_autogenerated.h

HOSTARCH = i386
HOSTOS = Linux
export HOSTARCH HOSTOS

VENDOR=   #开发商
我们通常在编译的时候没有指定安装目录,所以BULID_DIR为NULL

export TOPDIR SRCTREE OBJTREE

MKCONFIG := $(SRCTREE)/mkconfig
export MKCONFIG
 
# load ARCH, BOARD, and CPU configuration
include $(OBJTREE)/include/config.mk    //这里将前面mkconfig脚本生成的include/config.mk文件包含进来了
export ARCH CPU BOARD VENDOR SOC

ifeq ($(ARCH),arm)
CROSS_COMPILE = /usr/local/arm/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/bin/arm-linux-gnu-
endif
//配置交叉编译工具链
export CROSS_COMPILE

# load other configuration
include $(TOPDIR)/config.mk    //将顶层目录的config.mk包含进来,该文件中将会包含其他.mk文件
***********************顶层config.mk文件分析**************************************************
obj :=
src :=

# clean the slate ...
PLATFORM_RELFLAGS =
PLATFORM_CPPFLAGS =
PLATFORM_LDFLAGS =

PLATFORM_CPPFLAGS+= -D__ARM__
inlcude  ./arm_config.mk       //PLATFORM_CPPFLAGS += -DCONFIG_ARM -D__ARM__
include  ./cpu/arm920t/config.mk
             //PLATFORM_RELFLAGS += -fno-strict-aliasing  -fno-common -ffixed-r8 -msoft-float
             //PLATFORM_CPPFLAGS += -march=armv4
             //PLATFORM_CPPFLAGS +=$(call cc-option,-mapcs-32,-mabi=apcs-gnu)
             //PLATFORM_RELFLAGS +=$(call cc-option,-mshort-load-bytes,/
              $(call cc-option,-malignment-traps,))
include  ./cpu/arm920t/s3c24x0/config.mk   //没有该文件
BOARDDIR = fs2410
include  ./board/fs2410/config.mk        //TEXT_BASE = 0x33f80000  链接地址

# Load generated board configuration
include ./include/autoconf.mk
该文件中包含了一些重要的命令行参数:
CONFIG_ETHADDR="08:00:3e:26:0a:5b"
CONFIG_IPADDR="192.168.1.134"
CONFIG_GATEWAYIP="192.168.1.1"
CONFIG_NETMASK="255.255.255.0"
CONFIG_SERVERIP="192.168.1.23"
CONFIG_BOOTARGS=""root=/dev/nfs rw nfsroot=" MK_STR(CONFIG_SERVERIP) ":" MK_STR(CONFIG_ROOTPATH) " ip=" MK_STR(CONFIG_IPADDR) ":" MK_STR(CONFIG_SERVERIP) ":" MK_STR(CONFIG_GATEWAYIP) ":" MK_STR(CONFIG_NETMASK) ":" MK_STR(CONFIG_HOSTNAME) ":" MK_STR(CONFIG_NETDEV) ":off console=" MK_STR(CONFIG_CONSOLE) "," MK_STR(CONFIG_BAUDRATE)"
CONFIG_BOOTCOMMAND="nand read 30008000 40000 1c0000 /; go 30008000"
CONFIG_LOADADDR="0x30800000"

HOSTCC  = gcc
HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
HOSTSTRIP = strip

AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
RANLIB = $(CROSS_COMPILE)RANLIB

LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds     //  ./board/fs2410/u-boot.lds u-boot链接文件
&&&&&&&&&&&&&&&&   ./board/fs2410/u-boot.lds内容
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
 . = 0x00000000;

 . = ALIGN(4);
 .text      :
 {
   cpu/arm920t/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 = .;

 . = ALIGN(4);
 __bss_start = .;
 .bss : { *(.bss) }
 _end = .;
}
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

CPPFLAGS := $(DBGFLAGS) $(OPTFLAGS) $(RELFLAGS) -D__KERNEL__ -DTEXT_BASE=$(TEXT_BASE)
CPPFLAGS += -I$(TOPDIR)/include
CPPFLAGS += -fno-builtin -ffreestanding -nostdinc -isystem $(gccincdir) -pipe $(PLATFORM_CPPFLAGS)

CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes
/**********************************************
预定义的宏:
c/c++:
__KERNEL__
TEXT_BASE=0x33f80000
CONFIG_ARM 
__ARM__

汇编:
__ASSEMBLY__
__KERNEL__
TEXT_BASE=0x33f80000
CONFIG_ARM 
__ARM__

*********************************************/

AFLAGS := $(AFLAGS_DEBUG) -D__ASSEMBLY__ $(CPPFLAGS)
LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS)   //链接选项
%%%%%%%%注意%%%%%%%%%%%%%
从很早之前用u-boot的时候我心里就有个疑惑,为什么这里使用了-T指定了链接脚本之后,又用-Ttext指定text的开始地址,今天突然想通了,原来是这样:
先来看一下三星cpu专用bootloader vivi在这里是怎么的
Makefile中有这么一句:
LINKFLAGS = -T arch/vivi.lds -Bstatic
但是在arch下没有vivi.lds,而是有vivi.lds.in,下面是.in文件的内容:
SECTIONS {
  . = TEXTADDR;
  .text : { *(.text) }
  .data ALIGN(4) : { *(.data) }
  .bss ALIGN(4) : { *(.bss) *(COMMON) }
}
很显然TEXTADDR是要被替换的,在哪里替换的呢?还是在Makefile中了:
LDSCRIPT = arch/vivi.lds.in
 
ifeq ($(CONFIG_ARCH_S3C2410),y)
MACHINE = s3c2410
  ifeq ($(CONFIG_S3C2410_NAND_BOOT),y)
    TEXTADDR = 0x33f00000
  else
    TEXTADDR = 0x00000000
  endif
endif
 
vivi: $(HEAD) arch/vivi.lds
arch/vivi.lds: $(LDSCRIPT)
        @sed s/TEXTADDR/$(TEXTADDR)/ $(LDSCRIPT) >$@
这个链接地址就这样被替换了,后来我想来想,这里这个vivi的做法和u-boot的做法其实本质上是一样的,怎么说,
就是为了支持多种平台不同的链接要求或者方便使用者修改而将最终的链接地址弄成来一个
变量来代替。u-boot中也是使用变量来代替,然后在命令行中用-Ttext来指定,这样在链接的时候最终的链接地址
还是取决于-Ttext,而不会使用.lds文件中规定的地址。甚至如果不考虑地址对其的话,完全可以不使用.lds文件,直接在
命令行中使用-Ttext xxxxxxx来实现链接。

下面顺便列出ld的常用需选项:
-b TARGET  设置目标文件的文件格式
-e ADDRESS 设置目标文件的开始地址
-EB  链接big-endian的目标文件
-EL  链接small-endian的目标文件
-l LIBNAME    创建执行程序时要链接的库文件(比如某个库为test,则可以为-ltest)
-L DIRECTORY  寻找要链接的库文件时搜索的文件路径
-o FILE  设置输出文件的名字
-s  去除输出文件中的所有符号信息
-S  去除输出文件中的调试符号信息
-T FILE  读取链接描述脚本,以确定符号等的定位地址
-v  输出ld的版本信息
-x  去除所有的局部符号信息
-X  去除临时的局部符号信息,默认情况下会设置这个选项
-Bstatic   创建的输出文件链接静态链接库
-Bdynamic  创建的输出文件链接动态链接库
-Tbss ADDRESS  设置section bss的起始地址
-Tdata ADDRESS 设置section data的起始地址
-Ttext ADDRESS 设置section text的起始地址
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

***********************顶层config.mk文件分析  end**************************************************
列出u-boot所需目标文件列表:顺序很重要,也就是说OBJS  = cpu/$(CPU)/start.o必须放在第一个的位置
这里是cpu/arm920t/start.o文件
LIBS  = lib_generic/libgeneric.a
。。。
。。。

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.sha1: $(obj)u-boot.bin
  $(obj)tools/ubsha1 $(obj)u-boot.bin

$(obj)u-boot.dis: $(obj)u-boot
  $(OBJDUMP) -d $< > $@

$(obj)u-boot:  depend version $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT)
  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

实际编译的打印信息如下:
编译汇编代码时:
/usr/local/arm/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/bin/arm-linux-gnu-gcc  -D__ASSEMBLY__ -g  -Os   -fno-strict-aliasing  -fno-common -ffixed-r8 -msoft-float -malignment-traps -D__KERNEL__ -DTEXT_BASE=0x33F80000  -I/home/lzg/sdc/u-boot-1.3.1_fs_modified/include -fno-builtin -ffreestanding -nostdinc -isystem /usr/local/arm/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/bin/../lib/gcc/arm-linux-gnu/3.4.5/include -pipe  -DCONFIG_ARM -D__ARM__ -march=armv4 -mapcs-32 -c -o start.o start.S

__ASSEMBLY__   __KERNEL__   TEXT_BASE=0x33F80000  CONFIG_ARM   __ARM__

编译c代码时
/usr/local/arm/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/bin/arm-linux-gnu-gcc -g  -Os   -fno-strict-aliasing  -fno-common -ffixed-r8 -msoft-float -malignment-traps -D__KERNEL__ -DTEXT_BASE=0x33F80000  -I/home/lzg/sdc/u-boot-1.3.1_fs_modified/include -fno-builtin -ffreestanding -nostdinc -isystem /usr/local/arm/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/bin/../lib/gcc/arm-linux-gnu/3.4.5/include -pipe  -DCONFIG_ARM -D__ARM__ -march=armv4 -mapcs-32 -Wall -Wstrict-prototypes -c -o cmd_mac.o cmd_mac.c

__KERNEL__   TEXT_BASE=0x33F80000  CONFIG_ARM   __ARM__


UNDEF_SYM=`/usr/local/arm/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/bin/arm-linux-gnu-objdump -x lib_generic/libgeneric.a board/fs2410/libfs2410.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 drivers/bios_emulator/libatibiosemu.a drivers/block/libblock.a drivers/hwmon/libhwmon.a drivers/i2c/libi2c.a drivers/input/libinput.a drivers/misc/libmisc.a drivers/mtd/libmtd.a drivers/mtd/nand/libnand.a drivers/mtd/nand_legacy/libnand_legacy.a drivers/mtd/onenand/libonenand.a drivers/net/libnet.a drivers/net/sk98lin/libsk98lin.a drivers/pci/libpci.a drivers/pcmcia/libpcmcia.a drivers/rtc/librtc.a drivers/serial/libserial.a drivers/usb/libusb.a drivers/video/libvideo.a post/libpost.a post/drivers/libpostdrivers.a common/libcommon.a libfdt/libfdt.a |sed  -n -e 's/.*/(__u_boot_cmd_.*/)/-u/1/p'|sort|uniq`;/
  cd /home/lzg/sdc/u-boot-1.3.1_fs_modified && /usr/local/arm/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/bin/arm-linux-gnu-ld -Bstatic -T /home/lzg/sdc/u-boot-1.3.1_fs_modified/board/fs2410/u-boot.lds -Ttext 0x33F80000  $UNDEF_SYM cpu/arm920t/start.o /
   --start-group lib_generic/libgeneric.a board/fs2410/libfs2410.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 drivers/bios_emulator/libatibiosemu.a drivers/block/libblock.a drivers/hwmon/libhwmon.a drivers/i2c/libi2c.a drivers/input/libinput.a drivers/misc/libmisc.a drivers/mtd/libmtd.a drivers/mtd/nand/libnand.a drivers/mtd/nand_legacy/libnand_legacy.a drivers/mtd/onenand/libonenand.a drivers/net/libnet.a drivers/net/sk98lin/libsk98lin.a drivers/pci/libpci.a drivers/pcmcia/libpcmcia.a drivers/rtc/librtc.a drivers/serial/libserial.a drivers/usb/libusb.a drivers/video/libvideo.a post/libpost.a post/drivers/libpostdrivers.a common/libcommon.a libfdt/libfdt.a --end-group -L /usr/local/arm/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/bin/../lib/gcc/arm-linux-gnu/3.4.5 -lgcc /
   -Map u-boot.map -o u-boot

链接成u-boot elf32

/usr/local/arm/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/bin/arm-linux-gnu-objcopy --gap-fill=0xff -O srec u-boot u-boot.srec
/usr/local/arm/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/bin/arm-linux-gnu-objcopy --gap-fill=0xff -O binary u-boot u-boot.bin
生成.bin文件和.srec文件

阅读(886) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~