u-boot中的Makefile

  在windos下,pc机上电之后,BIOS会初始化硬件配置,为内核传递参数,引导操作系统启动,并且识别C盘、D盘。等整个操作系统启动起来之后,才可以运行应用程序比如QQ、QQ音影。同理,在嵌入式Linux操作系统中,bootloader在上电之后初始化硬件设备,引导Linux内核启动,并且挂在文件系统,等整个操作系统启动之后。运行应用程序。              bootloader其实就是一个单片机程序,一般采用开发的语言是汇编和C语言,但是不同的硬件平台下的boot是不同的。booloader的启动是:首先将bootloader存在Flash中,开发板通常把板上ROM或者Flash映射到CPU开始执行的地址,当系统加电后,CPU将执行它。

  bootloader的功能很明确:那就是引导内核启动。

  bootloader 的启动通常分为两个阶段

第一阶段:初始化基本的硬件(时钟,关闭看门狗,SDRAM等),把bootloader自己搬运到RAM中,并且设置堆栈,搭建C语言运行环境。

第二阶段:初始化本阶段需要的硬件(USB,串口,网口等),读取环境变量,给内核传参数,从Flash中读将内核加载到RAM中,为内核传递参数,引导内核启动。

u-boot的结构:想要分析u-boot的结构,最简单直接的途径就是分析Makefile。生成u-boot.bin的过程首先要配置Makefile,然后载编译Makefile。

一、配置过程

在编译时首先执行make 100ask24x0_config在Makefile中找到100ask24x0_config。

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

  MKCONFIG这个变量的定义为    MKCONFIG := $(SRCTREE)/mkconfig  $(SRCTREE)表示源文件路径下面有个mkconfig文件

  @:_config= 中的 @表示目标 100ask24x0,_config=表示替换掉。那么

  @$(MKCONFIG) $(@:_config=) arm arm920t 100ask24x0 NULL s3c24x0的实际意思为mkconfig 100ask24x0 arm arm920t 100ask24x0 NULL s3c24x0

  那么紧接着进入u-boot-1.1.6目录打开mkconfig,分析这个文件

  在脚本文件中#表示注释。

