Linux系统移植——学习笔记


一、u-boot工程

1、BootLoader介绍

BootLoader是操作系统运行之前要执行的一段程序,它负责初始化硬件设备、建立内容空间映射,从而操作系统的运行做好准备,是一个专门加载操作系统的程序。
对于嵌入式系统而言,没有通用的硬件平台,因此也没有通用的BootLoader,不同的平台、不同的CPU构架都有不同的BootLoader,因为BootLoader不光依赖CPU的体系结构也依赖硬件平台的配置,对于不同的开发板而言,那怕它的CPU一样,而BootLoader都会有区别,因此我们要为每一款开发板制作它属于它的BootLoader程序。
但大部分开发板的BootLoader仍有许多共性,所以我们没有必须全部从零制作,而对一个基础的BootLoader进行修改,而制作出能用的BootLoader程序。

2、u-boot简介

u-boot( Universal Boot Loader)是BootLoader的一种,它遵循GPL通用许可证的开源项目,它的源码的目录、编译形式都和Linux的源码很相似,可以说u-boot就是仿照Linux而开发的。

3、u-boot源码的获取

1.源头的代码是u-boot官网下载的,这种源码是最干净最纯粹的,一般CPU的生产厂商会下载这种源码,当CPU厂商生产出一款CPU之后就会使用这款CPU制作出一块公板(它会把这款CPU所具备的功能全部体现出来),然后会根据公板修改出一份符合它的u-boot。
2.开发板的供应商会购买CPU厂商的公板,然后对公板进行裁剪(去掉一些不需要的功能、替换掉一些不必要的硬件),然后再根据裁剪后开板有厂商提供的u-boot进行修改,从而制作出属于这款开发板的u-boot。
3.官网、CPU厂商、开发板厂商处可以获取u-boot源码,而从开发板厂商处获取的u-boot源码基本上是可以使用的,不需要做什么大的修改。

4、u-boot源码结构

    顶层的u-boot源有30多个目录,大致分为三类:
        1.与CPU体系结构或开发板硬件直接相关的代码。
        2.能用的函数、驱动程序
        3.应用程序、工具、文档
    board 平台相关 存储电路板相关的目录文件
    cpu 平台相关 与CPU的体系结构相关的库文件,由于S5PC11x的CPU早于S5PV210,而还兼容S5PV210,所以在这个目录只能看到S5PC110。
    include 通用 u-boot通用的一些头文件,还有一些各种硬件平台的汇编文件、系统配置和支持文件系统,configs目录有与开发板配置相关的头文件。
    common 通用 里面有u-boot所有支持的命令,每一个文件就代表一个命令。
    lib_generic 通用 里面是通用的库函数。
    net 通用 里面是与网络协议相关的代码。
    fs 通用 所支持的文件系统(管理硬盘上的文件的程序)。
    drivers 通用 所支持的设备驱动,如:网卡、串口、USB。
    disk 通用 对磁盘的支持。
    doc 文档 里面非常完整的u-boot说明文档。
    tools 通用 u-boot的一些工具
    examples 案例 一些能够独立运行的应用程序。

5、u-boot的配置编译

    u-boot是通过Makefile组织编译的,顶层的Makefile可以对开发板进行整体配置,然后递归调用各级目录下的Makefile,最后把所有编译过的代码链接成u-boot镜像。
    注意:编译前确定交叉编译,Makefile的147行。
    1.清理之前的编译的残留。
        make distclean
    2.配置编译方法
        make x210_sd_config
        注意:chmod +x mkconfig
    3.多线程编译
        make -jn 一般n是CPU内核数量的2倍。

6、u-boot的运行

    1.u-boot是ELF格式的,而u-boot.bin才是纯二进制指令格式的。
    2.u-boot.bin并不能直接运行,原因是没有添加校验和,而且之前添加校和的工具不能继续使用。
    3.sd_fusing目录中有为u-boot.bin添加校验和的工具,但并不能直接使用,需要在Makefile添加以下指令。
        291 all:
            cd sd_fusing && make
            ./sd_fusing/mkbl1 u-boot.bin sd-bl1-8k.bin 8192
            dd if=sd-bl1-8k.bin of=u-boot_image.bin
            dd if=u-boot.bin of=u-boot_image.bin seek=48
            rm -rf sd-bl1-8k.bin
            cp u-boot_image.bin /media/sf_shared/image/

二、u-boot常用命令

1、帮助命令
    help/p/?
