打印
[嵌入式linux]

BootLoader原理和移植

[复制链接]
1262|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Ketose|  楼主 | 2023-1-29 10:09 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 Ketose 于 2023-1-29 11:09 编辑

1. 什么是BootLoader

就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境,他就是所谓的引导加载程序(Boot Loader)。

flash中存储文件的分布大致为:

2. 为什么要移植系统前要移植BootLoader?

BootLoader的任务是引导操作系统,所谓引导操作系统,就是启动内核,让内核运行就是把内核加载到内存RAM中去运行,那先问两个问题:第一个问题,是谁把内核搬到内存中去运行?第二个问题:我们说的内存是SDRAM,大家都知道,这种内存和SRAM不同,最大的不同就是SRAM只要系统上电就可以运行,而SDRAM需要软件进行初始化才能运行,那么在把内核搬运到内存运行之前必须要先初始化内存吧,那么内存是由谁来初始化的呢?其实这两件事情都是由bootloader来干的,目的是为内核的运行准备好软硬件环境,没有bootloadr我们的系统当然不能跑起来。
3. BootLoader的分类

首先我么需要申明一个比较容易犯错的概念:uboot其实是BootLoader的一种,uboot也就是universal boot loader(通用引导程序),BootLoader是有很多种的他们根据所支持的平台和功能特性有所不同(请看下表)。但通常有的同学认为uboot就是BootLoader,BootLoader就是uboot这是错误的。Uboot只是BootLoader的一种。下表列出了常见的BootLoader的功能特性以及其所支持的平台。

由上图可以看出,不同的bootloader具有不同的使用范围,其中最令人瞩目的就是有一个叫U-Boot的bootloader,是一个通用的引导程序,而且同时支持X86、ARM和PowerPC等多种处理器架构。U-Boot,全称 Universal Boot Loader,是遵循GPL条款的开放源码项目,是由德国DENX小组开发的用于多种嵌入式CPU的bootloader程序,对于Linux的开发,德国的u-boot做出了巨大的贡献,而且是开源的。
4. U-Boot的特点

我们现在使用的BootLoader绝大部分都是uboot,那么到底是什么原因导致uboot这么受欢迎呢?首先uboot具有以下特点:

① 开放源码;      

② 支持多种嵌入式操作系统内核,如Linux、NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS;      

③ 支持多个处理器系列,如PowerPC、ARM、x86、MIPS、XScale;      

④ 较高的可靠性和稳定性;      

⑤ 高度灵活的功能设置,适合U-Boot调试、操作系统不同引导要求、产品发布等;      

⑥ 丰富的设备驱动源码,如串口、以太网、SDRAM、FLASH、LCD、NVRAM、EEPROM、RTC、键盘等;      

⑦ 较为丰富的开发调试文档与强大的网络技术支持;      

其实,把u-boot可以理解为是一个小型的操作系统。

U-Boot的目录结构

前面讲了uboot可以看作是一个小型的操作系统,上面这些目录可以看作类似于Linux一样的文件系统。

U-Boot的工作模式

U-Boot的工作模式有启动加载模式和下载模式。

启动加载模式是Bootloader的正常工作模式,嵌入式产品发布时,Bootloader必须工作在这种模式下,Bootloader将嵌入式操作系统从FLASH中加载到SDRAM中运行,整个过程是自动的。

下载模式就是Bootloader通过某些通信手段将内核映像或根文件系统映像等从PC机中下载到目标板的SDRAM中运行,我们可以利用Bootloader提供的一些指令接口来完成自己想要的操作,这种模式主要用于测试和开发。
5. U-Boot启动过程

大多数BootLoader都分为stage1和stage2两大部分,U-boot也不例外。依赖于cpu体系结构的代码(如设备初始化代码等)通常都放在stage1且可以用汇编语言来实现,而stage2则通常用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。

    stage1(start.s代码结构)  

U-boot的stage1代码通常放在start.s文件中,它用汇编语言写成,其主要代码部分如下:

(1) 定义入口。由于一个可执行的image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在rom(Flash)的0x0地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本来完成。

(2)设置异常向量(exception vector)。

(3)设置CPU的速度、时钟频率及中断控制寄存器。

(4)初始化内存控制器 。

(5)将rom中的程序复制到ram中。

(6)初始化堆栈 。

(7)转到ram中执行,该工作可使用指令ldr pc来完成。

2. stage2(C语言代码部分)

lib_arm/board.c中的start armboot是C语言开始的函数,也是整个启动代码中C语言的主函数,同时还是整个u-boot(armboot)的主函数,该函数主要完成如下操作:

(1)调用一系列的初始化函数。

