i.MX6ULL - 从零构建SD卡启动盘:分区、引导与系统部署实战
1. 环境准备与SD卡基础认知第一次接触i.MX6ULL开发板时最让我头疼的就是制作启动盘。和普通U盘装系统不同嵌入式设备的存储介质布局就像拼乐高——每个组件必须放在芯片设计时规定的卡槽里。我们先来认识下这个特殊的拼图板一张普通的SD卡在i.MX6ULL眼中会被划分为三个功能明确的区域。我习惯用停车场来类比这三个分区第一个是VIP专属车位uboot区位置固定在第1KB偏移处第二个是临时停车区FAT格式的kernel区方便快速存取第三个是长期车库Ext4格式的rootfs区存放系统日常运行所需的所有文件。这种设计源于NXP芯片的启动机制——上电后ROM固件会从SD卡固定位置加载uboot就像保安必须按照固定路线巡逻。实际操作前需要准备容量≥4GB的SD卡我用SanDisk Ultra 16GB实测最稳定Ubuntu 18.04以上系统的开发机Windows子系统会有权限问题已编译好的四件套u-boot.imx、zImage、dtb文件、rootfs压缩包读卡器建议用USB3.0接口的烧录速度更快特别提醒所有操作建议在root权限下进行避免频繁输入sudo。可以通过sudo -i切换但操作要格外小心——dd命令一旦写错设备名可能直接清空你的硬盘。2. 分区规划与实战操作2.1 理解NXP官方分区布局打开NXP的《i.MX_Linux_Users_Guide.pdf》官方给出的SD卡布局就像一张精密的地图uboot区从第2扇区开始即1KB偏移占用20478个扇区约10MBkernel区从20480扇区开始即10MB处默认分配500MB FAT32分区rootfs区剩余所有空间格式化为Ext4为什么uboot要从1KB偏移开始这是芯片ROM代码的硬性规定——就像CPU只认自家后门的钥匙孔。我在IMX6ULLRM手册第8.5.1节找到答案芯片上电后ROM会从存储介质第1KB位置读取IVT镜像向量表这个数据结构相当于uboot的入职通知书。2.2 分区实操步骤插入SD卡后先确认设备节点。我吃过亏——把/dev/sda当成SD卡操作结果系统盘数据全毁。安全做法是lsblk # 插入前记录现有设备 插入SD卡后再执行 lsblk # 新增的设备就是SD卡比如/dev/sdb接下来是分区魔术时刻fdisk /dev/sdb依次输入#后为注释d # 删除现有分区 n # 新建主分区1 p # 类型为主分区 1 # 分区号1 20480 # 起始扇区10MB处 500M # 分配500MB n # 新建主分区2 p 2 # 分区号2 1044480 # 起始扇区约510MB处 # 直接回车使用剩余空间 w # 写入分区表分区完成后需要格式化这里有个坑Windows格式化的FAT32默认簇大小是32KB但嵌入式系统建议用4KB。正确做法mkfs.vfat -F 32 -s 4 /dev/sdb1 # FAT32格式4KB簇大小 mkfs.ext4 /dev/sdb2 # 推荐ext4而非ext33. 组件烧录的精准操作3.1 烧写uboot的玄机看似简单的dd命令藏着三个关键参数dd ifu-boot.imx of/dev/sdb bs1k seek1 convfsyncbs1k以1KB为块大小对应SD卡扇区512字节*2seek1跳过1个块即从1KB处开始写convfsync确保数据完全写入物理介质我曾尝试去掉conv参数结果开发板启动失败——缓存没刷新的数据就像没寄出的信CPU根本收不到。3.2 内核与设备树的部署挂载FAT分区时建议使用noatime选项减少不必要的写操作mkdir -p /mnt/sd_boot mount -o noatime /dev/sdb1 /mnt/sd_boot cp zImage *.dtb /mnt/sd_boot/ sync umount /mnt/sd_boot设备树文件命名有讲究如果是imx6ull-14x14-evk.dtb这样的通用文件建议复制一份改名为imx6ull.dtb作为默认设备树避免uboot环境变量配置错误导致启动失败。3.3 根文件系统解压技巧解压rootfs时推荐用pv监控进度需安装pv包mount /dev/sdb2 /mnt/sd_root pv rootfs.tar.bz2 | tar -xjf - -C /mnt/sd_root遇到cannot create symlink错误时需要给tar加上--no-overwrite-dir参数。解压完成后执行chown -R root:root /mnt/sd_root/*确保权限正确。4. 验证与调试技巧4.1 启动日志分析连接串口终端推荐picocom后正常启动会看到如下关键阶段U-Boot 2020.04 (Jun 15 2023 - 16:20:35 0800) # uboot版本信息 DRAM: 512 MiB # 内存初始化 MMC: FSL_SDHC: 0 # SD卡识别 Loading Environment from MMC... OK # 环境变量加载 Kernel image 0x80800000 [ 0x000000 - 0x5f2e28 ] # 内核加载 Starting kernel ... # 交接控制权如果卡在某个阶段可以尝试uboot阶段失败检查dd命令参数和SD卡接触内核panic确认设备树是否匹配开发板型号卡在文件系统挂载检查rootfs是否完整解压4.2 分区完整性检查拔出SD卡前务必执行sync更好的做法是eject /dev/sdb # 确保所有缓存写入物理介质在Windows下看到SD卡只剩一个500MB分区是正常的——Ext4分区Windows不识别。可以用DiskGenius等工具验证分区实际存在。遇到启动问题时我最常用的三板斧重新烧写uboot最容易出问题的环节检查启动引脚设置开发板上的拨码开关换张SD卡测试劣质卡会导致玄学问题记得第一次成功启动时串口打印出Linux小企鹅logo那一刻的成就感——这大概就是嵌入式开发的魅力所在。现在每次看到这个logo都会想起当初因为少写一个sync参数调试到凌晨三点的经历。