2、环境变量相关命令
    printenv 显示所有环境变量
    setenv 添加/删除/修改环境变量
    saveenv 保存环境变量到硬盘
    注意:环境变量都是字符串,没有数据类型之分。
    注意:修改只是临时有效,重启后就会还原,必须使用保存命令才能长期有效。
    u-boot中的环境变量
    netmask:子网掩码
    ipaddr:板子的ip地址
    ethaddr:mac地址
    baudrate:串口波特率
    bootdelay:启动系统前的等待秒数
    gatewayip:网关ip地址
    bootcmd:默认启动时执行的命令
    bootargs:启动时传递给内核的参数
    serverip:服务器ip地址

3、网络相关的命令
    ping ip 测试与服务器是连通
    tftp 0x01020304 file.bin 可以从服务器下载程序到指定的内存地址。
        1.ubuntu系统需要搭建tftp服务器
        2.在ubuntu系统关机的情况下,设置网络模式为桥接模式,然后启动。
        3.设置ubuntu的ip地址,保证ubuntu、windows、开发板三者ip地址在同一网段、子网掩码一致。
        4.开发板ping通windows系统。
        5.开发板ping通ubuntu系统。
        6.在u-boot中执行 tftp d0020010 led.bin,可以将程序下载到开发板的d0020010地址处,go d0020010 可以到此地址执行。
        注意:Windows防火墙,如果不会配置规则,建议关闭。
4、启动命令
    boottm 0x01020304 从该内存地址启动系统。
    boot 它需要与bootcmd环境变量配合,根据bootcmd的设置来启动系统。

一、u-boot编译过程分析

u-boot顶层目录下的Makefile负责u-boot的整体编译过程,因此想要了解u-boot的编译过程需要阅读Makefile文件。
Makefile中没有数据类型之分,全部都是字符串数据。
具体分析过程参见 Makefile_bck 文件

总结:
    1、u-boot的源码不是一行行代码写出来的,而拼凑出来的,一份u-boot源码中可能包含了适用于各种开发板的源码,用条件编译进行区分的。
    2、很多文件不自带的,而是配置过程根据一些原材料生成的。
    3、u-boot的整体的代码构架是参考了Linux内核,而编译过程与Linux也很相似。

二、u-boot的配置过程

1、执行make x210_sd_config 命令,然后make会执行Makefile脚本中的x210_sd_config目标。
2、x210_sd_config依赖了unconfig,unconfig中会删除所有旧的头文件、mk文件。
3、然后调用了mkconfig脚本,并传递了6个参数,分别是x210_sd arm s5pc11x x210      samsung s5pc110。
4、在mkconfig脚本中先确定的开发板的名字,检查参数的数量。
5、根据参数3,删除旧的链接文件,创建新的链接文件。
6、然后把参数2、3、4、5、5写到include目录下的config.mk中
7、在include目录下创建config.h头文件,并让它实际指向,config/下的以参数1命名的头文件。
8、把0xc3e00000写入board/samsung/x210/config.mk文件中,用于指定链接地址。

三、u-boot的链接脚本

 u-boot的链接脚本在board/samsung/x210/u-boot.lds,与裸机课程中讲的链接脚本没有本质区别,只是复杂度高一些,文件多一些,使用的技巧多一些。
    1、ENTRY(_start) 指定整个uboot的入口地址,类似于C语言中的main函数。
    2、指定程序链接地址的方法有两种
        在Makefile文件中通过参数 -Ttext=0xc3e00000
        在链接脚本中的SECTIONS里 .=0x00000000
    注意:如果两个方式都设置,优先使用-Ttext设置的地址,而u-boot实际使用的是0xc3e00000。

一、u-boot第一阶段启动流程

根据u-boot的配置过程可以找到它的链接脚本,然后根据链接脚本中代码段的排列位置找到u-boot的入口代码应该是cpu/s5pc11x/start.S文件。

