250210_Linux_021记录一次成功的linux系统移植 1

2025-02-10 12:07:16

写在前面的理论知识和学习经验:

Linux内核层,我大概折腾了二十天。
前面半个月,学习理论和代码。
后面一周,前面五天用来买开发板和等快递到货,后面两天用来测试和实践。
这次算是证明了:实践是检验真理的唯一标准。
过程中遇到很多错误,很多bug,一度想放弃。但是都耐着性子一点点改过来了。
只能说,我目前从零开始学C语言,到单片机,再到RTOS;这些加起来可能才相当于我从Linux应用层学到现在内核层的难点总和;Linux不愧是嵌入式门槛最高的行业方向,够难!
笔记写了很多,知识导图也找了一些。实在找不到的我就自己画了。enjoy it!

Linux系统启动流程:
UBOOT-->Linux_Kernel-->DTS-->RootFS-->(UserLogin)

它们的工作环境为:

裸机 内核空间 用户空间
UBOOT Linux_Kernel | DTS RootFS

嵌入式Linux学习路线:

attachment/2025-02-10_114418.png

Linux系统架构组成 Venn图

attachment/Linux架构层级 1.png

UBOOT引导Linux内核启动流程分析:

attachment/uboot启动流程详解.jpg

Linux Kernel(内核)启动与加载设备树 流程分析

attachment/linux_kernel_start.png

Linux内核挂载根文件系统(RootFS) 启动流程分析:

attachment/linux挂载rootfs.png

主要参考资料:

内部库引用:
【04-00】HTML_HTM资料索引与管理文档-dataviewjs
2025-02-09
2025-02-08

外部参考资料:
https://blog.csdn.net/qq_41839588/category_12279858.html
https://blog.csdn.net/qq_41839588/article/details/130000855
https://blog.csdn.net/qq_41839588/article/details/130025674
https://blog.csdn.net/qq_41839588/article/details/130028841
https://blog.csdn.net/qq_41839588/article/details/130038297
https://gitcode.csdn.net/65acabdab8e5f01e1e451ac1.html

如果链接失效,可以查阅网页存档:
\总知识库\04 HTML_HTM资料\Linux类\v3S编译大全(uboot 主线linux buildroot).htm
\总知识库\04 HTML_HTM资料\Linux类\荔枝派Zero(全志V3S)编译Kernel.htm
\总知识库\04 HTML_HTM资料\Linux类\荔枝派Zero(全志V3S)编译rootfs.htm
\总知识库\04 HTML_HTM资料\Linux类\荔枝派Zero(全志V3S)编译Uboot及配置.htm
\总知识库\04 HTML_HTM资料\Linux类\荔枝派Zero(全志V3S)烧录Uboot、Kernel及rootfs到SD卡并运行在板子上.htm

移植过程中遇到的问题与解决方案:

1、拉取源码时发现文件太多下载失败

梯子环境下用手机下载压缩包解决此问题。

2、忘记了添加bootargs和bootcmd

这会导致开机之后无法自启动linux系统,不过我们可以手动启动linux系统。

用户名root
用户光标overloadlicheepi
登陆密码licheepi

将所有输出的uboot、kernel、设备树和根文件系统的压缩包或可执行文件放在同一个目录,开始拷贝到SD卡中制作系统盘。

sudo dd if=u-boot-sunxi-with-spl.bin of=/dev/sdb bs=1024 seek=8
cp ./zImage /media/overload/KERNEL/
cp ./sun8i-v3s-licheepi-zero-dock.dtb /media/overload/KERNEL/
sudo tar -xf ./rootfs.tar -C /media/overload/rootfs/

进入uboot:

mmc list
mmc dev 0
setenv bootm_boot_mode sec
setenv bootargs 'console=ttyS0,115200 panic=5 rootwait root=/dev/mmcblk0p2 earlyprintk rw  vt.global_cursor_default=0'
saveenv
load mmc 0:1 0x41000000 zImage
load mmc 0:1 0x41800000 sun8i-v3s-licheepi-zero-dock.dtb
bootz 0x41000000 - 0x41800000

这里需要注意一下,荔枝派zeroplus(v3s)的默认配置下,烧录内核文件的DDR RAM地址是0x41000000,而设备树可执行文件的DDR RAM地址是0x41800000

下面是对上面的指令的注释解释:

mmc list
# 列出系统中所有可用的 MMC(MultiMediaCard)设备。
# 作用:显示当前系统中已识别的 MMC 设备及其编号。
# 无输入参数,输出为设备列表及其状态信息。

