LV05-06-系统烧写-01-shell脚本烧写系统到SD卡
本文主要是系统烧写——在ubuntu中通过shell脚本制作一个sd卡启动盘的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。
点击查看使用工具及版本
PC端开发环境 | Windows | Windows11 |
Ubuntu | Ubuntu20.04.2的64位版本 | |
VMware® Workstation 17 Pro | 17.6.0 build-24238078 | |
终端软件 | MobaXterm(Professional Edition v23.0 Build 5042 (license)) | |
Win32DiskImager | Win32DiskImager v1.0 | |
Linux开发板环境 | Linux开发板 | 正点原子 i.MX6ULL Linux 阿尔法开发板 |
uboot | NXP官方提供的uboot,使用的uboot版本为U-Boot 2019.04 | |
linux内核 | linux-4.19.71(NXP官方提供) |
点击查看本文参考资料
分类 | 网址 | 说明 |
官方网站 | https://www.arm.com/ | ARM官方网站,在这里我们可以找到Cotex-Mx以及ARMVx的一些文档 |
https://www.nxp.com.cn/ | NXP官方网站 | |
https://www.nxpic.org.cn/ | NXP 官方社区 | |
https://u-boot.readthedocs.io/en/latest/ | u-boot官网 | |
https://www.kernel.org/ | linux内核官网 |
点击查看相关文件下载
分类 | 网址 | 说明 |
NXP | https://github.com/nxp-imx | NXP imx开发资源GitHub组织,里边会有u-boot和linux内核的仓库 |
nxp-imx/linux-imx/releases/tag/v4.19.71 | NXP linux内核仓库tags中的v4.19.71 | |
nxp-imx/uboot-imx/releases/tag/rel_imx_4.19.35_1.1.0 | NXP u-boot仓库tags中的rel_imx_4.19.35_1.1.0 | |
I.MX6ULL | i.MX 6ULL Applications Processors for Industrial Products | I.MX6ULL 芯片手册(datasheet,可以在线查看) |
i.MX 6ULL Applications ProcessorReference Manual | I.MX6ULL 参考手册(下载后才能查看,需要登录NXP官网) | |
Source Code | https://elixir.bootlin.com/linux/latest/source | linux kernel源码 |
https://elixir.bootlin.com/u-boot/latest/source | uboot源码 |
一、有哪些文件?
前面我们学习linux系统组件,知道它包括uboot、kernel、设备树、根文件系统,我们前面做完移植,得到了下面这些文件。
前面我们将uboot的imx文件烧写到sd卡中,从tftp下载zImage和dtb,从nfs挂载根文件系统,那么我们怎么脱离网络启动?我们从这一节开始来详细学习一下系统的烧写。
二、怎么给SD卡分区
首先,我们来学习一下SD卡分区,后面会知道为什么要先学习这个了。这里我们在ubuntu中操作。
1. 查看SD卡信息,确定挂载点
1.1 插入sd卡
首先我们要将SD卡插入PC电脑,保证vmware中的ubuntu识别到了sd卡,这个一般都没啥问题。
1.2 相关命令
1 | fdisk -l # 查看系统真实存在的设备,也就是说,是一直处于动态监控设备状态,只要有一个设备‘消失’,它都会显示。 |
注意: 查看系统真实存在的硬盘设备的时候
- 查看系统真实存在的硬盘设备,看到的不一定是系统识别的
- 存在的,不一定是识别的
- 识别的,不一定是使用的
- 使用的,不一定是正在用的
- 系统真实存在的不一定能被识别,能识别的不一定能被用,能用的不一定是正在用
1.3 确定挂载点
然后我们通过下面的命令查看一下sd信息:
1 | sudo fdisk -l |
然后会有如下打印信息:
可以看到SD卡的扇区大小是512字节,挂载点是sdc。sd卡挂载之后的节点一般都是sd开头的,我们可以在/dev下看到对应的节点:
1 | ls /dev/sd* |
还有一个命令,可以直接打印出系统识别到的设备:
1 | cat /proc/partitions |
反正最后能确定挂载点就可以了。
2. 卸载SD卡
在进行分区操作时,我们需要先卸载SD卡:
1 | umount /dev/sdx |
上面是sdc,所以就是:
1 | umount /dev/sdc |
要是没挂载就算了。
3. 分区操作
3.1 进入分区菜单
1 | sudo fdisk /dev/sdc |
3.2 m——查看命令菜单
1 | m |
3.3 p——查看当前SD卡状态
1 | p |
可以看到我这里SD卡有没有分区,在进行SD卡分区前,我们要删除所有分区。这个删除操作后面再说。
3.4 创建分区
1 | n # 新建一个分区 |
然后我们再用p看一下sd卡当前状态:
可以看到这里产生了一个sdc1节点,大小为10M,这就是我们刚才制作的10M的分区。
3.5 设置分区类型
上面已经创建好分区了,接下来就是设置分区的类型:
1 | t # 设置分区类型 |
然后我们再查看一下分区的结果:
3.6 写入分区
前面我们的分区实际上还并未生效,我们要输入w命令才可以:
1 | w # 写入分区 |
输入完成后会直接退出fdisk的菜单界面。
3.7 格式化分区
我们下来看一下我们分区好后的节点情况:
1 | ls /dev/sd* |
1 | sudo mkfs.vfat -F 32 -n boot /dev/sdc1 |
mkfs.vfat
:这是一个用于创建 VFAT 文件系统的命令。VFAT 是 FAT 文件系统的一个变种,它支持长文件名,通常用于 USB 闪存驱动器、SD 卡等存储设备。尽管名为vfat
,这个命令也可以用来创建标准的 FAT12、FAT16 和 FAT32 文件系统。-F 32
:这个选项指定了要创建的 FAT 文件系统的类型。数字32
表示创建一个 FAT32 文件系统。FAT32 支持更大的分区和文件大小,通常用于大于 2GB 的分区。-n boot
:这个选项用来设置文件系统的卷标(volume label)。在这个例子中,卷标被设置为boot
。卷标是一个简短的文本字符串,用于在文件系统中标识分区,通常在挂载点、文件浏览器等地方显示。/dev/sdc1
:这是指定要格式化的分区的设备文件。在 Linux 系统中,硬盘和分区通常以/dev/sdX
的形式表示,其中X
是字母,表示设备(如sda
表示第一个硬盘),数字(如1
)表示分区号(如sda1
表示第一个硬盘的第一个分区)。在这个例子中,/dev/sdc1
表示第三个硬盘的第一个分区。
会发现这里报了个警告。
先了解一下了解一下簇的概念和扇区的区别:
簇和扇区不是属于一个范畴。簇是系统在硬盘上读写文件时的单位,是一个数据块。而扇区是硬盘划分的最小单位值,就是簇(数据块)占用的地方。
簇的大小大于扇区的大小。硬盘每簇的扇区数与硬盘的总容量大小有关。扇区是存储介质上可由硬件寻址的基本单位,x86系统几乎总是定义512字节的扇区大小;簇是许多文件系统格式使用的可寻址数据块,簇的大小总是扇区大小的整数倍,且不同文件系统对于不同大小的卷(分区)会有不同的默认簇大小,比如FAT32对于8GB以下的分区,默认簇大小为4KB,对于8GB ~ 16GB的分区,默认簇大小为16个扇区(8KB),NTFS对于大于2GB的分区,默认簇大小为8个扇区(4KB)。
打个比方,我们(系统)要在仓库(仓库可视为硬盘)里存放一些书(数据)。我们先把书分门别类放到一些大纸箱(簇)里,然后放进仓库,纸箱的体积是根据我们仓库大小来决定的,而仓库始终划分成单位为0.1立方米的小格子(扇区),仓库大了,纸箱就大些,仓库小了,纸箱就小些。制作fat32文件系统有个最小的簇的个数要求:这里扇区大小为512bytes,经测试当簇大小等于1个扇区时,分区最少需要40MB,当簇大小设为2个扇区时,分区至少需要80MB,40M / 512 = 81920, 80M / 512 / 2 = 81920,计算出制作fat32的分区大小至少需要有81920个簇。
我后面重新创建了一个40M的分区,然后格式化就没问题了:
这里这个这个警告信息是在提醒我们,在使用DOS或Windows系统时,使用小写的标签(labels)可能会导致一些问题或无法正常工作。这通常发生在处理文件系统、批处理脚本、环境变量或其他需要区分大小写的场景中,但DOS和早期版本的Windows(如Windows 95, 98, ME)的文件系统通常是不区分大小写的,而它们的某些命令行工具和环境变量处理却可能是区分大小写的。这里其实不用关心。
3.8 删除分区
上面不是刚好报了警告,我们学习一下怎么删除分区:
1 | d # 删除分区 |
有多个分区?这个会提示我们选择要删除的分区的:
3.9 挂载分区
格式化完成后我们需要将SD卡挂载到系统,直接点击系统边上的U盘图标(要是没有的画,直接拔掉重新插一下就可以了):
可以看到这里的卷标就是boot,使我们刚才设置的。我们还可以用df命令看一下:
1 | df -h |
我们也可以手动挂载:
1 | sudo mkdir -p /mnt/sdc1_tmp # mkdir命令创建一个空目录,用于挂载SD卡上的文件系统。 |
3.10 卸载分区
1 | sudo umount <sdcard mount dir> |
三、SD卡启动盘制作
1. 参考资料
NXP为我们提供了一份文档,,这个其实位于L4.1.15_2.0.0_LINUX_DOCS (nxp.com.cn)这个压缩包内
我们下载下来解压就可以看到:
里面有一章在介绍这个:
这里有一份在线的,i.MX Linux User’s Guide (nxp.com),但是不是这个4.15版本,不过都差不多。
2. SD卡分区情况说明
先来看一下i.MX6ULL使用SD卡启动时的分区情况,NXP官方给的镜像布局结构如下所示(《i.MX Linux User’s Guide》的4.3 Preparing an SD/MMC card to boot ):
可以看到,上图将一张SD卡分成了三部分:
第一部分:扇区起始地址0x400bytes(2),大小为20478个扇区,分区格式为原始格式,用于存放uboot。0x400 bytes转为10进制是1024 bytes, 刚好等于2个扇区大小;这两个扇区是为了保存分区表的信息。所以从0x400地址开始存放U-boot,括号中的2可以理解为从第2个扇区的起始地址开始,扇区编号从0开始数起。
第二部分:扇区起始地址0xa0000 bytes(20480个扇区),大小为500M(1024000个扇区),分区格式为FAT,用于存放内核和设备树;
第三部分:扇区起始地址0x25800000(1228800个扇区),大小为SD卡剩余的空间,分区格式为Ext3或Ext4,用于存放rootfs,也就是文件系统。(注意:就这里其实有个坑的,我也不知道为啥,后面会说到这个地方,这里注意下)
由于第一部分用于存放U-Boot,无文件系统格式的要求,所以我们对分区的创建从第二部分(第20480扇区所在的地址)开始就可以。拿到一张SD卡,首先将SD卡在windows下格式化成FAT32格式:
这里只有40M应该是因为我前面做实验的时候的第一个分区是40M的原因。
3. 对SD卡重新分区
3.1 确认节点名称
我这里重新插入ubuntu后节点是sdc:
可以看到是没有其他分区的,但有时候拿到的sd卡可能有分区,就按后面的继续处理。有分区的是这样的:
3.2 卸载所有分区
当有其他分区存在的时候,我们需要卸载所有分区
1 | ls /dev/sdc* |
3.3 清空SD卡
一般来说清空前面的部分数据即可:
1 | sudo dd if=/dev/zero of=/dev/sdc bs=1024 count=1024 |
3.4 两个分区
手册上fdisk的命令说明:
1 | sudo fdisk /dev/sdx |
这里我不按NXP的文档来了,主要是出现了这个问题,相同的步骤我按照NXP的文档,最后我挂载sdc2的时候出现了这个问题:
我按照网上的说法用下面这个命令处理:
1 | sudo fsck -y /dev/sdc2 # 出现"结构需要清理"说明磁盘文献问题,需要使用这个命令进行检查修复 |
但是最后没啥用,我甚至还怀疑是我sd卡有问题,然后我去试了正点原子教程的分区方式,就没问题,说明还是分区的问题。最后也没解决,不过,分区还是为了放文件,也没有必要那么严格的按照NXP文档来。后面我就按需要来了。
3.4.1 分区1——64M
这个分区用于存放kernel和设备树文件,我们可以看一下这两个文件多大:
发现一个文件8M,一个文件27K,所以其实第一个分区根本没必要500M,这里给64M吧:
3.4.2 分区2——剩余部分
3.4.3 设置分区格式
这里其实在NXP的文档中并没有,不过我看正点原子脚本中有,就也加上了:
这里主要是设置一下分区1的格式就行。然后我们再设置一下分区1为启动分区(官方文档没有这一步,正点原子的脚本有,这里就一起加上了):
3.4.4 最终分区情况
3.4.5 写入分区
最后的最后一定要输入w命令写入分区,确认分区的修改:
3.5 格式化分区
1 | 设置sdc1分区格式为FAT |
3.6 SD卡分区情况分析
我们来看一下最终的sd卡分区情况:
此时sd卡分布如下图:
前面好像就留了大概1M来写uboot,够吗》我们看一下uboot镜像文件的大小:
基本上够了,uboot只是拿来引导一下启动linux内核,也不会增加什么额外的功能,这个大小差不多够了。
4. 烧写uboot到sd卡
这个和前面没什么区别,就是从偏移1KB的位置开始烧写uboot的imx文件即可:
1 | sudo dd if=u-boot-dtb.imx of=/dev/sdc bs=1024 seek=1 conv=fsync |
从上面我们对SD卡分区的时候知道,uboot需要从第0分区的扇区地址2开始的,SD卡中一个扇区占512字节,SD卡偏移1K字节处开始保存uboot。上面这条命令中,bs设置dd命令的读写块为1K大小(这个数据可以任意设置,设置大一点读写就快),并且设置seek=1(单位为KB),表示从SD卡/dev/sdb开头偏移1K字节处开始写u-boot-dtb.imx,正好就是写到了u-boot在SD卡中0区所在位置处,前面预留1K字节刚好2个扇区大小保存分区表信息。
为什么从SD卡1K位置处存放uboot而不是从SD卡头部开始?
这是NXP官方手册《i.MX Linux® User’s Guide 》上写前面1K字节是保存分区表的信息,在Rev. L4.1.15_2.0.0-ga, 10/2016这个版本上没有,但是后面更新的文档都有说明了,例如这个:i.MX Linux User’s Guide (nxp.com)
5. 拷贝kernel和dtbs
接下来就是把kernel和设备树拷贝到分区1中。
- 创建挂载点
1 | mkdir -p ~/tmp/sd_sdc1 |
- 挂载分区1
1 | sudo mount /dev/sdc1 ~/tmp/sd_sdc1 # (注意根据上面的分区这是sdc1,存放kernal image和dtbs) |
- 使用cp命令将zImage和*.dtb文件拷贝进/media/sd_sdc1目录
1 | sudo cp zImage ~/tmp/sd_sdc1/ |
- 取消挂载点
1 | sudo umount ~/tmp/sd_sdc1 |
6. 拷贝文件系统到SD卡
6.1 拷贝文件
和分区1的操作流程一样:
1 | mkdir -p ~/tmp/sd_sdc2 |
6.2 解压根文件系统
1 | sudo mkdir rootfs |
可能是打包方式问题吧,需要解压两次,但感觉又不应该,算了就这样吧。
6.3 拷贝到顶层目录
1 | sudo cp -a * ~/tmp/sd_sdc2 |
其实吧,直接在挂载的目录下解压就可以了,没必要多此一举,之前是以为有什么问题,后面直接挂载目录解压就可以。
6.4 取消挂载
1 | sudo umount /dev/sdc2 |
7. 总结
到此为止,sd卡启动盘就算是做好了,我们已经在sd卡中烧写了uboot、kernel、dtb文件以及根文件系统:
四、从SD卡启动
1. 拨码开关设置
我们要先设置为SD卡启动:
2. uboot相关命令
我们先复习几个命令,后面会用到的。
2.1 进入uboot
2.2 EMMC和SD卡操作
我们来熟悉一下mmc相关的命令。uboot 支持 EMMC 和 SD 卡,因此也要提供 EMMC 和 SD 卡的操作命令。一般认为 EMMC
和 SD 卡是同一个东西 。
1 | => mmc |
可以看出, mmc 后面跟不同的参数可以实现不同的功能 :
命令 | 描述 |
---|---|
mmc info | 输出 MMC 设备信息 |
mmc read | 读取 MMC 中的数据。 |
mmc wirte | 向 MMC 设备写入数据。 |
mmc rescan | 扫描 MMC 设备。 |
mmc part | 列出 MMC 设备的分区。 |
mmc dev | 切换 MMC 设备。 |
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 寄存器的值。 |
2.2.1 mmc rescan 命令
1 | => mmc rescan |
好像没见打印输出,先不管。
2.2.2 mmc list 命令
list 命令用于来查看当前开发板一共有几个 MMC 设备,输入“mmc list” :
1 | => mmc list |
可以看出当前开发板有两个 MMC 设备: FSL_SDHC:0 和 FSL_SDHC:1 (eMMC),这是因为我现在用的是 EMMC 版本的核心板,加上 SD 卡一共有两个 MMC 设备, FSL_SDHC:0 是 SD卡, FSL_SDHC:1(eMMC)是 EMMC。
2.2.3 mmc dev 命令
mmc dev 命令用于切换当前 MMC 设备,命令格式如下
1 | mmc dev [dev] [part] |
dev用来设置要切换的 MMC 设备号, part是分区号。如果不写分区号的话默认为分区 0。使用如下命令切换到 SD 卡:
1 | => mmc dev 0 # 切换到 SD 卡, 0 为 SD 卡, 1 为 eMMC |
2.2.4 mmc info 命令
mmc info 命令用于输出当前选中的 mmc info 设备的信息,输入命令“mmc info”即可:
1 | => mmc info |
看出当前 SD 卡为 1.10 版本的,容量为 1.9GiB(2GB 的 SD 卡), 4 位宽的总线。
2.2.5 mmc part 命令
SD 卡或者 EMMC 会有多个分区,可以使用命令“mmc part”来查看其分区
- 查看emmc分区
1 | => mmc dev 1 |
这里好像切换失败了,先不管吧,后面再说。
- 查看sd卡分区
1 | => mmc dev 0 |
此时 SD卡 有两个分区, 第一个分区起始扇区为 2048,长度为 131072个扇区; 第二个分区起始扇区为 133120,长度为 3798016个扇区。如果 SD卡 里面烧写了 Linux 系统的话, SD 是有 3 个分区的,第 0 个分区存放 uboot,第 1 个分区存放Linux 镜像文件和设备树,第 2 个分区存放根文件系统。但是在上面只有两个分区,那是因为第 0 个分区没有格式化,所以识别不出来,实际上第 0 个分区是存在的。一个新的 SD卡默认只有一个分区,那就是分区 0,前面我们就是把uboot烧写到了分区0.
2.3 FAT格式文件系统操作
有时候需要在 uboot 中对 SD 卡或者 EMMC 中存储的文件进行操作,这时候就要用到文件操作命令,跟文件操作相关的命令有: fatinfo、 fatls、 fstype、 fatload 和 fatwrite,但是这些文件操作命令只支持 FAT 格式的文件系统!!
2.3.1 fatinfo 命令
fatinfo 命令用于查询指定 MMC 设备分区的文件系统信息 :
1 | fatinfo <interface> [<dev[:part]>] |
interface 表示接口,比如 mmc, dev 是查询的设备号, part 是要查询的分区。比如我们要查询 SD卡 分区 1 的文件系统信息 :
1 | => fatinfo mmc 0:1 |
2.3.2 fatls 命令
atls 命令用于查询 FAT 格式设备的目录和文件信息 :
1 | fatls <interface> [<dev[:part]>] [directory] |
interface 是要查询的接口,比如 mmc, dev 是要查询的设备号, part 是要查询的分区, directory是要查询的目录。比如查询 SD卡分区 1 中的所有的目录和文件,输入命令:
1 | => fatls mmc 0:1 |
可以看到分区1中就是zImage和dtb文件。
2.3.3 fstype 命令
fstype 用于查看 MMC 设备某个分区的文件系统格式 :
1 | fstype <interface> <dev>:<part> |
我们来看一下SD卡的几个分区:
1 | => fstype mmc 0:0 |
分区 0 格式未知,因为分区 0 存放的 uboot,并且分区 0 没有格式化,所以文件系统格式未知。分区 1 的格式为 fat,分区 1 用于存放 linux 镜像和设备树。分区 2 的格式为 ext4,用于存放 Linux 的根文件系统(rootfs)。
2.3.4 fatload 命令
fatload 命令用于将指定的文件读取到 DRAM 中 :
1 | fatload <interface> [<dev[:part]> [<addr> [<filename> [bytes [pos]]]]] |
interface 为接口,比如 mmc, dev 是设备号, part 是分区, addr 是保存在 DRAM 中的起始地址, filename 是要读取的文件名字。 bytes 表示读取多少字节的数据,如果 bytes 为 0 或者省略的话表示读取整个文件。 pos 是要读的文件相对于文件首地址的偏移,如果为 0 或者省略的话表示从文件首地址开始读取。我们将 SD卡分区 1 中的 zImage 文件读取到 DRAM 中的0X80800000 地址处,
1 | => fatload mmc 0:1 80800000 zImage |
2.3.5 fatwrite 命令
注意! uboot 默认没有使能 fatwrite 命令,需要修改板子配置头文件,比如 mx6ullevk.h、mx6ull_alpha_emmc.h 等等,板子不同,其配置头文件也不同。找到自己开发板对应的配置头文件然后添加如下一行宏定义来使能 fatwrite 命令:
1 |
我用的这个2019版本的直接打开了好像,没打开的话在源码修改一下就可以了。fatwirte 命令用于将 DRAM 中的数据写入到 MMC 设备中,命令格式如下:
1 | fatwrite <interface> <dev[:part]> <addr> <filename> <bytes> |
interface 为接口,比如 mmc, dev 是设备号, part 是分区, addr 是要写入的数据在 DRAM中的起始地址, filename 是写入的数据文件名字, bytes 表示要写入多少字节的数据。我们可以通过 fatwrite 命令在 uboot 中更新 linux 镜像文件和设备树。
所以我们可以在uboot下在线更新kernel镜像文件和设备树文件,我们可以直接从tftp下载这两个文件到内存中,然后写入到对应的分区中去。
我们以更新 linux 镜像文件 zImage为例,首先将 zImage 镜像文件拷贝到 Ubuntu 中的tftpboot 目录下,命令 tftp 将 zImage 下载到 DRAM 的 0X80800000 地址处,命令如下:
1 | => tftp 80800000 zImage |
zImage 大小为 8315704(0x7ee338)个字节 ,接下来使用命令 fatwrite 将其写入到 SD卡的分区 1 中,文件名字为 zImage :
1 | => fatwrite mmc 0:1 80800000 zImage 7ee338 |
3. 手动启动内核
3.1 进入uboot界面
跟前面操作一样。
3.2 设置bootargs参数
设置bootargs参数,指定根文件系统保存的路径:
1 | 指定根文件系统在mmc设备0的2分区上。并且ip地址为静态ip地址 |
这里主要是设置根文件系统的挂载路径,需要知道的是,不管是sd卡还是emmc在linux中的文件节点都叫mmcblk,这里的mmc0就表示sd卡,p2就表示sd卡的第二个分区,也就是我们前面创建的根文件系统所在分区。
3.3 加载内核镜像
加载zImage内核到内存的0x80800000地址上:
1 | => load mmc 0:1 0x80800000 zImage |
其实和前面的fatload是一样的。
3.4 加载设备树
加载设备树到0x83000000内存地址上:
1 | => load mmc 0:1 0x83000000 imx6ull-alpha-emmc.dtb |
3.5 启动内核
1 | => bootz 0x80800000 - 0x83000000 |
然后内核就起来了,然后就出问题了:
4. 问题解决
4.1 JBD2——问题一
4.1.1 问题分析
我们先来看这两行:
1 | [ 6.761505] JBD2: no valid journal superblock found |
这里吧其实我没怎么深入研究,大概的原因就是新的操作系统上使用系统自带的 mkfs.ext4 对文件系统进行了格式化,默认使用了一些新的的特性,这些新的特性在旧的系统上是无法使用的,即在旧的内核上不支持。
我们可以看一下ubuntu的内核版本:
而我使用的linux内核是4.19版本的,也许是中间加入了某些新的特性吧。这里主要是journal相关的这个特性出了问题,怎么处理呢?网上搜了一堆,简单说就是把这个属性去掉就好了。
4.1.2 解决方法
- (1)确定sd卡节点
这里出问题的是sd卡的ext4分区,也就是sdx2,我的挂载上来就是sdc2:
1 | sumu@sumu-virtual-machine:~/7Linux/imx6ull-alpha-release/release$ cat /proc/partitions |
- (2)看分区journal日志
1 | sudo tune2fs -l /dev/sdc2 | grep feature |
发现是有这个has_journal特性,我们接下来要做的就是去掉这个特性。
- (3)卸载分区
1 | sudo mount /dev/sdc2 |
- (4)修改分区journal日志
1 | sudo tune2fs -O ^has_journal /dev/sdc2 |
- (5)检查是否成功
1 | sudo tune2fs -l /dev/sdc2 | grep feature |
发现已经没有了。
4.1.3 开发板验证
我们来验证一下,和前面的步骤一摸一样,正常应该是问题已经解决了:
发现可以这次正常挂载了
4.2 EXT2-fs——问题二
甚至第二个问题也没了,大概应该是上面的问题一引起的第二个问题吧。那这里就不管了。
5. 自动挂载
每次都要敲那么多的命令,其实uboot是有自动运行的命令的,就是bootcmd环境变量,在uboot启动后,会自动运行这个环境变量里面的命令。我们来配置一下:
1 | 设置启动参数 |
然后我们复位开发板就会发现可以自动加载镜像和设备树,并且自动启动了:
最后也是可以正常启动了:
五、做成shell脚本
每次敲那么多命令肯定很烦,做成shell脚本呗:release/imx6ull_sd_boot.sh · 苏木/imx6ull-alpha-release - 码云 - 开源中国 (gitee.com)
参考资料:
SD卡启动与uboot 、zImage、dtb、rootfs固化_怎么让 uboot kernel rootfs 在 sd 卡里运行-CSDN博客
imx6ul基于zImage,dtb 在SD卡制作linux镜像 - 知乎 (zhihu.com)
imx6ull开发板设置SD卡启动,SD卡中烧写uboot,kernel,设备树,根文件系统fs_imx6ull sd卡-CSDN博客
解决 EXT4 使用无法挂载-阿里云开发者社区 (aliyun.com)
linux开机启动挂载mmc错误解决_qqliyunpeng-GitCode 开源社区 (csdn.net)
[Linux如何关闭分区journal日志 - 飞入云端_blog - 博客园 (cnblogs.com)](https://www.cnblogs.com/zhangyunfei-blog/p/9288482.html#:~:text=1.重启系统,进入单用户模式 2.查看要修改的分区 %23df -h 3.查看分区journal日志 (如%2Fdev%2Fsda1) %23tune2fs -l,|grep feature 查看是否有has_journal字段 4.以只读模式挂载根分区 %23mount -o remount%2Cro %2Fdev%2Fsda1)