一、环境变量 bootcmd
bootcmd 和 bootagrs 是采用类似 shell 脚本语言编写的,里面很多的变量引用,这些变量都是环境变量,很多是 NXP 定义的。文件mx6ull_alientek_emmc.h 中的宏 CONFIG_EXTRA_ENV_SETTINGS 保存着这些环境变量的默认值,内容如下:
#if defined(CONFIG_SYS_BOOT_NAND)
#define CONFIG_EXTRA_ENV_SETTINGS
CONFIG_MFG_ENV_SETTINGS
'panel=TFT43AB '
'fdt_addr=0x83000000 '
'fdt_high=0xffffffff '
......
'bootz ${loadaddr} - ${fdt_addr} '
#else
#define CONFIG_EXTRA_ENV_SETTINGS
CONFIG_MFG_ENV_SETTINGS
'script=boot.scr '
'image=zImage '
'console=ttymxc0 '
'fdt_high=0xffffffff '
'initrd_high=0xffffffff '
'fdt_file=undefined '
......
'findfdt='
'if test $fdt_file = undefined; then '
'if test $board_name = EVK && test $board_rev = 9X9; then '
'setenv fdt_file imx6ull-9x9-evk.dtb; fi; '
'if test $board_name = EVK && test $board_rev = 14X14; then '
'setenv fdt_file imx6ull-14x14-evk.dtb; fi; '
'if test $fdt_file = undefined; then '
'echo WARNING: Could not determine dtb to use; fi; '
'fi; '
宏 CONFIG_EXTRA_ENV_SETTINGS 是个条件编译语句,使用 NAND 和 EMMC 的时候宏 CONFIG_EXTRA_ENV_SETTINGS 的值是不同的。用户可以根据需求自定义修改这些默认值,如前面移植 LCD 时修改默认屏幕为'panel=KODO_TFT4384 '。
bootcmd 的默认值就是 CONFIG_BOOTCOMMAND,bootargs 的默认值就是 CONFIG_BOOTARGS。
在 mx6ull_alientek_emmc.h 文件中通过设置宏 CONFIG_BOOTCOMMAND 来设置 bootcmd 的默认值,NXP 官方设置的 CONFIG_BOOTCOMMAND 值如下:
#define CONFIG_BOOTCOMMAND
'run findfdt;'
'mmc dev ${mmcdev};'
'mmc dev ${mmcdev}; if mmc rescan; then '
'if run loadbootscript; then '
'run bootscript; '
'else '
'if run loadimage; then '
'run mmcboot; '
'else run netboot; '
'fi; '
'fi; '
'else run netboot; fi'
使用了类似 shell 脚本语言的方式来编写。
第 2 行:run findfdt;使用的是 uboot 的 run 命令来运行 findfdt,findfdt 是 NXP 自行添加的环境变量。findfdt 是用来查找开发板对应的设备树文件(.dtb)。IMX6ULL EVK 的设备树文件为 imx6ull-14x14-evk.dtb,findfdt 内容如下:
'findfdt='
'if test $fdt_file = undefined; then '
'if test $board_name = EVK && test $board_rev = 9X9; then '
'setenv fdt_file imx6ull-9x9-evk.dtb; fi; '
'if test $board_name = EVK && test $board_rev = 14X14; then '
'setenv fdt_file imx6ull-14x14-evk.dtb; fi; '
'if test $fdt_file = undefined; then '
'echo WARNING: Could not determine dtb to use; fi; '
'fi; '
findfdt 里面用到的变量有 fdt_file,board_name,board_rev,这三个变量内容如下:
fdt_file=undefined,board_name=EVK,board_rev=14X14
findfdt 做的事情就是判断,fdt_file 是否为 undefined,如果 fdt_file 为 undefined 的话那就要根据板子信息得出所需的.dtb 文件名。
此时 fdt_file 为 undefined,所以根据 board_name 和 board_rev 来判断实际所需的.dtb 文件,如果 board_name 为 EVK 并且 board_rev=9x9 的话 fdt_file 就为 imx6ull-9x9-evk.dtb。如果 board_name 为 EVK 并且 board_rev=14x14 的话 fdt_file 就设置为 imx6ull-14x14-evk.dtb。因此 IMX6ULL EVK 板子的设备树文件就是 imx6ull-14x14-evk.dtb,因此 run findfdt 的结果就是设置 fdt_file 为 imx6ull-14x14-evk.dtb。
第 3 行:mmc dev
m
m
c
d
e
v
用
于
切
换
m
m
c
设
备
,
m
m
c
d
e
v
为
1
,
因
此
这
行
代
码
就
是
:
m
m
c
d
e
v
1
,
也
就
是
切
换
到
E
M
M
C
上
。
第
4
行
:
先
执
行
m
m
c
d
e
v
{mmcdev}切换到 EMMC 上,然后使用命令 mmc rescan 扫描看有没有 SD 卡或者 EMMC 存在,如果没有的话就直接跳到 216 行,执行 run netboot,netboot 也是一个自定义的环境变量,这个变量是从网络启动 Linux 的。如果 mmc 设备存在的话就从 mmc 设备启动。
第 5 行:运行 loadbootscript 环境变量,此环境变量内容如下:
loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};
其中 mmcdev=1,mmcpart=1,loadaddr=0x80800000,script= boot.scr,因此展开以后就是:
loadbootscript=fatload mmc 1:1 0x80800000 boot.scr;
loadbootscript 就是从 mmc1 的分区 1 中读取文件 boot.src 到 DRAM 的 0X80800000 处。但是 mmc1 的分区 1 中没有 boot.src 这个文件,可以使用命令“ls mmc 1:1”查看一下 mmc1 分区 1 中的所有文件,看看有没有 boot.src 这个文件。
第 6 行:如果加载 boot.src 文件成功的话就运行 bootscript 环境变量,bootscript 的内容如下:
bootscript=echo Running bootscript from mmc ...;
source
因为 boot.src 文件不存在,所以 bootscript 也就不会运行。
第 8 行:如果 loadbootscript 没有找到 boot.src 的话就运行环境变量 loadimage,环境变量 loadimage 内容如下:
loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}
其中 mmcdev=1,mmcpart=1,loadaddr=0x80800000,image = zImage,展开以后就是:
loadimage=fatload mmc 1:1 0x80800000 zImage
可以看出 loadimage 就是从 mmc1 的分区中读取 zImage 到内存的 0X80800000 处,而 mmc1 的分区 1 中存在 zImage。
第 9 行:加载 linux 镜像文件 zImage 成功以后就运行环境变量 mmcboot,否则的话运行 netboot 环境变量。mmcboot 环境变量如下:
'mmcboot=echo Booting from mmc ...; '
'run mmcargs; '
'if test ${boot_fdt} = yes || test ${boot_fdt} = try; then '
'if run loadfdt; then '
'bootz ${loadaddr} - ${fdt_addr}; '
'else '
'if test ${boot_fdt} = try; then '
'bootz; '
'else '
'echo WARN: Cannot load the DT; '
'fi; '
'fi; '
'else '
'bootz; '
'fi; '
第 1 行:输出信息“Booting from mmc ...”。
第 2 行:运行环境变量 mmcargs,mmcargs 用来设置 bootargs,后面分析 bootargs 的时候再学习。
第 3 行:判断boot_fdt是否为 yes 或者 try,根据 uboot 输出的环境变量信息可知 boot_fdt=try。因此会执行第 4 行的语句。
第 4 行:运行环境变量 loadfdt,环境变量 loadfdt 定义如下:
loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}
展开以后就是:
loadfdt=fatload mmc 1:1 0x83000000 imx6ull-14x14-evk.dtb
因此 loadfdt 的作用就是从 mmc1 的分区 1 中读取 imx6ull-14x14-evk.dtb 文件并放到 0x83000000 处。
第 5 行:如果读取.dtb 文件成功的话那就调用命令 bootz 启动 linux,调用方法如下:
bootz ${loadaddr} - ${fdt_addr};
展开就是:
bootz 0x80800000 - 0x83000000 (注意‘-’前后要有空格)
至此 Linux 内核启动,如此复杂的设置就是为了从 EMMC 中读取 zImage 镜像文件和设备树文件。经过分析,浓缩出来的仅仅是 4 行精华:
mmc dev 1 //切换到 EMMC
fatload mmc 1:1 0x80800000 zImage //读取 zImage 到 0x80800000 处
fatload mmc 1:1 0x83000000 imx6ull-14x14-evk.dtb //读取设备树到 0x83000000 处
bootz 0x80800000 - 0x83000000 //启动 Linux
二、环境变量 bootargs
bootargs 保存着 uboot 传递给 Linux 内核的参数,在上一小节讲解 bootcmd 的时候说过,bootargs 环境变量是由 mmcargs 设置的,mmcargs 环境变量如下:
mmcargs=setenv bootargs console=${console},${baudrate} root=${mmcroot}
其中 console=ttymxc0,baudrate=115200,mmcroot=/dev/mmcblk1p2 rootwait rw,因此将 mmcargs 展开以后就是:
mmcargs=setenv bootargs console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw
可以看出环境变量 mmcargs 就是设置 bootargs 的值为“console= ttymxc0, 115200 root=/dev/mmcblk1p2 rootwait rw”,bootargs 就是设置了很多的参数的值,这些参数 Linux 内核会使用到,常用的参数有:
1、console 参数
console 用来设置 linux 终端(或者叫控制台),也就是通过什么设备来和 Linux 进行交互,是串口还是 LCD 屏幕?如果是串口的话应该是串口几等等。一般设置串口作为 Linux 终端,这样我们就可以在电脑上通过 SecureCRT 来和 linux 交互了。这里设置 console 为 ttymxc0,因为 linux 启动以后 I.MX6ULL 的串口 1 在 linux 下的设备文件就是/dev/ttymxc0,在 Linux 下,一切皆文件。
ttymxc0 后有个“,115200”,是设置串口波特率,console=ttymxc0,115200 综合起来就是设置 ttymxc0(也就是串口 1)作为 Linux 的终端,并且串口波特率设置为 115200。
2、root 参数
root 用来设置根文件系统的位置,root=/dev/mmcblk1p2 用于指明根文件系统存放在 mmcblk1 设备的分区 2 中。EMMC 版本的核心板启动 linux 以后会存在/dev/mmcblk0、/dev/mmcblk1、/dev/mmcblk0p1、/dev/mmcblk0p2、/dev/mmcblk1p1 和/dev/mmcblk1p2 这样的文件,其中/dev/mmcblkx(x=0~n)表示 mmc 设备,而/dev/mmcblkxpy(x=0n,y=1n)表示 mmc 设备 x 的分区 y。在 I.MX6U-ALPHA 开发板中/dev/mmcblk1 表示 EMMC,而/dev/mmcblk1p2 表示
EMMC 的分区 2。
root 后面有“rootwait rw”,rootwait 表示等待 mmc 设备初始化完成以后再挂载,否则的话 mmc 设备还没初始化完成就挂载根文件系统会出错的。rw 表示根文件系统是可以读写的,不加 rw 的话可能无法在根文件系统中进行写操作,只能进行读操作。
3、rootfstype 参数
此选项一般配置 root 一起使用,rootfstype 用于指定根文件系统类型,如果根文件系统为 ext 格式的话此选项无所谓。如果根文件系统是 yaffs、jffs 或 ubifs 的话就需要设置此选项,指定根文件系统的类型。
4、mem 参数
mem=xxM 指定内存的大小,不是必须的
5、ramdisk_size 参数(一般不用)
ramdisk 即虚拟内存盘,是通过软件将部分内存模拟为硬盘来使用的一种技术。
ramdisk=xx //不推荐
ramdisk_size=xx //推荐
上面这两个都可以告诉 ramdisk 驱动,创建的 ramdisk 的 size,默认情况下是4m(s390默认8M),可以查看 Documentation/ramdisk.txt 找到相关的描述,不过 ramdisk=xx 在新版的内核都已经没有提了,不推荐使用。
6、initrd、noinitrd 参数
当没有使用 ramdisk 启动系统的时候,需要使用 noinitrd 这个参数,但是如果使用了的话,就需要指定 initrd=r_addr,size,r_addr 表示 initrd 在内存中的位置,size 表示 initrd 的大小。
7、 init 参数
init 指定内核启动后进入系统中运行的第一个脚本,一般 init=/linuxrc, 或者 init=/etc/preinit,preinit 的内容一般是创建 console null 设备节点、运行 init 程序、挂载一些文件系统等操作。
注:很多初学者以为 init=/linuxrc 是固定写法,其实不然,/linuxrc 指的是/目录下面的 linuxrc 脚本,一般是一个链接罢了。
此参数一般不需要设置,因为内核源码中有一定的启动项,内核如何启动 init 进程在内核的 init/main.c 中 static init noinline init_post(void)。
若出现 No init found Try passing init= 这种错误的时候可能原因是内核找不到文件系统或者无法挂载文件系统,不用考虑是init参数设置的错误。
Eg:kernelpanic-nosyncing :no init found.Tying init= option to know 此错误的原因是因为 root=/dev/mtdblock4 但是 nand 中没有烧写文件系统,而不是因为 init 参数设置不对。
8、mtdparts 参数
mtdparts=fc000000.nor_flash:1920k(linux),128k(fdt),20M(ramdisk),4M(jffs2),38272k(user),256k(env),384k(uboot)
要想这个参数起作用,内核中的 mtd 驱动必须要支持,即内核配置时需要选上:
Device Drivers --->
Memory Technology Device (MTD) support--->
Command line partition table parsing
mtdparts 的格式如下:
mtdparts= mtddef 可以由 mtd-id 和一个或多个 partdef 组成,每个 partdef 定义如下: 参数含义如下: 因此在使用的时候,需要按照下面的格式来设置: mtdparts=mtd-id: 这里需要注意的地方如下: (1) mtd-id 必须跟当前平台 flash 的 mtd-id 一致,不然整个 mtdparts 会失效。 (2)size 在设置的时候,可以为实际的 size(xxM,xxK,xx),也可以为‘-’,表示剩余的所有空间,相关信息可以查看 drivers/mtd/cmdlinepart.c 中注释找到相关描述。 mtdparts 参数格式及当前平台的 flash 的 mtd-id 如何查找? 先看看 linux-4.14.63/Documentation 里面怎么说的: ~/opt/linux-4.14.63/Documentation$ grep mtdparts . -rn ./admin-guide/kernel-parameters.txt:2408: mtdparts= [MTD]
上一篇:【IMX6ULL学习笔记】七、Linux 顶层Makefile
下一篇:【IMX6ULL学习笔记】五、U-BOOT移植与解析
推荐阅读最新更新时间:2026-03-16 22:28
- DC2588A-B,基于 LTC2387-16、16 位、15Msps 高速 SAR ADC 的演示板
- S5U13A03P00C000,基于S1D13705F00A Em的开发套件
- LT1074,抽头电感降压转换器
- MPC866ADS_KIT: MPC866应用开发系统套件
- 具有高调光比和 LED 开路报告的 LT3756EUD 降压模式 1A LED 驱动器的典型应用电路
- ADA4075-2ACPZ-R7 平衡线路接收器运算放大器的典型应用电路
- 使用 ON Semiconductor 的 FAN7190_F085 的参考设计
- AM1G-0512SZ 12V 1 瓦 DC/DC 转换器的典型应用
- ADP2323 同步降压稳压器的典型应用 并行单路输出应用,VIN = 12 V,VOUT = 1.8 V,IOUT = 6 A,fSW = 600 kHz
- 新的低功耗、高输出电流双 CFA 使 xDSL 线路驱动干净、简单



U-Boot源码解析(LoongArch版)
现代雷达系统的信号设计
BFR340T






京公网安备 11010802033920号