mmc dev 0
# 设置当前操作的 MMC 设备为编号 0 的设备。
# 作用:指定后续 MMC 操作的目标设备。
# 输入参数:
#   0:设备编号,表示选择第 0 个 MMC 设备。
# 返回值:无返回值,但会输出当前选择的设备信息。

setenv bootm_boot_mode sec
# 设置环境变量 `bootm_boot_mode` 的值为 `sec`。
# 作用:配置 U-Boot 的启动模式为安全模式(sec)。
# 输入参数:
#   bootm_boot_mode:环境变量名称。
#   sec:环境变量的值。
# 返回值:无返回值,但会更新环境变量。

load mmc 0:1 0x41000000 zImage
# 从 MMC 设备 0 的第 1 分区加载文件 `zImage` 到内存地址 0x41000000。
# 作用:将内核镜像文件加载到内存中,为启动内核做准备。
# 输入参数:
#   mmc 0:1:指定从设备 0 的第 1 分区加载文件。
#   0x41000000:目标内存地址,表示将文件加载到该地址。
#   zImage:要加载的文件名,通常是 Linux 内核镜像。
# 返回值:无返回值,但会输出加载成功的信息。

load mmc 0:1 0x41800000 sun8i-v3s-licheepi-zero-dock.dtb
# 从 MMC 设备 0 的第 1 分区加载文件 `sun8i-v3s-licheepi-zero-dock.dtb` 到内存地址 0x41800000。
# 作用:将设备树文件加载到内存中,为内核提供硬件描述信息。
# 输入参数:
#   mmc 0:1:指定从设备 0 的第 1 分区加载文件。
#   0x41800000:目标内存地址,表示将文件加载到该地址。
#   sun8i-v3s-licheepi-zero-dock.dtb:要加载的文件名,通常是设备树文件。
# 返回值:无返回值,但会输出加载成功的信息。

setenv bootargs 'console=ttyS0,115200 panic=5 rootwait root=/dev/mmcblk0p2 earlyprintk rw  vt.global_cursor_default=0'
# 设置环境变量 `bootargs`,用于传递内核启动参数。
# 作用:配置内核启动时的命令行参数。
# 输入参数:
#   bootargs:环境变量名称。
#   'console=ttyS0,115200 panic=5 rootwait root=/dev/mmcblk0p2 earlyprintk rw  vt.global_cursor_default=0':
#       - console=ttyS0,115200:指定串口控制台为 ttyS0,波特率为 115200。
#       - panic=5:内核崩溃后 5 秒钟自动重启。
#       - rootwait:等待根文件系统设备准备就绪。
#       - root=/dev/mmcblk0p2:指定根文件系统所在分区。
#       - earlyprintk:启用早期内核调试信息输出。
#       - rw:以读写模式挂载根文件系统。
#       - vt.global_cursor_default=0:禁用虚拟终端光标。
# 返回值:无返回值,但会更新环境变量。

bootz 0x41000000 - 0x41800000
# 使用 zImage 格式启动内核。
# 作用:启动加载到内存中的 Linux 内核。
# 输入参数:
#   0x41000000:内核镜像的内存地址。
#   -:表示不加载 initrd(初始 RAM 磁盘)。
#   0x41800000:设备树文件的内存地址。
# 返回值:无返回值,但会启动内核并将控制权交给内核。

或者也可以在uboot编译之前添加自启动:

 vim include/configs/sun8i.h 

修改 文件内容:


#define CONFIG_BOOTCOMMAND   "setenv bootm_boot_mode sec; " \
                            "load mmc 0:1 0x41000000 zImage; "  \
                            "load mmc 0:1 0x41800000 sun8i-v3s-licheepi-zero-dock.dtb; " \
                            "bootz 0x41000000 - 0x41800000;"

#define CONFIG_BOOTARGS      "console=ttyS0,115200 panic=5 rootwait root=/dev/mmcblk0p2 earlyprintk rw  vt.global_cursor_default=0"

进入linux系统后,可以写个简单的shell的helloworld程序来验证是否成功移植系统:
多注意一下,如果bush不能用,那么可以用sh来代替引用。
helloworld测试 程序:
vi hello.sh
add:
#!/bin/sh
echo "Hello World!!"

3、SD卡分区格式化后,首次烧录时无法写入

这是因为SD卡格式化完毕后并没有正确加载。想要解决只需要将格式化并分区完毕后的SD卡在虚拟机弹出并物理拔出,然后重新插入后成功挂载即可继续操作。