(2)初始化flash设备。

(3)初始化系统内存分配函数。

(4)如果目标系统拥有nand设备,则初始化nand设备。

(5)如果目标系统有显示设备,则初始化该类设备。

(6)初始化相关网络设备,填写ip,mac地址等。

(7)进入命令循环(即整个boot的工作循环),接受用户从串口输入的命令,然后进行相应的工作。

以基于cortex-A8的s5pc100 bootloader为例,分析其启动过程

s5pc100支持两种启动方式,分别为USB启动方式和NandFlash启动方式:

S5PC100 USB启动过程

[1] A8 reset, 执行iROM中的程序

[2] iROM中的程序根据S5PC100的配置管脚(SW1开关4,拨到4对面),判断从哪里启动(USB) (选择启动方式)

[3] iROM中的程序会初始化USB,然后等待PC机下载程序

[4] 利用DNW程序,从PC机下载SDRAM的初始化程序到iRAM中运行,初始化SDRAM

[5] SDRAM初始化完毕,iROM中的程序继续接管A8, 然后等待PC下载程序(BootLoader)

[6] PC利用DNW下载BootLoader到SDRAM

[7] 在SDRAM中运行BootLoader ,BootLoader运行起来后,A8就由BootLoader来接管了。

S5PC100 Nandflash启动过程

[1] A8 reset, 执行IROM中的程序

[2] iROM中的程序根据S5PC100的配置管脚(SW1开关4,拨到靠4那边),判断从哪里启动(Nandflash) (选择启动方式)

[3] iROM中的程序驱动Nandflash

[4] iROM中的程序会拷贝Nandflash前16k到iRAM

[5] 前16k的程序(BootLoader前半部分)初始化SDRAM,然后拷贝完整的BootLoader到SDRAM并运行

[6] BootLoader拷贝内核到SDRAM,并运行它

[7] 内核运行起来后,挂载rootfs,并且运行系统初始化脚本,接管A8。
uboot的移植

uboot的移植主要分为如下几步:

1. 在PC机上面

(1) 下载源码包

(2) 解压后添加我们自己的平台信息,以smdkc100为参考版,移植自己s5pc100的开发板

(3) 修改相应目录的文件名,和相应目录的Makefile,指定交叉工具链。

(4) 编译

(5) 针对我们的平台进行相应的移植,主要包括修改SDRAM的运行地址,从0x20000000

(6) “开关”相应的宏定义

(7) 添加Nand和网卡的驱动代码

(8) 优化go命令

(9) 重新编译

make distclean(彻底删除中间文件和配置文件)

make s5pc100_config(配置我们的开发板)  

make(编译出我们的u-boot.bin镜像文件)

(10) 设置环境变量,即启动参数,把编译好的u-boot下载到内存中运行,过程如下:

(11) 配置开发板网络        

ip地址配置:        

$setenv ipaddr 192.168.0.6               配置ip地址到内存的环境变量        

$saveenv                                 保存环境变量的值到nandflash的参数区

网络测试:        

在开发开发板上ping虚拟机:        

$ ping 192.168.0.157(虚拟机的ip地址)

如果网络测试失败,从下面几个方面检查网络:        

1. 网线是否连接好      

2. 开发板和虚拟机的ip地址是否配置在同一个网段      

3. 虚拟机网络一定要采用桥接(VM--Setting-->option)      

4. 连接开发板时,虚拟机需要设置成静态ip地址   

2. 在开发板上,配置tftp服务器(虚拟机)的ip地址        

$setenv serverip 192.168.0.157(虚拟机的ip地址)        

$saveenv   

3. 拷贝u-boot.bin到/tftpboot(虚拟机上的目录)   

4. 通过tftp下载u-boot.bin到开发板内存        

$ tftp 20008000(内存地址即可) u-boot.bin(要下载的文件名)      

如果上面的命令无法正常下载:        

1. serverip配置是否正确        

2. tftp服务启动失败,重启tftp服务         

#sudo service tftpd-hpa restart   

5. 烧写u-boot.bin到nandflash的0地址        

$nand erase 0(起始地址)  40000(大小)                    擦除nandflash 0 - 256k的区域        

$nand write 20008000((缓存u-boot.bin的内存地址) 0(nandflash上u-boot的位置) 40000(烧写大小)         

6. 切换开发板的启动方式到nandflash

1. 关闭开发板      

2. 把SW1的开关4拨到4的那边        

3. 启动开发板,它就从nandflash启动

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:我最讨厌两种人:一是有种族歧视的; 二是黑人;三是不识数的!

64

主题

3211

帖子

15

粉丝