imx6ull 开发板,SD卡启动,给EMMC分区,烧系统。
接上一篇博客本文内容采用脚本一键分区格式化 一键烧录系统。运行脚本需要 sfdisk 工具上一篇博客有用 buildroot 安装 sfdisk 的方法。emmc 重新规划分区分区类型起始扇区结束扇区扇区数大小文件系统用途p1 (主)c204813311913107264 MiBFAT32bootA内核设备树p2 (主)c13312026419113107264 MiBFAT32bootB内核设备树p3 (主)83264192445849541943042 GiBext4rootfsA当前运行系统p4 (扩展)544584961526988710811392~5.16 GiB—扩展容器p5 (逻辑)834460544865484741943042 GiBext4rootfsB待升级槽p6 (逻辑)838656896152698876612991~3.15 GiBext4data用户数据 recovery 子目录U-Boot 冗余 由 boot0 boot1 分区硬件双备份保证 把主分区槽位空出来留给更关键的系统组件。recovery 独立分区的需求不变但受主分区数量限制放入扩展分区会降低安全性。这里我们先保留 154M 空间不分配待以后升级 U-Boot 支持 GPT 或改用 4 主分区方案时再调整。当前我们可将 recovery 的内容放在 data 分区的一个子目录如/data/recovery中系统挂死时通过 U-Boot 命令行手动加载。在 MBR 的扩展分区中每一个逻辑分区前面都需要一个 EBR扩展引导记录来描述自己。p5 EBR4460544p5数据起始扇区44605442048 4462592p6 EBR8654848p6数据起始扇区86548482048 8656896分区脚本 emmc_part.sh 代码#!/bin/sh # 等待设备节点就绪 while [ ! -e $1 ] do sleep 1 echo [Log]: wait for $1 appear done DEV$1 # 擦除旧的 MBR 分区表 (擦除前1MB) echo [Log]: Wiping old partition table... dd if/dev/zero of${DEV} bs1024 count1 sync # p1主分区 结束1M 64M 65M # p2主分区 结束65M 64M 129M # p3主分区 (rootfsA, 2G) 结束129M 2G 2177M # p4扩展容器 起始2177M # p5逻辑分区 (rootfsB, 2G) 结束(1M(EBR) 2177M) 2G 4226M # P6逻辑分区 data用户数据起始1M(EBR) 4226M 4227M echo [Log]: Creating partitions... sfdisk --force ${DEV} EOF 1M,64M,0c 65M,64M,0c 129M,2G,83 2177M,,0x05 2178M,2G,83 4227M,,83 EOF # 确保内核识别到新分区 再格式化分区 echo [Log]: Reloading partition table... partprobe ${DEV} 2/dev/null || sleep 2 echo [Log]: Formatting... mkfs.fat ${DEV}p1 mkfs.fat ${DEV}p2 mkfs.ext4 -F ${DEV}p3 mkfs.ext4 -F ${DEV}p5 mkfs.ext4 -F ${DEV}p6 echo [Log]: Partition and Format Complete! sfdisk -l ${DEV}SD卡 启动linux运行脚本分区、格式化 成功。挂载测试测试完后卸载所有挂载点挂载测试是为了验证文件系统没有损坏能正常读写。mkdir -p /mnt/bootA /mnt/bootB /mnt/rootA /mnt/rootB /mnt/data参考图片 挂载每个分区 p4 不要挂载。卸载所有挂载点umount /mnt/bootAumount /mnt/bootBumount /mnt/rootAumount /mnt/rootBumount /mnt/data验证已卸载确认不再有 /mnt/bootA 等条目。df -h下一步给 emmc 烧录系统我是nfs挂载的根文件系统 通过 NFS 传到板子上烧录。在虚拟机上把 u-boot.imx 内核、设备树、根文件系统压缩包 拷贝到 NFS 上自己创建的目录里。1.烧录 U-Boot到 eMMC boot0/boot1 执行脚本 01_burn_uboot.sh下面是脚本代码#!/bin/sh # 01_burn_uboot.sh - 烧录 U-Boot 到 eMMC boot0/boot1 # 更新频率极低仅 U-Boot 升级时使用 DEV/dev/mmcblk1 echo [Log] Burn U-Boot to eMMC # 检查文件 if [ ! -f u-boot.imx ]; then echo [Log] ERROR: u-boot.imx not found! exit 1 fi echo [Log] Burning to boot0... echo 0 /sys/block/mmcblk1boot0/force_ro dd ifu-boot.imx of${DEV}boot0 bs512 seek2 echo 1 /sys/block/mmcblk1boot0/force_ro sync echo [Log] Burning to boot1 (backup)... echo 0 /sys/block/mmcblk1boot1/force_ro dd ifu-boot.imx of${DEV}boot1 bs512 seek2 echo 1 /sys/block/mmcblk1boot1/force_ro sync # 设置 u-boot 从boot0 启动 echo [Log] Setting eMMC to boot from boot0... mmc bootpart enable 1 1 ${DEV} # 确认 mmc extcsd read ${DEV} | grep PARTITION_CONFIG echo [Log] U-Boot burn complete!开机测试开发板的拨码开关选择 emmc 启动开机boot0 boot1 双 U-Boot 备份完全正常。boot0 和 boot1 各有一套独立的 U-Boot双备份但它们读写环境变量时, 共用一份 env。env的存储位置是由编译 u-boot 时指定偏移量。固化环境变量从 boot0 启动mmc partconf 1 1 1 1从 boot1 启动 mmc partconf 1 1 2 1切回 boot0 输入下面的命令固化环境变量mmc partconf 1 1 1 1mmc dev 1 0设置启动后 使用 emmc 分区3 的根文件系统可以读写setenv bootargs consolettymxc0,115200 root/dev/mmcblk1p3 rootwait rw或者 只读挂载防篡改二选一。setenv bootargs consolettymxc0,115200 root/dev/mmcblk1p3 rootwait ro设置从 emmc 分区1加载 内核 设备树setenv bootcmd fatload mmc 1:1 0x80800000 zImage; fatload mmc 1:1 0x83000000 imx6ull-emmc.dtb; bootz 0x80800000 - 0x83000000保存 saveenv重启 reset2 . 烧录内核 设备树到 bootA 和 bootBSD 卡 启动 linux继续烧录。下面是 脚本 02_burn_kernel.sh 代码#!/bin/sh # 烧录内核 设备树到 bootA 和 bootB, 可以自己指定目标 # 内核/设备树 更新时使用 DEV/dev/mmcblk1 echo [Log] Burn Kernel / DTB to Boot Partitions # 检查文件 if [ ! -f zImage ]; then echo [Log] ERROR: zImage not found! exit 1 fi DTB$(ls *.dtb 2/dev/null | head -1) if [ -z $DTB ]; then echo [Log] ERROR: dtb file not found! exit 1 fi echo [Log] Copying to bootA (p1)... mount ${DEV}p1 /mnt cp zImage /mnt/ cp $DTB /mnt/imx6ull-emmc.dtb sync umount /mnt echo [Log] Copying to bootB (p2)... mount ${DEV}p2 /mnt cp zImage /mnt/ cp $DTB /mnt/imx6ull-emmc.dtb sync umount /mnt echo [Log] Kernel / DTB burn complete!运行脚本然后验证mount /dev/mmcblk1p1 /mntls /mntumount /mnt用同样的方法验证 mmcblk1p202_burn_kernel.sh 脚本的24、31行拷贝时 DTB 改名字了知道就行。3 . 烧录 根文件系统下面是 脚本 03_burn_rootfs.sh 代码#!/bin/sh # 烧录根文件系统到 rootfsA DEV/dev/mmcblk1 echo [Log] Burn Rootfs to rootfsA (p3) # 检查文件 if [ ! -f rootfs.tar ]; then echo [Log] ERROR: rootfs.tar not found! exit 1 fi echo [Log] Formatting rootfsA... mkfs.ext4 -F ${DEV}p3 echo [Log] Extracting rootfs... mount ${DEV}p3 /mnt tar -xf rootfs.tar -C /mnt sync umount /mnt echo [Log] Rootfs burn complete!运行脚本然后验证mount /dev/mmcblk1p3 /mntls /mntumount /mnt开机测试开发板的拨码开关选择 emmc 启动开机p6 数据分区 没挂载所以看不到。数据区 (独立分区6) 设置为开机自动挂载 mkdir -p /datamount /dev/mmcblk1p6 /dataecho /dev/mmcblk1p6 /data ext4 defaults 0 0 /etc/fstabcat /etc/fstab目录用途/data数据区随便读写/data/lostfoundext4 文件系统修复后找回的损坏文件碎片不要手动动它以后你的应用数据、日志、用户文件全部放 /data 目录下不是 /data/lostfoundlostfound 是每个 ext4 分区格式化后自动生成的系统目录正常使用不用管。home 目录 和 data 目录的区别目录位置用途/homep6rootfs A根文件系统系统的一部分升级会被覆盖/datap8data独立分区升级不丢补充说明刚才设置的data分区 开机自动挂载只在当前根文件系统生效如果烧录新的根文件系统这个开机自动挂载会失效被新的rootfs覆盖。设置永久自动挂载的方法是写入buildroot的overlay在后面的OTA升级系统 博客文章里有参考设置方法。因为是自己调试用烧录环节分成3个脚本烧录方便更新指定的文件也可以整合为1个脚本一次烧录全部系统。关于升级正常启动 → rootfs AOTA 升级 → 新系统写到 rootfs B → 切换启动 → rootfs B下次升级 → 新系统写到 rootfs A → 切换启动 → rootfs A系统运行时当前根分区处于占用状态无法完整重刷镜像因此升级包先写入闲置备用分区完成后再切换启动分区。U-Boot、内核设备树、根文件系统 全部做双备份逻辑和手机OTA升级一致在线升级完成后重启设备运行新版本系统若升级启动失败设备回滚至旧系统正常运行。从上篇博客到这篇博客最终成果脚本用途00_part.sh分区01_burn_uboot.sh烧 U-Boot 设启动02_burn_kernel.sh烧内核 dtb03_burn_rootfs.sh烧根文件系统从零到完整 A/B 双系统全部搞定。

相关新闻