1、start.S

    a、导入了一些头文件,这些头文件都配置过程中生成的链接文件(u-boot不能在windows目录下配置、编译)。
    b、config.h头文件是配置过程中生成了,里面的内容只有一行,#include <configs/x210_sd.h>,所以实际被包含的是configs/x210_sd.h。
    c、x210_sd.h文件中有大量的宏,里面都u-boot所需要的一些参数。
    d、version.h里面只记录一行有效内容,#include "version_autogenerated.h",version_autogenerated.h是配置过程中自动生成的,里面记录是u-boot的版本号。
    e、asm不是u-boot中的原生目录,而配置过程中生成的软链接,实际指向是asm-arm目录,而最终被包含的应该是asm-arm/proc-armv/domain.h。
    f、regs.h配置过程中生成的,实际被包含的是s5pc110.h。
    g、16个字节的校验和,而裸机课程时mkv210_image.c的功能就添加16个字节的校验和。
    h、_start:函数中就是用指令模拟的异常向量表,而_start依赖了reset函数,因此真正的入口函数是reset。
    i、而reset函数中禁用了外部中断和快速中断,设置cpu为SVC(特权模式)。
    j、接下顺序执行了cpu_init_crit函数,首先禁用了二级缓存,然后设置二级缓存,最后再启动二级缓存。
    k、然后初始化一级缓存、禁用MMU(内存管理单元,负责内存映射),然后读取启动介绍信息,根据r2寄存器中的值,确定启动介绍,最终会以SD/MMC BOOT方式启动。
    l、设置sram内存中位置为栈指针,然后调用lowlevel_init函数,而此函数在board/samsung/x210/lowlevel_init.S。

2、lowlevel_init.S

    a、检查复位状态,原因是reset函数被执行的原因有很多,比如:冷上电、热启动、睡眠状态下的唤醒,而它们区别是冷上电需要初始化DDR内存,而其它不用,如果是冷上则继续向下执行,否则调用wake。
    b、关闭看门狗,初始化SRAM相关的GPIO管脚,电源锁定。
    c、判断当前代码在什么位置,如果在DDR内存中则直接开始加载系统,如果在SRAM中则需要初始化时钟、DDR等。
    d、初始化时钟,205行~385行的代码都是初始化时钟系统。
    e、初始化DDR内存,mem_ctrl_asm_init函数不在当前文件中,而是定义在cpu/s5pc11x/s5pc110/cpu_init.S。
    f、初始uart,当完成uart的初始化后,向uart发送一个'O'。
    g、初始化TrustZone,开户系统保护。
    h、关闭基带模拟,到此为止lowlevel_init的工作已经全部完成,向uart发送一个'K',然后返回start.S中。
    总结lowlevel_init中一共做哪些事情:
        检查复位状态、SRAM相关GPIO管理的初始化,关闭看门狗、电源锁定、初始化时钟、初始化DDR内存、初始化串口关打印'O',启动TZPC、关闭基带模拟关打开'K'。

3、Start.S

    a、从lowlevel_init函数中返回,再次锁定电源。
    b、再次设置栈指针,因为之前已经设置过了,但当时DDR内存还没有初始化只能调到到SRAM中,而此时DDR已经完成初始化可以设置到DDR内存中了。
    c、再交判断代码的执行位置,这次判断的目的与之前的不同,这是为了决定是否重定位而判断的,如果此时代码运行在SRAM中,则说当前代码不是完成的u-boot,而初始化工作也已经全部完成,接下来则要把完整的u-boot从SD拷贝到DDR中运行。
    d、确定SD卡的通道号,会根据开发板的拨码开关设置自动在内存中设置相应的值。
    e、确定拷贝源,也就是什么介质中拷贝u-boot,最终会调用mmcsd_boot函数。
    f、mmcsd_boot函数中首先调用了movi_bl2_copy函数,而movi_bl2_copy函数会调用iROM中的拷贝函数。
        u32(*copy_sd_mmc_to_mem)(
            u32 channel, 表示通道号
            u32 start_block, 开始扇区号
            u16 block_size, 要拷贝的扇区数量
            u32 *trg, 拷贝到的目标位置
            u32 init); 保留
    g、重定位完成后则开始执行after_copy函数,开启域访问控制(为MMU做准备)。
    h、接下来设置TTB(内存映射转换表),然后开户MMU。
    物理地址:就是设置在生产时赋予的地址,它是根据在CPU管理上的接线位置决定的,物理地址是硬件编码一旦确定无法修改。
        我们在裸机编程时使用到的寄存器的地址都是物理地址,可以通过查阅芯片手册获取并操作,物理地址的缺点就是不够灵活。
    虚拟地址:就是在物理的软件操作之间加一个转换,这个转换操作就地址映射。
        物理地址到虚拟地址的映射时会建立一个地址映射表,操作硬件时,只需要操作虚拟地址,然后MMU芯片会根据地址映射表自动去操作对应的物理地址,这个过程由MMU芯片负责。
    地址映射的好处:
        1、可以编程更灵活
        2、使用代码的通用性更强
        3、在映射时还可以给虚拟地址设置权限,如:可读、可写、可执行等,提高内存的安全性。
        4、还可以把零散的内存映射成为一整块的内存,x210共有两个内存接入口,DRAM0可以接512M内存实际只接入了256M,DRAM1可以接1024M内存而实际只接入了256M内存,因此DRAM0与DRAM1中间是不连续的,而通过MMU的映入可以把DRAM0与DRAM1合并成一整块512M内存更方便使用。
    i、接下来再次设置栈指针,此次设置是在MMU开启之后,现在已经有了一块连续的512M内存,这次的设置会让内存的使用更安全,更紧凑,更节约内存。
    j、清理bss内存段,如果不清理全局变量和static变量就无法定义、使用。
    k、以后工作完成后则调用start_armboot函数,此函数位于lib_arm/board.c中,是一个C语言的函数,此时会跳转到DDR内存中开始第二阶段的u-boot运行。
    u-boot第一阶段启动流程总结:
        1、构建异常向量表
        2、设置CPU工作模式为特权模式
        3、关闭看门狗
        4、开发板电源锁定
        5、时钟系统初始化
        6、DDR内存初始化
        7、初始化串口并打印OK
        8、重定位
        9、建立映射表并开户MMU
        10、跳转到第二阶段