#mkconfig  100ask24x0 arm arm920t 100ask24x0 NULL s3c24x0
    #在这里声明一下,mkconfig  100ask24x0 arm arm920t 100ask24x0 NULL s3c24x0这个命令在执行过程中会
    #    给mkconfig传入参数,$0 为mkconfig, $1 为100ask24x0,$2为arm,以此类推...

    APPEND=no    # Default: Create new config file
    BOARD_NAME=""    # Name to print in make output

    while [ $# -gt 0 ] ; do    #$#表示执行脚本文件时所传入的参数的个数,当参数个数大于0时,开始往下执行

        case "$1" in #case中$1表示执行命令时传入的参数,比如mkconfig  100ask24x0 arm arm920t 100ask24x0 NULL s3c24x0
                      #这个命令中$1表示100ask24x0,而以下代码中没有匹配项
        --) shift ; break ;;
        -a) shift ; APPEND=yes ;;
        -n) shift ; BOARD_NAME="${1%%_config}" ; shift ;;
        *)  break ;;
        esac
    done

    [ "${BOARD_NAME}" ] || BOARD_NAME="$1" #表示BOARD_NAME如果没有定义,则定义为所传入的参数即100ask24x0

    [ $# -lt 4 ] && exit 1 #若参数个数小于4则退出
    [ $# -gt 6 ] && exit 1 #若参数个数大于6则退出

    echo "Configuring for ${BOARD_NAME} board..." #echo 表示打印,相当于c语言中的printf配置文件名称

    #
    # Create link to architecture specific headers
    #
    if [ "$SRCTREE" != "$OBJTREE" ] ; then #在makefile中找到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 #ln -s asm-arm asm 表示建立一个连接文件并且指向asm-arm,进入终端执行ls -la asm 就可以查看
                         #lrwxrwxrwx 1 book book 7 2015-04-06 19:49 asm -> asm-arm
                         #这样做的目的就是在编译asm的头文件时,汇编指令为asm-arm架构下的。
    fi

    rm -f asm-$2/arch    #rm -f asm-arm/arch

    if [ -z "$6" -o "$6" = "NULL" ] ; then         #如果第六个参数为空或者等于null
        ln -s ${LNPREFIX}arch-$3 asm-$2/arch
    else
        ln -s ${LNPREFIX}arch-$6 asm-$2/arch    #ln -s arch-s3c24x0 asm-arm/arch 建立连接文件
    fi

    if [ "$2" = "arm" ] ; then
        rm -f asm-$2/proc                          #rm -f asm-arm/proc 删除asm-arm/proc
        ln -s ${LNPREFIX}proc-armv asm-$2/proc    #ln -s proc-armv asm-arm/proc
    fi

    #
    # Create include file for Make
    #
    echo "ARCH   = $2" >  config.mk #>表示创建config.mk
    echo "CPU    = $3" >> config.mk    #>>表示追加到config.mk 文件中
    echo "BOARD  = $4" >> config.mk

    [ "$5" ] && [ "$5" != "NULL" ] && echo "VENDOR = $5" >> config.mk   #$5存在或者不为空

    [ "$6" ] && [ "$6" != "NULL" ] && echo "SOC    = $6" >> config.mk

    #在config.mk 中
    #ARCH   = arm
    #CPU    = arm920t
    #BOARD  = 100ask24x0
    #SOC    = s3c24x0

    #
    # Create board specific header file
    #
    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  #同上,在config.h 中追加
    echo "#include <configs/$1.h>" >>config.h

    #在config.h中
    #/* Automatically generated - do not edit */
    ##include <configs/100ask24x0.h>

    exit 0

mkconfig

二、编译过程

  在配置config.mk脚本文件时,相应的ARCH架构,CPU类型,BOARD平台都会相应的赋值,那么在编译过程中这些参数的值将会被带入进行相应的判断,编译时进入Makefile。查找与mkconfig赋值相关的变量

  #通过上面的分析可以知道,在config.mk 中

  #ARCH = arm

  #CPU = arm920t

  #BOARD = 100ask24x0

  #SOC = s3c24x0

  紧接着分析Makefile

ifeq ($(ARCH),arm)
    CROSS_COMPILE = arm-linux- endif

   如果ARCH的值与arm 相等,则执行CROSS_COMPILE = arm-linux-

# load other configuration
include $(TOPDIR)/config.mk
     $(TOPDIR)表示顶端目录
LIBS  = lib_generic/libgeneric.a
LIBS += board/$(BOARDDIR)/lib$(BOARD).a
LIBS += cpu/$(CPU)/lib$(CPU).a

  #相当于链接以下的库:
  LIBS = lib_generic/libgeneric.a
  LIBS += board/$(BOARDDIR)/lib100ask24x0.a
  LIBS += cpu/arm920t/libarm920t.a

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

    OBJS  = cpu/$(CPU)/start.o

$(CPU)为arm920t

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

  #在Makefile中如果不指定目标,那么生成的目标就是ALL变量指向的内容

  查找上边的u-boot.bin所依赖的文件

$(obj)u-boot.bin:    $(obj)u-boot  #u-boot.bin依赖于u-boot
            $(OBJCOPY) ${OBJCFLAGS} -O binary $< [email protected]

  #u-boot.bin依赖于u-boot

$(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

#u-boot所依赖的库之类的文件
在实际编译过程过的打印消息为

UNDEF_SYM=`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 /home/book/system/u-boot-1.1.6 &&
            arm-linux-ld -Bstatic -T /home/book/system/u-boot-1.1.6/board/100ask24x0/u-boot.lds -Ttext 0x33F80000  $UNDEF_SYM cpu/arm920t/start.o                 --start-group 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                 -Map u-boot.map -o u-boot

  放在最前边的是链接脚本arm-linux-ld -Bstatic -T /home/book/system/u-boot-1.1.6/board/100ask24x0/u-boot.lds -Ttext 0x33F80000,链接地址为0x33F80000

  那么现在进入链接文件/u-boot-1.1.6/board/100ask24x0/u-boot.lds中

OUTPUT_ARCH(arm)
    ENTRY(_start)
    SECTIONS
    {
        . = 0x00000000; #表示最开始的地址,而在u-boot.lds -Ttext 0x33F80000中指定地址为0x33F80000,所以开始执行的地址为0x33F80000

        . = ALIGN(4); #表示对齐方式以2的4次方对齐
        .text      :
        {
          cpu/arm920t/start.o    (.text) #start.o文件的代码段
          board/100ask24x0/boot_init.o (.text) #boot_init.o 文件的代码段
          *(.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的命令段
        __u_boot_cmd_end = .;

        . = ALIGN(4);
        __bss_start = .;
        .bss : { *(.bss) } #放置bss段
        _end = .;
    }
    

u-boot.lds 

  分析完这个u-boot.lds,就可以知道u-boot.bin里具体放置的内容,就知道u-boot的执行顺序了,很显然放置在最前边的是start.o和boot_init.o。进入start.S中进行分析

  通过分析Makefile可以得到的结论就是:

1.u-boot中执行的第一个文件就是start.S

2.u-boot存放的地址为0x33F80000。这个0x33F80000定义的地方为./board/100ask24x0/config.mk:25:TEXT_BASE = 0x33F80000

如果想修改u-boot的存放地址,则可以修改./board/100ask24x0/config.mk文件中的TEXT_BASE的值

 
时间: 2024-10-26 12:57:12

u-boot中的Makefile的相关文章

3.Spring Boot中使用Swagger2构建强大的RESTful API文档

原文:http://www.jianshu.com/p/8033ef83a8ed 由于Spring Boot能够快速开发.便捷部署等特性,相信有很大一部分Spring Boot的用户会用来构建RESTful API.而我们构建RESTful API的目的通常都是由于多终端的原因,这些终端会共用很多底层业务逻辑,因此我们会抽象出这样一层来同时服务于多个移动端或者Web前端. 这样一来,我们的RESTful API就有可能要面对多个开发人员或多个开发团队:IOS开发.Android开发或是Web开发

spring-boot实战【10】【转】:Spring Boot中使用@Async实现异步调用

什么是"异步调用"? "异步调用"对应的是"同步调用",同步调用指程序按照定义顺序依次执行,每一行程序都必须等待上一行程序执行完成之后才能执行:异步调用指程序在顺序执行时,不等待异步调用的语句返回结果就执行后面的程序. 同步调用 下面通过一个简单示例来直观的理解什么是同步调用: 定义Task类,创建三个处理函数分别模拟三个执行任务的操作,操作消耗时间随机取(10秒内) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

spring-boot实战【07】【转】:Spring Boot中Web应用的统一异常处理

我们在做Web应用的时候,请求处理过程中发生错误是非常常见的情况.Spring Boot提供了一个默认的映射:/error,当处理中抛出异常之后,会转到该请求中处理,并且该请求有一个全局的错误页面用来展示异常内容. 选择一个之前实现过的Web应用(Chapter3-1-2)为基础,启动该应用,访问一个不存在的URL,或是修改处理内容,直接抛出异常,如: 1 2 3 4 @RequestMapping("/hello") public String hello() throws Exce

spring-boot实战【09】【转】:Spring Boot中使用@Scheduled创建定时任务

我们在编写Spring Boot应用中经常会遇到这样的场景,比如:我需要定时地发送一些短信.邮件之类的操作,也可能会定时地检查和监控一些标志.参数等. 创建定时任务 在Spring Boot中编写定时任务是非常简单的事,下面通过实例介绍如何在Spring Boot中创建定时任务,实现每过5秒输出一下当前时间. 在Spring Boot的主类中加入@EnableScheduling注解,启用定时任务的配置 1 2 3 4 5 6 7 8 9 10 @SpringBootApplication @E

spring-boot实战【12】:Spring Boot中使用JavaMailSender发送邮件

相信使用过Spring的众多开发者都知道Spring提供了非常好用的JavaMailSender接口实现邮件发送.在Spring Boot的Starter模块中也为此提供了自动化配置.下面通过实例看看如何在Spring Boot中使用JavaMailSender发送邮件. 快速入门 在Spring Boot的工程中的pom.xml中引入spring-boot-starter-mail依赖: 1 2 3 4 <dependency> <groupId>org.springframew

再谈Spring Boot中的乱码和编码问题

编码算不上一个大问题,即使你什么都不管,也有很大的可能你不会遇到任何问题,因为大部分框架都有默认的编码配置,有很多是UTF-8,那么遇到中文乱码的机会很低,所以很多人也忽视了. Spring系列产品大量运用在网站开发中,而Spring Boot是为了简化配置而出现的,理论上讲Spring Boot应该默认配置UTF-8为默认编码,但是网络上依然可以看到很多关于Spring Boot乱码的文章,大部分解决方案沿用Spring MVC的方案,自定义EncodingFilter. 但是仔细查看Spri

Spring Boot中的注解

文章来源:http://www.tuicool.com/articles/bQnMra 在Spring Boot中几乎可以完全弃用xml配置文件,本文的主题是分析常用的注解. Spring最开始是为了解决EJB等大型企业框架对应用程序的侵入性,因此大量依靠配置文件来“非侵入式”得给POJO增加功能,然而,从Spring 3.x开始,Spring被外界最为诟病的一点就是配置繁多,号称“配置地狱”,各种xml文件,出了问题非常难排查.从Spring 4.x开始,Spring.io提供了三种方式编织B

Spring Boot中使用Swagger2生成RESTful API文档(转)

效果如下图所示: 添加Swagger2依赖 在pom.xml中加入Swagger2的依赖 <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <versi

SpringBoot(三) :Spring boot 中 Redis 的使用

前言: 这一篇讲的是Spring Boot中Redis的运用,之前没有在项目中用过Redis,所以没有太大的感觉,以后可能需要回头再来仔细看看. 原文出处: 纯洁的微笑 SpringBoot对常用的数据库支持外,对NoSQL 数据库也进行了封装自动化. redis介绍 Redis是目前业界使用最广泛的内存数据存储.相比memcached,Redis支持更丰富的数据结构,例如hashes, lists, sets等,同时支持数据持久化.除此之外,Redis还提供一些类数据库的特性,比如事务,HA,

Spring Boot中使用AOP统一处理Web请求日志

AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是Spring框架中的一个重要内容,它通过对既有程序定义一个切入点,然后在其前后切入不同的执行内容,比如常见的有:打开数据库连接/关闭数据库连接.打开事务/关闭事务.记录日志等.基于AOP不会破坏原来程序逻辑,因此它可以很好的对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率.