Linux系统移植之—uboot移植,你们要的uboot终于来了,堪称精品
作为一名过来人,uboot、kernel对每个学linux的来说都有很深的情谊,因为它们是一个系统跑起来的最基础,每个学linux的都会首先接触到。而它们本身就是一个精美的小系统,里边代码所体现的逻辑、算法以及每个绝妙的C知识点都让你沉醉其中。
uboot 属于bootloader的一种,是用来引导启动内核的,它的最终目的就是,从flash中读出内核,放到内存中,启动内核。具体内容如下:
1 uboot 的介绍及系统结构
1.1 uboot 介绍
1.2 获取 uboot
1.3 uboot 体系结构
1.3.1 uboot 目录结构
2 uboot 的启动过程及工作原理
2.1 启动模式介绍
2.2 阶段 1 介绍
2.2.1 定义入口
2.2.2 设置异常向量
2.2.3 设置 CPU 的模式为 SVC 模式
2.2.4 关闭看门狗
2.2.5 禁掉所有中断
2.2.6 设置以 CPU 的频率
2.2.7 设置 CP15
2.2.8 配置内存区控制寄存器
2.2.9 安装 UBOOT 使的栈空间
2.2.10 BSS 段清 0
2.2.11 搬移 Nand Flash 代码
2.2.12 进入 C 代码部分
2.3 阶段 2 的 C 语言代码部分
2.3.1 调用一系列的初始化函数
2.3.2 初始化网络设备
2.3.3 进入主 UBOOT 命令行
2.4 代码搬运
3 uboot 的移 植过程
3.1 环境
3.2 步骤
3.2.1 修改 Makefile
3.2.2 在 board 子目录中建立 crane2410
3.2.3 在 include/configs/中建立配置头文件
3.2.4 指定交叉编译工具的路径
3.2.5 测试编译能否成功
3.2.6 修改 lowlevel_init.S 文件
2.9 UBOOT 的 Nand Flash 移植
3.2.8 重新编译 uboot
3.2.9 把 uboot 烧入 flash
4.2 常用命令使用说明
4.2.1 askenv(F)
在标准输入(stdin)获得环境变量。
4.2.2 autoscr
从内存(Memory)运行脚本。(注意,从下载地址开始,例如我们的开发板是从 0x30008000 处开始运
行).
CRANE2410 # autoscr 0x30008000
## Executing script at 30008000
4.2.3 base
打印或者设置当前指令与下载地址的地址偏移。
4.2.4 bdinfo
打印开发板信息
CRANE2410 # bdinfo
-arch_number = 0x000000C1 (CPU 体系结构号)
-env_t = 0x00000000 (环境变量)
-boot_params = 0x30000100 (启动引导参数)
-DRAM bank = 0x00000000 (内存区)
--> start = 0x30000000 (SDRAM 起始地址)
--> size = 0x04000000 (SDRAM 大小)
-ethaddr = 01:23:45:67:89:AB (以太网地址)
-ip_addr = 192.168.1.5 (IP 地址)
-baudrate = 115200 bps (波特率)
4.2.5 bootp
通过网络使用 Bootp 或者 TFTP 协议引导境像文件。
CRANE2410 # help bootp
bootp [loadAddress] [bootfilename]
4.2.6 bootelf
默认从 0x30008000 引导 elf 格式的文件(vmlinux)
CRANE2410 # help bootelf
bootelf [address] - load address of ELF image.
4.2.7 bootd(=boot)
引导的默认命令,即运行 U-BOOT 中在“include/configs/smdk2410.h” 中设置的“bootcmd” 中
的命令。如下:
#define CONFIG_BOOTCOMMAND "tftp 0x30008000 uImage; bootm 0x30008000";
在命令下做如下试验:
CRANE2410 # set bootcmd printenv
CRANE2410 # boot
bootdelay=3
baudrate=115200
ethaddr=01:23:45:67:89:abCRANE2410 # bootd
bootdelay=3
baudrate=115200
ethaddr=01:23:45:67:89:ab
4.2.8 tftp(tftpboot)
即将内核镜像文件从 PC 中下载到 SDRAM 的指定地址,然后通过 bootm 来引导内核,前提是所用 PC 要安装设
置 tftp 服务。
下载信息:
CRANE2410 # tftp 0x30008000 zImage
TFTP from server 10.0.0.1; our IP address is 10.0.0.110
Filename 'zImage'.
Load address: 0x30008000
Loading: #################################################################
#################################################################
#################################################
done
Bytes transferred = 913880 (df1d8 hex)
4.2.9 bootm
内核的入口地址开始引导内核。
CRANE2410 # bootm 0x30008000
## Booting image at 30008000 ...
Starting kernel ...
Uncompressing
Linux......................................................................
done, .
4.2.10 go
直接跳转到可执行文件的入口地址,执行可执行文件。
CRANE2410 # go 0x30008000
## Starting application at 0x30008000 ...
4.2.11 cmp
对输入的两段内存地址进行比较。
CRANE2410 # cmp 0x30008000 0x30008040 64
word at 0x30008000 (0xe321f0d3) != word at 0x30008040 (0xc022020c)
Total of 0 words were the same
CRANE2410 # cmp 0x30008000 0x30008000 64
Total of 100 words were the same
4.2.12 coninfo
打印所有控制设备和信息,例如
-List of available devices:
-serial 80000003 SIO stdin stdout stderr
4.2.13 cp
内存拷贝,cp 源地址 目的地址 拷贝大小(字节)
CRANE2410 # help cp
cp [.b, .w, .l] source target count
ANE2410 # cp 0x30008000 0x3000f000 644.2.14 date
获得/设置/重设日期和时间
CRANE2410 # date
Date: 2006-6-6 (Tuesday) Time: 06:06:06
4.2.15 erase(F)
擦除 FLASH MEMORY, 由于该 ARM 板没有 Nor Flash, 所有不支持该命令.
CRANE2410 # help erase
erase start end
- erase FLASH from addr 'start' to addr 'end'
erase start +len
- erase FLASH from addr 'start' to the end of sect w/addr 'start'+'len'-1
erase N:SF[-SL]
- erase sectors SF-SL in FLASH bank # N
erase bank N
- erase FLASH bank # N
erase all
- erase all FLASH banks
4.2.16 flinfo(F)
打印 Nor Flash 信息, 由于该 ARM 板没有 Nor Flash, 所有不支持该命令.
4.2.17 iminfo
打印和校验内核镜像头, 内核的起始地址由 CFG_LOAD_ADDR 指定:
#define CFG_LOAD_ADDR 0x30008000 /* default load address */
该宏在 include/configs/crane2410.h 中定义.
CRANE2410 # iminfo
## Checking Image at 30008000 ...
Image Name: Linux-2.6.14.1
Created: 2006-06-28 7:43:01 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1047080 Bytes = 1022.5 kB
Load Address: 30008000
Entry Point: 30008040
Verifying Checksum ... OK
4.2.18 loadb
从串口下载二进制文件
CRANE2410 # loadb
## Ready for binary (kermit) download to 0x30008000 at 115200 bps...
## Total Size = 0x00000000 = 0 Bytes
## Start Addr = 0x30008000
4.2.19 md
显示指定内存地址中的内容
CRANE2410 # md 0
00000000: ea000012 e59ff014 e59ff014 e59ff014 ................
00000010: e59ff014 e59ff014 e59ff014 e59ff014 ................
00000020: 33f80220 33f80280 33f802e0 33f80340 ..3...3...3@..3
00000030: 33f803a0 33f80400 33f80460 deadbeef ...3...3`..3....
00000040: 33f80000 33f80000 33f9c0b4 33fa019c ...3...3...3...3
00000050: e10f0000 e3c0001f e38000d3 e129f000 ..............).00000060: e3a00453 e3a01000 e5801000 e3e01000 S...............
00000070: e59f0444 e5801000 e59f1440 e59f0440 D.......@...@...
00000080: e5801000 e59f043c e3a01003 e5801000 ....<...........
00000090: eb000051 e24f009c e51f1060 e1500001 Q.....O.`.....P.
000000a0: 0a000007 e51f2068 e51f3068 e0432002 ....h ..h0... C.
000000b0: e0802002 e8b007f8 e8a107f8 e1500002 . ............P.
000000c0: dafffffb e51f008c e2400803 e2400080 ..........@...@.
000000d0: e240d00c e51f0094 e51f1094 e3a02000 ..@.......... ..
000000e0: e5802000 e2800004 e1500001 dafffffb . ........P.....
000000f0: eb000006 e59f13d0 e281f000 e1a00000 ................
4.2.20 mm
顺序显示指定地址往后的内存中的内容,可同时修改,地址自动递增。
CRANE2410 # mm 0x30008000
30008000: e1a00000 ? fffff
30008004: e1a00000 ? eeeeee
30008008: e1a00000 ? q
CRANE2410 # md 30008000
30008000: 000fffff 00eeeeee e1a00000 e1a00000 ................
30008010: e1a00000 e1a00000 e1a00000 e1a00000 ................
30008020: ea000002 016f2818 00000000 000df1d8 .....(o.........
30008030: e1a07001 e3a08000 e10f2000 e3120003 .p....... ......
4.2.21 mtest
简单的 RAM 检测
CRANE2410 # mtest
Pattern FFFFFFFD Writing... Reading...
4.2.22 mw
向内存地址写内容
CRANE2410 # md 30008000
30008000: ffffdffd ffffdffc ffffdffb ffffdffa ................
CRANE2410 # mw 30008000 0 4
CRANE2410 # md 30008000
30008000: 00000000 00000000 00000000 00000000 ................
4.2.23 nm
修改内存地址, 地址不递增
CRANE2410 # nm 30008000
30008000: de4c457f ? 00000000
30008000: 00000000 ? 11111111
30008000: 11111111 ?
4.2.24 printenv
打印环境变量
CRANE2410 # printenv
bootdelay=3
baudrate=115200
ethaddr=01:23:45:67:89:ab
ipaddr=10.0.0.110
serverip=10.0.0.1
netmask=255.255.255.0
stdin=serial
stdout=serialstderr=serial
Environment size: 153/65532 bytes
4.2.25 ping
ping 主机
CRANE2410 # ping 10.0.0.1
host 10.0.0.1 is alive
4.2.26 reset
复位 CPU
4.2.27 run
运行已经定义好的 U-BOOT 的命令
CRANE2410 # set myenv ping 10.0.0.1
CRANE2410 # run myenv
host 10.0.0.1 is alive
4.2.28 saveenv(F)
保存设定的环境变量
4.2.29 setenv
设置环境变量
CRANE2410 # setenv ipaddr 10.0.0.254
CRANE2410 # printenv
ipaddr=10.0.0.254
4.2.30 sleep
命令延时执行时间
CRANE2410 # sleep 1
4.2.31 version
打印 U-BOOT 版本信息
CRANE2410 # version
U-Boot 1.1.4 (Jul 4 2006 - 12:42:27)
4.2.32 nand info
打印 nand flash 信息
CRANE2410 # nand info
Device 0: Samsung K9F1208U0B at 0x4e000000 (64 MB, 16 kB sector)
4.2.33 nand device <n>
显示某个 nand 设备
CRANE2410 # nand device 0
Device 0: Samsung K9F1208U0B at 0x4e000000 (64 MB, 16 kB sector)
... is now current device
4.2.34 nand bad
CRANE2410 # nand bad
Device 0 bad blocks:4.2.35 nand read
nand read InAddr FlAddr size
InAddr: 从 nand flash 中读到内存的起始地址。
FlAddr: nand flash 的起始地址。
size: 从 nand flash 中读取的数据的大小。
CRANE2410 # nand read 0x30008000 0 0x100000
NAND read: device 0 offset 0, size 1048576 ...
1048576 bytes read: OK
4.2.36 nand erease
nand erase FlAddr size
FlAddr: nand flash 的起始地址
size: 从 nand flash 中擦除数据块的大小
CRANE2410 # nand erase 0x100000 0x20000
NAND erase: device 0 offset 1048576, size 131072 ... OK
4.2.37 nand write
nand write InAddr FlAddr size
InAddr: 写到 Nand Flash 中的数据在内存的起始地址
FlAddr: Nand Flash 的起始地址
size: 数据的大小
CRANE2410 # nand write 0x30f00000 0x100000 0x20000
NAND write: device 0 offset 1048576, size 131072 ...
131072 bytes written: OK
4.2.37 nboot
u-boot-1.1.4 代码对于 nboot 命令的帮助不正确,修改如下:
正确的顺序为:
nboot InAddr dev FlAddr
InAddr: 需要装载到的内存的地址。
FlAddr: 在 nand flash 上 uImage 存放的地址
dev: 设备号
需要提前设置环境变量,否则 nboot 不会调用 bootm
CRANE2410 #setenv autostart yes
CRANE2410 # nboot 30008000 0 100000
Loading from device 0: <NULL> at 0x4e000000 (offset 0x100000)
Image Name: Linux-2.6.14.3
Created: 2006-07-06 7:31:52 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 897428 Bytes = 876.4 kB
Load Address: 30008000
Entry Point: 30008040
Automatic boot of image at addr 0x30008000 ...
## Booting image at 30008000 ...
Starting kernel ...
4.3 命令简写说明
所以命令都可以简写,只要命令前面的一部分不会跟其它命令相同,就可以不用写全整个命令.save 命令
CRANE2410 # sa
Saving Environment to Flash...
Un-Protected 1 sectors
Erasing Flash...Erasing sector 10 ... Erased 1 sectors
4.4 把文件写入 NandFlash
如果把一个传到内存中的文件写入到 Nand Flash 中, 如:新的 uboot.bin, zImage(内核),
rootfs 等, 如果做呢?我们可以用 Nand Flash 命令来完成. 但是 Nand Flash 写时,必须先要把 Nand
Flash 的写入区全部擦除后,才能写. 下面以把内存 0x30008000 起长度为 0x20000 的内容写到 Nand
Flash 中的 0x100000 为例.
CRANE2410 # nand erase 0x100000 20000
NAND erase: device 0 offset 1048576, size 131072 ... OK
CRANE2410 # nand write 0x30008000 0x100000 0x20000
NAND write: device 0 offset 1048576, size 131072 ...
131072 bytes written: OK
汽车整车OTA升级篇之 uboot介绍
前面提到FOTA,需要升级的时候如果涉及到uboot部分,这部分会要求非常高,毕竟我是硬件出身,就在这里班门弄斧简单通过有趣的内容给大家介绍一下uboot,为什么需要uboot。
先进行一下科普吧,大家都在家炒过菜吧,其实你发现做一顿晚餐的过程就特别像安卓系统的工作原理。
1、首先要有基本的炒菜的环境,厨房要有电、天然气要通气,有锅和铲子等工具,这些类似底层硬件的电源管理,需要有这些基本的电气条件满足。
2、其次要有炒菜的基本佐料,包括盐、酱油、白醋、陈醋,糖、味精、鸡精,生抽、老抽、香油,芝麻油,葱,姜,蒜,孑然,耗油、白胡椒、黑胡椒,番茄酱,花椒,辣椒,辣椒油。
无论你炒什么菜,都首先把这些佐料准备好,可能炒爆炒肥肠和番茄炒蛋所需要的佐料有很多不同的,但是盐和油肯定是都需要的,只是其他佐料有区别,这个不影响提前把这些炒菜的佐料进行准备好,尽可能的把这些佐料都准备齐全。
这里就相当于Linux内核层,进行USB接口、蓝牙、wifi、摄像头、音视频、显示屏等基本服务,可能不同的APP应用所需要调用的这些服务不同,比如一款聊天软件可能需要使用到WIFI、摄像头、显示等等,不需要使用USB接口,但是不影响另外APP会可能调用到USB、存储等等。
3、不知道你们炒菜是否需要菜谱,至少机哥我炒菜需要使用到菜谱的,需要百度一下某个菜需要什么佐料,什么样的配比材料,没错机哥这期内容修改为美食栏目去了,下面是网上水煮肉片的菜谱。
其实这里使用到的菜谱就可以理解为安卓系统里面的硬件抽象层,这里简单理解为,就是你如果知道这个菜谱中佐料的比例,在你自己家里炒菜和在朋友家里炒菜,这个炒出来的味道基本上也就味道相同,就可以理解为为什么这个在安卓系统中硬件抽象层可以在不同的平台进行移植,也就是掌握了菜谱的精髓,功夫我有,天下我走。
4、最后就是炒菜的动作了,其实熟练的厨师是可以至少掌握好几个菜同时操作,这个不仅考验厨师的速度,也考验厨师的精准度,对于火候的掌控要精准,对于佐料使用要合理分配。
其实这里炒不同的菜就类似于使用不同的APP的应用,这里如果有一个菜炒胡了,不能影响到另外一个菜的正常发挥,类似于多线程中的某个APP挂掉了,但是不能影响到其他APP的正常使用。
这里也会出现占用资源的情况,比如同时用两个锅炒菜,左边那个锅在炒爆炒肥肠,直接把所有的盐都一不小心全部倒完了,此时右边锅里面的菜也就报废掉了,没有盐的菜不能称之为一道菜。这个是不是类似于某个APP调用内存泄露,把全部的内存占用没有释放,导致机器只能重启。
安卓系统启动简单介绍
1、安卓系统平台架构
可以看出整个架构由5部分构成,从下到上分别为:
1. Linux内核层
Android 的核心系统服务基于Linux 内核,在此基础上添加了部分Android专用的驱动。系统的安全性、内存管理、进程管理、网络协议栈和驱动模型等都依赖于该内核。
2. 硬件抽象层(HAL)
硬件抽象层是位于操作系统内核与硬件电路之间的接口层,其目的在于将硬件抽象化,为了保护硬件厂商的知识产权,它隐藏了特定平台的硬件接口细节,为操作系统提供虚拟硬件平台,使其具有硬件无关性,可在多种平台上进行移植。HAL 由多个库模块组成,每个模块都为特定类型的硬件组件实现了一个接口,例如相机或蓝牙模块。当框架 API 调用设备硬件时,Android 系统为该硬件组件加载库模块。
3. 系统运行库层(Native)
系统运行库层分为两部分,分别是C/C++程序库和Android运行时库。C/C++程序库被Android中不同的部分使用 runtime库主要是Java核心库(提供了Java语言核心功能因此开发者可以使用Java编写应用)和ART(Android 5.0 之前是Dalvik)该虚拟机不同于JVM是专门用于移动设备的虚拟机 允许在有限的内存内运行多个虚拟机实例 并且每个应用都是独立的linux进程这样可以防止虚拟机崩溃时不会导致所有的进程被关闭。
4. 应用框架层(Java Framework)
应用框架层为开发人员提供了可以开发应用程序所需要的API,我们平常开发应用程序都是调用的这一层所提供的API,当然也包括系统的应用。这一层的是由Java代码编写的,可以称为Java Framework
5、应用层
系统内置的应用程序以及非系统级的应用程序都是属于应用层。负责与用户进行直接交互,通常都是用Java进行开发的
2、安卓系统启动介绍
上图是车载中控导航的系统启动的简单介绍
1. POWER 部分
目前的导航系统基本上都是CPU+MCU的架构,MCU进行电源部分的管理,CAN通讯的处理、收音部分的处理,所以这里的开电源的时候,一定是MCU完成整个中控导航系统的电源初始化。
MCU内部的电源管理器(regulator)将系统置于POR复位状态,直到VDD电压上升到超过POR复位门限电平,然后低电压检测模块会接管系统复位,直到VDD电压上升超过其LVR复位门限电平。在完成POR和LVR复位后,MCU系统的电源系统已经能够为内部时钟(FIRC、SIRC和LPO等)和存储器(NVM)模块以及CPU内核提供稳定的工作电压了。
这里的加载时间一般是500ms,这里考验的时间其实更多的是MCU的启动时间,一些整车的网络管理也要求ECU在低功耗模式唤醒后,能够尽快响应CAN/LIN总线报文,也要求MCU的启动时间要足够快。
一些功能安全要求较高的汽车ECU应用,比如电子助力转向(EPS)、电子档位控制(gear control)等,对于ECU的启动时间(startup/boot time)有严格的要求, 希望ECU使用的MCU能够尽快完成系统启动初始化,执行功能程序。
2. uboot 部分
这里的uboot主要进行CPU状态检查、DDR/emmc/usb等初始化,同时也有电源管理、USB升级检测等等,这里耗时基本上1S左右。
3.kernel部分
linux内核的启动,包括硬件初始化,驱动模块加载,包括USB、video、camera、touch等初始化,init进程,这里耗时1.5S左右。
4. Android初始化
init进程启动程序,zygote加载进程,系统启动服务。这里其实就是我们常见的开机动画就在这个初始化的时候完成的,这包含窗口管理服务,蓝牙服务、GPS服务,这里的GPS默认设置为打开状态,即服务初始化完成后就可以马上启动GSP定位开始,所以GPS的冷启动定位时间不是进入主界面开始算的时间,而且在动画界面初始化完成后就可以算时间了,这样可以让用户感觉体验更快就能GPS定位了。
5.主界面
系统启动,以下应用启动工作:收音、音视频播放、导航、语音、倒车、DVR、360全景、蓝牙等其他应用,这里的时间为2S左右。
一般的安卓系统启动时间为18S左右,应用启动2S,总计20S就可以正常操作APP应用了,这就是为什么安卓车机开机时间都会很久的,不太适合用于仪表,因为仪表要求开机5S左右就能正常显示工作。
从这个耗时来看,Android初始化的时间15S最长,所以要优化整个系统的启动时间的话,可以优先考虑这部分的优化时间。
吃瓜群众:机哥,你说的这些我都不懂,我们还是说回炒菜吧。
机哥:好的,那我们再来看看uboot在整个炒菜中,它是起到什么作用,初始化uboot,如果是炒菜,就是准备了哪些东西。
其实这里的uboot主要进行CPU状态检查、DDR/emmc/usb等初始化,同时也有电源管理、USB升级检测等等,想想炒菜之前是不是要检查锅是否干净,是否需要重新洗一遍,然后佐料这些是否足够,炒菜的燃气是否够大,有一个初步的火量大小的控制,等后面放好佐料后根据实际运气的情况再调节燃气大小的控制,就类似于前面初始化DDR和FLASH的运行速率,后面实际还可以调整这部分的运行速率。
Uboot 的简单介绍
1、为什么需要uboot
计算机系统的组成部件非常多,不同的计算机系统组成部件也不同。但是所有的计算机系统运行时需要的主要核心部件都是3个东西:CPU+外部存储器(Flash/硬盘+内部存储器(DDR SDRAM/SDRAM/SRAM)。
而一般的PC机启动过程为:PC上电后先执行BIOS程序(实际上PC的BIOS就是NorFlash),BIOS程序负责初始化DDR内存,负责初始化硬盘,然后从硬盘上将OS镜像读取到DDR中,然后跳转到DDR中去执行OS直到启动(OS启动后BIOS就无用了)。
总结:嵌入式系统和PC机的启动过程几乎没有两样,只是BIOS成了uboot,硬盘成了Flash。
从第一章节中我们简单介绍了Android系统的启动流程,Android系统的启动流程大致分为三个阶段:
1、电源键按下后加载引导程序Bootloader到RAM 然后Bootloader把OS拉起
2、Linux 内核层面的启动
3、Android系统层面的启动
这里的uboot就是刚开始被放到flash中,板子上电后,会自动把其中的一部分代码拷到内存中执行,这部分代码负责把剩余的uboot代码拷到内存中,然后uboot代码再把kernel部分代码也拷到内存中,并且启动,内核启动后,挂着根文件系统,执行应用程序。
2、uboot有什么特点
uboot 属于bootloader的一种,是用来引导启动内核的,它的最终目的就是,从flash中读出内核,放到内存中,启动内核。
1.自身可开机直接启动
1)一般的SoC都支持多种启动方式,譬如SD卡启动、NorFlash启动、NandFlash启动等•••••uboot要能够开机启动,必须根据具体的SoC的启动设计来设计uboot。
上图是安霸A12的boot支持的启动方式,有NOR FLASH,NAND FLASH,USB、EMMC等多种存储设备,但是要注意,这里启动的地址默认都是从第一个零地址开始,比如NAND FLASH就是BLOCK 0启动,如果这个block损坏那么就无法启动,如果要跳转到block 1,那么就需要CPU芯片内部支持存储代码进行判断,否则只能从默认block 0启动。
2)uboot必须进行和硬件相对应的代码级别的更改和移植,才能够保证可以从相应的启动介质启动。uboot中第一阶段的start.S文件中具体处理了这一块。
2.能够引导操作系统内核启动并给内核传参
1)uboot的终极目标就是启动内核。
2)linux内核在设计的时候,设计为可以被传参。也就是说我们可以在uboot中事先给linux内核准备一些启动参数放在内存中特定位置然后传给内核,内核启动后会到这个特定位置去取uboot传给他的参数,然后在内核中解析这些参数,这些参数将被用来指导linux内核的启动过程。
3.能提供系统部署功能
1)uboot必须能够被人借助而完成整个系统(包括uboot、kernel、rootfs等的镜像)在Flash上的烧录下载工作。
2)裸机教程中刷机(ARM裸机第三部分)就是利用uboot中的fastboot功能将各种镜像烧录到iNand中,然后从iNand启动。
4. 能进行soc级和板级硬件管理
1)uboot中实现了一部分硬件的控制能力(uboot中初始化了一部分硬件),因为uboot为了完成一些任务必须让这些硬件工作。譬如uboot要实现刷机必须能驱动iNand,譬如uboot要在刷机时LCD上显示进度条就必须能驱动LCD,譬如uboot能够通过串口提供操作界面就必须驱动串口。譬如uboot要实现网络功能就必须驱动网卡芯片。
2)SoC级(譬如串口)就是SoC内部外设,板级就是SoC外面开发板上面的硬件(譬如网卡、iNand)
5. uboot的"生命周期"
1)uboot的生命周期就是指:uboot什么时候开始运行,什么时候结束运行。
2)uboot本质上是一个裸机程序(不是操作系统),一旦uboot开始SoC就会单纯运行uboot(意思就是uboot运行的时候别的程序是不可能同时运行的),一旦uboot结束运行则无法再回到uboot(所以uboot启动了内核后uboot自己本身就死了,要想再次看到uboot界面只能重启系统。重启并不是复活了刚才的uboot,重启只是uboot的另一生)
3)uboot的入口和出口。uboot的入口就是开机自动启动,uboot的唯一出口就是启动内核。uboot还可以执行很多别的任务(譬如烧录系统),但是其他任务执行完后都可以回到uboot的命令行继续执行uboot命令,而启动内核命令一旦执行就回不来了。
总结:uboot的一切都是为了启动内核。
1)uboot主要作用是用来启动操作系统内核。体现在uboot最后一句代码就是启动内核。
2)uboot还要负责部署整个计算机系统。体现在uboot最后的传参。
3)uboot中还有操作Flash等板子上硬件的驱动。例如串口要打印,ping网络成功,擦除、烧写flash是否成功等。
4)uboot还得提供一个命令行界面供人来操作。很简单,至少你能看到。
3、Uboot完成后进入的模式有哪些。
安卓开机后,硬件系统上电,首先是完成一系列的初始化过程,如 CPU、串口、中断、timer、DDR 等硬件设备,然后接着加载 bootloader,为后面内核的加载作好准备。在一些系统启动必要的初始完成之后,系统会通过检测三个条件来判断要进入何种工作模式,流程如图。
这里重点说说Recovery模式,我们可以简单的理解为工程模式,手机进入Recovery模式可以进行重启手机、清空SD卡数据、恢复出厂设置、刷机、备份与恢复数据等诸多功能。
以前买到小米手机,手机无法正常开机进入不了系统了,此时就从百度上搜索怎么强制恢复出厂设置,方法是先关闭小米手机,然后同时按住“小米3音量+键”和“电源键”,大约3s左右,即可进入小米3Recovery模式了。
怎么加快uboot的启动时间
1、使用通讯速率快的存储,接口需要不占用
一些功能安全要求较高的汽车ECU应用,比如电子助力转向(EPS)、电子档位控制(gear control)等,对于ECU的启动时间(startup/boot time)有严格的要求, 希望ECU使用的MCU能够尽快完成系统启动初始化,执行功能程序。此外,一些整车的网络管理也要求ECU在低功耗模式唤醒后,能够尽快响应CAN/LIN总线报文,也要求MCU的启动时间要足够快。
在有双核的CPU的时候,可以在不同的内核执行不同的程序,这样可以缩短启动时间。
液晶仪表的开机速度要求比较快,一般要求在6S之内要进行开机进行工作,这样就可以更快的让用户处理相关的车身检测和报警功能。
其实这里比较简单粗暴的方便就是使用通信速度更快的存储,下图就是东芝产品介绍boot time的在使用普通NOR flash,EMMC、UFS的存储设备,可以看到UFS接口的EMMC在64MB的数据下,也就115ms可以运行完成,而SPI NOR FLASH需要1185ms,基本上差了10倍时间的差距。
这里唯一的不同就是存储设备的通讯速率不同,UFS的通讯速率可以达到850MB/S,而NOR FLASH最快也就是54MB/S。
在仪表赛普拉斯推荐的平台上,使用hyperflash,可以让开机时间在2S之内。
赛普拉斯主推的hyperflash,独占带宽无抢占的情况下,目标带宽为200MB/s,1280x480的标清屏的开机速度可以达到0.7S。目前创维汽车智能在使用这个平台供货仪表,做的非常棒。
2、优化一些时钟、ECC校验等方法加快启动速度(参考 浅谈嵌入式MCU软件开发之S32K1xx系列MCU的启动过程和启动时间优化方法详细 )
下图是S32KXX系列的MCU的启动流程图,首先是关闭CPU到的全局中断,把CPU的内核寄存器清零,初始化SRAM的ECC,然后进行系统的初始化等等。
比如在MCU的硬件加密模块CSEc的安全启动(Secure boot)功能,建议使用串行(Sequential) Secure boot而不是并行(Parallel) Secure boot, 因为后者工作时CSEc和CPU内核都会访问P-Flash,从而导致CPU内核从P-Flash取指令的速度变慢,从而拉长Startup运行时间,而且Secure boot运行完之前不允许修改系统时钟配置(尤其是Flash的工作时钟FLASH_CLK):
Freescale S12G系列汽车MCU的外部晶振时钟起振时间如下,作为参考,也是频率越高,启动越快(start-up时间越短)
BOOT升级的模式
正常情况下,下载了升级固件,肯定是要把新固件替换到老固件,这个时候就涉及到两种模式。
其实这个最容易理解了,机哥给你说一个生活中的例子就好理解了,你手里拿着一个冰淇淋,现在老板告诉你有新款的冰淇淋来了,可以免费领取一个,你会怎么做呢?
有的人是把手里的冰淇淋扔掉,直接去领取新的冰淇淋,这样的做法是不占用手的资料,反正都只占用一个手,缺点就是可能去排队的时候,老板新的冰淇淋都领取完了,这个时候你就一个冰淇淋都没有了。
有的人的做法是先排队,确认领用到新的冰淇淋后再把老的冰淇淋扔掉,此时在领用的过程中会耗费掉两个手的资源,不过这样最保险,哪怕没有领用到最新的冰淇淋,老的冰淇淋还可以继续吃。
同样的道理,新固件替换老固件覆盖的两种方式:双区模式和单区模式。
双区模式:
双区模式中老固件和新固件在flash中各占一块bank(存储区)。假设老固件放在bank0(运行区)中,新固件放在bank1(下载区)中,升级的时候,应用程序先把新固件下载到bank1中,只有当新固件下载完成并校验成功后,系统才会跳入BootLoader程序,然后擦除老固件所在的bank0区,并把bank1的新固件拷贝到bank0中。后台式下载必须采用双区模式进行升级。
优点:升级过程中出现问题或者新固件有问题,它还可以选择之前的老固件老系统继续执行而不受其影响。
缺点:多占用flash空间的一个存储区,在系统资源比较紧张的时候较为困难。
单区模式:
单区模式的非后台式下载只有一个bank0(运行区),老固件和新固件共享这一个bank0。升级的时候,进入bootloader程序后先擦除老固件,然后直接把新固件下载到同一个bank中,下载完成后校验新固件的有效性,新固件有效升级完成,否则要求重来。
优点:跟双区模式相比,单区模式节省了Flash空间的一个bank,在系统资源比较紧张的时候,单区模式是一个不错的选择。
缺点:如果升级过程中出现问题或者新固件有问题,单区模式碰到这种情况就只能一直待在bootloader中,然后等待再次升级尝试,此时设备的正常功能已无法使用,从用户使用这个角度来说,可以说此时设备已经“变砖”了。
相比较,双区模式虽然牺牲了很多存储空间,但是换来了更好的升级体验。
相关问答
UBOOT 移植时,不同型号的 NANDFLASH 存储的起始地址怎么得到?你只能通过NandFlash控制器访问NandFlash,即是只要知道Nand控制器的寄存器地址即可。NandFlash不是一个RamLike的器件。Uboot放入nand中,在nand的0地址开...
路由器刷了爱快固件肿么升级固件-ZOL问答回复mganqyikfz需要一个RS232串口或USB口转TTL电平的转换器,然后电脑通过简...不知道你是要整个flash的编程器用固件,还是刷的那个固件?整个flash的内容用下...
没有usb口小米路由器肿么刷机-ZOL问答第一次刷机更麻烦,要拆下flash芯片刷uboot,uboot刷好后就可以任性刷机了。有用(0)回复A152521用的一直很好,我家里用的小米路由器3,女朋友这我给买的mini...