以前看别人讲课,说移植uboot需要哪些哪些步骤,听过之后总是容易忘,而且有些配置为什么要这样配置也没讲,只是告诉你怎么用,今天,我打算从uboot源码开始学习。提前预告一下,其实对于uboot的操作在readme文件中有很详细的讲述,而且有详细的来龙去脉。以下内容来自我从uboot readme文件的摘抄和总结,所以有些我认为不重要的内容没有留下,更全的内容请看uboot readme源文件。

1.uboot 可以支持很多类型的处理器。
2.uboot与Linux kernel有很大关系,有些头文件甚至直接来源于kernel源码树。
3.uboot的终端命令都是使用同一个接口定义的,所以添加新命令很容易。
4.通常,在Makefile中存在配置项的所有板子都是经过了一定程度的测试的,而且可以认为是工作的,事实上,它们很多都已经在生产线上使用了。
5.如果出现了问题,请查阅CHANGELOG和CREDITS文件查找是谁贡献的特定端口,MAINTAINERS文件里面列出了项目维护人员的名单。
6.有问题或者有贡献,请联系相关邮箱······
7.uboot下载网站:1>git://www.denx.de/git/u-boot.git
                  2>http://www.denx.de/cgi-bin/gitweb.cgi?p=u-boot.git;a=summary
                  3>ftp://ftp.denx.de/pub/u-boot/directory
8.软件配置
    配置项采用C预处理器定义,背后的原因是避免死代码
    有两类配置项变量
        _OPTIONS_:名字以CONFIG_开头的都是用户可以选择的配置项。
        _SETTINGS_:这些与硬件相关,最好不要碰,它们的名字以CFG_开头。

    配置工具和Linux kernel很像,现在以TQM8xxL开发板为例介绍配置过程
    a.选择处理器架构和开发版
        所有支持的板子都有现成默认的配置选项可以使用,只需要make<board_name>_config,比如TQM8xxL,cd /u-boot make TQM8XXL_config;
    b.配置项取决于CPU和开发版型号的结合,所有的信息都保存在include/configs/<board_name>.h中;很多的配置项和对应的Linux配置项完全一样,这样做的目的是为了以后构建配置工具的时候更容易。
    198-2540行全在介绍配置相关,但大篇幅的内容是将配置项陈列出来并加以解释,此部分跳过。
9.构建uboot
    a.设置环境变量CROSS_COMPILE
    b.通过make NAME_config来为特定的板型做配置,其中NAME_config是现有配置项之一的名字,在主Makefile中可以查看支持的配置项。
    c.最后make all,得到uboot的可执行文件。
uboot默认情况下编译得到的镜像是在源码目录下,如果需要指定编译到其他地方,可以有两种方法,一是设置环境变量BUIL_DIR指向目标位置,第二种是命令行make时加上"O=xxx/bb",但是第二种会覆盖第一种

10.如果主Makefile中没有列出我的系统板配置项,我需要按照以下步骤进行移植
    a.添加新的配置项到顶层Makefile和makeall脚本中去
    b.添加一个新的文件夹保存板子相关的代码,在这个文件夹中加入任何需要的文件,最少需要Makefile、<board>.c、flash.c和u-boot.lds
    c.为自己的板子添加一个文件“include/configs/<board>.h”
    d.如果是移植到一个新的CPU,新建一个文件夹保存CPU相关的代码以及任何需要的文件
    e.然后用新的名字make <board>_config
    f.make
    g.调试和测试可能出现的bug
    
11.修改uboot源码后(添加新的CPU或者板子或者设备)需要测试有没有破坏原来支持的所有系统,测试方法就是运行makeall脚本,默认是在本地构建uboot,但是为了不污染源码树,可以通过设置环境变量BUIL_DIR来改变镜像文件存放的地址,makeall脚本文件的运行默认会生成两个日志文件,这两个日志文件也可以通过设置环境变量MAKEALL_LOGDIR来改变其存放的位置。

