正点原子 i.MX6ULL 从 SD 卡启动 Linux 实战笔记
正点原子 i.MX6ULL 从 SD 卡启动 Linux 实战笔记
为什么先做这个
我想把 openEuler Embedded 移植到手上的正点原子阿尔法开发板(i.MX6ULL,eMMC 版本)。
但问题来了——这块板子还在跑我的毕设,eMMC 里的系统和代码不能随便动。
所以我选了一条更保险的路:eMMC 原样保留,专门做一张 SD 启动卡,从 SD 卡独立启动 Linux。
这样做的好处很直接:
- 毕设环境不受影响
- 随时切回 eMMC 继续干活
- 先完整跑通启动链,后面移植 openEuler 才有底气
这次要打通什么
目标很明确:从 SD 卡启动一个能进 shell 的最小 Linux 系统。
也就是下面这条链:
ROM → U-Boot → zImage → dtb → rootfs → shell
不要求跑 openEuler,先验证板子能从 SD 卡独立启动,后面再逐步替换组件。
开发板和资料
- 板子:正点原子阿尔法,i.MX6ULL,eMMC 版
- 资料包里可用的文件(注意是分组件提供,不是整盘镜像):
01、u-boot镜像/emmc/u-boot.imx
02、kernel镜像/zImage
02、kernel镜像/imx6ull-alientek-emmc.dtb
03、文件系统/02、busybox-1.29.0根文件系统/rootfs.tar.bz2
因为是分组件,所以不能直接 dd 一个 .img 完事,得手工做 SD 卡。
启动模式拨码
正点原子给的拨码定义:
- SD 卡启动:
1000 0010 - eMMC 启动:
1010 0110
(ON = 1,OFF = 0)
做实验前先把拨码切到 SD 启动模式,做完实验切回来就能回毕设环境。
制作 SD 启动卡(在 Ubuntu 主机上)
1. 确认 SD 卡设备名
插卡后:
lsblk
我这边识别到的是 /dev/sdb。
注意:后面所有操作都是针对整张卡 /dev/sdb,不是 /dev/sdb1。
2. 卸载自动挂载的分区
sudo umount /dev/sdb1
3. 清盘 + 重新分区
sudo wipefs -a /dev/sdb
sudo parted -s /dev/sdb mklabel msdos
sudo parted -s /dev/sdb mkpart primary fat32 8MiB 128MiB
sudo parted -s /dev/sdb set 1 boot on
sudo parted -s /dev/sdb mkpart primary ext4 128MiB 100%
sudo partprobe /dev/sdb
分区规划:
sdb1:FAT32,放 kernel 和 dtbsdb2:ext4,放 rootfs
4. 格式化
sudo mkfs.vfat -F 32 -n BOOT /dev/sdb1
sudo mkfs.ext4 -F -L rootfs /dev/sdb2
再确认一下分区结果:
lsblk
我这里是:
sdb 8:16 1 7.3G 0 disk
├─sdb1 8:17 1 120M 0 part
└─sdb2 8:18 1 7.2G 0 part
5. 写入 U-Boot
这一步很关键:u-boot.imx 不是拷贝到某个分区,而是直接写到 SD 卡前部的固定偏移,SoC 上电时才会加载。
sudo dd if="./01、u-boot镜像/emmc/u-boot.imx" of=/dev/sdb bs=1K seek=1 conv=fsync
sync
6. 挂载两个分区,拷贝文件
mkdir -p ~/sdboot ~/sdroot
sudo mount /dev/sdb1 ~/sdboot
sudo mount /dev/sdb2 ~/sdroot
拷贝 kernel 和 dtb:
sudo cp "./02、kernel镜像/zImage" ~/sdboot/
sudo cp "./02、kernel镜像/imx6ull-alientek-emmc.dtb" ~/sdboot/
sync
解压 rootfs:
sudo tar -xjf "./03、文件系统/02、busybox-1.29.0根文件系统/rootfs.tar.bz2" -C ~/sdroot
sync
检查一下:
ls ~/sdboot
# 应该看到 zImage 和 imx6ull-alientek-emmc.dtb
ls ~/sdroot | head
# 应该看到 bin、dev、etc、linuxrc 等
7. 卸载 SD 卡
sudo umount ~/sdboot
sudo umount ~/sdroot
sync
卡就做好了。
上电启动,进 U-Boot
- 开发板断电
- 插 SD 卡
- 拨码切到 SD 启动
- 接好串口(我用 MobaXterm)
- 上电
上电后顺利进入 U-Boot,说明串口和启动模式正常,SD 卡上的 U-Boot 已经被加载了。
在 U-Boot 里看看环境
敲几个命令:
version
bdinfo
printenv
mmc list
fatls mmc 0:1
fatls mmc 1:1
有两个发现:
(1)SD 卡和 eMMC 的编号
mmc list 输出:
FSL_SDHC: 0 (SD)
FSL_SDHC: 1
mmc 0是 SD 卡mmc 1是 eMMC
(2)U-Boot 默认找的 dtb 名字对不上
printenv 里看到 fdt_file=imx6ull-14x14-emmc-7-1024x600-c.dtb,但我 SD 卡里放的是 imx6ull-alientek-emmc.dtb。
如果直接 run mmcboot,会因为找不到正确的 dtb 而失败——后面果然遇到了。
碰到的坑:Bad Linux ARM zImage magic!
我一开始图省事,直接敲:
run mmcboot
结果报错:
Bad Linux ARM zImage magic!
原因其实不复杂:mmcboot 这个环境变量里虽然有加载 kernel 的动作,但在某些板子上它依赖的条件没满足,导致实际上没有把 zImage 正确加载到内存,就贸然执行了 bootz。
解决办法:不依赖乱七八糟的自动脚本,手工一步一步加载。
最终成功启动的命令
在 U-Boot 下依次敲:
fatload mmc 0:1 ${loadaddr} zImage
fatload mmc 0:1 ${fdt_addr} imx6ull-alientek-emmc.dtb
setenv bootargs console=ttymxc0,115200 root=/dev/mmcblk0p2 rootwait rw
bootz ${loadaddr} - ${fdt_addr}
每条命令在干什么:
- 把 SD 卡第 1 分区的
zImage读到内存${loadaddr}(一般是0x80800000) - 把第 1 分区的 dtb 读到内存
${fdt_addr}(一般是0x83000000) - 告诉内核:根文件系统在
/dev/mmcblk0p2,串口用ttymxc0,波特率 115200,其他参数是标准挂载选项 - 启动内核
执行完,等了片刻,出现:
Please press Enter to activate this console.
/ #
进去了。启动链完全打通。
途中还闪过一条 No soundcards found...,那是 alsactl 脚本报的,不是启动失败,不用管。
这次实验让我学到的东西
以前总觉得“移植 Linux”或“移植 openEuler”是个很大的事。实际做下来发现,它可以先拆成几个具体到不能再具体的问题:
- 板子能不能从指定介质启动?
- U-Boot 能不能起来?
- U-Boot 能不能找到 kernel?
- dtb 是否匹配硬件?
- kernel 能不能找到 rootfs?
- rootfs 起来后能不能进 shell?
这些问题都摸清楚了,后面再去适配 openEuler 才不会像盲人摸象。
这对后续 openEuler 移植有什么用?
虽然这次用的是正点原子提供的 kernel + dtb + busybox rootfs,和 openEuler 还没直接关系,但这一步是实实在在的垫脚石:
- 确认了板子可以从 SD 启动
- 串口正常
- U-Boot 工作正常
- SD / eMMC 的编号关系清楚了
- 手工启动命令已经验证
- rootfs 挂载路径也跑通了
接下来要过渡到 openEuler Embedded,可以按顺序替换:
- 先保留厂商 U-Boot,只换 rootfs
- 再换 kernel 和 dtb
- 最后做 machine 和 BSP 层面的正式适配
这样一步步来,比一上来就硬怼 openEuler 靠谱得多。
一句话总结
如果手里有一块还在正常工作的板子,又想折腾系统移植,eMMC 保留旧系统,SD 卡做实验 是最舒服的路线——安全、可回滚、而且能让你真正搞懂启动链。
附:这次用到的关键命令汇总
Ubuntu 侧(制作 SD 卡)
lsblk
sudo umount /dev/sdb1
sudo wipefs -a /dev/sdb
sudo parted -s /dev/sdb mklabel msdos
sudo parted -s /dev/sdb mkpart primary fat32 8MiB 128MiB
sudo parted -s /dev/sdb set 1 boot on
sudo parted -s /dev/sdb mkpart primary ext4 128MiB 100%
sudo partprobe /dev/sdb
sudo mkfs.vfat -F 32 -n BOOT /dev/sdb1
sudo mkfs.ext4 -F -L rootfs /dev/sdb2
sudo dd if="./01、u-boot镜像/emmc/u-boot.imx" of=/dev/sdb bs=1K seek=1 conv=fsync
sync
mkdir -p ~/sdboot ~/sdroot
sudo mount /dev/sdb1 ~/sdboot
sudo mount /dev/sdb2 ~/sdroot
sudo cp "./02、kernel镜像/zImage" ~/sdboot/
sudo cp "./02、kernel镜像/imx6ull-alientek-emmc.dtb" ~/sdboot/
sudo tar -xjf "./03、文件系统/02、busybox-1.29.0根文件系统/rootfs.tar.bz2" -C ~/sdroot
sync
sudo umount ~/sdboot
sudo umount ~/sdroot
sync
U-Boot 侧(手工启动)
mmc list
fatls mmc 0:1
fatls mmc 1:1
fatload mmc 0:1 ${loadaddr} zImage
fatload mmc 0:1 ${fdt_addr} imx6ull-alientek-emmc.dtb
setenv bootargs console=ttymxc0,115200 root=/dev/mmcblk0p2 rootwait rw
bootz ${loadaddr} - ${fdt_addr}
更多推荐



所有评论(0)