嵌入式Linux系统从软件角度通常可以分为以下4个层次:

引导加载程序 | Linux内核 | 文件系统 | 用户应用程序

嵌入式Linux系统中典型分区结构:

正常启动过程中,Bootloader首先运行,然后它将内核复制到内核中,并且在内存某个固定地址设置好要传递给内核的参数,最后运行内核。内核启动之后,它会挂接根文件系统,启动文件系统中的应用程序。

一、Bootloader的作用:

CPU上电后,会从某个地址开始执行,对于ARM结构的CPU是从0x00000000开始,Bootloader就存放在这个地址的开始处。这样一上电就可以执行。Bootloader主要用于初始化最基本的硬件、准备好软件环境和加载Linux操作系统。

二、嵌入式Linux中为什么要有Bootloader?

在Linux内核启动时,除了内核映像必须在主存的适当位置外,CPU还必须满足以下条件:

  CPU寄存器的设置

    1、R0 = 0

    2、R1 = Machine ID

    3、R2 = 内核启动参数在RAM中的起始基地址

  U-boot最终是调用theKernel函数来跳转执行linux内核的,uboot调用此函数(即linux内核)时会直接传递给linux内核3个参数,而这3个参数就是通过寄存器来实现传参的。

  其中第1个参数固定为0,就放在r0寄存器中,第二个参数为机器类型ID即机器码,放在r1寄存器,第3个参数就是启动参数标记列表在RAM中的首地址,就放在r2寄存器中。

  CPU模式

    1、必须禁止中断(IRQs 和 FIQs,中断请求和快速中断请求)

    2、CPU必须是SVC模式(特权模式)

  为何要禁止中断?---因为U-Boot只是完成硬件初始化、环境参数设置、代码搬运等工作,用不到中断,屏蔽中断是为了避免因为意外中断使得boot失败,毕竟很多外设还

  没有初始化,对应中断代码也都没有准备好。

  为何特权模式?---从uboot方面考虑,其要做的事情是初始化系统相关硬件资源,需要获取尽量多的权限,以方便操作硬件,初始化硬件。设置为svc模式,更有利于其工作。

  Cache 和MMU 的设置
    1、 MMU 必须关闭。
     2、 指令Cache 可以打开也可以关闭。
     3、数据Cache 必须关闭。

  MMU在上电之初没有任何作用,即U-boot第一阶段的汇编代码与第二阶段的源代码初始化相关外设时访问的都是实际地址,为了启动之初不影响对程序启动常关MMU。

  Cache是位于RAM和CPU内部寄存器之间的一个存储设施,用来加速二者之间的数据传输速度,即用来加快CPU从内存中取出指令的速度。但是在上电后CPU的初始化要比内存RAM快一拍,当CPU初始化完成后需要读取来自内存的数据,若内存还没有准备好那势必会造成异常,系统就挂掉了,因此需要关闭数据Cache,而指令Cache关与不关影响不大。

三、U-boot 源码分析

1、源代码组织

对于ARM而言,主要的目录如下:

board               平台依赖      存放电路板相关的目录文件,每一套板子对 应一个目录。如smdk2410(arm920t)
cpu 平台依赖 存放CPU相关的目录文件,每一款CPU对应一个目录,例如:arm920t、 xscale、i386等目录
lib_arm 平台依赖 存放对ARM体系结构通用的文件,主要用于实现ARM平台通用的函数,如软件浮点。
common 通用 通用的多功能函数实现,如环境,命令,控制台相关的函数实现。
include 通用 头文件和开发板配置文件,所有开发板的配置文件都在configs目录下
lib_generic 通用 通用库函数的实现
net 通用 存放网络协议的程序
drivers 通用 通用的设备驱动程序,主要有以太网接口的驱动,nand驱动。
.......

启动相关的几个重要文件:

1)cpu/arm920t 目录下

  Start.S文件是一个汇编代码文件,是Bootloader运行的第一个文件,Bootloader的入口。

  U-boot.lds 文件是一个连接器用的连接脚本文件,用来指定映像文件中各段的加载地址和运行地址。

......

2)Makefile简要分析

  所有这些目录的编译连接都是由顶层目录的makefile来确定的。
  在执行make之前,先要执行make $(board)_config 对工程进行配置,以确定特定于目标板的各个子目录和头文件。
  $(board)_config:是makefile 中的一个伪目标,它传入指定的CPU,ARCH,BOARD,SOC参数去执行mkconfig脚本。
  这个脚本的主要功能在于连接目标板平台相关的头文件夹,生成config.h文件包含板子的配置头文件。
  使得makefile能根据目标板的这些参数去编译正确的平台相关的子目录。
  以smdk2410板为例,执行 make smdk2410_config,
  主要完成三个功能:
    1)在include文件夹下建立相应的文件(夹)软连接,

    #如果是ARM体系将执行以下操作:
    #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头文件,只有一行:

    /* Automatically generated - do not edit */
    #include "config/smdk2410.h"

    顶层makefile先调用各子目录的makefile,生成目标文件或者目标文件库。
    然后再连接所有目标文件(库)生成最终的u-boot.bin。
    连接的跟平台相关的主要目标(库)如下:

    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(见上述)。
    其余的均与平台无关。
    所以考虑移植的时候也主要考虑这几个目标文件(库)对应的目录。

