Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3184
  • 博文数量: 6
  • 博客积分: 165
  • 博客等级: 入伍新兵
  • 技术积分: 70
  • 用 户 组: 普通用户
  • 注册时间: 2011-10-15 22:26
文章分类

全部博文(6)

文章存档

2011年(6)

我的朋友
最近访客

分类: 嵌入式

2011-10-23 11:20:30

    u-boot-1.1.6源码学习主要讲述和总结了本人在学习u-boot中的每个步骤,由于水平有限,难免有误,欢迎指正。
 
U-Boot启动内核的过程可以分为两个阶段,两个阶段的功能如下:
 
    1. 第一阶段的功能:
        (1)硬件设备初始化;
        (2)加载U-Boot第二阶段代码到RAM空间;
        (3)设置好栈;
        (4)跳转到第二阶段代码入口;
   2. 第一阶段的功能:
        (1)初始化本阶段使用的硬件设备
        (2)检测系统内存映射
        (3)将内核从Flash读取到RAM
        (4)为内核设置启动参数
        (5)调用内核。
 

1. 了解u-boot主要的目录结构和启动流程,如下图。

u-boot的stage1代码通常放在cpu/xxxx/start.S文件中,他用汇编语言写成;
u-boot的stage2代码通常放在lib_xxxx/board.c文件中,他用C语言写成。
各个部分的流程图如下:
 
2. u-boot源码分析——Makefile简要分析
 
    u-boot下所有目录的编译连接都是由顶层目录的Makefile来决定的。在执行make之前,先要执行 make $(board)_config 对工程进行配置,以确定特定于目标板的各个子目录和头文件。$(board)_config 是Makefile 中的一个伪目标,它传入指定的CPU,ARCH,BOARD,SOC参数去执行mkconfig脚本。这个脚本的主要功能在于连接目标板平台相关的头文件夹,生成config.h文件包含板子的配置头文件,使得Makefile能根据目标板的这些参数去编译正确的平台相关的子目录。
 
    以smdk2410为例:make  smdk2410_config
 
    该配置主要完成以下三个功能:
 
(1)在include文件夹下建立相应的文件(夹)软连接;
       #ln -s asm-arm asm
       #ln -s arch-s3c24x0 asm-arm/arch
       #ln -s proc-armv asm-arm/proc
 
(2)生成Makefile包含文件include/config.mk,内容很简单,定义了四个变量
       ARCH   = arm
       CPU    = arm920t
       BOARD  = smdk2410
       SOC    = s3c24x0

(3)生成include/config.h头文件,只有一行
     #include
 
    顶层makefile先调用各子目录的makefile,生成目标文件或者目标文件库,然后再连接所有目标文件(库)生成最终的u-boot.bin。
    连接的主要目标(库)如下:
 
  OBJS = cpu/$(CPU)/start.o
    LIBS = lib_generic/libgeneric.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
    LIBS += fs/cramfs/libcramfs.a fs/fat/libfat.a   \
              fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a    
    LIBS += net/libnet.a
    LIBS += disk/libdisk.a
    LIBS += rtc/librtc.a
    LIBS += dtt/libdtt.a
    LIBS += drivers/libdrivers.a
    LIBS += drivers/nand/libnand.a
    LIBS += drivers/nand_legacy/libnand_legacy.a
    LIBS += drivers/sk98lin/libsk98lin.a
    LIBS += post/libpost.a post/cpu/libcpu.a
    LIBS += common/libcommon.a
    LIBS += $(BOARDLIBS)
显然跟平台相关的主要是:
     cpu/$(CPU)/start.o 
     board/$(BOARDDIR)/lib$(BOARD).a 
     cpu/$(CPU)/lib$(CPU).a
     cpu/$(CPU)/$(SOC)/lib$(SOC).a 
     lib_$(ARCH)/lib$(ARCH).a
 
    这里面的四个变量定义在include/config.mk(见上述)。其余的均与平台无关,所以考虑移植的时候也主要考虑这几个目标文件(库)对应的目录。
3. u-boot源码分析——u-boot的通用目录是怎么做到与平台无关的

    现在来看smdk2410重要的头文件smdk2410.h,该文件在include/configs/ 中,这个头文件中主要定义了两类变量。
   
    (1)选项类,前缀是CONFIG_,用来选择处理器、设备接口、命令、属性等,主要用来决定是否编译某些文件或者函数。
 
    (2)参数类,前缀是CFG_,用来定义总线频率、串口波特率、Flash地址等参数,这些常数参量主要用来支持通用目录中的代码,定义板子资源参数。
    两类参数对u-boot的移植性非常关键,比如drive/CS8900.c,对cs8900而言,很多操作都是通用的,但不是所有的板子上面都有这个芯片,即使有它在内存中映射的基地址也是平台相关的。所以对于smdk2410板,在smdk2410.h中定义了:
             #define CONFIG_DRIVER_CS8900 1     /* we have a CS8900 on-board */
             #define CS8900_BASE 0x19000300     /*IO mode base address*/

      CONFIG_DRIVER_CS8900的定义使得cs8900.c可以被编译(当然还得定义CFG_CMD_NET才行),因为cs8900.c中在函数定义的前面就有编译条件判断:#ifdef CONFIG_DRIVER_CS8900 如果这个选项没有定义,整个cs8900.c就不会被编译了。
 
    而常数参量CS8900_BASE则用在cs8900.h头文件中定义各个功能寄存器的地址。u-boot的CS8900工作在IO模式下,只要给定IO寄存器在内存中映射的基地址,其余代码就与平台无关了。
       u-boot的命令也是通过目标板的配置头文件来配置的,比如要添加ping命令,就必须添加CFG_CMD_NETCFG_CMD_PING才行。不然common/cmd_net.c就不会被编译了。
 
    从这里可以这么认为,u-boot工程可配置性和移植性可以分为两层:
(1)由Makefile来实现,配置工程要包含的文件和文件夹上,用什么编译器。

(2)由目标板的配置头文件来实现源码级的可配置性,通用性。主要使用的是#ifdef #else #endif 之类来实现的。
 
 
4. u-boot源码分析——smdk2410其余重要的文件
 
   include/s3c24x0.h  定义了s3x24x0芯片的各个特殊功能寄存器(SFR)的地址。

   cpu/arm920t/start.s 在flash中执行的引导代码,也就是bootloader中的stage1,负责初始化硬件环境,把u-boot从flash加载到RAM中去,然后跳到lib_arm/board.c中的start_armboot中去执行。
   lib_arm/board.c   u-boot的初始化流程,尤其是u-boot用到的全局数据结构gd,bd的初始化,以及设备和控制台的初始化。
   board/smdk2410/flash.c 在board目录下代码的都是严重依赖目标板,对于不同的CPU,SOC,ARCH,u-boot都有相对通用的代码,但是板子构成却是多样的,主要是内存地址,flash型号,外围芯片如网络。
 
   
     接下来就分析u-boot第一阶段的代码。
阅读(74) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~