引入,有人说bootloader就是U-boot,这种说法是错误的。u-boot应该是bootloader的一种,不同的ooloader具有不同的使用范畴,其中最常见的应该就是名字为u-boot的bootloader,是一个通用的引导程序 。
一.bootloader的概念
它其实就是在操作系统内核运行之前运行的一小段程序,我们可以初始化硬件设备,建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境,他就是所谓的引导加载程序(BootLoader)
Flash存储中存放文件的分布图
二.为什么系统移植之前必须要先移植bootloader?
bootloader的任务就是引导启动内核,第一个点是把内核加载到内存RAM中去运行;第二个点是我们说的内存是SDRAM,这种内存和SRAM不同,SRAM只需要系统上电就可以运行,但是SDRAM需要软件进行初始化才能运行。这两点都是bootloader来干的,目的是为内核的运行准备好软硬件环境,所以bootloader对系统来说很重要。
三.bootloader的分类
之间我们提过,u-boot是bootloader的一种,那就是说,bootloader有很多种类,如下图:
可以看出不同的bootloader具有不同的支持程度,其中我最常用的是u-boot,它同时支持X86,ARM和PowerPC等多种处理器架构。U-boot,遵循GPL条款的开放源码项目,是由德国DENX小组开发的用于多种嵌入式CPU的bootloader程序,对于Linux的开发,德国的u-boot做出了巨大的贡献,而且是开源的。
u-boot具有以下优点:
(1)开放源码,就是通俗点免费
(2)支持多种嵌入式操作系统内核,如Linux,netbsd,vxworks,qnx,rtems,artos,lynxos;
(3)支持多个处理器系列,如PowerPC,ARM,x86,MIPS。XScale
(4)较高的可靠性和稳定性
(5)特别灵活的功能设置,适合U-Boot调试,操作系统不同引导要求,产品发布等;
(6)丰富的设备驱动源码,如串口,以太网,SDRAM,FLASH,LCD,NVRAM,EEPROM,RTC,键盘等;
(7)较为丰富的开发调试文档与强大的网络技术支持;
u-boot都可以看成是一个小型的操作系统了。
四.u-boot的目录结构
![](https://img-blog.csdnimg.cn/dccd7990f072474daff009f7f48b76c1.png) * board 目标板相关文件,主要包含SDRAM、FLASH驱动; * common 独立于处理器体系结构的通用代码,如内存大小探测与故障检测; * cpu 与处理器相关的文件。如mpc8xx子目录下含串口、网口、LCD驱动及中断初始化等文件; * driver 通用设备驱动,如CFI FLASH驱动(目前对INTEL FLASH支持较好) * doc U-Boot的说明文档; * examples可在U-Boot下运行的示例程序;如hello_world.c,timer.c; * include U-Boot头文件;尤其configs子目录下与目标板相关的配置头文件是移植过程中经常要修改的文件; * lib_xxx 处理器体系相关的文件,如lib_ppc, lib_arm目录分别包含与PowerPC、ARM体系结构相关的文件; * net 与网络功能相关的文件目录,如bootp,nfs,tftp; * post 上电自检文件目录。尚有待于进一步完善; * rtc RTC驱动程序; * tools 用于创建U-Boot S-RECORD和BIN镜像文件的工具;
五.u-boot的工作模式
U-Boot的工作模式有启动加载模式和下载模式。启动加载模式是Bootloader的正常工作模式,嵌入式产品发布时,Bootloader必须工作在这种模式下,Bootloader将嵌入式操作系统从FLASH中加载到SDRAM中运行,整个过程是自动的。下载模式就是Bootloader通过某些通信手段将内核映像或根文件系统映像等从PC机中下载到目标板的SDRAM中运行,用户可以利用Bootloader提供的一些令接口来完成自己想要的操作,这种模式主要用于测试和开发。
六.u-boot的启动过程
大多数BootLoader都分为stage1和stage2两大部分,U-boot也不例外。依赖于cpu体系结构的代码(如设备初始化代码等)通常都放在stage1且可以用汇编语言来实现,而stage2则通常用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。
1、 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中执行,该工作可使用指令ldrpc来完成。
2、 stage2(C语言代码部分)
lib_arm/board.c中的start armboot是C语言开始的函数,也是整个启动代码中C语言的主函数,同时还是整个u-boot(armboot)的主函数,该函数主要完成如下操作:
(1)调用一系列的初始化函数。
(2)初始化flash设备。
(3)初始化系统内存分配函数。
(4)如果目标系统拥有nand设备,则初始化nand设备。
(5)如果目标系统有显示设备,则初始化该类设备。
(6)初始化相关网络设备,填写ip,c地址等。
(7)进入命令循环(即整个boot的工作循环),接受用户从串口输入的命令,然后进行相应的工作。
**七.基于cortex-A9的fs4412的移植过程分析 **
(1).下载源码包2013.03版本,比较稳定
(2).解压后添加我们自己的平台信息,以fs4412为参考版,移植自己fs4412的开发板
(3).修改相应目录的文件名,和相应目录的Makefile,指定交叉工具链。
(4).编译
(5).针对我们的平台进行相应的移植,主要包括修改SDRAM的运行地址,从0x20000000
(6).“开关”相应的宏定义
(7).添加Nand和网卡的驱动代码
(8).优化go命令
(9).重新编译 make distclean(彻底删除中间文件和配置文件) make fs4412_config(配置我们的开发板) make(编译出我们的u-boot.bin镜像文件)
(10).设置环境变量,即启动参数,把编译好的u-boot下载到内存中运行,过程如下:
- 配置开发板网络
uImage dtb ramdisk.img ---> mytftp2、准备好应用程序 a.out ---> mytftp
【超级终端】
1、set bootargs root=/dev/ram rw console=ttySAC2,115200 clk_ignore_unused init=/linuxrc
2、tftp 41000000 uImage tftp 42000000 xxxx.dtb tftp 43000000 ramdisk.img
3、bootm 41000000 43000000 42000000
【linux】
ifconfig xxx
tftp -g -r a.out 192.168.3.11
1、清理环境
make distclean
2、在boards.cfg 找到我们要的目标板
找到了 --》 go end 没有找到: 找 芯片(一样的!!!) 没有找到芯片?? --> 找新版本 找厂家提供 找到芯片, go end
3、编译fs4412步骤
1.源码移植: cp board/samsung/origen/ board/samsung/fs4412 -af cp include/configs/origen.h include/configs/fs4412.h 2. 添加目标:boards.cfg --> origen --> fs4412 3. make fs4412_config 4. make --->u-boot.bin
4、烧写
1)SD卡启动 2)tftp下载 u-boot.bin 3)烧写:movi write uboot 41000000 4)断电、拨码开关EMMC启动,上电。
执行上述步骤后我们发现。。。。。板子变砖了。
我们重点是去培养一种分析的思维,现在我们带着大家一步步分析思考。
八.fs4412开发板变板砖分析步骤
现象:板子变砖了。。。。
** 思考:1)程序运行,but 运行中出错,强行退出。**
** 2)程序未运行 ---> 调试手段 ---> 点灯**
tips:点灯是我们最简单的裸机驱动,可以运来判断是否程序开始运行。
uboot入口函数 --> 连接文件(.lds) --> Makefile u-boot-2013.01\arch\arm\cpu\armv7\start.S 现象:板子依然是板砖。。。。。 **思考:程序没有被执行** 上电 ---> 芯片????? ---> uboot ----》b1 + bl2 + uboot 现象:灯终于亮了,but 它又灭了 then 又亮了 。。。。。loop
** 思考:程序开始执行了。**
** 灯在闪烁--->板子复位---> 异常 X不是这个原因**
** 看门狗 X不是这个原因**
** ???问题在哪里**
** 电源管理模块 <--- 发送复位信号 <--- 复位的原因 ???**
|-->复位功能相关地方,让它不处理复位信号 |-->找到复位章节-->尝试去关闭 7个复位功能 --> 1. RM1B&&RM2B H level 现象:灯亮了,,,,一直亮的,,,,但是 界面还是没有反应
** 思考:界面输出 <--- 串口 <--- 串口初始化有问题**
看串口初始化代码 波特率设置值 <--- 串口时钟 <--- 系统时钟分频 现象:有数据输出,but ping tftp网络命令不能使用 **思考:ping 常用的命令 --> common ---> cmd_net.c ---> ping命令代码 由宏开关把控** 现象:ping命令有了,but 执行ping命令 卡住了。。。 **思考: 一直在ping 网卡驱动没有 ping问题 ---》网络初始化** dm9000_initialize <--- board_eth_init<---eth_initialize<---... 现象:ping命令没卡了,0x5000000 地址有问题 **思考: 地址是没有问题的,地址设备的初始化有问题 **---> SROM --->s5p_config_sromc <----pre_init<---board_init
最后问题解决,这种推理逻辑就是我们嵌入式工程师系统移植的精髓所在,关于我们对于所在问题的思考,想得出越多越好,如果自己想不出来那就找前辈,他们有丰富的经验,学会不耻下问。
那今天也就到这了,下次我们进入内核(kernel)的配置,编译和移植,谢谢大家阅读,我的实力有限,如果大佬发现问题请指出,万分感谢。
版权归原作者 飞赴 所有, 如有侵权,请联系我们删除。