【嵌入式Linux】Uboot初步认识 笔记

整体简介

本笔记为记录嵌入式Linux的uboot部分基础知识,结合源码对uboot的实现原理和应用展开学习

授课老师:朱有鹏
时间:2017年10月1日

本part讲uboot的使用和相关概念。
后面会讲uboot的设计和组成原理,再往后就是移植过程。
我们的目的就是把ARM端的操作系统搭建起来,以后就不玩裸机了。


笔记正文

一、学习前传

1.1为什么要有uboot

uboot是用来 启动操作系统内核 的!还有别的辅助功能。
1启动操作系统内核
2部署计算机系统
3操作Flash等上硬盘驱动
4提供命令行界面

uboot类似于PC机系统中的BIOS设计。典型的嵌入式系统的部署是uboot在一块支持启动的Flash上,OS部署在Flash(通常是另一块Flash,NandFlash or iNand,慢慢会发展成一块儿)。

其中,环境变量和命令是uboot的重要部分。此外uboot对于Flash和DDR有管理功能。

启动过程
step1: 先执行uboot
step2: uboot初始化DDR,初始化Flash
step3: 将OS从Flash读取到DDR中,启动OS。启动完成后uboot就无用了。

总结:嵌入式系统启动其实和PC没两样
只是BIOS代替成uboot
硬盘替换成了Flash


1.2 uboot之发展历史

uboot经过多年发展,已经成为事实上业内的bootloader标准。

uboot的版本号问题
早期的uboot版本号类似于:

uboot1.3.4	//这个1.3.4是最后的老版本

从2008左右开始就不是这样子了,后来变成了类似于:

uboot-2010-06
(后缀带有 -rc 的是非正式版本)

核心部分就几乎没变化,越新版本支持的开发板越多。当然也不是越新越好,新的东西有很多冗余。

uboot可移植理解
universal bootloader(通用的启动代码),具有可移植性。
注意:并不是说在哪个开发板都可以随便用。而是具有在源代码级别的移植能力。如果没有移植的话就可以直接用的。代码必然是要修改的!不是下载下来就能用。

uboot的成功:时势造英雄,他的出现是一种必然。如果没有uboot也会有另一个bootloader代替。
在那个年代嵌入式疯狂的发展,很需要一种bootloader能够移植上去,启动操作系统。所以uboot站出来了


1.4 uboot工作方式

uboot是一个单线程裸机程序。一旦运行uboot就不能运行别的 程序。
入口是开机自动启动
出口是唯一出口,启动内核

内核启动之后,uboot就会结束,而且不再重生。除非下一次开机。
uboot没有运行时表现为uboot.bin,放在存储介质里,运行时被加载入内存,逐步执行。


1.5 常用命令

uboot的命令和环境变量机制几乎和OS完全一样,连题目的名称都不带变的。

命令使用行缓冲。		//linux缓冲方式还有无缓冲和全缓冲
简写命令:
	printenv 	= print	//打印环境变量
	setenv	= set	//设置环境变量
	注意:自己尝试过,pri就能自己打印出printenv的内容


命令族
	有些命令有衍生的 多个命令
	如 movi
	movi init,movi read等。命令一样,参数不一样。

环境变量和全局变量的不同
环境变量生命周期长,他存储在FLash的一块专门区域。而全局变量在程序结束后消亡。

理论上讲,环境变量在更改后,下一次开机依然保留才对,但是我试过的和老朱说的不一样。
是因为我们没有保存!命令:save/saveenv
我们操作的环境变量的是DDR中的环境变量,
DDR断电不保存,save命令是就把运行时内存中的环境变量写回Flash

注意这里的 save,会让原来的Flash中环境变量完全重写。

Flash里面有好多分区

完整Linux系统分区简表(按顺序,uboot为最开始)

序号 分区名 简写名
1 uboot uboot
2 环境变量 env
3 操作系统内核 kernel
4 根文件系统 rootfs

1.9 uboot指令

指令规范
movi read {aaa | bbb} [xxxx]
//movi read 是必填,{ }里面的内容多选一,[ ]的内容是选填

uboot默认数字问题
命令行中,uboot中所有的数字都会被当做16进制处理!!
uboot中没有默认十进制的。uboot中出现数字90%的情况都是地址,是有意义的。