U-boot启动流程:

从文件层面上看主要流程是在两个文件中:cpu/arm920t/start.s,lib_arm/board.c,下一节开始分析start.s

思考:

为什么引导代码不全用C语言写?

1、在初始化硬件时,需要设置特殊功能寄存器,比如CPU工作模式,C语言不能对这些寄存器操作

2、C程序运行需要提前设置栈空间。

  

U-BOOT概述及源码分析(一)的更多相关文章

  1. spring boot 2.0 源码分析(一)

    在学习spring boot 2.0源码之前,我们先利用spring initializr快速地创建一个基本的简单的示例: 1.先从创建示例中的main函数开始读起: package com.exam ...

  2. spring boot 2.0 源码分析(四)

    在上一章的源码分析里,我们知道了spring boot 2.0中的环境是如何区分普通环境和web环境的,以及如何准备运行时环境和应用上下文的,今天我们继续分析一下run函数接下来又做了那些事情.先把r ...

  3. Spring Boot 自动配置 源码分析

    Spring Boot 最大的特点(亮点)就是自动配置 AutoConfiguration 下面,先说一下 @EnableAutoConfiguration ,然后再看源代码,到底自动配置是怎么配置的 ...

  4. spring boot 2.0 源码分析(二)

    在上一章学习了spring boot 2.0启动的大概流程以后,今天我们来深挖一下SpringApplication实例变量的run函数. 先把这段run函数的代码贴出来: /** * Run the ...

  5. spring boot 2.0 源码分析(三)

    通过上一章的源码分析,我们知道了spring boot里面的listeners到底是什么(META-INF/spring.factories定义的资源的实例),以及它是创建和启动的,今天我们继续深入分 ...

  6. spring boot 2.0 源码分析(五)

    在上一篇文章中我们详细分析了spring boot是如何准备上下文环境的,今天我们来看一下run函数剩余的内容.还是先把run函数贴出来: /** * Run the Spring applicati ...

  7. spring boot中扩展spring mvc 源码分析

    首先,确认你是对spring boot的自动配置相关机制是有了解的,如果不了解请看我spring boot相关的源码分析. 通常的使用方法是继承自org.springframework.boot.au ...

  8. ArrayList源码分析-jdk11 (18.9)

    目录 1.概述 2.源码分析 2.1参数 2.2 构造方法 2.2.1 无参构造方法 2.2.2 构造空的具有特定初始容量值方法 2.2.3构造一个包含指定集合元素的列表,按照集合的迭代器返回它们的顺 ...

  9. 精尽Spring Boot源码分析 - 序言

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

随机推荐

  1. Step by Step Do IOS Swift CoreData Simple Demo

    简单介绍 这篇文章记录了在 IOS 中使用 Swift 操作 CoreData 的一些基础性内容,因为缺乏文档,基本上都是自行实验的结果.错漏不可避免,还请谅解. 部分内容借鉴了 Tim Roadle ...

  2. 深入C++ new/delete,malloc/free解析

    深入C++ new/delete,malloc/free解析 1.malloc与free是C++/C语言的标准库函数.new/delete是C++的运算符. 它们都可用于申请动态内存和释放内存 2.对 ...

  3. js绑定事件方法:addEventListener与attachEvent的不同浏览器的兼容性写法

    js的事件绑定方法中,ie仅仅支持attachEvent,而FF和Chrome仅仅支持addEventListener,所以就必须为这两个方法做兼容处理,原理是先推断attachEvent仅仅否为真( ...

  4. Oracle 常用内置函数

    --绝对值 ) --求模 ,) --取整 --四舍五入 )from dual;--123.5 ) --截取 )from dual;--123.4 ) --字符串长度 --截取 select st.sn ...

  5. 51Nod 1433 0和5(数论)

    小K手中有n张牌,每张牌上有一个一位数的数,这个字数不是0就是5.小K从这些牌在抽出任意张(不能抽0张),排成一行这样就组成了一个数.使得这个数尽可能大,而且可以被90整除. 注意: 1.这个数没有前 ...

  6. 把ISO文件当作光盘挂载

    当不能挂载光盘或者U盘时候,只需要把ISO文件传到某个目录中,比如/data下,即可挂载,如下所示:   mount -o loop /data/rhel-server-6.3-x86_64-dvd. ...

  7. Chromium Graphics: Video Playback and Compositor

    Video Playback and Compositor Authors: jamesr@chromium.org, danakj@chromium.org The Chromium composi ...

  8. Web开发、原生开发、混合开发的区别优势:

    一.Web 应用 Web应用本质上是为移动浏览器设计的基于Web的应用,它们是用普通Web开发语言开发的,可以在各种智能手机浏览器上运行. 优点: 支持设备广泛: 较低的开发成本: 可即时上线: 无内 ...

  9. Debian9.5 WPS for Linux字体配置(字体缺失解决办法)

    启动WPS for Linux后,出现提示"系统缺失字体" . 出现提示的原因是因为WPS for Linux没有自带windows的字体,只要在Linux系统中加载字体即可. 具 ...

  10. iOS——集成支付宝 private key is NULL

    问题描述:将生成的私钥,写进官方demo,还是一直报错:rsa_private read error : private key is NULL 解决方案:需要将RSA私钥转换成PKCS8格式