【嵌入式Linux驱动进阶】U-boot 学习
I.MX6UL启动方式
通过设置i.MX6UL启动相关引脚的电平状态来改变芯片的启动方式。 BOOT_MODE[1:0] = 10B ,i.MX6UL将会从“内部”启动,所谓“内部”是相对于“Serial Download”来说的, “内部”可以认为是i.MX6UL支持的启动存储设备,例如emmc、nandflash、SD card、norFlash等等。 具体从那种“内部”设备启动,由BOOT_CFG1[7:4]决定,如下表所示。
BOOT_CFG1[7:4] | Boot Device |
---|---|
0000 | NOR/O呢NAND(EIM) |
0001 | QSPI(norFlash启动) |
0011 | Serial ROM(SPI) |
010x | SD/eSD/SDXC(SD卡启动) |
011x | MMC/eMMC(eMMC启动) |
1xxx | Raw NAND(nandFlash启动) |
烧写系统
- 在window下烧写,通过mfgtool这个工具,先将Linux系统烧写到DDR中,再烧写到EMMC或NAND中
- mfgtool这个工具会将uboot、zImage、rootfs全部烧写,所以后期当我们只更新一个uboot,可能全部都再重新烧录,这个可能就是mfgtool一个最大的缺点了。
- 解决方案1:mfgtool单独创建一个.vbs文件只烧写uboot
- 解决方案2:uboot.bin使用imxdownload脚本烧写到SD卡中(带有调试性质的开发,这样比较方便。)
./imxdownload u-boot.bin /dev/sdf
- 在Ubuntu下少些,通过脚本,先将Linux系统烧写到SD卡中,再烧写到EMMC或NAND中
烧写系统时SD卡注意事项
- SD卡一定要是FAT32格式!
- 如何确定SD卡?
- ls /dev/sd* 比如出现sdf、sdf1,那就是sdf了
- sudo fdisl -l 也可以查看到对应分区
- 将文件拷贝到SD卡中需要等待系统进行缓存同步,这段时间不确定,所以最好直接在命令行输入
sync
进行手动同步
uboot介绍
- uboot就是一个bootloader,作用就是用于启动Linux或其他系统。
- Uboot最主要的工作就是初始化DDR,因为Linux是运行在DDR里面的。
- 一般Linux镜像zImage(uImage)+设备树(.dtb)存放在SD、EMMC、NAND、SPI FLASH等等外置存储区域。这就需要将Linux镜像从外置flash拷贝到DDR中,再去启动。
- Uboot不仅仅能启动Linux,也可以启动其他系统;Linux不仅仅能通过uboot启动。
uboot获取
- 首先就是uboot官网,缺点就是支持少,比如某一款具体芯片驱动等不完善。
- SOC厂商会从uboot官网下载某一个版本的uboot,然后在这个版本的uboot上加入相应的SOC以及驱动,这就是SOC厂商定制版的uboot。
- 做开发板的厂商会参考SOC厂商的板子,开发板必然会和官方的板子不一样。因此开发板厂商又会去修改SOC厂商做好的uboot,以适应自己的板子。
uboot编译
- 为了方便开发,建议直接在uboot顶层Makefile里面设置好ARCH和CORSS_COMPILE这两个变量的值。
- 编译UBOOT的时候需要先配置。
- 图形界面配置
- 源码配置
- 编译完成以后就会生成一个u-boot.bin。必须向u-boot.bin添加头部信息。Uboot编译最后会通过/tools/mkimage软件添加头部信息,生成u-boot.imx。
- 如果配置过uboot,make clean会清除整个工程,那么配置的文件也会被删除,配置项也会被删除掉。
- 注意这里说的是通过图形界面配置uboot需要注意make clean会清除配置项,但是你如果是通过修改uboot源码来配置的话,就不需要担心!
- uboot编译命令三部曲
make distclean //清理配置
make xxx_defconfig //配置到.config文件
make -j4 //4核编译
- 1
- 2
- 3
可以通过时间戳,查看uboot是不是最新编译的!
uboot命令
uboot命令中的数字都是十六进制的!不是十进制!
mmc list
- 查看当前板子的mmc设备。
- 将EMMC和SD卡统称为MMC
help
或者?
- 打印uboot支持的所有的命名
- 查看某一个命令的帮助
? xxx
bdinfo
- 打印板子信息
version
- 查看uboot版本相关信息
reset
- uboot的重启命令
环境变量相关
printenv
(重要)- 查看当前板子的环境变量
- 当然直接输入
print
要是可以的
saveenv
(重要)- 保存环境变量
setenv
(重要)- 修改现有环境变量
- eg:
setenv bootdelay 5
然后saveenv
这样就把uboot的倒计时改成了5s - eg:
set bootcmd 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
然后saveenv
。注意环境变量是字符串的一定要用单引号引起来!
- eg:
- 新建环境变量
- eg:
setenv author 'xxx'
然后saveenv
- eg:
- 删除环境变量
- eg:
setenv author
然后saveenv
,不设置值即可实现删除操作!
- eg:
- 修改现有环境变量
内存操作相关
-
md
- 显示指定地址内存值md[.b, .w, .l] address [# of objects]
b w l
分别对应1 2 4字节,address
对应内存起始地址[# of objects]
要查看的数据长度(十六进制格式)- eg:想查看以 0X80000000 开始的 20 个字节的内存值,显示格式为.b 的话:
md.b 80000000 14
注意14是0x14!直接写md.b 80000000 0x14
不容易弄混。
-
nm
- 修改指定地址内存值(修改完地址不会自增)nm [.b, .w, .l] address
- eg:以.l 格式修改 0x80000000 地址的数据为 0x12345678:输入
nm.l 0x80000000
按下回车后,输入0x12345678
,按下回车,然后再输入q
即可退出。
- eg:以.l 格式修改 0x80000000 地址的数据为 0x12345678:输入
-
mm
- 修改指定地址内存值(修改完地址会自增) -
mw
- 使用一个指定数据填充一段内存mw [.b, .w, .l] address value [count]
- eg:使用.l 格式将以 0X80000000 为起始地址的 0x10 个内存块(0x10 * 4=64 字节)填充为 0X0A0A0A0A:
mw.l 80000000 0A0A0A0A 10
-
cp
- 数据拷贝cp [.b, .w, .l] source target count
- eg:使用.l 格式将 0x80000000 处的地址拷贝到 0X80000100 处,长度为 0x10 个内存块(0x10 * 4=64 个字节):
cp.l 80000000 80000100 10
-
cmp
- 比较命令cmp [.b, .w, .l] addr1 addr2 count
- eg:使用.l 格式来比较 0x80000000 和 0X80000100 这两个地址数据是否相等,比较长度为 0x10 个内存块:
cmp.l 80000000 80000100 10
网络相关命令(重点)
开发板网线需要插到网口2上(左边那个) ,保证开发板和电脑在同一个网段。只要uboot的网络配置好了,便可以通过tftp或NFS连接ubuntu,这样直接从ubuntu下载zImage和rootfs将会方便开发许多!
环境变量 | 描述 |
---|---|
ipaddr | 开发板 ip 地址,可以不设置,使用 dhcp 命令来从路由器获取 IP 地址(dhcp获取的仅仅本次有效,不会修改环境变量的ipaddr,下次启动依然是ipaddr的地址)。 |
ethaddr | 开发板的 MAC 地址,一定要设置。 |
gatewayip | 网关地址。 |
netmask | 子网掩码。 |
serverip | 服务器 IP 地址,也就是 Ubuntu 主机 IP 地址,用于调试代码。 |
setenv ipaddr 192.168.1.50
setenv ethaddr 00:04:9f:04:d2:35
setenv gatewayip 192.168.1.1
setenv netmask 255.255.255.0
setenv serverip 192.168.1.250
saveenv
- 1
- 2
- 3
- 4
- 5
- 6
- 开始之前,最好将ubuntu的ip地址给写死(手动设置)
- ipaddr - 设置之前在ubuntu看看能不能ping通,ping不通板子才能用。
- ethaddr - 也要保证唯一
- serverip - 这个地址就是ubuntu的地址
-
ping
测试网络- 上述设置完毕之后,通过
ping ubuntu地址
,查看是否设置成功!
- 上述设置完毕之后,通过
-
nfs
命令 - 目的就是为了调试程序- nfs 也就是网络文件系统,通过 nfs 可以在计算机之间通过网络来分享资源,比如我们将linux 镜像和设备树文件放到 Ubuntu 中,然后在 uboot 中使用 nfs 命令将 Ubuntu 中的 linux 镜像和设备树下载到开发板的 DRAM 中。这样做的目的是为了方便调试 linux 镜像和设备树,也就是网络调试, 通过网络调试是 Linux 开发中最常用的调试方法。
- 当然使用NFS前提需要在ubuntu开启NFS服务,并且创建设置NFS目录。
nfs [loadAddress] [[hostIPaddr:]bootfilename]
- eg:将 zImage 下载到开发板 DRAM 的 0X80800000 地址处:
nfs 80800000 192.168.1.250:/home/zuozhongkai/linux/nfs/zImage
-
tftp
命令 - 目的就是为了调试程序- tftp 命令的作用和 nfs 命令一样,都是用于通过网络下载东西到 DRAM 中,只是 tftp 命令使用的 TFTP 协议, Ubuntu 主机作为 TFTP 服务器。
tftpboot [loadAddress] [[hostIPaddr:]bootfilename]
- 和 nfs 命令的区别在于, tftp 命令不需要输入文件在 Ubuntu 中的完整路径,只需要输入文件名即可。
- eg:将 tftpboot 文件夹里面的 zImage 文件下载到开发板 DRAM 的 0X80800000 地址处:
tftp 80800000 zImage
- 注意:从windows下拷贝到ubuntu中的文件,在用tftp下载的时候就会有权限问题。但是直接在ubuntu下编译生成的文件在用tftp下载的时候就不存在权限问题。
mmc相关命令
命令 | 描述 |
---|---|
mmc info | 输出 MMC 设备信息 |
mmc read | 读取 MMC 中的数据。 |
mmc wirte | 向 MMC 设备写入数据(可以通过网络下载.imx文件升级uboot)。 |
mmc rescan | 扫描 MMC 设备。 |
mmc part | 列出 MMC 设备的分区。 |
mmc dev 0 | 切换 MMC 设备0。 |
mmc list | 列出当前有效的所有 MMC 设备。 |
mmc hwpartition | 设置 MMC 设备的分区。 |
mmc bootbus…… | 设置指定 MMC 设备的 BOOT_BUS_WIDTH 域的值。 |
mmc bootpart…… | 设置指定 MMC 设备的 boot 和 RPMB 分区的大小。 |
mmc partconf…… | 设置指定 MMC 设备的 PARTITION_CONFG 域的值。 |
mmc rst | 复位 MMC 设备 |
mmc setdsr | 设置 DSR 寄存器的值 |
FAT文件系统相关命令
对于I.MX6U来说,SD/EMMC分为三个分区:
- 第一个:存放uboot
- 第二个:存放Linux zImage,.dtb。FAT格式
- 第三个:系统的根文件系统。EXT4格式
-
fatinfo
- 查询指定 MMC 设置指定分区的文件系统信息fatinfo <interface> [<dev[:part]>]
interface 表示接口,比如 mmc, dev 是查询的设备号, part 是要查询的分区。- eg:要查询 EMMC 分区 1 的文件系统信息:
fatinfo mmc 1:1
-
fatls
- 查询 FAT 格式设备的目录和文件信息fatls <interface> [<dev[:part]>] [directory]
directory是要查询的目录- eg:查询 EMMC 分区 1 中的所有的目录和文件:
fatls mmc 1:1
-
fstype
- 查看 MMC 设备某个分区的文件系统格式fstype <interface> <dev>:<part>
- eg:EMMC 核心板上的 EMMC 默认有 3 个分区,我们来查看一下第0个分区的文件
系统格式:fstype mmc 1:0
-
fatload
- 将指定的文件读取到 DRAM 中- eg:将 EMMC 分区 1 中的 zImage 文件读取到 DRAM 中的0X80800000 地址处:
fatload mmc 1:1 80800000 zImage
- eg:将 EMMC 分区 1 中的 zImage 文件读取到 DRAM 中的0X80800000 地址处:
-
fatwrite
- 将 DRAM 中的数据写入到 MMC 设备中fatwrite <interface> <dev[:part]> <addr> <filename> <bytes>
EXT文件系统相关命令
uboot 有 ext2 和 ext4 这两种格式的文件系统的操作命令,常用的就四个命令,分别为:ext2load、 ext2ls、 ext4load、 ext4ls 和 ext4write。这些命令的含义和使用与 fatload、 fatls 和 fatwrit一样,只是 ext2 和 ext4 都是针对 ext 文件系统的。
- eg:查询 EMMC 的分区 2 中的文件和目录:
ext4ls mmc 1:2
BOOT操作命令
要启动 Linux,需要先将 Linux 镜像文件和设备树拷贝到 DRAM 中,然后使用 bootz 命令来启动Linux系统。拷贝镜像和设备树到DRAM有好2中方式:①、通过tftp从ubuntu下载 ②、通过fatload从EMMC中读取到DRAM中!
-
bootz
- 用于自动 zImage 镜像文件bootz [addr [initrd[:size]] [fdt]]
addr 是 Linux 镜像文件在 DRAM 中的位置, initrd 是 initrd 文件在DRAM 中的地址,如果不使用 initrd 的话使用‘-’代替即可, fdt 就是设备树文件在 DRAM 中的地址。- zImage 一般放到 DRAM 的 0X80800000 地址;设备树放到 DRAM 中的 0X83000000 地址处
- 输入
bootz 80800000 - 83000000
便可启动Linux!
-
boot
- 启动Linux系统- boot 命令也是用来启动 Linux 系统的,只是 boot 会读取环境变量 bootcmd 来启动 Linux 系统, bootcmd 是一个很重要的环境变量!这个环境变量保存着引导命令,其实就是启动的命令集合,具体的引导命令内容是可以修改的。
- eg:我们要想使用 tftp 命令从网络启动 Linux 那么就可以设置 bootcmd 为“tftp
80800000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000”,然后使用 saveenv 将 bootcmd 保存起来。然后直接输入 boot 命令即可从网络启动 Linux 系统,命令如下:
setenv bootcmd 'tftp 80800000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz
80800000 - 83000000'
saveenv
boot
- 1
- 2
- 3
- 4
Uboot源码目录分析
- 因为uboot会使用到一些经过编译才会生成的文件,因此在分析uboot的时候,需要先编译一下uboot。
- 整个UBOOT的链接脚本在arch\arm\cpu\u-boot.lds,编译后uboot根目录下也会有个u-boot.lds,注意后者由前者生成的!
移植uboot的时候重点要关注
-
board\freescale\mx6ullevk目录,参考此目录创建自己的板子
-
configs目录,uboot的默认配置文件目录,此目录下都是以_defconfig结尾的,这些配置文件对应不同的板子。
- 其中mx6ull_alientek_alpha_ddr256_emmc_defconfig是正点原子的配置文件!
-
执行make xxx_defconfig,会在uboot根目录下生成.config文件,此文件保存了详细的uboot配置信息。
-
顶层README,非常重要,介绍uboot。
-
根目录下的u-boot,这个是编译出来带ELF信息的uboot可执行文件
-
bootcmd - 命令列表,这些命令一般都是用来启动 Linux 内核的。(如通过tftp下载zImage和dtb文件,启动Linux内核)
bootcmd=tftp 80800000 zImage;tftp 83000000 imx6ull.dtb;bootz 80800000 - 83000000;
-
Bootargs - 命令行参数,传递给Linux内核。(通常用来设置控制台和指定根文件系统)
bootargs=console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw
配置uboot有3种方法:
- 通过 mx6ull_alientek_emmc_defconfig 来配置
- 通过文件 mx6ull_alientek_emmc.h 来配置
- 通过图形化配置
- 在图形化界面可以保存配置
- 图形界面可以通过
?
查看使能具体宏的名字。 - 图形界面启动前需要安装
ncurses 库
sudo apt-get install build-essential
sudo apt-get install libncurses5-dev
- 1
- 2
配置完成之后会在.config中定义相应的宏。
文章来源: recclay.blog.csdn.net,作者:ReCclay,版权归原作者所有,如需转载,请联系作者。
原文链接:recclay.blog.csdn.net/article/details/105247350
- 点赞
- 收藏
- 关注作者
评论(0)