野火ebf6ull系列之uboot移植


摘要:在这里使用野火的板子,根据正点原子的教程进行学习;并在网上记录。
首要确定EBF6ull S1的配置:

  • eMMC:8GB
  • DDR:512MB

在这里插入图片描述

整个学个过程根据正点原子的教程,分别有uboot,linux 内核,linux 驱动,linux 应用等。这里重点描述uboot移植。
这里仅是使用野火的板子,全部使用正点原子的教程。

认识uboot以及编译

1 嵌入式Linux移植概述

Linux 的移植主要包括3部分:

移植 「 b o o t l o a d e r 代 码 」 \color{#4285f4}{「bootloader 代码」} bootloader, Linux 系统要启动就必须需要一个 bootloader 程序,也就说芯片上电以后先运行一段bootloader程序。 这段bootloader程序会先初始化DDR等外设, 然后将Linux内核从flash(NAND,NOR FLASH,SD,MMC 等)拷贝到 DDR 中,最后启动 Linux 内核。 bootloader 有很多,常用的就是 U-Boot。

bootloader 和 Linux 内核的关系就跟 PC 上的 BIOS 和 Windows 的关系一样,bootloader 就相当于 BIOS。

移植 「 L i n u x 内 核 」 \color{#4285f4}{「Linux 内核」} Linux,Linux内核由一系列程序组成,包括负责响应中断的中断服务程序、负责管理多个进程从而分享处理器时间的调度程序、负责管理地址空间的内存管理程序、网络、进程间通信的系统服务程序等。内核负责管理系统的硬件设备。

移植 「 根 文 件 系 统 ( r o o t f s ) 」 \color{#4285f4}{「根文件系统(rootfs)」} (rootfs),Linux 中的根文件系统更像是一个文件夹或者叫做目录,在这个目录里面会有很多的子目录。根目录下和子目录中会有很多的文件,这些文件是 Linux 运行所必须的,比如库、常用的软件和命令、设备文件、配置文件等等。根文件系统里面包含了一些最常用的命令和文件。

「 U − B o o t 、 L i n u x k e r n e l 和 r o o t f s 」 \color{#4285f4}{「U-Boot、Linux kernel和rootfs」 } UBootLinuxkernelrootfs这三者一起构成了一个完整的Linux系统,一个可以正常使用、功能完善的Linux系统。

2 U-Boot简介

uboot 的全称是 「 U n i v e r s a l B o o t L o a d e r 」 \color{#4285f4}{「Universal Boot Loader」} UniversalBootLoader,遵循 GPL 协议的开源软件。

uboot 是一个裸机代码,可以看作是一个裸机综合例程。现在的 uboot 已经支持 「 液 晶 屏 、 网 络 、 U S B 」 \color{#4285f4}{「液晶屏、网络、USB」} USB等高级功能。uboot 官网为 https://www.denx.de/wiki/U-Boot/
在这里插入图片描述
移植uboot时一般不会直接用 uboot 官方的源码的,官方的源码是给半导体厂商准备的,半导 体厂商会根据自家的芯片,维护自己芯片对应的uboot。

NXP(freescale)维护的的uboot地址: https://github.com/Freescale/u-boot-fslc

git下载:

git clone https://github.com/Freescale/u-boot-fslc

查看最新分析:

git branch -a

切换分支:

git checkout remotes/origin/2016.03+fslc:

查看是否切换分支成功:

git branch

3 NXP uboot测试

uboot移植并不需要从零开始将 uboot 移植到我们现在所使用的开发板上。因为半导体厂商通常都会自己做一个开发板 「 原 厂 开 发 板 」 \color{#4285f4}{「原厂开发板」} ,将uboot移植到他们自己的原厂开发板上,再将这个uboot(原厂BSP 包)发布出去。

市面上的开发板,通常会参考原厂的开发板做硬件,然后在原厂提供的 BSP 包上做修改,如正点原子和野火的 I.MX6ULL 开发板参考的就 是 「 N X P 官 方 的 I . M X 6 U L L E V K 开 发 板 」 \color{#4285f4}{「NXP官方的I.MX6ULL EVK开发板」} NXPI.MX6ULLEVK 做的硬件:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iUREcvTY-1670901347787)(IMX6ULL-EVK.jpg)]

3.1 编译环境搭建

3.1.1 交叉编译器下载

嵌入式Linux开发,程序编译通常在电脑端的Linux(如虚拟机中的Ubuntu)下进行编译,Ubuntu 自带gcc 编译器,但该编译器是针对 X86 架构的!而嵌入式Linux是ARM架构的, 所以需要一个在 X86 架构上可以编译 ARM 架构代码的 gcc编译器,即「交叉编译器」。

交叉编译器有很多,本实验使用 Linaro 出品的交叉编译器,下载地址:

https://releases.linaro.org/components/toolchain/binaries/4.9-2017.01/arm-linux-gnueabihf/

在这里插入图片描述

3.1.2 交叉编译器安装

在Ubuntu中创建目录:/usr/local/arm,并将下载的gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.xz复制到此文件中,然后 「 解 压 」 \color{#4285f4}{「解压」} ,解压命令如下:

sudo tar -vxf gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.xz

解压完成以后会生成一个名为“gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf”的文件夹,这个文件夹里面就是我们的交叉编译工具链。然后,需要将该目录 「 添 加 到 环 境 变 量 」 \color{#4285f4}{「添加到环境变量」} 中。

1. ~/.bashrc (用户的环境变量)

打开~/.bashrc 以后,在最后面输入如下所示内容:

#export ARCH=arm
#export CROSS_COMPILE=arm-none-linux-gnueabihf-
export PATH=$PATH:/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k40hd6h2-1670901347788)(bashrc.jpg)]

2. /etc/profile (所有用户的环境变量)

打开/etc/profile 以后,在最后面输入如下所示内容:

export PATH=$PATH:/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ocrMDCSp-1670901347788)(profile.jpg)]

使用交叉编译器之前还需要 「 安 装 其 它 的 库 」 \color{#4285f4}{「安装其它的库」} ,命令如下:

sudo apt-get install lsb-core lib32stdc++6 

安装完之后,可以 「 查 看 交 叉 编 译 工 具 的 版 本 号 」 \color{#4285f4}{「查看交叉编译工具的版本号」} ,输入如下命令:

arm-linux-gnueabihf-gcc -v 

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fc1KqC4b-1670901347789)(gccversion.jpg)]

以看出当前交叉编译器的版本号为 4.9.4,说明交叉编译工具链安装成功。

3.2 编译原厂uboot

编译前还要在Ubuntu 中 「 安 装 n c u r s e s 库 」 \color{#4285f4}{「安装ncurses 库」} ncurses,安装命令如下:

sudo apt-get install libncurses5-dev 

使用的是 「 正 点 原 子 」 \color{#4285f4}{「正点原子」} 提供的NXP官方原版Uboot源码包( uboot-imx-rel_imx_4.1.15_2.1.0_ga.tar.bz2)

进行解压:

tar -vxjf uboot-imx-rel_imx_4.1.15_2.1.0_ga.tar.bz2

解压后的源码文件如下:

在这里插入图片描述

首先看下 「 u b o o t 的 配 置 」 \color{#4285f4}{「uboot的配置」} uboot,configs 目录下有很多跟 I.MX6UL/6ULL 有关的配置,找到与mx6ull相同的,如下图。

因为我这个开发板是emmc版本的,所有就使用这个mx6ull_14x14_evk_emmc_defconfig。

编译uboot使用下面3条指令:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_evk_emmc_defconfig
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j8

这3条命令中 :

  • ARCH=arm 设置目标为 arm 架构

  • CROSS_COMPILE 指定所使用的交叉编译器。

  • 第1条命令相当于make distclean,目的是清除工程,一般在第一次编译的时候最好清理一下工程。

  • 第2条指令相当于make mx6ull_14x14_evk_emmc_defconfig,用于配置 uboot,配置文件为 mx6ull_14x14_evk_emmc_defconfig。

  • 第3条指令相当于make -j8,也就是使用8核来编译uboot。

为了方便的执行着3条指令,可以将这些指令写成 「 s h e l l 脚 本 」 \color{#4285f4}{「 shell脚本」} shell,比如在uboot源码目录下新建一个build.sh文件,写入如下内容:

#!/bin/bash

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_evk_emmc_defconfig
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j8

然后进行编译:

./build.sh    

在这里插入图片描述

编译完成以后uboot 源码多了一些文件,其中u-boot.bin就是编译出来的 uboot二进制文件。 uboot是个裸机程序, 因此需要在其前面

加上头部(IVT、 DCD等数据)才能在I.MX6U上执行,u-boot.imx文件就是添加头部以后的 u-boot.bin。

u-boot.imx 就是我们最终要烧写到开发板中的 uboot 镜像文件。

在这里插入图片描述

3.3 烧录开发板

这是的烧录开发板,实际是要 「 烧 录 到 S D 卡 中 」 \color{#4285f4}{「烧录到SD卡中」} SD,然后将SD卡插入开发板,让开发板从SD卡启动(需要在开发板上设置拨码开关来选择启动方式)。

3.3.1 烧录到SD卡

「 正 点 原 子 」 \color{#4285f4}{「正点原子」} 专门编写了一个小软件用来将编译出来的.bin 文件烧写到 SD 卡中,这个软件叫做“imxdownload”

将imxdownload 复制到 Ubuntu 中的uboot源码文件夹,再使用如下指令,给予 imxdownload 可执行权限:

chmod 777 imxdownload

然后 「 电 脑 U S B 中 插 入 S D 卡 ( 读 卡 器 ) 」 \color{#4285f4}{「电脑USB中插入SD卡(读卡器)」} USBSD,并在虚拟机中设置usb加载(VMware或VirtualBox虚拟机需要先安装 「 增 强 功 能 」 \color{#4285f4}{「增强功能」} 才能使用)
然后可以使用如下指令来查看SD卡的挂载标识符:

ls /dev/sd* 

查看输出结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jyTPanN8-1670901347790)(sd.jpg)]
imxdownload向SD卡烧写led.bin文件,命令格式如下:

./imxdownload u-boot.bin /dev/sdb 

烧写过程会输入如下信息:

在这里插入图片描述

注意: /dev/sda
不能烧写到/dev/sda或sda1设备里面!那是系统磁盘。
烧写的最后一行会显示烧写大小、用时和速度,比如u-boot.bin烧写到SD卡中的大小是 423KB,用时 1.7s,烧写速度是 236KB/s。

注意: 烧写速度
这个烧写速度,如果这个烧写速度在几百KB/s以下那么就是正常烧写。 如果这个烧写速度大于几十MB/s、甚至几百MB/s那么肯定是烧写失败了! 重新插拔/格式化SD卡或重启ubuntu再试。

烧写完成以后会在当前工程目录下生成一个load.imx的文件,这个文件就是软件 imxdownload 根据 NXP 官方启动方式介绍的内容, 在 bin 文件前面添加了一些数据头以后生成的。最终烧写到SD卡里面的就是这个imx文件。

3.3.2 启动开发板

烧录完之后,将 「 S D 卡 插 入 开 发 板 启 动 」 \color{#4285f4}{「SD卡插入开发板启动」} SD,使用 「 串 口 连 接 电 脑 」 \color{#4285f4}{「串口连接电脑」} ,查看uboot启动信息。 设置好串口参数(波特率115200)并打开,按键 「 复 位 开 发 板 」 \color{#4285f4}{「复位开发板」} 。 当串口打印上出现Hit any key to stop autoboot倒计时的时候 「 按 下 键 盘 上 的 回 车 键 」 \color{#4285f4}{「按下 键盘上的回车键」} ,默认是 3 秒倒计时,在 3 秒倒计时结束以后如果没有按下回车键的话 uboot 就会使用默认参数来启动 Linux 内核了。

如果在 3 秒倒计时结束之前按下回车键,那么就会进入 uboot 的命令行模式:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0leVCSqo-1670901347791)(ubootnxpinit.jpg)]

解读一下这些信息的含义:

  • 第1行是 uboot 「 版 本 号 和 编 译 时 间 」 \color{#4285f4}{「版本号和编译时间」} :当前的 uboot 版本号是 2016.03,编译时间是 2021/7 /11/15:22:25
  • 第3、4 行是 「 C P U 信 息 」 \color{#4285f4}{「CPU 信息」} CPU:当前使用的 CPU 是飞思卡尔(属于NXP)的 I.MX6ULL (频率为 792MHz),此时运行在 396MHz。这颗芯片是工业级的,结温为-40°C~105°C
  • 第 5 行是 「 复 位 原 因 」 \color{#4285f4}{「复位原因」} :I.MX6ULL 芯片上有个 POR_B 引脚,将这个引脚拉低即可复位 I.MX6ULL。
  • 第 6 行是 「 板 子 名 字 」 \color{#4285f4}{「板子名字」} ,“MX6ULL 14x14 EVK”即NXP原厂开发板的名字 。
  • 第 7 行提示 「 I 2 C 准 备 就 绪 」 \color{#4285f4}{ 「I2C 准备就绪」} I2C
  • 第 8 行提示当前板子的 「 D R A M ( 内 存 ) 」 \color{#4285f4}{「DRAM(内存)」} DRAM() 为 512MB
  • 第 9 行提示当前有 「 两 个 M M C / S D 卡 控 制 器 」 \color{#4285f4}{「两个MMC/SD 卡控制器」} MMC/SD:FSL_SDHC(0)和 FSL_SDHC(1)。I.MX6ULL支持两个 MMC/SD,正点原子的 I.MX6ULL EMMC 核心板上 FSL_SDHC(0)接的 SD(TF)卡,FSL_SDHC(1)接的 EMMC。
  • 第10行是一条警告信息,先忽略。
  • 第 12、13 行是 「 L C D 型 号 」 \color{#4285f4}{ 「LCD 型号」} LCD,原厂默认的是TFT43AB (480x272)。
  • 第 14~16 是 「 标 准 输 入 、 标 准 输 出 和 标 准 错 误 」 \color{#4285f4}{「标准输入、标准输出和标准错误」} 所使用的终端,这里都使用串口(serial)作为终端。
  • 第 17 、18行是 「 切 换 到 e m m c 的 第 0 个 分 区 上 」 \color{#4285f4}{「切换到emmc的第0个分区上」} emmc0,因为当前的 uboot 是 emmc 版本的,也就是从 emmc 启动的。我们只是为了方便将其烧写到了 SD 卡上,但是它的“内心”还是 EMMC的。所以 uboot 启动以后会将 emmc 作为默认存储器 。
  • 第 19行是 「 网 口 信 息 」 \color{#4285f4}{「网口信息」} ,提示我们当前使用的 FEC1 这个网口,I.MX6ULL 支持两个网口。
  • 第 20行提示 「 F E C 1 网 卡 地 址 没 有 设 置 」 \color{#4285f4}{「FEC1网卡地址没有设置」} FEC1(后面我们会讲解如何在uboot 里面设置网卡地址)。
  • 第 22行提示 「 正 常 启 动 」 \color{#4285f4}{「正常启动」} , 也就是说 uboot要从emmc里面读取环境变量和参数信息启动 Linux内核了。
  • 第23行是 「 倒 计 时 提 示 」 \color{#4285f4}{「倒计时提示」} ,默认倒计时 3 秒,倒计时结束之前按下回车键就会进入 Linux 命令行模式。如果在倒计时结束以后没有按下回车键,那么 Linux 内核就会启动,Linux 内核一旦启动,uboot 就运行结束了。
  • 第23行是在倒计时 3 秒内按了回车键,符号=>表示可以继续与uboot进行 「 命 令 交 互 」 \color{#4285f4}{「命令交互」}
    看过了串口的uboot信息,再来看一下板子是实际运行情况:

由于原厂的uboot驱动的屏幕是TFT43AB (480x272),与我这里屏幕不一样,所以「屏幕没有正常显示」(现在的屏幕看起来有许多彩色的小点点),接下来,就是对uboot进行屏幕驱动的修改。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fYXOxyiB-1670901347791)(ubootnxpef.png)]

在本篇结束之前,再来研究一下uboot的串口指令。

3.4 uboot命令初探

上面说道,在uboot启动的3 秒倒计时内,串口界面如果按下了回车键,uboot就会输出符号=>,则 「 可 以 继 续 与 u b o o t 进 行 命 令 交 互 」 \color{#4285f4}{「可以继续与uboot进行命令交互」} uboot。那可以输入哪些命令呢?
输入help或?,然后按下回车即可查看当前 uboot 所支持的命令:

=> help
?       - aliasfor'help'
base    - print or set address offset
bdinfo  - print Board Info structure
bmode   - sd1|sd2|qspi1|normal|usb|sata|ecspi1:0|ecspi1:1|ecspi1:2|ecspi1:3|esdhc1|esdhc2|esdhc3|esdhc4 [noreset]
bmp     - manipulate BMP image data
boot    - boot default, i.e., run 'bootcmd'
bootd   - boot default, i.e., run 'bootcmd'
bootelf - Boot from an ELF image in memory
bootm   - boot application image from memory
bootp   - boot image via network using BOOTP/TFTP protocol
bootvx  - Boot vxWorks from an ELF image
bootz   - boot Linux zImage image from memory
clocks  - display clocks
clrlogo - fill the boot logo area with black
cmp     - memory compare
coninfo - print console devices and information
cp      - memory copy
crc32   - checksum calculation
dcache  - enable or disable data cache
dhcp    - boot image via network using DHCP/TFTP protocol
dm      - Driver model low level access
echo    - echo args to console
editenv - edit environment variable
env     - environment handling commands
erase   - erase FLASH memory
exit    - exit script
ext2load- load binary file from a Ext2 filesystem
ext2ls  - list files in a directory (default /)
ext4load- load binary file from a Ext4 filesystem
ext4ls  - list files in a directory (default /)
ext4size- determine a file's size
ext4write- create a file in the root directory
false   - do nothing, unsuccessfully
fatinfo - print information about filesystem
fatload - load binary file from a dos filesystem
fatls   - list files in a directory (default /)
fatsize - determine a file's size
fdt     - flattened device tree utility commands
flinfo  - print FLASH memory information
fstype  - Look up a filesystem type
fuse    - Fuse sub-system
go      - start application at address 'addr'
gpio    - query and control gpio pins
help    - printcommand description/usage
i2c     - I2C sub-system
icache  - enable or disable instruction cache
iminfo  - print header information for application image
imxtract- extract a part of a multi-image
itest   - returntrue/false on integer compare
load    - load binary file from a filesystem
loadb   - load binary file over serial line (kermit mode)
loads   - load S-Record file over serial line
loadx   - load binary file over serial line (xmodem mode)
loady   - load binary file over serial line (ymodem mode)
loop    - infinite loop on address range
ls      - list files in a directory (default /)
md      - memory display
mdio    - MDIO utility commands
mii     - MII utility commands
mm      - memory modify (auto-incrementing address)
mmc     - MMC sub system
mmcinfo - display MMC info
mtest   - simple RAM read/write test
mw      - memory write (fill)
nfs     - boot image via network using NFS protocol
nm      - memory modify (constant address)
ping    - send ICMP ECHO_REQUEST to network host
pmic    - PMIC
printenv- print environment variables
protect - enable or disable FLASH write protection
reset   - Perform RESET of the CPU
run     - run commands in an environment variable
save    - save file to a filesystem
saveenv - save environment variables to persistent storage
setenv  - set environment variables
setexpr - set environment variable as the result of eval expression
sf      - SPI flash sub-system
showvar - printlocal hushshell variables
size    - determine a file's size
sleep   - delay execution for some time
source  - run script from memory
test    - minimal test like /bin/sh
tftpboot- boot image via network using TFTP protocol
true    - do nothing, successfully
usb     - USB sub-system
usbboot - boot from USB device
version - print monitor, compiler and linker version
=>
3.4.2 查看指令的使用说明

命令的具体使用方法,可以输入help 命令名或? 命令名查看,以“bootz”这个命令为例:

=> help bootz
bootz - boot Linux zImage image from memory
Usage:
bootz [addr [initrd[:size]] [fdt]]
    - boot Linux zImage stored in memory
        The argument 'initrd' is optional and specifies the address
        of the initrd in memory. The optional argument ':size' allows
        specifying the size of RAW initrd.
        When booting a Linux kernel which requires a flat device-tree
        a third argument is required which is the address of the
        device-tree blob. To boot that kernel without an initrd image,
        use a '-'for the second argument. If you do not pass a third
        a bd_info struct will be passed instead

=>
3.4.3 信息查询命令

常用的和信息查询有关的命令有3个: b d i n f o 、 p r i n t e n v 和 v e r s i o n \color{#4285f4}{ bdinfo、printenv和version } bdinfoprintenvversion

bdinfo 板子信息

=> bdinfo
arch_number = 0x00000000
boot_params = 0x80000100
DRAM bank   = 0x00000000
-> start    = 0x80000000
-> size     = 0x20000000
eth0name    = FEC1
ethaddr     = (not set)
current eth = FEC1
ip_addr     = <NULL>
baudrate    = 115200 bps
TLB addr    = 0x9FFF0000
relocaddr   = 0x9FF47000
reloc off   = 0x18747000
irq_sp      = 0x9EF44EA0
sp start    = 0x9EF44E90
FB base     = 0x00000000
=>

从打印信息可以得出DRAM的 「 起 始 地 址 和 大 小 、 启 动 参 数 保 存 起 始 地 址 、 波 特 率 、 s p ( 堆 栈 指 针 ) 起 始 地 址 」 \color{#4285f4}{「起始地址和大小、启动参数保存起始地址、波特率、sp(堆栈指针)起始地址」} sp()等信息.

printenv 打印环境变量

=> printenv
baudrate=115200
board_name=EVK
board_rev=14X14
boot_fdt=try
bootcmd=run findfdt;mmc dev ${mmcdev};mmc dev ${mmcdev}; if mmc rescan; thenif run loadbootscript; then run bootscript; elseif run loadimage; thn run mmcboot; else run netboot; fi; fi; else run netboot; fi
bootcmd_mfg=run mfgtool_args;bootz ${loadaddr}${initrd_addr}${fdt_addr};
bootdelay=3
bootscript=echo Running bootscript from mmc ...; source
console=ttymxc0
ethact=FEC1
ethprime=FEC
fdt_addr=0x83000000
fdt_file=undefined
fdt_high=0xffffffff
findfdt=iftest$fdt_file = undefined; theniftest$board_name = EVK && test$board_rev = 9X9; then setenv fdt_file imx6ull-9x9-evk.dtb; fi; if tst $board_name = EVK && test$board_rev = 14X14; then setenv fdt_file imx6ull-14x14-evk.dtb; fi; iftest$fdt_file = undefined; thenecho WARNING:Could not determine dtb to use; fi; fi;
image=zImage
initrd_addr=0x83800000
initrd_high=0xffffffff
ip_dyn=yes
loadaddr=0x80800000
loadbootscript=fatload mmc ${mmcdev}:${mmcpart}${loadaddr}${script};
loadfdt=fatload mmc ${mmcdev}:${mmcpart}${fdt_addr}${fdt_file}
loadimage=fatload mmc ${mmcdev}:${mmcpart}${loadaddr}${image}
mfgtool_args=setenv bootargs console=${console},${baudrate} rdinit=/linuxrc g_mass_storage.stall=0 g_mass_storage.removable=1 g_mass_storage.file=fat g_mass_storage.ro=1 g_mass_storage.idVendor=0x066F g_mass_storage.idProduct=0x37FF g_mass_storage.iSerialNumber="" clk_ignore_unused
mmcargs=setenv bootargs console=${console},${baudrate} root=${mmcroot}
mmcautodetect=yes
mmcboot=echo Booting from mmc ...; run mmcargs; iftest${boot_fdt} = yes || test${boot_fdt} = try; thenif run loadfdt; then bootz ${loadaddr} -${fdt_addr}; elseiftest${boot_fdt} = try; then bootz; elseecho WARN: Cannot load the DT; fi; fi; else bootz; fi;
mmcdev=0
mmcpart=1
mmcroot=/dev/mmcblk0p2 rootwait rw
netargs=setenv bootargs console=${console},${baudrate} root=/dev/nfs ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp
netboot=echo Booting from net ...; run netargs; iftest${ip_dyn} = yes; then setenv get_cmd dhcp; else setenv get_cmd tftp; fi; ${get_cmd}${imag}; iftest${boot_fdt} = yes || test${boot_fdt} = try; thenif${get_cmd}${fdt_addr}${fdt_file}; then bootz ${loadaddr} - ${fdt_addr}; elseif est ${boot_fdt} = try; then bootz; elseecho WARN: Cannot load the DT; fi; fi; else bootz; fi;
panel=TFT43AB
script=boot.scr

Environment size: 2431/8188 bytes
=>

这里有很多的环境变量, 比如 「 b a u d r a t e 、 b o a r d _ n a m e 、 b o a r d _ r e c 、 b o o t _ f d t 、 b o o t c m d 」 \color{#4285f4}{「baudrate、 board\_name、 board \_rec、 boot\_fdt、 bootcmd」} baudrateboard_nameboard_recboot_fdtbootcmd等。比如bootdelay这个环境变量就表示 uboot 启动延时时间,默认 bootdelay=3,也就默认延时 3秒。前面说的 3 秒倒计时就是由 bootdelay 定义的。另外uboot中的环境变量都是字符串。

version 版本信息

=> version

U-Boot 2016.03 (Aug 28 2022 - 12:17:58 +0800)
arm-linux-gnueabihf-gcc (Linaro GCC 4.9-2017.01) 4.9.4
GNU ld (Linaro_Binutils-2017.01) 2.24.0.20141017 Linaro 2014_11-3-git
=>

当前uboot 版本号为 2016.03,编译日期2022/8/28,编译器为arm-linux-gnueabihf-gcc。

uboot移植实践

我们介绍了如何使用NXP原厂的uboot进行编译和烧写,将uboot运行在自己的开发板上。NXP原厂的uboot,直接烧录到我的开发板中,LCD的驱动是不正常的,需要进行修改。本篇我们就来继续研究uboot, 「 使 得 u b o o t 能 匹 配 我 们 自 己 的 开 发 板 」 \color{#4285f4}{「使得uboot能匹配我们自己的开发板」} 使uboot

修改uboot以匹配开发板的方式有两种,一种是在NXP原厂开发板 「 I M X 6 U L L   E V K 」 \color{#4285f4}{「IMX6ULL\ EVK」} IMX6ULL EVK的文件上进行修改,另一种仿造NXP的开发板文件,添加自己的开发板文件。

为了能更多的了解uboot,我们使用代码改动较大的第二种方式进行uboot的移植。

在修改uboot之前,先来看一下uboot的源码结构。

1 uboot源码结构分析

uboot的源码如下,这里是源码编译后的结果,包含编译后的文件。
在这里插入图片描述

文件的含义如下:

NXP uboot 源码结构
类型名称描述备注
文件夹api与硬件无关的API函数uboot自带
arch与架构体系有关的代码
board不同板子(开发板)的定制代码
cmd命令相关代码
common通用代码
configs配置文件
disk磁盘分区相关代码
doc文档
drivers驱动代码
dts设备树
examples示例程序
fs文件系统
include头文件
lib库文件
Licenses许可证文件
net网络相关代码
post上电自检程序
scripts脚本文件
test测试文件
tools工具文件夹
文件.config配置文件编译生成的文件
build.sh编译原厂开发板的uboot脚本自己编写的编译脚本
build_fire.sh编译野火开发板的uboot脚本
comfig.mkMakefile编译文件uboot自带
imxdownload正点原子编写SD卡烧写软件正点原子
imxdownload正点原子编写SD卡烧写软件正点原子
kbuild用于生成和汇编有关的文件uboot自带
Kconfig图形配置界面描述文件
load.imx烧写SD卡后生成的文件烧写SD卡后生成
MAINTAINERS维护者联系方式文件uboot自带
MAKEALL帮助编译uboot
Makefile主makefile
README说明文件
Snapshot commit ?
Syatem.map系统映射文件编译生成文件
u-boot编译出来的u-boot文件
u-boot.*u-boot相关文件

1.1 vscode 配置

  • settings.json
{
	 //"search.exclude"里面是需要在搜索结果中排除的文件或者文件夹
	 "search.exclude": {
		"**/node_modules": true,
		"**/bower_components": true,
		"**/*.o":true,
		"**/*.su":true,
		"**/*.cmd":true,
		"arch/arc":true,
		"arch/avr32":true,
		"arch/blackfin":true,
		"arch/m68k":true,
		"arch/microblaze":true,
		"arch/mips":true,
		"arch/nds32":true,
		"arch/nios2":true,
		"arch/openrisc":true,
		"arch/powerpc":true,
		"arch/sandbox":true,
		"arch/sh":true,
		"arch/sparc":true,
		"arch/x86":true,
		"arch/arm/mach*":true,
		"arch/arm/cpu/arm11*":true,
		"arch/arm/cpu/arm720t":true,
		"arch/arm/cpu/arm9*":true,
		"arch/arm/cpu/armv7m":true,
		"arch/arm/cpu/armv8":true,
		"arch/arm/cpu/pxa":true,
		"arch/arm/cpu/sa1100":true,
		"board/[a-e]*":true,
		"board/[g-z]*":true,
		"board/[0-9]*":true,
		"board/[A-Z]*":true,
		"board/fir*":true,
		"board/freescale/b*":true,
		"board/freescale/l*":true,
		"board/freescale/m5*":true,
		"board/freescale/mp*":true,
		"board/freescale/c29*":true,
		"board/freescale/cor*":true,
		"board/freescale/mx7*":true,
		"board/freescale/mx2*":true,
		"board/freescale/mx3*":true,
		"board/freescale/mx5*":true,
		"board/freescale/p*":true,
		"board/freescale/q*":true,
		"board/freescale/t*":true,
		"board/freescale/v*":true,
		"configs/[a-l]*":true,
		"configs/[n-z]*":true,
		"configs/[A-Z]*":true,
		"configs/M[a-z]*":true,
		"configs/M[A-Z]*":true,
		"configs/M[0-9]*":true,
		"configs/m[a-w]*":true,
		"configs/m[0-9]*":true,
		"configs/[0-9]*":true,
		"include/configs/[a-l]*":true,
		"include/configs/[n-z]*":true,
		"include/configs/[A-Z]*":true,
		"include/configs/m[a-w]*":true,		
	},
	//"files.exclude"是左侧工程目录中需要排除的文件或者文件夹
	"files.exclude": {
		"**/.git": true,
		"**/.svn": true,
		"**/.hg": true,
		"**/CVS": true,
		"**/.DS_Store": true,
		"arch/arc":true,
		"arch/avr32":true,
		"arch/blackfin":true,
		"arch/m68k":true,
		"arch/microblaze":true,
		"arch/mips":true,
		"arch/nds32":true,
		"arch/nios2":true,
		"arch/openrisc":true,
		"arch/powerpc":true,
		"arch/sandbox":true,
		"arch/sh":true,
		"arch/sparc":true,
		"arch/x86":true,
		"arch/arm/mach*":true,
		"arch/arm/cpu/arm11*":true,
		"arch/arm/cpu/arm720t":true,
		"arch/arm/cpu/arm9*":true,
		"arch/arm/cpu/armv7m":true,
		"arch/arm/cpu/armv8":true,
		"arch/arm/cpu/pxa":true,
		"arch/arm/cpu/sa1100":true,
		"board/[a-e]*":true,
		"board/[g-z]*":true,
		"board/[0-9]*":true,
		"board/[A-Z]*":true,
		"board/fir*":true,
		"board/freescale/b*":true,
		"board/freescale/l*":true,
		"board/freescale/m5*":true,
		"board/freescale/mp*":true,
		"board/freescale/c29*":true,
		"board/freescale/cor*":true,
		"board/freescale/mx7*":true,
		"board/freescale/mx2*":true,
		"board/freescale/mx3*":true,
		"board/freescale/mx5*":true,
		"board/freescale/p*":true,
		"board/freescale/q*":true,
		"board/freescale/t*":true,
		"board/freescale/v*":true,
		"configs/[a-l]*":true,
		"configs/[n-z]*":true,
		"configs/[A-Z]*":true,
		"configs/M[a-z]*":true,
		"configs/M[A-Z]*":true,
		"configs/M[0-9]*":true,
		"configs/m[a-w]*":true,
		"configs/m[0-9]*":true,
		"configs/[0-9]*":true,
		"include/configs/[a-l]*":true,
		"include/configs/[n-z]*":true,
		"include/configs/[A-Z]*":true,
		"include/configs/m[a-w]*":true,		
	}
}

1.2 顶层Makefile

uboot研读笔记 | 13 - uboot编译构建Makefile分析研读(2016.03版本)

1.3 uboot启动分析

2 NXP官方uboot适配移植

2.1 添加开发板配置文件

首先是 「 创 建 自 己 开 发 板 的 配 置 文 件 」 \color{#4285f4}{「创建自己开发板的配置文件」} ,该文件可参考原厂开发板的配置文件,在configs文件夹下,将原来的默认配置文件mx6ull_14x14_evk_emmc_defconfig复制一份,并重命名为mx6ull_fire_emmc_defconfig,该文件即用于作为自己开发板的配置文件。

然后进行 「 内 容 修 改 」 \color{#4285f4}{「内容修改」} ,将原始内容:
CONFIG_SYS_EXTRA_OPTIONS=“IMX_CONFIG=board/freescale/mx6ullevk/imximage.cfg,MX6ULL_EVK_EMMC_REWORK”
CONFIG_ARM=y
CONFIG_ARCH_MX6=y
CONFIG_TARGET_MX6ULL_14X14_EVK=y
CONFIG_CMD_GPIO=y

修改为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z3A0CwD9-1670901347791)(imx6ull_fire_emmc_deconfig.jpg)]

2.2 添加开发板对应的头文件
在目录 include/configs 下添加自己开发板对应的头文件,复制mx6ullevk.h,并重命名为mx6ull_fireboard.h,将文件中的

#ifndef __MX6ULLEVK_CONFIG_H 
#define __MX6ULLEVK_CONFIG_H

修改为:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QxRw9sdl-1670901347792)(mx6ull_fireboard.jpg)]

该文件里面有很多宏定义,这些宏定义基本用于配置uboot,如果我们自己要想使能或者禁止uboot的某些功能,那就要在这里面修改。

2.3 添加开发板对应的板级文件夹

uboot中每个板子都有一个对应的文件夹来存放板级文件(如开发板上外设驱动文件等)。NXP的I.MX系列芯片的所有板级文件夹都存放在 board/freescale/目录下,在这个目录下有个名为mx6ullevk的文件夹,原厂开发板的板级文件夹。

复制 mx6ullevk,将其重命名为mx6ull_fireboard,进入mx6ull_fireboard目录中, 将其中的mx6ullevk.c文件重命名为mx6ull_fireboard.c。

2.3.1 修改Makefile文件

首先是修改 board/freescale/mx6ull_fireboard 目录下的Makefile文件

将原始内容:

# (C) Copyright 2015 Freescale Semiconductor, Inc.
#
# SPDX-License-Identifier:      GPL-2.0+
#

obj-y  := mx6ullevk.o

extra-$(CONFIG_USE_PLUGIN) :=  plugin.bin
$(obj)/plugin.bin: $(obj)/plugin.o
        $(OBJCOPY) -O binary --gap-fill 0xff $<$@

其中的依赖项修改为:

obj-y  := mx6ull_fireboard.o         

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PiAxzPWx-1670901347792)(mx6ull_fireboard_makefile.jpg)]

这样才会编译mx6ull_fireboard.c这个文件。

2.3.2 修改imximage.cfg文件

然后修改 board/freescale/mx6ull_fireboard 目录下的imximage.cfg文件

将imximage.cfg中的下面一句:

PLUGIN board/freescale/mx6ullevk/plugin.bin 0x00907000

改为:

PLUGIN board/freescale/mx6ull_fireboard/plugin.bin 0x00907000

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-umS6jkYf-1670901347792)(imximage.jpg)]

2.3.3 修改Kconfig文件

接着修改 board/freescale/mx6ull_fireboard 目录下的Kconfig文件

将原始内容:

if TARGET_MX6ULL_14X14_EVK || TARGET_MX6ULL_9X9_EVK

config SYS_BOARD
        default "mx6ullevk"

config SYS_VENDOR
        default "freescale"

config SYS_CONFIG_NAME
        default "mx6ullevk"

endif

修改为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kR00yib6-1670901347792)(ubootnxpkconfig.jpg)]

2.3.4 修改MAINTAINERS文件

再接着修改 board/freescale/mx6ull_fireboard 目录下的MAINTAINERS文件

将原始内容:

MX6ULLEVK BOARD
M:      Peng Fan <peng.fan@nxp.com>
S:      Maintained
F:      board/freescale/mx6ullevk/
F:      include/configs/mx6ullevk.h
F:      configs/mx6ull_14x14_evk_defconfig
F:      configs/mx6ull_9x9_evk_defconfig

修改为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2opLvq8j-1670901347792)(ubootnxpMAINTAINERS.jpg)]

2.3.5 重命名板子的c文件

将 board/freescale/mx6ull_fireboard 目录下原来的mx6ullevk.c重命名为mx6ull_fireboard.c

2.4 修改U-Boot图形界面配置文件

最后修改arch/arm/cpu/armv7/mx6/目录下的Kconfig文件

注意目录
  • 这里的Kconfig和board/freescale/c重命名为mx6ull_fireboard目录下的Kconfig是不一样的。

在207行插入一些内容:

config TARGET_MX6ULL_FIREBOARD
        bool "Support mx6ull_fireboard"
        select MX6ULL
        select DM
        select DM_THERMAL

然后,在最后一行的endif的前一行添加如下内容:

source "board/freescale/mx6ull_fireboard/Kconfig"

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fZQcwk1I-1670901347793)(ubootnxpcpukconfigend.jpg)]

2.5 创建编译脚本

在uboot-imx-rel_imx_4.1.15_2.1.0_ga目录下新建一个名为build_fireboard.sh的 shell 脚本,写入如下内容:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_fire_emmc_defconfig
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j8

至此,以上完成的工作,相当于将NXP原厂开发板相关的配置文件,重新复制了一份,并对板子名称修改为了自己板子的名字。

此时执行./build_fireboard.sh,等待编译完成后输入如下命令:

grep -nR "mx6ull_fireboard.h"

如果有很多文件都引用了这个头文件, 那就说明新板子添加成功:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7OC8XdRL-1670901347793)(grepmx6ullfireboard.jpg)]

将uboot进行编译并运行,实际的效果应该和原厂uboot的效果一样(LCD无法显示)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0A1fnit4-1670901347793)(ubootnxpef.png)]

总结一下刚才都有哪些修改」:

右端灰色的为原厂开发板的相关文件,修改的为模仿原厂文件,新添加并修改的自己开发板的文件。

修改
修改
修改
修改
uboot添加自己开发板
修改
configs/
include/configs
board/freescale
arch/arm/cpu/armv7/mx6
mx6ull_14x14_evk_emmc_defconfig
mx6ull_fire_emmc_defconfig
(配置文件)
mx6ullevk.h
mx6ull_fireboard.h
mx6ullevk
mx6ull_fireboard/
(板级文件夹)
Makefile
imximage.cfg
Kconfig
MAINTAINERS
mx6ull_fireboard.c
Kconfig
(uboot图形配置)

3 LCD驱动的修改

一般uboot中修改驱动都是在对应板子c文件和h文件,即board/freescale/mx6ull_fireboard/mx6ull_myboard.c和 include/configs/mx6ull_fireboard.h这两个文件。

一般修改 LCD 驱动重点注意以下几点:

LCD 所使用的 GPIO,查看 uboot 中 LCD 的 IO 配置是否正确
LCD 背光引脚 GPIO 的配置
LCD 配置参数是否正确
「 正 点 原 子 」 \color{#4285f4}{「正点原子」} 以及 「 野 火 」 \color{#4285f4}{「野火」} 的I.MX6ULL开发板的LCD原理图和NXP官方的开发板一致,也就是LCD的IO和背光IO都是一样的, 所以IO部分就不用修改了,只需修改之后的LCD参数。

3.1 修改c文件配置

打开文件 mx6ull_fireboard.c,需要修改下面这段内容:

struct display_info_t const displays[] = {{
    .bus = MX6UL_LCDIF1_BASE_ADDR,
    .addr = 0,
    .pixfmt = 24,
    .detect = NULL,
    .enable	= do_enable_parallel_lcd,
    .mode	= {
        .name			= "TFT43AB",
        .xres           = 480,
        .yres           = 272,
        .pixclock       = 108695,
        .left_margin    = 8,
        .right_margin   = 4,
        .upper_margin   = 2,
        .lower_margin   = 4,
        .hsync_len      = 41,
        .vsync_len      = 10,
        .sync           = 0,
        .vmode          = FB_VMODE_NONINTERLACED
} } };

先来分析一下这段代码,该代码定义了一个变量displays,类型为display_info_t,这个结构体是LCD信息结构体,其中包括了LCD的分辨率,像素格式,LCD的各个参数等。

display_info_t 定义在文件 arch/arm/include/asm/imx-common/video.h 中,定义如下:

struct display_info_t {
    int	bus;
    int	addr;
    int	pixfmt;
    int	(*detect)(struct display_info_tconst *dev);
    void (*enable)(struct display_info_tconst *dev);
    struct	fb_videomode mode;
};

结构体b_videomode里面的成员变量为LCD的参数,这些成员变量函数如下:

name :LCD 名字,要和环境变量中的 panel 相等
xres 、yres :LCD X 轴和 Y 轴像素数量
pixclock:像素时钟,每个像素时钟周期的长度,单位为皮秒
left_margin :HBP(horizontal back porch),水平同步后肩
right_margin :HFP(horizontal front porch),水平同步前肩
upper_margin:VBP(vertical back porch),垂直同步后肩
lower_margin:VFP(vertical front porch),垂直同步前肩
hsync_len :HSPW(horizontal sync pulse width),行同步脉宽
vsync_len:VSPW(vertical sync pulse width),垂直同步脉宽
vmode :大多数使用 FB_VMODE_NONINTERLACED,也就是不使用隔行扫描。
这些参数需要与实用的LCDd的参数一致。

「 野 火 的 7 寸 R G B 屏 幕 」 \color{#4285f4}{「野火的7寸RGB屏幕」} 7RGB(GT911,800x480)的一些参数如下:

参数
width
800
height
480
HBP
46
HFP
22
VBP
23
VFP
22
HSW
1
VSW
1

注意像素时钟pixclock的计算方法:以野火的 7 寸RGB屏为例,屏幕要求的像素时钟为27.4MHz,因此:pixclock=(1/27400000)*10^12=36496

像素时钟:
像素时钟就是 RGB LCD 的时钟信号,以 GT911这款屏幕为例,显示一帧图像所需要的时钟数就是:(VSPW+VBP+LINE+VFP) * (HSPW + HBP + HOZVAL + HFP) = (1 + 23 + 480+ 22) * (1+ 46+ 800+ 22)
= 526* 869 = 457094。显示一帧图像需要457094个时钟数, 那么显示60帧就是:457094* 60 = 27425640≈27.4M,所以像素时钟就是27.4MHz

由以上的屏幕参数,可以得出GT911屏幕的配置参数如下:

struct display_info_t const displays[] = {{
    .bus = MX6UL_LCDIF1_BASE_ADDR,
    .addr = 0,
    .pixfmt = 24,
    .detect = NULL,
    .enable	= do_enable_parallel_lcd,
    .mode	= {
        .name			= "GT911",
        .xres           = 800,
        .yres           = 480,
        .pixclock       = 36496,
        .left_margin    = 46,  //HBPD
        .right_margin   = 22,  //HFPD
        .upper_margin   = 23,  //VBPD
        .lower_margin   = 22,  //VFPD
        .hsync_len      = 1,   //HSPW
        .vsync_len      = 1,   //VSPW
        .sync           = 0,
        .vmode          = FB_VMODE_NONINTERLACED
} } };

3.2 修改h文件配置

另外还要修改include/configs/路径下的mx6ull_myboard.h,第140行中找到所有如下语句:

"panel=TFT43AB\0" \

修改为:

panel=GT911 //与mx6ull_fireboard.c中修改的名称保持一致

修改完成以后重新编译一遍 uboot 并烧写到 SD 中启动。

3.3 编译测试

将修改后的uboot编译下载以后,LCD 驱动一般就会工作正常了,LCD 上会显示 NXP 的 logo。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FysTQsSY-1670901347794)(ubootfirelcd.jpg)]

但某些情况有可能还会遇到LCD 并没有工作,还是黑屏,这是什么原因呢?

在 uboot 命令模式输入“print”来查看环境变量 panel 的值,会发现panel的值要是TFT43AB(或其他的,反正不是GT911):

panel=TFT43AB
script=boot.scr

Environment size: 2431/8188 bytes
=>

这是因为之前有将环境变量保存到EMMC中,uboot启动以后会先从EMMC中读取环境变量,如果EMMC中没有环境变量的话才会使用 mx6ull_alientek_emmc.h 中的默认环境变量。

如果EMMC中的环境变量panel不等于GT911,那么LCD显示肯定不正常,我们只需要在uboot中修改panel的值为GT911即可,在uboot的命令模式下输入如下命令:

setenv panel GT911 
saveenv

上述命令修改环境变量panel为GT911并保存后,按下复位键重启uboot,此时 LCD 驱动就工作正常了。
烧录到SD中

4 网络测试

I.MX6ULL内部有个以太网MAC外设,也就是ENET,需要外接一个PHY芯片来实现网络通信功能,也就是 「 内 部 M A C + 外 部 P H Y 芯 片 」 \color{#4285f4}{「内部MAC+外部PHY芯片」} MAC+PHY的方案。I.MX6ULL有两个网络接口ENET1和ENET2,野火的开发板提供了这两个网络接口,其中ENET1和ENET2都使用是和原厂开发板一样的KSZ8081作为PHY芯片。

因此,网络驱动部分的uboot不需要修改,下面就只是来测试一下网路功能。

4.1 连接网线并查看启动情况

首先将开发板通过网线连接到局域网的路由器中(自己的电脑也要在同一个局域网,这样ubuntu虚拟机则也在同一个局域网)。

然后启动uboot,串口查看相关的打印信息,如下图,可以看到网络端口的FEC1(注意是uboot程序中默认设置的,不是因为网线插在了左边就自动识别FEC1),但是提示网络地址未设置。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-22ZGNmMG-1670901347794)(ubootFEC1unset.jpg)]

4.2 设置网络参数

具体如下:

#擦除env设置
env default -a;saveenv
#开发板 IP 地址
setenv ipaddr 192.168.0.19
#开发板网卡 MAC 地址
setenv ethaddr 00:04:9f:04:d2:35
#开发板默认网关
setenv gatewayip 192.168.0.1
#开发板子网掩码
setenv netmask 255.255.255.0
#服务器地址,也就是 Ubuntu 地址
setenv serverip 192.168.0.159
#保存环境变量
saveenv

开发板的MAC地址是一个长度为48位(6个字节)的地址,每个字节间通过冒号间隔,理论上只要局域网内各网络设备不冲突,该地址可任意设置。

局域网的默认网关和子网掩码需要根据自己的实际情况设置(不知道是多少的,可以借助Windows电脑的cmd中的ipconfig指令来查看)

服务器的地址就是ubuntu虚拟机的地址(可以通过linux的ifconfig指令来查看)

5 uboot启动Linux内核测试

uboot的最终目的就是启动Linux内核,所以需要通过启动Linux内核来判断uboot移植是否成功。

启动Linux内核。我们测试两种启动Linux内核的方法:

从EMMC启动
从网络启动

「 从 E M M C 启 动 」 \color{#4285f4}{「从EMMC启动」} EMMC也就是将编译出来的 「 L i n u x 镜 像 文 件 z I m a g e 」 \color{#4285f4}{「Linux镜像文件zImage」} LinuxzImage 「 设 备 树 文 件 」 \color{#4285f4}{「设备树文件」} 保存在EMMC中,uboot从EMMC中读这两个文件并启动。由于我们板子的EMMC中可能还没有linux镜像文件和设备树文件,所以先不测试这种方法。

「 从 网 络 启 动 」 \color{#4285f4}{「从网络启动」} ,是指将linux镜像文件和根文件系统都放到Ubuntu下某个指定的文件夹中,然后通过nfs或者tftp等传输方式将系统文件(zImage和设备树文件)从Ubuntu中直接下载到开发板的内存中,EMMC中则不需要有系统文件。这种方式的作用就是方便调试,免去将代码固化到开发板的过程。当然,当开发板掉电,内存的系统文件就没了。

下面就来通过网络调试的方法来测试uboot是否能正常启动Linux内核。

5.1 tftp服务搭建

Ubuntu上搭建TFTP服务器,需要安装tftp-hpa和tftpd-hpa,命令如下:

sudo apt-get install tftp-hpa tftpd-hpa xinetd -y

TFTP也需要一个文件夹来存放文件,在用户目录下新建一个目录,示例命令如下:

mkdir /home/alientek/atk/linux/tftp
chmod 777 /home/alientek/atk/linux/tftp

最后配置 tftp, 安装完成以后,新建文件/etc/xinetd.d/tftp, 如果没有/etc/xinetd.d 目录的话自行创建,然后在里面输入如下内容:

 server tftp 
 { 
     socket_type    = dgram 
     protocol       = udp 
     wait           = yes 
     user           = root 
     server         = /usr/sbin/in.tftpd 
     server_args    = -s /home/alientek/atk/linux/tftp
     disable        = no 
     per_source     = 11 
     cps            = 100 2 
     flags          = IPv4 
 }

完了以后启动tftp服务,命令如下:

sudo service tftpd-hpa start

打开/etc/default/tftpd-hpa文件,将其修改为如下所示内容:

 # /etc/default/tftpd-hpa 

 TFTP_USERNAME="tftp"
 TFTP_DIRECTORY="/home/alientek/atk/linux/tftp"
 TFTP_ADDRESS=":69"
 TFTP_OPTIONS="-l -c -s"

TFTP_DIRECTORY就是我们上面创建的tftp文件夹目录,以后我们就将所有需要通过TFTP传输的文件都放到这个文件夹里面,并且要给予这些文件相应的权限。

最后输入如下命令, 重启 tftp 服务器:

sudo service tftpd-hpa restart

至此,tftp服务器已经搭建好了,可以先来测试一下功能是否正常。

5.2 tftp加载内核zImage

测试tftp功能是否正常,主要分为两步:

首先是 「 将 某 个 z I m a g e 镜 像 文 件 拷 贝 到 u b u n t u 虚 拟 机 的 t f t p 文 件 夹 中 」 \color{#4285f4}{「将某个zImage镜像文件拷贝到ubuntu虚拟机的tftp文件夹中」} zImageubuntutftp,并且给予 zImage 相应777的权限。

然后是 「 通 过 开 发 板 u b o o t 的 串 口 交 互 指 令 将 文 件 从 u b u n t u 传 输 到 开 发 板 的 内 存 」 \color{#4285f4}{「通过开发板uboot的串口交互指令将文件从ubuntu传输到开发板的内存」} ubootubuntu

uboot串口交互指令中的 「 t f t p 命 令 格 式 」 \color{#4285f4}{「tftp命令格式」} tftp如下:

#tftp [loadAddress] [[hostIPaddr:]bootfilename]
tftp 192.168.0.159

loadAddress是文件在DRAM中的存放地址,[[hostIPaddr:]bootfilename]是要从Ubuntu中下载的文件。

tftp传输文件,不需要输入文件在Ubuntu中的完整路径,只需要输入文件名即可。

比如我们现在 「 将 t f t p 文 件 夹 里 面 的 z I m a g e 文 件 下 载 到 开 发 板 D R A M 的 0 X 80800000 地 址 处 」 \color{#4285f4}{「将tftp文件夹里面的zImage文件下载到开发板DRAM的0X80800000地址处」} tftpzImageDRAM0X80800000,命令如下:

tftp 80800000 zImage

网络挂载

uboot配置

env default -a;saveenv
setenv ipaddr 192.168.0.100
setenv ethaddr 00:04:9f:04:d2:35
setenv gatewayip 192.168.0.1
setenv netmask 255.255.255.0
setenv serverip 192.168.0.159
saveenv

TFTP 挂载内核、设备树

setenv bootcmd 'tftp 80800000 zImage;tftp 83000000 imx6ull-alientek-emmc.dtb;bootz 80800000 - 83000000'
saveenv

NFS 挂载文件系统

setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.0.159:/home/alientek/atk/linux/nfs/rootfs,proto=tcp rw ip=192.168.0.158:192.168.0.159:192.168.0.1:255.255.255.0::eth0:off'
saveenv
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值