【movi read】
movi read u-boot 0x30000000
//将iNand中的u-boot分区读到DDR的0x30000000处,注意读的是分区
//也许uboot本身不大,但分区有1M那么这里还是读1M大小过去
//在uboot代码中,iNand被分成了很多个分区,每个分区都有独自的地址和名称。
movi read {sector#} {byte(hex)} {addr}
//sector是扇区,读某扇区多少字节,读到哪个地址。

【nand】
//完全类似movi,操作NandFlash

【内存操作指令:mm mw md】
内存是没有分区的,我们要注意防止越界,越界会踩到别人。操作系统中不容易越界,但uboot是裸机程序,因此我们使用uboot时不注意,就可能发生自己把自己数据给覆盖了的问题。
我们之前usb下载放在0x23E00000地址处就是放在了一个低地址。(也和虚拟地址映射有关)

md,memory display
mw,写内存,一般用的很少
mm,批量写内存

【启动内核指令:bootm, go】
bootm是能够传参的,他其实是正宗的启动命令

go不能传参,他本身不是为了启动内核用的,内部就是吧pc跳转到一个内存地址去执行。
go可以在uboot中执行任何的裸机程序
有一种调试裸机程序的方法就是事先启动uboot,然后再uboot中下载裸机程序 ,用go命令执行裸机程序。


1.10 uboot常用环境变量

ipaddr:开发板ip地址
serverip:tftp服务器的ip地址
gatewayip:开发板的本地网关地址
ethaddr:开发板本地网卡的MAC地址。

Tips:重装系统为什么MAC地址会变?是因为驱动重新安装了

启动内核的最关键环境变量
bootcmd(重要)自动运行命令设置
uboot启动后会倒数秒数,如果没有人按下回车键打断则会启动内核
这个 启动内核的 功能其实内部就是执行了bootcmd

查一下:

bootcmd=movi read kernel 30008000

//读iNand中内核分区到30008000
movi read rootfs 30B00000 300000; //读根文件系统
bootm 30008000 30B00000 //启动内核和根文件系统
//iNand,可以简单的看成SD卡或MMC卡芯片化

bootargs(重要)
bootargs是uboot给kernel传参用的。linux内核与uboot有约定好的参数。这样的设计是为了灵活,为了内核在不重新编译的条件下以不同方式启动。

    bootargs=console=ttySAC2,115200 	//控制台使用SAC2,即串口2,波特率115200
	root=/dev/mmcblk0p2 rw	            //rootfs使用mmc,block端口0,第二分区
										//rw表示可读可写
	init=/linuxrc 	                    //linux的进程1(init进程)的路径
	rootfstype=ext3		                //rootfs类型,ext3是一种文件系统类型。

内核传参是非常重要的,新手经常忘记和内核传参,或者传参不对,造成内核启动失败。

【新建、删除环境变量】

set var value	//新建、更改
set var			//删除

1.12.uboot中对Flash和DDR的管理

uboot对Flash和内存进行分区。

分区方法不是一定的,不是固定的,是可以变动的。但是在一个移植中必须事先设计好定死,一般在设计系统移植时就会定好,定的标准是:

uboot:uboot必须从Flash起始地址开始存放(也许是扇区0,也许是扇区1,也许是其他,取决于SoC的启动设计),uboot分区的大小必须保证uboot肯定能放下,一般设计为512KB或者1MB(因为一般uboot肯定不足512KB,给再大其实也可以工作,但是浪费);

环境变量:环境变量分区一般紧贴着uboot来存放,大小为32KB或者更多一点。

kernel:kernel可以紧贴环境变量存放,大小一般为3MB或5MB或其他。

rootfs:rootfsl可以紧贴kernel存放

再往后面:则是自由分区。

总结:一般规律如下:
(1)各分区彼此相连,前面一个分区的结尾就是后一个分区的开头。
(2)整个flash充分利用,从开头到结尾。
(3)uboot必须在Flash开头,其他分区相对位置是可变的。
(4)各分区的大小由系统移植工程师自己来定,一般定为合适大小(不能太小,太小了容易溢出;不能太大,太大了浪费空间)
(5)分区在系统移植前确定好,在uboot中和kernel中使用同一个分区表。将来在系统部署时和系统代码中的分区方法也必须一样。

12.2、uboot阶段DDR的分区

(1)DDR的分区和Flash的分区不同,因为Flash是掉电存在的,而DDR是掉电消失,因此可以说DDR是每次系统运行时才开始部署使用的。
(2)内存的分区主要是在linux内核启动起来之前,linux内核启动后内核的内存管理模块会接管整个内存空间,那时候就不用我们来管了。
(3)注意内存分区关键就在于内存中哪一块用来干什么必须分配好,以避免各个不同功能使用了同一块内存造成的互相踩踏。譬如说我们tftp 0x23E00000 zImage去下载zImage到内存的0x23E00000处就会出错,因为这个内存处实际是uboot的镜像所在。这样下载会导致下载的zImage把内存中的uboot给冲掉。


2.1.shell介绍

shell是操作系统的终端命令行
系统提供给用户操作的命令行界面,是人

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

谦谦青岫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值