二、u-boot第二阶段启动流程

1、从宏观角度分析u-boot第二阶段启动流程应该做什么
    a、第一阶段主要是初始化CPU内部的一些硬件(看门狗、时钟、uart等),然后初始化DDR内存、重定位、开户MMU。
2、第二阶段就应该初始化CPU外部的一些硬件设备了,如:iNand、网卡、ADC。
3、u-boot本身所需要的一些事情,如:环境变量、命令。
4、完成所有的初始化工作后开始倒计时:
    1.等待超时,开始加载操作、加载文件系统,然后就是操作系统启动完成。
    2.按任意键,进入u-boot的命令行,在命令行中中可以执行命令、设置或查看环境变量。
        u-boot的命令行就是个死循环,不停的接收命令、解析命令、执行命令。

三、u-boot源码分析

1、u-boot的源码不是某个人或某人组织完成的,而是不同的组织完成了不同的工作,最终让u-boot具备引导操作系统的能力。
    u-boot官网负责整体代码的组织架构。
    半导体生产广商,根据CPU的特性对BL1段的代码进行修改,添加。
    开发板的生产广商,根据开发板的外部硬件对BL1、BL2阶段的代码进行修改、添加。
2、所有在修改u-boot代码时都遵循这样的原则:
    尽量不删除代码,那代码会接下的启动流程也是选择注释掉,而不是删除。
    u-boot为了兼容更多的CPU会做一些对于个别CPU无意义的事情。
    尽量多做不要少做,那怕做一些无意义的事情,也要让操作系统顺利启动。
3、由于u-boot只负责把操作系统启动起来,因此它不需要效率高、安全、稳定。
4、由于u-boot的代码构成比较复杂,所以质量不高,因此没有借鉴价值。
5、但u-boot代码是按照Linux内存的框架设计的,因此我们分析、研究、了解是为Linux内核的学习打开基础。

四、u-boot启动过程特征总结

1、从代码角度来看,第一阶段主要以汇编代码为主,第二阶段以C代码为主。
2、从内存角度来看,第一阶段主要运行在SRAM中,第二阶段在主要运行在DDR中。
3、从硬件角度来看,第二阶段注重的是CPU内部,第二阶段注意的是CPU外部、开发板的内部。

Author: Ikaros
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source Ikaros !
评论
 Previous
Linux驱动——学习笔记 Linux驱动——学习笔记
一、烧写Linux系统到inand1、烧写u-boot到inand tftp 30008000 u-boot.bin movi write u-boot 30008000 2、烧写Linux内核到inand tftp
Next 
ARM体系结构(重制版)——九鼎创展 x210V3s ARM体系结构(重制版)——九鼎创展 x210V3s
检查开发板:1、网线 2、电源 3、USB转串口 4、SD卡 5、开发板任务:1、试用开发板 2、阅读用户手册搭建开发板的开发环境:1、安装USB转串口的驱动,安装完成后重启。 查看串口信息,设置编号,设置波特率。 右击此电
2019-11-29
  TOC