平台:正点原子I.MX6ULL开发板,Linux4.1.15内核 目标:搞懂嵌入式Linux系统移植整体概念、三大镜像文件、三种烧录模式,理清开发调试与量产的不同使用场景。

一、什么是Linux系统移植

简单来说,系统移植就是让Linux操作系统能够在我们的开发板硬件上跑起来。

PC机的Linux已经适配好了X86硬件,但是i.MX6ULL是ARM硬件,原厂内核不能直接运行,我们需要准备三套核心组件,把它们烧写到开发板存储介质,才能完整启动Linux。

Linux内核可以给开发板提供这些核心能力:

  • 内存管理
  • 进程调度
  • 虚拟文件系统
  • 进程间通信IPC
  • 网络接口

移植需要的4个关键文件

文件作用对应文件名
U‑Boot(BootLoader)初始化硬件,引导内核启动u‑boot.imx
Linux内核镜像操作系统内核本体,管理软硬件资源zImage
设备树描述板载硬件资源信息(Linux3.0之后独立出来,旧版本直接编译进内核)imx6ull‑alientek‑emmc.dtb
根文件系统rootfs用户空间程序、库、配置文件,提供人机交互rootfs.tar.bz2

启动链路:U‑Boot → dtb设备树 + zImage内核 → rootfs根文件系统

开发板启动方式(拨码开关选择)

  1. USB启动:芯片下载模式,烧写系统时使用
  2. SD卡启动:软件开发调试阶段,SD卡存放整套系统
  3. EMMC启动:产品量产阶段,系统固化到板载EMMC
  4. Nand Flash:本开发板无此硬件

存储器分布:ROM固件 | uboot | zImage | dtb | rootfs | userdata

二、三种系统烧录模式对比

实际开发中有三种常用烧录方案,不同场景选不同模式,不要全部都用EMMC烧写做开发调试。

模式实现方式使用场景
模式一:烧写到SD卡将整套系统烧录进SD卡,板子从SD卡启动快速部署、系统刷机恢复,调试前期
模式二:烧写到EMMC将整套系统固化到板载EMMC芯片开发完成,产品量产出厂
模式三:uboot存SD卡,TFTP下载内核,NFS挂载根文件系统SD只放uboot;内核、dtb网络下载;rootfs网络挂载开发阶段首选,不用反复烧写存储,修改内核/文件系统直接生效,效率最高

模式一:烧写到SD卡

两种操作途径:Windows下MfgTool工具;Ubuntu下shell脚本。

Windows MfgTool烧写SD卡
  1. 解压mfgtool工具,路径不能有中文,推荐7z/winrar解压,不要Windows自带解压,长文件名会解压失败。
  2. Profiles/Linux/OS Firmware/files目录:
    • boot:存放uboot、zImage、dtb
    • filesystem:存放rootfs.tar.bz2根文件系统压缩包
  3. 运行脚本:Mfgtool2‑eMMC‑ddr512‑SDCard.vbs(DDR512版本核心板,烧录目标SD卡)
  4. 硬件操作:
    • 开发板12V供电;Type‑C接底板USB_OTG,关闭VMware虚拟机,让OTG设备识别到Windows主机
    • 拨码设置为USB启动模式(01000000)
    • 先拔掉SD卡,上电等待MfgTool识别开发板;识别成功后插入SD卡,点击Start开始烧录
  5. 等待约5分钟烧录完成;烧录完成后,拨码切换为SD卡启动,开发板上电即可运行Linux系统。

⚠️小提示:烧写时不要接LCD屏幕,容易出现白屏液化现象。

Ubuntu脚本烧写SD卡
  1. SD卡插入读卡器接入虚拟机,执行sudo fdisk -l确认SD卡设备名,一般为/dev/sdb
  2. 将mfgtool中files整个文件夹拷贝到Ubuntu。
  3. 执行烧录脚本:
sudo ./imx6mksdboot.sh -device /dev/sdb -flash emmc -ddrsize 512
  1. 脚本执行完毕,SD卡就已经写好系统;拨码切SD卡启动即可。
SD卡分区布局
  • 0扇区:MBR分区表(512字节)
  • 1KB开始存放U‑Boot镜像,最大占用至1MB
  • 分区1 FAT32(64MB)挂载/boot,存放zImage、dtb
  • 分区2 EXT3,占用剩余全部SD卡空间,挂载/根目录,存放整个rootfs

模式二:烧写到EMMC(量产模式)

同样支持Windows MfgTool、Ubuntu脚本两种方式。

Windows MfgTool烧写EMMC
  1. 使用脚本Mfgtool2‑eMMC‑ddr512‑eMMC.vbs,其余硬件接线、USB启动拨码操作与SD卡烧录基本一致。
  2. 不要插入SD卡,上电识别OTG设备,点击Start烧录,等待完成。
  3. 烧写结束,拨码切换为EMMC启动,板子直接从板载存储启动系统。
Ubuntu脚本烧写EMMC

前提:SD卡已经烧录好系统,开发板SD卡启动先跑起Linux。

  1. 串口工具minicom连接开发板,开发板与Ubuntu虚拟机处于同一局域网,网络ping通。
  2. Ubuntu开启NFS服务,开发板通过NFS挂载Ubuntu共享目录:
mount -o nolock,rw,nfsvers=3 192.168.1.100:/home/linux/nfs/rootfs /mnt
  1. 将烧录脚本和固件放到共享目录,开发板进入共享目录,执行imx6mkemmcboot.sh脚本,完成EMMC烧写。
  2. 烧写完毕拨码切换EMMC启动。

模式三:TFTP+NFS网络启动(开发调试神器)

✅开发阶段强烈推荐!不需要反复烧写SD/EMMC,每次编译出新内核、新设备树直接放在Ubuntu服务器,开发板网络加载,极大节约调试时间。

工作原理

  1. SD卡只烧录U‑Boot,板子SD卡启动,上电运行uboot。
  2. uboot通过TFTP协议从Ubuntu服务器下载zImage内核、.dtb设备树到DDR内存。
  3. 内核启动之后,不使用本地存储的rootfs,通过NFS网络直接挂载Ubuntu主机上的根文件系统。
  4. 整套系统运行,修改内核、驱动、应用只需要更新Ubuntu服务器的文件,重启板子就生效。
操作步骤
  1. 使用模式一把uboot烧录进SD卡,板子设置SD卡启动。
  2. Ubuntu配置TFTP、NFS服务:
    • tftpboot目录存放zImage、imx6ull‑alientek‑emmc.dtb
    • nfs共享目录解压好完整rootfs.tar.bz2根文件系统。
  3. 串口进入U‑Boot交互终端,配置环境变量:
env default -a
saveenv
#网络参数
setenv ipaddr 192.168.1.50          #开发板IP
setenv ethaddr 00:04:9f:04:d2:35    #MAC地址
setenv gatewayip 192.168.1.1
setenv netmask 255.255.255.0
setenv serverip 192.168.1.100       #Ubuntu虚拟机桥接网卡IP
saveenv

#bootcmd:tftp下载内核和dtb,启动内核
setenv bootcmd 'tftp 80800000 zImage;tftp 83000000 imx6ull‑alientek‑emmc.dtb;bootz 80800000 - 83000000'
saveenv

#bootargs:内核启动参数,指定nfs根文件系统
setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.1.100:/home/linux/nfs/rootfs,proto=tcp,nfsvers=3 rw ip=192.168.1.50:192.168.1.100:192.168.1.1:255.255.255.0::eth0:off'
saveenv

reset
  1. 板子重启,uboot自动执行bootcmd,通过网络加载内核和挂载NFS根文件系统,成功进入Linux。

注意:uboot中的ping命令只能开发板ping虚拟机,不能虚拟机ping开发板。

三、i.MX6ULL完整启动流程梳理

  1. Boot ROM阶段(芯片内置固化代码,不属于U‑Boot) 上电复位,芯片内部ROM固件运行。读取拨码的启动模式;把uboot.imx头部IVT/DCD/bootdata加载到片内OCRAM(片上SRAM);初始化基础时钟,DDR控制器。
  2. U‑Boot第一阶段(SPL,运行在片内OCRAM) 完成DDR完整初始化;把完整U‑Boot镜像拷贝到DDR内存(0x87800000);跳转到DDR执行U‑Boot主程序。
  3. U‑Boot第二阶段(DDR内存运行) 初始化外设,读取环境变量,执行bootcmd;把zImage内核、dtb设备树加载到DDR指定地址;通过bootargs向内核传递启动参数;调用bootz启动Linux内核。
  4. Linux内核启动 内核解压运行,执行start_kernel,完成内核各个子系统初始化,创建pid=1的init进程。
  5. 根文件系统阶段 内核按照bootargs找到rootfs,执行/etc/inittab、/etc/init.d/rcS脚本,挂载各类文件系统,启动shell,提供控制台交互,系统完全就绪。

四、烧录自己编译的镜像

当自己编译完uboot、内核、设备树、构建完rootfs之后,替换对应目录文件即可:

  1. boot目录:替换自己编译生成的u‑boot.imx、zImage、dtb设备树文件。
  2. filesystem目录:把自制根文件系统打包为rootfs.tar.bz2放入。
  3. 执行烧录脚本:
sudo ./imx6mksdboot.sh -device /dev/sdb -flash emmc -ddrsize 512

烧录完成后,可在uboot设置启动参数:

  • EMMC本地启动示例bootcmd
setenv bootcmd 'mmc dev 1; fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ull‑alientek‑emmc.dtb; bootz 80800000 - 83000000;'
setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
saveenv

五、学习心得总结

  1. 分清开发和量产模式:开发调试优先TFTP+NFS网络启动,减少SD/EMMC反复擦写;产品定稿后,再烧写到EMMC。
  2. 四大件缺一不可:uboot负责引导,zImage是内核本体,dtb描述硬件资源,rootfs提供用户态环境。
  3. 设备树是Linux3.0之后重大改进,把硬件资源描述从内核剥离,实现驱动代码和硬件资源描述分离,提升代码可移植性。
  4. 启动链路要记牢:ROM → U‑Boot → 内核(zImage+dtb) → rootfs。任何一个环节出错,开发板都无法正常进入控制台。
  5. 做系统移植,不仅仅是会烧写镜像,更要理解每个组件在整个启动流程中承担的工作,出现启动失败(黑屏、卡死、panic)才能够快速定位问题。

后续学习:U‑Boot编译、Linux内核裁剪编译、设备树语法、busybox构建根文件系统。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