Linux系统镜像构建(1):uboot编译烧录与移植
1. Linux系统构成简单介绍
一个完整的linux系统,通常包含了Uboot、kernel、设备树以及根文件系统。
1.1. Uboot
U-Boot 是一个主要用于嵌入式系统的引导加载程序,可以支持多种不同的计算机系统结构,包括PPC、ARM、AVR32、MIPS、x86、68k、Nios与MicroBlaze。这也是一套在GNU通用公共许可证之下发布的自由软件。 Uboot的全称 Universal Boot Loader,是遵循GPL条款的开源项目, U-Boot的主要作用是用来启动操作系统内核,它分为两个阶段,即boot + loader, boot阶段启动系统,初始化硬件设备,建立内存空间映射图,将系统的软硬件带到一个合适的状态, loader阶段将操作系统内核文件加载至内存,之后跳转到内核所在地址运行。
另外,某些BootLoader可能含有一些高级特性,如校验操作系统镜像,从多个操作系统镜像中选择引导合适的操作系统, 或者添加网络功能,让系统自主从网上寻找合适的镜像并且进行引导等等。
1.2. Linux内核
Linux是一种开源电脑操作系统内核。它是一个用C语言写成,符合POSIX标准的类Unix操作系统。 Linux内核是一个用来和硬件打交道并为用户程序提供一个有限服务集的低级支撑软件。一个计算机系统是一个硬件和软件的共生体,它们互相依赖,不可分割。计算机的硬件,含有外围设备、处理器、内存、硬盘和其他的电子设备组成计算机的发动机。但是没有软件来操作和控制它,自身是不能工作的。完成这个控制工作的软件就称为操作系统,在Linux的术语中被称为“内核”,也可以称为“核心”。Linux内核的主要模块(或组件)分以下几个部分:进程管理子系统、内存管理子系统、文件子系统、网络子系统、设备子系统等。
1.3. 设备树
设备树是一种描述硬件的数据结构,它包含这些硬件设备的信息, 而这个文件,就是Device Tree(设备树),设备树包括设备树源码(Device Tree Source,DTS)文件、 设备树编译工具(Device Tree Compiler,DTC)与二进制格式设备树(Device Tree Blob,DTB), DTS包含的头文件格式为DTSI。
Uboot和Linux不能直接识别DTS文件, 而DTB可以被内核与BootLoader识别解析,通常在制作NAND Flash、SD Card启动镜像时, 通常会为DTB文件留下一部分存储区域以存储DTB,在BootLoader启动内核时,会先读取DTB到内存,再提供给内核使用。
1.4. 根文件系统
根文件系统(rootfs)是linux在初始化时加载的第一个文件系统, 根文件系统包括根目录和真实文件系统,它包含系统引导和使其他文件系统得以挂载(mount)所必要的文件。 根文件系统包含Linux启动时所必须的目录和关键性的文件,例如Linux启动时必要的初始化文件, 它在init目录下,此外根文件系统中还包括了许多的应用程序bin目录等, 任何包括这些Linux 系统启动所必须的文件都可以成为根文件系统。
在Linux内核启动的初始阶段,首先内核会初始化一个基于内存的文件系 统,如initramfs,initrd等,然后以只读的方式去加载根文件系统(load rootfs), 读取并且运行/sbin/init初始化文件,根据/etc/inittab配置文件完成系统的初始化工作 (提示:/sbin/init是一个二进制可执行文件,为系统的初始化程序,而/etc/inittab是它的配置文件), 在初始化的过程中,还会以读写的方式重新挂载根文件系统,在系统启动后, 根文件系统就可用于存储数据了,存在根文件系统是Linux启动时的必要条件。
我们常见的根文件系统制作工具有 buildroot、Ubuntu、Debian、yocto、busybox,这些工具的优缺点列出如下
2. Uboot的介绍
2.1. uboot简介
uboot是从FADSROM、8xxROM、PPCBOOT逐步发展演化而来的。uboot发展至今,已经可以实现非常多的功能, 在操作系统方面,它不仅支持嵌入式Linux系统的引导,还支持NetBSD,VxWorks, QNX, RTEMS, ARTOS, LynxOS, Android等嵌入式操作系统的引导。在CPU架构方面, uboot支持PowerPC、MIPS、x86、ARM、NIOS、XScale等诸多常用系列的处理器。
一般来说BootLoader必须提供系统上电时的初始化代码,在系统上电时初始化相关环境后, BootLoader需要引导完整的操作系统,然后将控制器交给操作系统。 简单来说BootLoader是一段小程序,它在系统上电时执行,通过这段小程序可以将硬件 设备进行初始化,如CPU、SDRAM、Flash、串口、网络等,初始化完毕后调用操作系统内核。
2.2. 启动uboot
以野火imx6ull 2020.10版本uboot为例,介绍uboot的使用, 在开发板上电uboot启动kernel之前按下键盘的空格或回车键, 进入uboot的命令模式。如下所示
uboot 2020.10-g4f79a1a2 (Feb 20 2021 - 11:25:18 +0800)
CPU: Freescale i.MX6ULL rev1.1 792 MHz (running at 396 MHz)
CPU: Industrial temperature grade (-40C to 105C) at 49C
Reset cause: WDOG
Model: Freescale i.MX6 UltraLiteLite 14x14 EVK Board
Board: MX6ULL 14x14 EVK
DRAM: 512 MiB
MMC: FSL_SDHC: 0, FSL_SDHC: 1
Loading Environment from MMC... OK
In: serial
Out: serial
Err: serial
Net: eth1: ethernet@20b4000 [PRIME]Could not get PHY for FEC0: addr 2
Hit any key to stop autoboot: 0
=>
可以看出uboot打印出了板子的一些基本信息,包括CPU、内存等信息。
2.3. uboot命令
当不清楚uboot支持什么命令时, 可输入 help 或 ? 可查看uboot支持的命令列表,如下所示
? - alias for 'help'
base - print or set address offset
bdinfo - print Board Info structure
blkcache - block cache diagnostics and control
bmode - sd1|sd2|qspi1|normal|usb|sata|ecspi1:0|ecspi1:1|ecspi1:2|ecspi1:3|esdhc1|esdhc2|esdhc3|esdhc4
bmode - getprisec
boot - boot default, i.e., run 'bootcmd'
bootd - boot default, i.e., run 'bootcmd'
bootefi - Boots an EFI payload from memory
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
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
dtfile - dtoverlay utility commands
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 /)
fatmkdir - create a directory
fatrm - delete a file
fatsize - determine a file's size
fatwrite - write file into a dos filesystem
fdt - flattened device tree utility commands
flinfo - print FLASH memory information
fstype - Look up a filesystem type
fstypes - List supported filesystem types
fuse - Fuse sub-system
go - start application at address 'addr'
gpio - query and control gpio pins
help - print command 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 - return true/false on integer compare
ln - Create a symbolic link
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
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)
panic - Panic with optional message
ping - send ICMP ECHO_REQUEST to network host
pinmux - show pin-controller muxing
printenv - print environment variables
protect - enable or disable FLASH write protection
random - fill memory with random pattern
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 - print local 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
version - print monitor, compiler and linker version
可看到uboot支持很多的命令,功能十分强大,与linux类似,在执行某条uboot命令时, 可使用 tab 自动补全命令,在没有命令名冲突的情况下可以使用命令的前几个字母作为命令的输入, 例如想要执行 reset 命令,输入 res 或 re 即可。
当需要具体使用哪个命令时,可使用 “help 命令” 或 “? 命令” 的方式查看具体命令的使用说明。以 “help printenv” 为例,
=> help printenv
printenv - print environment variables
Usage:
printenv [-a]
- print [all] values of all environment variables
printenv name ...
- print value of environment variable 'name'
可以看到printenv命令的说明以及使用方法。
关于uboot命令的使用可参考uboot官方链接: The U-Boot Documentation — Das U-Boot unknown version documentation 5.9. uboot Command Line Interface 部分。
2.3.1. uboot常见命令
uboot命令众多,下面介绍常用的uboot命令,详细的uboot命令使用方式请使用 help [命令] 查看。
命令 | 说明 | 举例 |
---|---|---|
help | 列出当前uboot所有支持的命令 | |
help [命令] | 查看指定命令的帮助 | help printenv |
reset | 重启uboot | |
printenv | 打印所有环境参数的值 | |
printenv [环境参数名] | 查看指定的环境参数值 | printenv bootdelay |
setenv | 设置/修改/删除环境参数的值 | setenv bootdelay 3 |
saveenv | 保存环境参数 | |
ping | 检测网络是否连通 | ping 192.168.0.1 |
md | 查看内存地址上的值 | md.b 0x80000000 10 以字节查看0x80000000后0x10个数据 |
mw | 用于修改内存地址上的值 | mw.b 0x80000000 ff 10 以字节修改0x80000000后0x10个数据为ff |
echo | 打印信息,与linux下的echo类似 | |
run | 在执行某条环境参数命令 | run bootcmd,执行bootcmd |
bootz | 在内存中引导内核启动 | |
ls | 查看文件系统中目录下的文件 | |
load | 从文件系统中加载二进制文件到内存 |
以上为用户较为常用使用的部分命令,具体的使用方式可使用 help [命令] 查看。
2.3.2. mmc命令
mmc命令能够对如sd卡以及emmc类的存储介质进行操作,以下进行简单说明, 对于mmc命令不熟悉可使用 help mmc 查看相关命令的帮助,常用功能如下所示
命令 | 说明 |
---|---|
mmc list | 查看板子上mmc设备 |
mmc dev | 查看/切换当前默认mmc设备 |
mmc info | 查看当前mmc设备信息 |
mmc part | 查看当前mmc设备分区 |
mmc read | 读取当前mmc设备数据 |
mmc write | 写入当前mmc设备数据 |
mmc erase | 擦除当前mmc设备数据 |
2.3.2.1. 查看mmc设备
使用 mmc list 查看板子上相关设备,本人使用的是emmc版本的开发板,并插入了sd卡, 可看到打印信息如下。
=> mmc list
FSL_SDHC: 0 (SD)
FSL_SDHC: 1
使用 mmc dev 查看当前使用的mmc设备,打印信息如下,可看到当前设备为mmc0即sd卡。
=> mmc dev
switch to partitions #0, OK
mmc0 is current device
提示
可使用 mmc dev 1 命令切换当前设备为emmc设备
使用 mmc info 查看当前使用的sd卡设备的信息。
=> mmc info
Device: FSL_SDHC
Manufacturer ID: 3
OEM: 5344
Name: SC16G
Bus Speed: 50000000
Mode: SD High Speed (50MHz)
Rd Block Len: 512
SD version 3.0
High Capacity: Yes
Capacity: 14.8 GiB
Bus Width: 4-bit
Erase Group Size: 512 Bytes
2.3.2.2. 查看分区信息
使用 mmc part 列出当前mmc设备分区
=> mmc part
Partition Map for MMC device 0 -- Partition Type: DOS
Part Start Sector Num Sectors UUID Type
1 8192 81920 2ba51413-01 0e Boot
2 90112 31026176 2ba51413-02 83
2.3.2.3. mmc操作
可使用以下指令对mmc存储介质以block为操作单位进行读、写、擦除操作,根据上面sd的信息可知, 一个block为512字节。
mmc read addr blk# cnt #读
mmc write addr blk# cnt #写
mmc erase blk# cnt #擦除
简单实例:将mmc设备的的前10个block读取到0x80000000地址处: mmc read 0x80000000 0 10
2.3.3. 文件系统操作命令
uboot能够对ext2/3/4以及fat文件系统设备进行访问, 可使用fstype命令判断存储介质分区使用的是什么类型的文件系统。 以mmc介质为例,判断sd的两个分区的文件系统类型
=> fstype mmc 0:1
fat
=> fstype mmc 0:2
ext4
野火linux开发板具有U盘功能,能够通过PC以访问U盘的形式访问/boot目录下的文件, /boot目录对应的即是 mmc 0:1 分区。
而ext4分区对应的则是Debian根文件系统。
知道了文件系统的类型即可使用相对应的命令对分区内容进行操作了。
2.3.3.1. FAT格式文件系统
uboot提供了能够对于FAT格式文件系统操作的各个指令, 如下所示,详细可通过 help [命令] 查看
命令 | 说明 |
---|---|
fatinfo | 打印关于文件系统的信息 |
fatls | 查看存储设备的fat分区里的内容 |
fatload | 从fat分区里读出文件到指定的内存地址 |
fatwrite | 把内存上的数据存储到fat分区的一个文件里 |
fatmkdir | 创建文件夹 |
fatrm | 删除文件 |
2.3.3.1.1. 查看文件系统信息
使用fatinfo查看文件系统信息,打印信息如下
=> fatinfo mmc 0:1
Interface: MMC
Device 0: Vendor: Man 000003 Snr 6d8b9601 Rev: 1.0 Prod: SC16G▒
Type: Removable Hard Disk
Capacity: 15193.5 MB = 14.8 GB (31116288 x 512)
Filesystem: FAT16 "BOOT "
2.3.3.1.2. 查看分区下的文件目录
使用fatls查看分区下的文件目录,打印信息如下
=> fatls mmc 0:1
38 ID.txt
kernel/
2418 uEnv.txt
577 SOC.sh
boot/
34 autorun.inf
System Volume Information/
dtbs/
1472 BOOTEX.LOG
5 file(s), 4 dir(s)
若想要查看其它目录下的文件列表,只要加上文件路径即可,如下
=> fatls mmc 0:1 kernel/
./
../
9187912 vmlinuz-4.19.35-imx6
143341 config-4.19.35-imx6
3104898 System.map-4.19.35-imx6
5160838 initrd.img-4.19.35-imx6
4 file(s), 2 dir(s)
2.3.3.1.3. 读取文件内容
使用fatload将FAT文件系统的文件加载到内存中,如下所示
=> fatload mmc 0:1 0x80000000 uEnv.txt
2418 bytes read in 13 ms (181.6 KiB/s)
可使用md命令查看0x80000000内存中的部分数据内容
=> md.b 0x80000000 0x80
80000000: 23 44 6f 63 73 3a 20 68 74 74 70 73 3a 2f 2f 65 #Docs: https://e
80000010: 6d 62 65 64 2d 6c 69 6e 75 78 2d 74 75 74 6f 72 mbed-linux-tutor
80000020: 69 61 6c 2e 72 65 61 64 74 68 65 64 6f 63 73 2e ial.readthedocs.
80000030: 69 6f 2f 7a 68 5f 43 4e 2f 6c 61 74 65 73 74 2f io/zh_CN/latest/
80000040: 52 45 41 44 4d 45 2e 68 74 6d 6c 0a 0a 75 6e 61 README.html..una
80000050: 6d 65 5f 72 3d 34 2e 31 39 2e 33 35 2d 69 6d 78 me_r=4.19.35-imx
80000060: 36 0a 23 75 75 69 64 3d 0a 6d 6d 63 5f 64 74 62 6.#uuid=.mmc_dtb
80000070: 3d 69 6d 78 36 75 6c 6c 2d 6d 6d 63 2d 6e 70 69 =imx6ull-mmc-npi
读取到的内容就是我们日常在/boot/uEnv.txt文件中的看到的内容了。
2.3.3.1.4. FAT文件系统其他操作
uboot还提供了FAT文件系统的其他操作命令,可用于创建目录、写入、删除等操作, 通常情况下在uboot中需要使用这类命令的场景很少,简单介绍如下:
-
fatmkdir:创建目录
-
fatrm:删除文件
-
fatwrite:把内存上的数据存储到FAT分区的一个文件里
2.3.3.2. ext4格式文件系统
ext4文件系统的命令使用方式和FAT使用方式相似,仅命令名不同, uboot提供的ext文件系统命令如下
命令 | 说明 |
---|---|
ext4ls | 查看存储设备的ext4分区里的内容 |
ext4load | 从ext4分区里读出文件到指定的内存地址 |
ext4write | 把内存上的数据存储到ext4分区的一个文件里 |
2.3.3.2.1. ext4文件系统操作
下面以将/etc/apt/sources.list的内容读取到内存实例,简单说明uboot对ext4文件系统操作。
1.查看/etc/apt目录中的文件内容,
=> ext4ls mmc 0:2 /etc/apt/
<DIR> 1024 .
<DIR> 5120 ..
<DIR> 3072 trusted.gpg.d
865 sources.list
2175 trusted.gpg
<DIR> 1024 auth.conf.d
<DIR> 1024 apt.conf.d
<DIR> 1024 sources.list.d
<DIR> 1024 preferences.d
382 trusted.gpg~
2.将/etc/apt/sources.list 文件读取到内存地址0x8000 0000处
=> ext4load mmc 0:2 0x80000000 /etc/apt/sources.list
865 bytes read in 30 ms (27.3 KiB/s)
3.查看内存0x8000 0000的部分数据内存
=> md.b 0x80000000 0x80
80000000: 64 65 62 20 68 74 74 70 3a 2f 2f 6d 69 72 72 6f deb http://mirro
80000010: 72 73 2e 74 75 6e 61 2e 74 73 69 6e 67 68 75 61 rs.tuna.tsinghua
80000020: 2e 65 64 75 2e 63 6e 2f 64 65 62 69 61 6e 20 62 .edu.cn/debian b
80000030: 75 73 74 65 72 20 6d 61 69 6e 20 63 6f 6e 74 72 uster main contr
80000040: 69 62 20 6e 6f 6e 2d 66 72 65 65 0a 23 64 65 62 ib non-free.#deb
80000050: 2d 73 72 63 20 68 74 74 70 3a 2f 2f 6d 69 72 72 -src http://mirr
80000060: 6f 72 73 2e 74 75 6e 61 2e 74 73 69 6e 67 68 75 ors.tuna.tsinghu
80000070: 61 2e 65 64 75 2e 63 6e 2f 64 65 62 69 61 6e 20 a.edu.cn/debian
2.4. uboot启动内核过程
bootcmd与bootargs可以说是uboot最重要的两个环境参数, uboot执行完毕之后,如果没有按下回车,则会自动执行bootcmd命环境参数里的内容, 而bootargs则是传递给内核的启动参数。
使用 printenv bootcmd 可查看bootcmd的内容。
1 2 | => printenv bootcmd bootcmd=run distro_bootcmd |
bootcmd执行了distro_bootcmd,同样可以使用 printenv distro_bootcmd 查看distro_bootcmd的内容如下
1 2 3 4 5 | => printenv distro_bootcmd distro_bootcmd=for target in ${boot_targets}; do run bootcmd_${target}; done #boot_targets的值如下 boot_targets=mmc0 mmc1 |
也就是说distro_bootcmd会执行 bootcmd_mmc0、bootcmd_mmc1 这两个环境参数, 在前面我们知道,mmc0表示的sd卡的存储设备,mmc1表示的emmc设备, 也就是说当sd卡插在板子时,若sd卡装有系统则会优先从sd卡内启动。
1 2 3 4 | => printenv bootcmd_mmc0 bootcmd_mmc0=setenv devtype mmc; setenv mmcdev 0; setenv bootpart 0:1 ; setenv rootfpart 0:2 ; run boot => printenv bootcmd_mmc1 bootcmd_mmc1=setenv devtype mmc; setenv mmcdev 1; setenv bootpart 1:1 ; setenv rootfpart 1:2 ; run boot |
bootcmd_mmc0与bootcmd_mmc1均设置各自 devtype、mmcdev、bootpart、rootfpart 环境参数的值, 最后运行 boot 环境参数,boot内容如下
"boot=mmc check;${devtype} dev ${mmcdev};mmc rescan; " \
"echo loading [${devtype} ${bootpart}] /uEnv.txt ...; "\
"if run loaduEnv; then " \
"run importbootenv;" \
"if test ${second_flash} = emmc; then " \
"setenv dtb ${mmc_dtb};" \
"setenv storage_media init=/opt/scripts/tools/eMMC/init-eMMC-flasher-v3.sh;" \
"else " \
"setenv dtb ${nand_dtb};" \
"setenv storage_media init=/opt/scripts/tools/Nand/init-Nand-flasher-v1.sh;" \
"fi; " \
"if test -n ${flash_firmware}; then " \
"echo setting flash firmware...;" \
"setenv flashtype ${storage_media};" \
"fi;" \
"run args_mmc_old;" \
"echo loading vmlinuz-${uname_r} ...; "\
"load ${devtype} ${bootpart} 0x80800000 /kernel/vmlinuz-${uname_r};"\
"echo loading ${dtb} ...; "\
"load ${devtype} ${rootfpart} 0x83000000 /usr/lib/linux-image-${uname_r}/${dtb};"\
"dtfile 0x83000000 0x87000000 /uEnv.txt ${loadaddr};" \
"load ${devtype} ${bootpart} 0x88000000 /kernel/initrd.img-${uname_r};"\
"echo debug: [${bootargs}] ... ;" \
"echo debug: [bootz] ... ;" \
"bootz 0x80800000 0x88000000:${filesize} 0x83000000;" \
"fi;\0" \
提示:若从uboot中直接使用printenv查看boot的内容会显得格式很乱,推荐在uboot源码 include/configs/mx6ullfire.h 中查看。
-
第3行,运行loading,loading的内容是将uEnv.txt文件的内容读取到内存中, 如下所示
1 2
#其中loadaddr的值为0x8200 0000 loaduEnv=load ${devtype} ${bootpart} ${loadaddr} /uEnv.txt;
-
第4行,运行importbootenv,从内存地址中导入环境参数。
1 2
"importbootenv=echo Importing environment from ${devtype} ...; " \ "env import -t ${loadaddr} ${filesize}\0" \
-
第5-11行,判断启动介质类型,设置 dtb、storage、init 环境参数。
-
第12-15行,判断是否需要使用利用现有镜像烧录固件到其他介质。
-
第16行,args_mmc_old 的作用主要用于设置 bootargs 环境参数。如下所示
1 2 3 4
"args_mmc_old=setenv bootargs console=ttymxc0 " \ "root=/dev/mmcblk${mmcdev}p2 rw " \ "rootfstype=ext4 " \ "rootwait ${cmdline} ${flashtype}\0" \
-
第18行,将kernel内核加载到内存地址0x8080 0000处。
-
第20行,将主设备树加载到内存地址 0x8300 0000处。
-
第21行,将设备树插件的内容解析合成到主设备树上,dtfile命令并不是原来uboot就有的, 为了方便用户使用/boot/uEnv.txt文件使用设备树插件而添加的,有兴趣的读者可自行查看相关源码。
-
第22行,将虚拟文件系统加载到0x8800 0000中。
-
第25行,启动linux内核。
2.5. uboot环境参数介绍
uboot中环境参数为我们提供一种不修改uboot源码的情况下, 能够修改kernel启动倒计时、ip地址、以及向内核传递不同的参数等。
在板子上使用 printenv 可查看板子上所有的环境参数, 使用 setenv 添加/修改/删除环境参数,具体说明如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #设置新的环境参数名为abc,值为100 => setenv abc 100 => echo $abc = 100 #将值修改为200 => setenv abc 200 => echo $abc 200 #删除abc环境参数 => setenv abc => echo $abc => |
默认情况下使用setenv命令修改环境参数重启后就会消失, 若想要掉电保存需要执行 saveenv 将环境参数保存到存储介质。
uboot上有一些官方规定的环境变量,这些环境变量在uboot有着特殊的作用, 可通过以下链接查看: https://www.denx.de/wiki/view/DULG/UBootEnvVariables
3. Uboot的编译
3.1. 下载安装编译镜像系统
使用平台:Ubuntu 18.04.5 LTS 版本
ubuntu 18.04.5 LTS官方镜像搭建
https://mirrors.aliyun.com/ubuntu-releases/bionic/ubuntu-18.04.5-desktop-amd64.isoIndex of /releases/18.04.5https://mirrors.aliyun.com/ubuntu-releases/bionic/ubuntu-18.04.5-desktop-amd64.iso
3.2. 安装编译工具和依赖
使用apt工具能快速安装好我们需要的工具和依赖
sudo apt install make git gcc-arm-none-eabi gcc bison flex libssl-dev dpkg-dev lzop libncurses5-dev
3.3. 获取uboot
3.3.1. 下载源代码
uboot的源代码有多种方式可下载,但各自又有不同,野火uboot是根据NXP官方提供的uboot进行板卡的修改与功能的添加,NXP官方的uboot是以uboot官方版本进行芯片的适配。
官方uboot GitHub:
https://github.com/u-boot/u-boot
NXP提供的uboot下载链接:
https://github.com/Freescale/u-boot-fslc
野火提供的uboot下载链接:
ebf_linux_uboot: 野火所有Linux系列产品使用的uboot源码仓库
或者
https://github.com/Embedfire/ebf_linux_uboot
注意:本教程以野火提供的uboot为分析样本
3.3.2. 查看切换分支
通常一个uboot仓库往往维护着不同分支的uboot,进入仓库目录下可通过命令查看及切换uboot分支, 例如在2021-04-08的镜像中使用的uboot分支为 ebf_v2020_10_imx 。
git clone https://gitee.com/Embedfire/ebf_linux_uboot.git
#查看uboot分支
git branch -a
#打印消息如下,默认为master主分支。
* master
remotes/origin/HEAD -> origin/master
remotes/origin/ebf_v2017_09_rk3328
remotes/origin/ebf_v2018.11_star
remotes/origin/ebf_v2020_10_imx
remotes/origin/imx_v2019.04_ls1043ardb
remotes/origin/imx_v2020.04_5.4.47_2.2.0
remotes/origin/master
#切换ebf_v2020_10_imx分支
git checkout ebf_v2020_10_imx
#打印消息如下
分支 'ebf_v2020_10_imx' 设置为跟踪来自 'origin' 的远程分支 'ebf_v2020_10_imx'。
切换到一个新分支 'ebf_v2020_10_imx'
#重新查看当前分支
git branch
* ebf_v2020_10_imx
master
也可以在下载时指定分支,如下所示
#使用-b参数指定ebf_v2020_10_imx分支
git clone -b ebf_v2020_10_imx https://gitee.com/Embedfire/ebf_linux_uboot
#或者
git clone -b ebf_v2020_10_imx https://github.com/Embedfire/ebf_linux_uboot
如需下载NXP的uboot可以使用如下命令
#获取默认的分支,再切换为需要的分支
git clone https://github.com/Freescale/u-boot-fslc.git
#或者-b参数指定需要的分支
git clone -b 2020.10+fslc https://github.com/Freescale/u-boot-fslc.git
3.4. uboot工程结构分析
学习一个软件,尤其是开源软件,首先应该从分析软件的工程结构开始。一个好的软件有良好的工程结构,对于读者学习和理解软件的架构以及工作流程都有很好的帮助。
uboot的源代码布局和我们后面讲的Linux类似,使用了按照模块划分的结构,并且充分考虑了体系结构和跨平台问题,其源代码树结构请参考下图
uboot目录 目录/文件
说明
目录/文件
说明
api
通用的API函数相关目录
arch
与芯片架构相关目录
board
板级相关信息目录
cmd
uboot命令相关目录
common
通用代码目录
configs
boot配置文件目录
disk
磁盘相关内容目录
doc
说明文档
drivers
驱动代码相关目录
dtoverlay
dts
设备树相关目录
env
uboot环境相关
examples
示例代码目录
fs
文件系统相关目录
include
头文件相关目录
lib
lib库文件目录
Licenses
许可证相关目录
net
网络相关代码目录
post
上电自检相关目录
scripts
相关脚本目录
test
测试代码目录
tools
uboot构建工具相关目录
Kconfig
图形配置界面相关文件
Makefile
Makefile文件
3.5. uboot编译
野火提供的imx6ull uboot分为nand版本和emmc版本,以编译emmc版本为例
提示
若想编译nand版本的uboot需要将 mx6ull_fire_mmc_defconfig 改为 mx6ull_fire_nand_defconfig
sudo make distclean
#编译emmc版本uboot
sudo make ARCH=arm CROSS_COMPILE=arm-none-eabi- mx6ull_fire_mmc_defconfig
#编译uboot
sudo make ARCH=arm CROSS_COMPILE=arm-none-eabi-
-
sudo make distclean 清除上次生成的编译环境,避免之前的环境干扰影响编译结果
-
sudo make ARCH=arm CROSS_COMPILE=arm-none-eabi- mx6ull_fire_mmc_defconfig 加载板级配置文件,具体的板级配置文件在uboot根目录下的configs目录下
-
sudo make ARCH=arm CROSS_COMPILE=arm-none-eabi- 设置编译架构为arm 编译工具链为arm-none-eabi- 然后开始编译
3.6. 编译产物分析
编译成功后,将打印以下信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 LD u-boot OBJCOPY u-boot-nodtb.bin OBJCOPY u-boot.srec SYM u-boot.sym DTC arch/arm/dts/imx6ull-14x14-evk.dtb DTC arch/arm/dts/imx6ull-fire-mmc.dtb DTC arch/arm/dts/imx6ull-fire-nand.dtb DTC arch/arm/dts/imx6ull-colibri.dtb DTC arch/arm/dts/imx6ull-myir-mys-6ulx-eval.dtb DTC arch/arm/dts/imx6ull-phytec-segin-ff-rdk-emmc.dtb DTC arch/arm/dts/imx6ull-dart-6ul.dtb DTC arch/arm/dts/imx6ull-somlabs-visionsom.dtb DTC arch/arm/dts/imx6ulz-14x14-evk.dtb DTC arch/arm/dts/imx6-apalis.dtb DTC arch/arm/dts/imx6-colibri.dtb SHIPPED dts/dt.dtb FDTGREP dts/dt-spl.dtb CAT u-boot-dtb.bin COPY u-boot.dtb COPY u-boot.bin CFGS u-boot-dtb.cfgout MKIMAGE u-boot-dtb.imx
-
u-boot:初步链接后得到的uboot文件
-
u-boot-nodtb.bin:是在u-boot的基础上,经过objcopy去除符号表信息之后的可执行程序,具体代码如下
arm-none-eabi-objcopy --gap-fill=0xff
-j .text -j .secure_text
-j .secure_data -j .rodata
-j .hash -j .data
-j .got -j .got.plt
-j .u_boot_list -j .rel.dyn
-j .binman_sym_table -j .text_rest
-j .dtb.init.rodata -j .efi_runtime
-j .efi_runtime_rel
-O binary u-boot u-boot-nodtb.bin
-
u-boot.dtb:uboot的设备树,是由arm-none-eabi-gcc和dtc编译出来的,详细的可以分析编译过程,这里就不展开分析了
-
u-boot.bin:是在u-boot-nodtb.bin后追加了u-boot.dtb形成的
-
u-boot-dtb.imx:是u-boot.bin 添加了3KB头部信息和尾部信息(结尾添加了1298字节的00,00实际没什么作用)组成的镜像
编译生成的u-boot-dtb.imx文件就是我们想要文件。
3.7. 参考资料
官方uboot下载链接: http://www.denx.de/wiki/uboot/WebHome
官方uboot GitHub: https://github.com/u-boot/u-boot
NXP提供的uboot下载链接: https://github.com/Freescale/u-boot-fslc
uboot wiki: http://www.denx.de/wiki/uboot/WebHome
4. Uboot的烧录
4.1. Mfgtool烧写Uboot到内部存储(EMMC/NAND通用)
4.1.1. 简介
MFGTool工具是NXP官方推荐的一个使用USB OTG来升级镜像的软件工具,它是NXP针对i.MX系列处理器专门使用的烧录工具,可以用来升级linux,单独烧录某一系统分区,独立 地烧录spi flash、 nor flash、sd card、nand flash,emmc等,只需简单的配置,就可以使用该工具将编译好 的文件系统和镜像文件烧录到开发板上,使用起来非常方便。而 且MFGtool工具作为一个可量产性的工具,它支持多通道的烧录,在实 际量产中,可以直接使用MFGtool工具同时将文件系统与镜像文件烧录 到多个开发板上。
4.1.2. MFGtool工具的工作原理
简单来说MFGtool工具的烧录步骤分为两个阶段:BurnStarp和Updater。第一阶段是 烧录前的准备工作,配置设备USB的vid和pid,来选择烧录的设备。第二阶段是MFGtools开 始烧录到结束烧录的过程,这个阶段的烧录过程是严格根据ucl2.xml文件来处理的,实际上是将bootloader加载到ram,然后在运行时将编译好的文件系统和镜像文件烧录到开发板上,烧录的 位置由用户指定,可以是sd card、nand flash,emmc等。
4.1.3. 环境搭建
4.1.3.1.NFS网络系统的搭建
先更新一下apt包 sudo apt update
sudo apt update
安装 NFS服务器端 sudo apt install nfs-kernel-server
sudo apt install nfs-kernel-server
创建NFS共享目录 mkdir /home/lhf && mkidr /home/lhf/nfs
mkdir /home/lhf && mkidr /home/lhf/nfs
编辑指定目录 sudo vim /etc/exports
sudo vim /etc/exports
添加入下代码 /home/lhf/nfs *(rw,sync,no_root_squash)
/home/lhf/nfs *(rw,sync,no_root_squash)
给目录添加权限 sudo chmod -R 777 /home/lhf/nfs && sudo chown root:root /home/lhf/nfs/ -R
sudo chmod -R 777 /home/lhf/nfs && sudo chown root:root /home/lhf/nfs/ -R
启动 NFS 服务 /etc/init.d/nfs-kernel-server restart
/etc/init.d/nfs-kernel-server restart
如图就是搭建成功了
4.1.3.2.TFTP网络系统的搭建
先更新一下apt包
sudo apt update
安装 NFS服务器端
sudo apt install xinetd tftp tftpd -y
创建TFTP共享目录,我这里使用和NFS共同的目录,你们也可以选择自己熟悉的目录
mkdir /home/lhf && mkidr /home/lhf/nfs
sudo chmod -R 777 /home/lhf/nfs
编辑指定目录
sudo vim /etc/xinetd.d/tftp
添加入下代码
service tftp
{
socket_type = dgram
protocol = udp
wait = yes
user = root
server = /usr/sbin/in.tftpd
server_args = /home/lhf/nfs
disable = no
per_source = 11
cps = 100 2
flags = IPv4
}
重启服务
sudo /etc/init.d/xinetd restart
4.1.3.3.SD卡烧写的搭建
-
准备Micro SD卡,推荐使用闪迪class 10的SD卡,容量2GB以上就完全足够。
-
准备读卡器,用于在电脑上读写SD卡。
-
电脑环境,Windows和Ubuntu系统均可。
-
下载Etcher软件,用于烧录镜像至SD卡,下载地址:https://www.balena.io/etcher , 根据自己的电脑系统下载对应版本即可。
-
下载一个其中一个镜像文件即可或者使用你们构建的镜像文件
4.1.3.4.USB方式烧写的搭建(mfgtool)
只要下载一个其中一个mfgtool压缩包即可
百度云链接:百度网盘 请输入提取码 提取码:uge1
我这里使用的是ebf_debian_2021_08_20 只需下载 Debian镜像/ebf_debian_2021_08_20/USB烧录镜像/mfgtool-releases.7z 即可
4.1.4. 替换uboot文件
将编译出的uboot-dtb.imx 更名
-
emmc 版本的重命名为 u-boot-mmc.imx
-
nand 版本的重命名为 u-boot-nand.imx
然后进入到mfgtool目录中的 mfgtools-release\Profiles\Linux\OS Firmware\release 目录将相应文件替换即可
4.1.5. 修改ucl2.xml文件
将mfgtools-release\Profiles\Linux\OS Firmware目录下的ucl2.xml替换为如下内容
<UCL>
<CFG>
<STATE name="BootStrap" dev="MX6ULL" vid="15A2" pid="0080"/>
<STATE name="Updater" dev="MSC" vid="066F" pid="37FF"/>
</CFG>
<LIST name="eMMC" desc="Choose eMMC as media">
<CMD state="BootStrap" type="boot" body="BootStrap" file ="firmware/u-boot-imx6ul%lite%%6uluboot%_emmc.imx" ifdev="MX6ULL">Loading U-boot</CMD>
<CMD state="BootStrap" type="load" file="firmware/zImage" address="0x80800000"
loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6SL MX6SX MX7D MX6UL MX6ULL">Loading Kernel.</CMD>
<CMD state="BootStrap" type="load" file="firmware/%initramfs%" address="0x83800000"
loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6SL MX6SX MX7D MX6UL MX6ULL">Loading Initramfs.</CMD>
<CMD state="BootStrap" type="load" file="firmware/zImage-imx6ul%lite%-%6uldtb%-emmc.dtb" address="0x83000000"
loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6ULL">Loading device tree.</CMD>
<CMD state="BootStrap" type="jump" > Jumping to OS image. </CMD>
<!-- create partition -->
<CMD state="Updater" type="push" body="send" file="mksdcard.sh.tar">Sending partition shell</CMD>
<CMD state="Updater" type="push" body="$ tar xf $FILE "> Partitioning...</CMD>
<CMD state="Updater" type="push" body="$ sh mksdcard.sh /dev/mmcblk%mmc%"> Partitioning...</CMD>
<!-- 烧录uboot 选择uboot的路径-->
<CMD state="Updater" type="push" body="$ dd if=/dev/zero of=/dev/mmcblk%mmc% bs=1k seek=768 conv=fsync count=8">clear u-boot arg</CMD>
<!-- access boot partition -->
<CMD state="Updater" type="push" body="$ echo 0 > /sys/block/mmcblk%mmc%boot0/force_ro">access boot partition 1</CMD>
<CMD state="Updater" type="push" body="send" file="%files_dir%/%my_uboot%" ifdev="MX6ULL">Sending u-boot.bin</CMD>
<CMD state="Updater" type="push" body="$ dd if=$FILE of=/dev/mmcblk%mmc%boot0 bs=512 seek=2">write U-Boot to sd card</CMD>
<CMD state="Updater" type="push" body="$ echo Update Complete!">Uboot Finishing</CMD>
</LIST>
<LIST name="NAND Flash" desc="Choose NAND as media">
<CMD state="BootStrap" type="boot" body="BootStrap" file ="firmware/u-boot.imx" ifdev="MX6ULL">Loading U-boot</CMD>
<CMD state="BootStrap" type="load" file="firmware/zImage" address="0x80800000"
loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6SL MX6SX MX7D MX6UL MX6ULL">Loading Kernel.</CMD>
<CMD state="BootStrap" type="load" file="firmware/%initramfs%" address="0x83800000"
loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6SL MX6SX MX7D MX6UL MX6ULL">Loading Initramfs.</CMD>
<CMD state="BootStrap" type="load" file="firmware/imx6ull-seeed-npi.dtb" address="0x83000000"
loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6ULL">Loading device tree.</CMD>
<CMD state="BootStrap" type="jump" > Jumping to OS image. </CMD>
<!--burn the uboot to NAND: -->
<CMD state="Updater" type="push" body="$ mount -t debugfs debugfs /sys/kernel/debug">Mounting debugfs</CMD>
<CMD state="Updater" type="push" body="$ flash_erase /dev/mtd%part_uboot% 0 0">Erasing Boot partition</CMD>
<CMD state="Updater" type="push" body="send" file="%files_dir%/%my_uboot%" ifdev="MX6ULL">Sending u-boot.bin</CMD>
<CMD state="Updater" type="push" body="$ kobs-ng init -x -v --chip_0_device_path=/dev/mtd%part_uboot% $FILE">Flashing Bootloader</CMD>
<CMD state="Updater" type="push" body="$ echo Update Complete!">Uboot Finishing</CMD>
</LIST>
</UCL>
4.1.6. 烧录
4.1.6.1. 烧录配置
解压后的“cfg.ini”文件默认为EMMC的烧写配置文件, 若想要烧写NAND版本镜像,将cfg.ini重命名为cfg-emmc.ini,并将cfg-nand.ini文件重命名为cfg.ini即可。
4.1.6.2. 设置为USB启动模式
将USB OTG与电脑连接
使用USB更新时不能插入SD卡,将拨码开关设置为USB启动。 配置拨码开关:
emmc版本:将1/4/5/7打到ON档,其他拨码开关打到OFF档。
nand版本:将1/3/6打到ON档,其他拨码开关打到OFF档。
提示
也可以选择通过按键方式进入烧录模式,按键法可以不用拨码,拨码状态在之前的 EMMC 或者 NAND 都可以。
上电
按下MODE按键
按下复位(RESET)按键
松开复位(RESET)按键
松开MODE按键
此时软件就可以识别到USB了,然后烧录完毕后重启即可。
4.2. Uboot烧写到SD卡镜像(常用于做uboot测试)
4.2.1. 环境搭建
准备好一个ubuntu操作系统。
4.2.2. 使用dd命令将uboot烧写到SD中
将u-boot-dtb.imx拷贝到ubuntu内。
编译emmc版本和nand版本默认输出都是u-boot-dtb.imx,无需更改。
重要
如果Ubuntu是虚拟机的话,需要确定挂载到虚拟机的的SD卡在/dev/sd中的哪个,一般为sdb,如果烧错设备可能导致虚拟机损坏,无法启动。
将以上的编译得到的mmc版本uboot烧录到SD卡中。uboot烧录sd卡会破坏原有数据,请做好sd卡数据备份后再执行以下步骤。
-
将sd卡通过读卡器连接到ubuntu前,使用lsblk命令查看当前磁盘设备。
lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT loop0 7:0 0 91M 1 loop /snap/core/6350 loop1 7:1 0 2.3M 1 loop /snap/gnome-calculator/260 loop2 7:2 0 13M 1 loop /snap/gnome-characters/139 loop3 7:3 0 140.7M 1 loop /snap/gnome-3-26-1604/74 loop4 7:4 0 3.7M 1 loop /snap/gnome-system-monitor/57 loop5 7:5 0 34.6M 1 loop /snap/gtk-common-themes/818 loop6 7:6 0 14.5M 1 loop /snap/gnome-logs/45 sda 8:0 0 100G 0 disk └─sda1 8:1 0 100G 0 part / sr0 11:0 1 58.3M 0 rom /media/embedfire/VBox_GAs_6.1.18
-
将sd卡通过读卡器连接到电脑上,并选择连接到ubuntu上。
-
再次使用lsblk命令插件磁盘设备,如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13
embedfire@embedfire-VirtualBox:~$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT loop0 7:0 0 91M 1 loop /snap/core/6350 loop1 7:1 0 2.3M 1 loop /snap/gnome-calculator/260 loop2 7:2 0 13M 1 loop /snap/gnome-characters/139 loop3 7:3 0 140.7M 1 loop /snap/gnome-3-26-1604/74 loop4 7:4 0 3.7M 1 loop /snap/gnome-system-monitor/57 loop5 7:5 0 34.6M 1 loop /snap/gtk-common-themes/818 loop6 7:6 0 14.5M 1 loop /snap/gnome-logs/45 sda 8:0 0 100G 0 disk └─sda1 8:1 0 100G 0 part / sdb 8:16 1 14.9G 0 disk sr0 11:0 1 58.3M 0 rom /media/embedfire/VBox_GAs_6.1.18
可看到新增加了sdb设备,此处请务必检查好sd卡所对应的磁盘设备,以免破坏其他磁盘的数据!
-
执行以下烧录命令,将u-boot-dtb.imx烧写到/dev/sdb中
示例命令
1
sudo dd iflag=dsync oflag=dsync if=u-boot-dtb.imx of=/dev/sdb seek=2
烧录成功提示如下信息。
1 2 3 4 5 6
embedfire@embedfire-VirtualBox:~$ sudo dd iflag=dsync oflag=dsync if=u-boot-dtb.imx of=/dev/sdb seek=2 [sudo] embedfire 的密码: 记录了782+0 的读入 记录了782+0 的写出 400384 bytes (400 kB, 391 KiB) copied, 15.0757 s, 26.6 kB/s embedfire@embedfire-VirtualBox:~$
-
将sd卡插到开发板上将拨码开关设置sd卡启动打开电源即可启动uboot。
5. Uboot的移植
该教程仅用于学习与参考,实际产品建议使用NXP官方或者我们提供的uboot源码
NXP提供的uboot下载链接:
https://github.com/Freescale/u-boot-fslc
野火提供的uboot下载链接:
ebf_linux_uboot: 野火所有Linux系列产品使用的uboot源码仓库
5.1. uboot介绍
Linux 系统要启动就必须需要一个 bootloader 程序,也就说芯片上电以后先运行一段bootloader程序。这段bootloader程序会先初始化DDR等外设,然后将Linux内核从flash(NAND,NOR FLASH, SD, MMC 等)拷贝到 DDR 中,最后启动 Linux 内核。当然了, bootloader 的实际工作要复杂的多,但是它最主要的工作就是启动 Linux 内核, bootloader 和 Linux 内核的关系就跟 PC 上的 BIOS 和 Windows 的关系一样, bootloader 就相当于 BIOS。所以我们要先搞定bootloader,不过,有很多现成的 bootloader 软件可以使用,比如 U-Boot、 vivi、 RedBoot 等等,其中以 U-Boot 使用最为广泛。
uboot 的全称是 Universal Boot Loader, uboot 是一个遵循 GPL 协议的开源软件, uboot 是一个裸机代码,可以看作是一个裸机综合例程。现在的 uboot 已经支持液晶屏、网络、 USB 等高级功能。 uboot 官网为 http://www.denx.de/wiki/U-Boot/
5.2. 下载安装编译镜像系统
使用平台:Ubuntu 18.04.5 LTS 版本
可以使用我们提供的虚拟机镜像 野火i.MX6ULL Linux开发板 — 野火产品资料下载中心 文档
也可以自己下载ubuntu 18.04.5 LTS官方镜像搭建
https://mirrors.aliyun.com/ubuntu-releases/bionic/ubuntu-18.04.5-desktop-amd64.iso
5.3. 安装编译工具和依赖
使用apt工具能快速安装好我们需要的工具和依赖
sudo apt install make git gcc-arm-none-eabi gcc bison flex libssl-dev dpkg-dev lzop libncurses5-dev
5.4. 获取uboot
5.4.1. 下载源代码
我们直接从uboot官方下载好最新的源码进行适配,将我们使用的旧版本uboot移植到新版本。
Index of /pub/u-boot/ 或 ftp://ftp.denx.de/pub/u-boot/
截止至写本教程的时间最新版本为 u-boot-2021.10-rc4.tar.bz2
建议第一次移植使用和我一样的版本,后续再移植到自己需要的版本
下载u-boot-2021.10版本的源码 u-boot-2021.10-rc4.tar.bz2
解压源码
tar -xjvf u-boot-2021.10-rc4.tar.bz2
获取“旧版本”的uboot,此处使用野火ebf_v2020_10_imx分支的uboot。
git clone -b ebf_v2020_10_imx https://gitee.com/Embedfire/ebf_linux_uboot
#或者
git clone -b ebf_v2020_10_imx https://github.com/Embedfire/ebf_linux_uboot
5.5. 移植
一般人移植主要是想获取新版本的uboot,对于底层的官方适配我们不需要详细了解
提示
后续讲到的文件中可能已经添加了需要添加的内容,但仍作说明,旨在方便大家后续移植自己需要的uboot。
5.5.1. 头文件
从旧版本uboot的include/configs复制一份相应头文件到新版本include/configs目录下
cp ebf_linux_uboot/include/configs/mx6ullfire.h u-boot-2021.10-rc4/include/configs/
-
mx6ullfire.h 头文件里包含了uboot的环境参数和一些配置信息。
5.5.2. 配置文件
emmc版本的配置文件为 mx6ull_fire_mmc_defconfig
nand版本的配置文件为 mx6ull_fire_nand_defconfig
将以上两版本的配置文件都复制到新版本uboot。
cp ebf_linux_uboot/configs/mx6ull_fire_* u-boot-2021.10-rc4/configs/
这里有几个参数要注意一下
-
CONFIG_TARGET_MX6ULL_FIRE=y 这行参数与两处有相对应,下面会讲到,这里留意一下。
-
CONFIG_DEFAULT_DEVICE_TREE=”imx6ull-fire-mmc” 这行参数是设备树名称,要与uboot设备树对应,等会讲设备树复制的时候会讲到,也留意一下。
-
CONFIG_SYS_EXTRA_OPTIONS=”IMX_CONFIG=board/freescale/mx6ullfire/imximage.cfg” 这行参数是配置头部信息的,指向的是板子目录的cfg文件。
5.5.3. 单板目录和文件
cp -rf ebf_linux_uboot/board/freescale/mx6ullfire/ u-boot-2021.10-rc4/board/freescale/
单板目录mx6ullfire的结构
./mx6ullfire
├── imximage.cfg
├── Kconfig
├── MAINTAINERS
├── Makefile
├── mx6ullfire.c
└── plugin.S
-
mx6ullfire.c :里写了一些uboot启动代码和我们对板子引脚读取的代码。
-
plugin.S :用汇编写的设置ddr和时钟,一般不需要更改。
-
Makefile :里面修改C文件编译后的o文件,有多少个就写多少个o文件,注意与c文件名字相同。
-
Kconfig :U-Boot配置选项文件,定义了编译时需要配置哪些选项用于生成适用于该开发板的U-Boot程序。
以上Kconfig文件中指定mx6ullfire板卡的代码片段
if TARGET_MX6ULL_FIRE (上面所说的两处对应其中的一处)
config SYS_BOARD
default "mx6ullfire" (目标文件夹)
config SYS_VENDOR
default "freescale" (路径)
config SYS_CONFIG_NAME
default "mx6ullfire" (头文件名称 注意:头文件在include/configs下名称为"头文件名称.h")
endif
-
imximage.cfg :NXP特有的文件,默认已添加头部信息。
在imximage.cfg添加的头部信息
PLUGIN board/freescale/mx6ullfire/plugin.bin 0x00907000
以上命令是U-Boot启动时加载插件的命令。其中board/freescale/mx6ullfire/plugin.bin 是插件的二进制文件路径,0x00907000 是插件的加载地址。可以用于扩展U-Boot功能。
5.5.4. 添加Kconfig信息
修改文件目录为:arch/arm/mach-imx/mx6/Kconfig
在这个文件中添加我们的板子信息方便Makefile识别编译。
5.5.4.1. 添加板卡支持
在上述Kconfig文件中的config TARGET_MX6ULL_14X14_EVK配置的下面添加如下代码。
config TARGET_MX6ULL_FIRE
bool "Support mx6ullfire"
depends on MX6ULL
select BOARD_LATE_INIT
select DM
select DM_THERMAL
imply CMD_DM
以上配置项定义了一个名为TARGET_MX6ULL_FIRE的目标设备,用于指定是否支持MX6ULL_FIRE开发板。
5.5.4.2. 添加配置选项
在上述Kconfig文件中的source “board/freescale/mx6ullevk/Kconfig”下添加如下代码
source "board/freescale/mx6ullfire/Kconfig"
将MX6ULL-FIRE开发板的配置选项包含到上层Kconfig文件中,即可调用mx6ullfire中的Kconfig进行配置。
5.5.5. 添加设备树
5.5.5.1. 添加设备树信息
修改文件目录为:arch/arm/dts/Makefile
在上述Makefile文件中的dtb-$(CONFIG_MX6ULL) += 下面添加设备树
设备树的名字,参考config里的CONFIG_DEFAULT_DEVICE_TREE=”imx6ull-fire-mmc”,如果是nand版本则是”imx6ull-fire-nand”。
添加的内容:
imx6ull-fire-mmc.dtb
imx6ull-fire-nand.dtb
dtb-$(CONFIG_MX6ULL) += \
imx6ull-14x14-evk.dtb \
imx6ull-fire-mmc.dtb \
imx6ull-fire-nand.dtb \
imx6ull-colibri.dtb \
imx6ull-myir-mys-6ulx-eval.dtb \
imx6ull-phytec-segin-ff-rdk-emmc.dtb \
imx6ull-dart-6ul.dtb \
imx6ull-somlabs-visionsom.dtb \
imx6ulz-14x14-evk.dtb
为什么在这添加,因为配置文件里设置了CONFIG_MX6ULL=y,该选项被启用,会生成针对该处理器的DTB文件。
5.5.5.2. 复制设备树源码
复制一份设备树源码到新版本的uboot。
将野火emmc版本和nand版本的设备树都复制到新版本uboot。
cp ebf_linux_uboot/arch/arm/dts/imx6ull-fire-* u-boot-2021.10-rc4/arch/arm/dts/
5.5.5.3. 修改板卡soc文件
修改文件目录为:arch/arm/mach-imx/mx6/soc.c
在soc.c文件开头加上
#include <asm/setup.h>
在soc.c文件末尾加上
#ifdef CONFIG_SERIAL_TAG
void get_board_serial(struct tag_serialnr *serialnr)
{
struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
struct fuse_bank *bank = &ocotp->bank[0];
struct fuse_bank0_regs *fuse =
(struct fuse_bank0_regs *)bank->fuse_regs;
serialnr->low = fuse->uid_low;
serialnr->high = fuse->uid_high;
}
#endif
以上是一个获取板级信息的函数,该函数使用了SoC内部的OTP存储器,读取存储在OTP中的唯一设备标识符UID,并将其保存到Linux内核启动参数中的struct tag_serialnr结构体中,使其成为内核启动参数之一。
5.5.6. 设备树插件移植(野火特有)
5.5.6.1. 设备树插件配置
5.5.6.1.1. 复制源码
cp -rf ebf_linux_uboot/cmd/dtfile.c u-boot-2021.10-rc4/cmd/
cp -rf ebf_linux_uboot/include/dtoverlay.h u-boot-2021.10-rc4/include/
cp -rf ebf_linux_uboot/include/ramblockdev.h u-boot-2021.10-rc4/include/
-
dtfile.c 用于实现uboot命令dtfile。该命令用于在uboot中加载并解析设备树文件,并将其显示输出或保存到指定的文件中。
-
dtoverlay.h 用于定义设备树相关的数据结构和函数声明。
-
ramblockdev.h 用于定义RAM块设备。
5.5.6.1.2. 修改Makefile
修改文件目录为:cmd/Makefile
修改Makefile加入编译dtfile.c配置,使编译uboot时将该文件编译进去。
在obj-$(CONFIG_CMD_FDT) += fdt.o的下面添加
obj-$(CONFIG_OF_LIBFDT) += dtfile.o
5.5.6.2. UID配置
5.5.6.2.1. 复制源码和添加源码
cp -rf ebf_linux_uboot/include/init.h u-boot-2021.10-rc4/include/
cp -rf ebf_linux_uboot/common/board_r.c u-boot-2021.10-rc4/common/board_r.c
cp -rf ebf_linux_uboot/dtoverlay/ u-boot-2021.10-rc4/
-
init.h 用于声明uboot启动过程中的初始化函数和数据结构。
-
board_r.c 包含一些通用的板级初始化函数和一些通用的工具函数,可以用于不同的硬件平台。
-
dtoverlay 提供了设备树覆盖的功能,通过加载这些覆盖文件,可以在U-Boot运行时动态地修改设备树。
5.5.6.2.2. 修改顶层Makefile
修改文件目录为:u-boot-2021.10-rc4/Makefile
添加如下代码
libs-y += dtoverlay/
添加dtoverlay目录下包含的所有库文件用于编译。
5.6. 编译及烧录
如何编译和烧录详细请看前面uboot的编译和uboot的烧录章节,下面以编译emmc版本为例。
cd u-boot-2021.10-rc4/
sudo make distclean
#选择emmc版本的配置文件,如果是nand版本则是mx6ull_fire_nand_defconfig
sudo make ARCH=arm CROSS_COMPILE=arm-none-eabi- mx6ull_fire_mmc_defconfig
#编译uboot
sudo make ARCH=arm CROSS_COMPILE=arm-none-eabi-
编译生成的u-boot-dtb.imx就是我们需要的uboot文件。
5.7. 启动
启动后可以看到确实可以正常使用,也具有我们的定制功能。
6. Uboot的GPIO控制
6.1. 简介
Uboot的GPIO是常用的功能,在开发中常常需要在上电时进行控制。
6.2. 下载安装编译镜像系统
使用平台:Ubuntu 18.04.5 LTS 版本
可以使用我们提供的虚拟机镜像 野火i.MX6ULL Linux开发板 — 野火产品资料下载中心 文档
也可以自己下载ubuntu 18.04.5 LTS官方镜像搭建
https://mirrors.aliyun.com/ubuntu-releases/bionic/ubuntu-18.04.5-desktop-amd64.iso
6.3. 安装编译工具和依赖
使用apt工具能快速安装好我们需要的工具和依赖
sudo apt install make git gcc-arm-none-eabi gcc bison flex libssl-dev dpkg-dev lzop libncurses5-dev vim
6.4. 下载Uboot源代码
可以到我们的gitee上下载我们的源码,也可以下载NXP官方的源码进行配置,本教程就以我们野火修改过的Uboot进行讲解
我们的UBOOT地址:ebf_linux_uboot: 野火所有Linux系列产品使用的uboot源码仓库 - Gitee.com
NXP官方的UBOOT地址:https://source.codeaurora.org/external/imx/uboot-imx/
git clone https://gitee.com/Embedfire/ebf_linux_uboot.git
6.5. 查找引脚
对于控制引脚,我们首先得认的出哪个是我们要使用的引脚
我这里用拨盘的3号位为例,在原理图(如果没有原理图可以从这里下载 野火_EBF6ULL S1 Pro 底板_原理图_20200729.pdf )中可以看出它的名称为:LCD_DATA4
可以到用户手册查询,也可以到 ebf_linux_uboot/arch/arm/dts/imx6ul-pinfunc.h 下查询
我们这里就在源码里查找,找到如图
我们主要看的是GPIOX_IOXX
#define MX6UL_PAD_LCD_DATA04__GPIO3_IO09 是我们拨盘上的3号拨盘。
这里看出分别是3和9,等会我们调用代码会使用到。
我们再看一下板子上的三色灯
我们就控制红灯引脚即可,查原理图得知,相应管脚为GPIO1_IO4
6.6. 编写代码
我们写一份调用GPIO库控制GPIO口的代码存在 ebf_linux_uboot/cmd目录下
新建一个c文件
文件位置:ebf_linux_uboot/cmd/ebf_gpio.c
vim ./cmd/ebf_gpio.c
#include <command.h>
#include <fdt_support.h>
#include <linux/string.h>
#include <fs.h>
#include <asm/gpio.h>
int gpiox=-1,iox=-1,ebf_lhf=-1,put_value=-1;
static int do_ebfgpio(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
{
if(strcmp(argv[1], "get") == 0)
{
gpiox=*argv[2]-'0';
iox=*argv[3]-'0';
gpio_request(IMX_GPIO_NR(gpiox, iox), "ebf_get");//初始化管脚
gpio_direction_input(IMX_GPIO_NR(gpiox, iox));//设置为输入管脚
ebf_lhf = gpio_get_value(IMX_GPIO_NR(gpiox, iox));//获取输入
if(ebf_lhf)
{
printf("Get! GPIO%d_IO%d:High level\r\n",gpiox,iox);
}
else
{
printf("Get! GPIO%d_IO%d:LOW level\r\n",gpiox,iox);
}
}
else if(strcmp(argv[1], "put") == 0)
{
gpiox=*argv[2]-'0';
iox=*argv[3]-'0';
put_value=*argv[4]-'0';
if(put_value!=1&&put_value!=0)
{
printf("put value err!\r\n");
return -1;
}
gpio_request(IMX_GPIO_NR(gpiox, iox), "ebf_put");//初始化管脚
gpio_direction_output(IMX_GPIO_NR(gpiox, iox),put_value);//设置为输出管脚
gpio_set_value(IMX_GPIO_NR(gpiox, iox),put_value);//输出电平
}
else
{
printf("Nothing to do\r\n");
}
return 0;
}
static char ebfgpio_help_text[] =
"[way GPIO IO [OUTPUT_VALUE]]\n"
"\tway:\"get\"or\"put\"\n"
"\tGPIO:GPIO Group\n"
"\tIO:IO NUMB\n"
"\tOUTPUT_VALUE:\"0\"or\"1\""
;
U_BOOT_CMD(
ebfgpio, 5, 0, do_ebfgpio,
"EBF control GPIO ", ebfgpio_help_text
);
6.7. 修改Makefile
修改Makefile的目的是让编译器知道我们要把这个文件编进uboot
文件位置:ebf_linux_uboot/cmd/Makefile
添加 obj-y += ebf_gpio.o 到如图位置
6.8. 编译
make distclean
make mx6ull_fire_mmc_defconfig CROSS_COMPILE=arm-none-eabi-
#编译uboot
make CROSS_COMPILE=arm-none-eabi- -j4
编译完再烧录进板子即可。
6.9. 演示
6.9.1. 输入演示
当我们将拨盘3拨到如图位置
在uboot命令行中调用命令
ebfgpio get 3 9
显示如图
当我们将拨盘3拨到如图位置
在uboot命令行中调用命令
ebfgpio get 3 9
显示如图
6.9.1.1. 输出演示
ebfgpio put 1 4 0
ebfgpio put 1 4 1
7. 定制自己的Uboot单板
7.1. 简介
我们提供的uboot中默认都是我们的开发板,虽说我们可以直接在我们的开发板上直接修改,使 uboot 可以完整的运行在我们的板子上。但是从学习的角度来讲,这样我们就不能了解到 uboot 是如何添加新平台的。接下来我们就参考我们的IMX6ULL开发板,学习如何在 uboot 中添加自己的开发板或者开发平台
7.2. 下载安装编译镜像系统
使用平台:Ubuntu 18.04.5 LTS 版本
可以使用我们提供的虚拟机镜像 野火i.MX6ULL Linux开发板 — 野火产品资料下载中心 文档
也可以自己下载ubuntu 18.04.5 LTS官方镜像搭建
https://mirrors.aliyun.com/ubuntu-releases/bionic/ubuntu-18.04.5-desktop-amd64.iso
7.3. 安装编译工具和依赖
使用apt工具能快速安装好我们需要的工具和依赖
sudo apt install make git gcc-arm-none-eabi gcc bison flex libssl-dev dpkg-dev lzop libncurses5-dev
7.4. 获取uboot
7.4.1. 下载源代码
下载我们的uboot源码
git clone -b ebf_v2020_10_imx https://gitee.com/Embedfire/ebf_linux_uboot
#或者
git clone -b ebf_v2020_10_imx https://github.com/Embedfire/ebf_linux_uboot
7.5. 添加开发板默认配置文件
下面以mmc版本为例,如果是nand版本把“mmc”改为“nand”即可。“name”可改为自己定义的名字。
先在 configs 目录下创建默认配置文件,复制 mx6ull_fire_mmc_defconfig,然后重命名为 mx6ull_name_mmc_defconfig,命令如下:
cd configs/
cp mx6ull_fire_mmc_defconfig mx6ull_name_mmc_defconfig
#若为nand版本则是以下命令,后续“mmc”版本和“nand”版本区别说明不再重复
cp mx6ull_fire_nand_defconfig mx6ull_name_nand_defconfig
然后将文件mx6ull_name_mmc_defconfig中的CONFIG_SYS_EXTRA_OPTIONS内容改成如下
CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/mx6ull_name/imximage.cfg"
board/freescale/mx6ull_name就是我们后续要添加的单板目录。
7.5.1. 添加头文件
复制一份include/configs/mx6ullfire.h更名为include/configs/mx6ull_name.h
cp include/configs/mx6ullfire.h include/configs/mx6ull_name.h
更改
#ifndef __MX6ULLFIRE_CONFIG_H
#define __MX6ULLFIRE_CONFIG_H
改为:
#ifndef __MX6ULL_NAME_CONFIG_H
#define __MX6ULL_NAME_CONFIG_H
以下是部分代码分析
#define PHYS_SDRAM_SIZE SZ_512M
....
#define CONFIG_SYS_MALLOC_LEN (16 * SZ_1M)
....
#define CONFIG_MXC_UART_BASE UART1_BASE
....
#define CONFIG_SYS_FSL_ESDHC_ADDR USDHC2_BASE_ADDR
....
#CONFIG_EXTRA_ENV_SETTINGS "....."
....
#define CONFIG_BOOTCOMMAND "....."
....
#define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR
#define CONFIG_SYS_HZ 1000
#define PHYS_SDRAM MMDC0_ARB_BASE_ADDR
....
#define CONFIG_SYS_INIT_SP_OFFSET \
(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
#define CONFIG_SYS_INIT_SP_ADDR \
(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
#define CONFIG_MMCROOT "/dev/mmcblk1p2" /* USDHC2 */
#define CONFIG_FEC_ENET_DEV 1
#if (CONFIG_FEC_ENET_DEV == 0)
#define CONFIG_ETHPRIME "eth0"
#elif (CONFIG_FEC_ENET_DEV == 1)
#define CONFIG_ETHPRIME "eth1"
-
PHYS_SDRAM_SIZE :设置了SDRAM的内存大小
-
CONFIG_SYS_MALLOC_LEN :为malloc内存池大小,这里设置为16MB
-
CONFIG_MXC_UART_BASE :这里使用串口1,基地址为 UART1_BASE, UART1_BASE 定义在文件arch/arm/include/asm/arch-mx6/imx-regs.h 中, imx-regs.h 是 I.MX6ULL 寄存器描述文件,根据imx-regs.h 可得到 UART1_BASE 的值如下
-
UART1_BASE= (ATZ1_BASE_ADDR + 0x20000) =AIPS1_ARB_BASE_ADDR + 0x20000 =0x02000000 + 0x20000 =0X02020000
可以看到在手册中UART1的基地址
-
CONFIG_SYS_FSL_ESDHC_ADDR:宏CONFIG_SYS_FSL_ESDHC_ADDR为 EMMC 所使用接口的寄存器基地址,也就是 USDHC2 的基地址
-
CONFIG_EXTRA_ENV_SETTINGS : 通 过 条 件 编 译 来 设 置 宏 CONFIG_EXTRA_ENV_SETTINGS,宏CONFIG_EXTRA_ENV_SETTINGS 也是设置一些环境变量,此宏会设置bootargs这个环境变量
-
CONFIG_BOOTCOMMAND:设置宏 CONFIG_BOOTCOMMAND,此宏就是设置环境变量bootcmd的值。
-
CONFIG_SYS_LOAD_ADDR:表示 linux kernel 在DRAM中的加载地址,也就是 linux kernel 在 DRAM 中的存储首地址,CONFIG_LOADADDR=0X80800000
-
CONFIG_SYS_HZ:宏 CONFIG_SYS_HZ 为系统时钟频率,这里为 1000Hz。
-
PHYS_SDRAM:为 I.MX6ULL 的 DRAM 控制器 MMDC0 所管辖的 DRAM 范围起始地址,也就是 0X80000000
-
CONFIG_SYS_SDRAM_BASE:为 DRAM 的起始地址。
-
CONFIG_SYS_INIT_RAM_ADDR:为 I.MX6ULL 内部 IRAM 的起始地址(也就是 OCRAM 的起始地址),为 0X00900000
-
CONFIG_SYS_INIT_RAM_SIZE:为 I.MX6ULL 内部 IRAM 的大小(OCRAM的大小),为 0X00040000=128KB
-
CONFIG_SYS_INIT_SP_OFFSET和CONFIG_SYS_INIT_SP_ADDR:CONFIG_SYS_INIT_SP_OFFSET 和 CONFIG_SYS_INIT_SP_ADDR 与初始 SP 有关,第一个为初始 SP 偏移,第二个为初始 SP 地址
-
CONFIG_MMCROOT :设置进入 linux 系统的根文件系统所在的分区,这里设置为”/dev/mmcblk1p2”,也就是 EMMC 设备的第 2 个分区。第 0 个分区保存 uboot,第 1 个分区保存 linux 镜像和设备树,第 2 个分区为 Linux 系统的根文件系统
-
CONFIG_FEC_ENET_DEV:指定 uboot 所使用的网口, I.MX6ULL 有两个网口,为 0 的时候使用 ENET1,为 1 的时候使用 ENET2
-
CONFIG_VIDEO:用于开启 LCD,CONFIG_VIDEO_LOGO 使能 LOGO 显示, CONFIG_CMD_BMP 使能 BMP 图片显示指令。这样就可以在 uboot 中显示图片了,一般用于显示 logo。
关于 mx6ull_name_emmc.h 就讲解到这里,其中以 CONFIG_CMD 开头的宏都是用于使能相应命令的,其他的以 CONFIG 开头的宏都是完成一些配置功能的。以后会频繁的和mx6ull_name_emmc.h 这个文件打交道。
7.5.2. 添加单板目录和文件
uboot 中每个板子都有一个对应的文件夹来存放板级文件,比如开发板上外设驱动文件等等。 NXP 的 I.MX 系列芯片的所有板级文件夹都存放在 board/freescale 目录下,在这个目录下有个名为 mx6ullfire的文件夹,这个文件夹就是我们IMX6LL的开发板的板级文件夹。复制 mx6ullfire,将其重命名为 mx6ull_name,命令如下:
cd board/freescale/
cp -rf mx6ullfire mx6ull_name
进入mx6ull_name目录中,将其中的mx6ullfire.c文件重命名为mx6ull_name.c,命令如下:
cd mx6ull_name/
mv mx6ullfire.c mx6ull_name.c
将mx6ull_name.c里面的mx6ullfire.h头文件修改为mx6ull_name.h
#include <configs/mx6ull_name.h>
mx6ull_name单板目录文件结构如下:
./mx6ull_name
├── imximage.cfg
├── Kconfig
├── MAINTAINERS
├── Makefile
├── mx6ull_name.c
└── plugin.S
-
mx6ull_name.c :里写了一些uboot启动代码和我们对板子引脚读取的代码
-
plugin.S :用汇编写的设置ddr和时钟,一般不需要更改
-
Makefile :里面修改C文件编译后的o文件,有多少个就写多少个o文件,注意与c文件名字相同
将Makefile里面的mx6ullfire.o修改为mx6ull_name.o
obj-y := mx6ull_name.o
-
Kconfig :(目录:board/路径/目标文件夹/Kconfig)
将Kconfig修改为以下内容:
if TARGET_MX6ULL_FIRE //上面所说的两处对应其中的一处
config SYS_BOARD
default "mx6ull_name" //目标文件夹
config SYS_VENDOR
default "freescale" //路径
config SYS_CONFIG_NAME
default "mx6ull_name" //头文件名称 注意:头文件在include/configs下名称为"头文件名称.h"
endif
-
imximage.cfg :(目录:board/路径/目标文件夹)(NXP特有的文件,只需要修改一处即可,这是添加头部信息的)
将imximage.cfg文件里面的PLUGIN board/freescale/mx6ullfire/plugin.bin 0x00907000 修改为以下内容,更改单板目录:
PLUGIN board/freescale/mx6ull_name /plugin.bin 0x00907000
7.5.3. 配置文件
emmc版本为 mx6ull_fire_mmc_defconfig
nand版本为 mx6ull_fire_nand_defconfig
以下以emmc版本为例:
cp configs/mx6ull_fire_mmc_defconfig configs/mx6ull_name_defconfig
这里有几个参数要注意一下
-
CONFIG_TARGET_MX6ULL_FIRE=y 这行参数与两处有相对应,下面会讲到,这里留意一下。
-
CONFIG_DEFAULT_DEVICE_TREE= 这行参数是设备树名称,要与uboot设备树对应,将其修改为如下配置:
CONFIG_DEFAULT_DEVICE_TREE="imx6ull-name-mmc"
因为后续准备使用的设备树为imx6ull-name-mmc.dts。
-
CONFIG_SYS_EXTRA_OPTIONS= 这行参数是配置头部信息的,指向的是板子目录的cfg文件,将其修改为如下配置,改为我们单板目录。
CONFIG_SYS_EXTRA_OPTIONS=="IMX_CONFIG=board/freescale/mx6ull_name/imximage.cfg"
7.5.4. 添加Kconfig信息
在这个文件中添加我们的板子信息方便Makefile识别编译
修改文件目录为:arch/arm/mach-imx/mx6/Kconfig
7.5.4.1. 修改U-Boot图形界面配置文件
在config TARGET_MX6ULL_14X14_EVK配置的下面添加如下代码
config TARGET_MX6ULL_FIRE
bool "Support mx6ull_name"
depends on MX6ULL
select BOARD_LATE_INIT
select DM
select DM_THERMAL
imply CMD_DM
在source “board/freescale/mx6ullevk/Kconfig”下添加如下代码
source "board/freescale/mx6ull_name/Kconfig"
7.5.5. 添加设备树
7.5.5.1. 添加设备树信息
修改文件目录为:arch/arm/dts/Makefile
在dtb-$(CONFIG_MX6ULL) += 下面添加(为什么在这添加,因为配置文件里设置了CONFIG_MX6ULL=y)
设备树的名字,参考config里的CONFIG_DEFAULT_DEVICE_TREE=”imx6ull-name-mmc”
添加内容:imx6ull-name-mmc.dtb
dtb-$(CONFIG_MX6ULL) += \
imx6ull-14x14-evk.dtb \
imx6ull-fire-mmc.dtb \
imx6ull-fire-nand.dtb \
imx6ull-name-mmc.dtb \
imx6ull-colibri.dtb \
imx6ull-myir-mys-6ulx-eval.dtb \
imx6ull-phytec-segin-ff-rdk-emmc.dtb \
imx6ull-dart-6ul.dtb \
imx6ull-somlabs-visionsom.dtb \
imx6ulz-14x14-evk.dtb
7.5.5.2. 复制设备树源码
cp arch/arm/dts/imx6ull-fire-mmc.dts arch/arm/dts/imx6ull-name-mmc.dts
7.5.6. 编译
make distclean
make mx6ull_name_mmc_defconfig
#编译uboot
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
7.6. 烧录启动
启动后可以发现确实可以正常使用。