【嵌入式Linux驱动进阶】U-boot 学习

举报
ReCclay 发表于 2022/02/21 22:34:01 2022/02/21
【摘要】 I.MX6UL启动方式 通过设置i.MX6UL启动相关引脚的电平状态来改变芯片的启动方式。 BOOT_MODE[1:0] = 10B ,i.MX6UL将会从“内部”启动,所谓“内部”是相对于“Seria...

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:setenv author 'xxx'然后saveenv
    • 删除环境变量
      • eg:setenv author然后saveenv,不设置值即可实现删除操作!
内存操作相关
  • 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即可退出。
  • 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
  • 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

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。