12.列出了uboot的命令列表

13.环境变量:
    setenv设置环境变量的值,如果setenv后面没有数值则表示删除该环境变量,saveenv将内存中的所有环境变量保存到flash中去,printenv打印所有的环境变量。为了防止flash中的环境变量被意外擦掉,uboot提供一份默认的环境变量。
    列出了所有的环境变量
    serial和ethaddr两个环境变量比较特殊,它们只能被设置一次且不能被覆盖,一般都是出厂的时候就写入了,ver环境变量是只读的
    
14.命令行剖析:
有两种命令shell,一种是老的,简单的;一种是强大的,新的;后者的功能更强大。
普遍规则:几个用分号隔开的命令一起执行,其中一个失败了,其他的命令会继续执行;几个环境变量一起执行,其中一个失败了,其余的就会停止,不会继续。

15.多个网卡:uboot支持多个网卡,而且会自动使用正在工作的网卡。当srom里的mac地址和环境变量里的不一样则使用环境变量里的那个并打印一个警告,如果srom和环境变量里面都没有设置mac地址则会报错。

16.镜像有两种。

17.bootm用于启动内核的时候,bootargs会作为参数传给内核。

18.examples/hello.c和time.c在构建uboot的时候会自动编译,加载uboot的时候可以用于测试,地址是0x40004

19.uboot的内部实现
    uboot运行以后开始耗尽ROM(闪存),通常是不能访问RAM内存的(因为内存控制器还没有被初始化),这意味着我们没有可写的数据段和BSS段,并且bss段还没有被初始化为0。为了使C环境能够工作,我们至少要分配一个最小栈,实现选项由CPU定义和限制。
    初始化全局数据(数据段)为只读,不要尝试去写入。
    不要使用任何为初始化的全局数据(这是未定义的),稍后初始化将执行(当重定位到RAM时)。
    栈的空间很小,避免使用大的数据缓冲区和类似操作。

----------------
初始化栈,全局数据
    只有栈空间可以作为可写内存的限制以为这不能使用正常的全局变量来共享代码之间的信息,通过为所有函数提供全局数据结构(gd_t)可以实现,但是这样会使代码变得庞大,可以利用GCC编译的一个特性来解决,将指向全局数据结构的指针放到我们为此准备的寄存器中。
    这个寄存器的选择受到当前体系架构和GCC实现的限制。
    在PC机上uboot将会使用R2寄存器来存储指向全局数据的指针;在ARM上uboot将会使用R8寄存器来存储指向全局数据的指针
----------------
内存管理        
    uboot在系统状态下运行,使用物理地址,MMU既不用于内存映射,也不用于内存保护
    
    可使用的内存通过内存控制器映射到固定的地址。
    uboot安装在闪存的一个山区的前128kB的位置,然后是初始化DRAM,代码将自己重定位到DRAM的尾部。在uboot下有一些内存被保留用于malloc(查看CFG_MALLOC_LEN),然后一个全局板卡信息结构体被放置到,然后是堆栈
    
    另外,一些异常处理代码会被复制到DRAM的低8kB的位置
    所以具有16MB DRAM的典型内存分配是这样的:
    0x0000 0000    Exception Vector code
          :
    0x0000 1FFF
    0x0000 2000    Free for Application Use
          :
    0x00FB FF20    Monitor Stack (Growing downward)
    0x00FB FFAC    Board Info Data and permanent copy of global data
    0x00FC 0000    Malloc Arena
          :
    0x00FD FFFF
    0x00FE 0000    RAM Copy of Monitor Code
    ...        eventually: LCD or video framebuffer
    ...        eventually: pRAM (Protected RAM - unchanged by reset)
    0x00FF FFFF    [End of RAM]

    只有重定位完成之后才算真正的拥有C环境
    
    uboot使用C语言来实现(小部分使用汇编语言),没有使用C++语言,所以不要使用C++风格的注释(//)

Logo

更多推荐