交叉编译环境搭建完成后,Linux移植工作需围绕目标硬件平台展开,核心是将编译好的内核、根文件系统及应用程序适配到目标板,确保系统能正常启动并运行,以下是详细的移植步骤及关键注意事项。
目标板硬件准备与环境确认
移植前需明确目标板的硬件架构(如ARM Cortex-A、RISC-V等)、处理器型号、外设接口(UART、SPI、I2C等)及启动方式(如U-Boot、SPI Flash启动等),需确认交叉编译工具链的架构与目标板一致(如arm-linux-gnueabihf、aarch64-linux-gnu等),并通过arm-linux-gnueabihf-gcc -v
验证工具链是否正常工作,准备目标板的硬件手册、数据手册及Linux内核对该板的官方支持情况(若有)。
Linux内核移植
内核移植是核心环节,需确保内核能识别目标板硬件并驱动外设。
内核源码获取与配置
下载与目标板硬件兼容的Linux内核版本(如官方主线版本或芯片厂商提供的定制版本),解压后进入内核源码目录,执行make menuconfig
进入图形化配置界面,关键配置项包括:
- 架构选择:在“System Type”中选中目标架构(如ARM 64-bit)。
- 目标板支持:若内核已支持目标板(如“ARM AMBA PrimeCell devices”),勾选对应板型;若无,需基于相近板型修改设备树(Device Tree)。
- 设备驱动:开启必要的外设驱动(如串口、网卡、存储控制器),关闭不需要的驱动以减小内核体积。
- 文件系统支持:选择根文件系统类型(如EXT4、JFFS2等),确保支持只读/读写模式。
配置完成后保存为.config
文件,可通过make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- oldconfig
基于已有配置更新。
内核编译与镜像生成
使用交叉编译工具链编译内核,命令如下:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j$(nproc) zImage # 生成ARM内核镜像 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j$(nproc) dtbs # 编译设备树文件
编译成功后,在arch/arm/boot/
目录下生成zImage
(内核镜像),在arch/arm/boot/dts/
目录下生成设备树文件(如.dtb
),若内核支持模块化,还可通过make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules
编译驱动模块。
设备树修改
若目标板无官方设备树支持,需基于相近板型修改设备树源文件(.dts
),关键修改包括:
- 节点调整:修改/添加CPU、内存、外设(如串口、网卡)节点,确保寄存器地址、中断号与硬件手册一致。
- 兼容性标记:在根节点中添加
compatible
属性,确保内核能正确识别设备。 - 启动参数:通过
chosen
节点设置启动参数(如bootargs
,包含根文件系统分区、启动模式等)。
修改后重新编译设备树,生成.dtb
文件并替换目标板启动所需的设备树文件。
根文件系统构建
根文件系统是内核运行的基础,需包含基本的系统工具、库文件及应用程序,常用构建方式有两种:BusyBox裁剪和Yocto Project定制。
BusyBox构建
BusyBox提供精简的Unix工具集,适合小型嵌入式系统,步骤如下:
- 编译BusyBox:下载BusyBox源码,执行
make menuconfig
,选择“静态链接”(避免动态库依赖),勾选需要的工具(如sh
、ls
、ifconfig
等)。 - 安装根文件系统:执行
make install
,将工具安装到指定目录(如rootfs
)。 - 创建必要文件:在
rootfs
中创建/etc/inittab
(设置启动进程)、/etc/fstab
(文件系统表)、/dev
(设备节点,可通过mdev -s
自动生成)等。
根文件系统镜像制作
将构建好的根文件系统制作成镜像文件(如EXT4格式),命令如下:
dd if=/dev/zero of=rootfs.ext4 bs=1M count=64 # 创建64MB空镜像 mkfs.ext4 rootfs.ext4 mkdir -p /tmp/rootfs mount rootfs.ext4 /tmp/rootfs cp -rf busybox_install/* /tmp/rootfs/ # 复制BusyBox文件到挂载点 umount /tmp/rootfs
最终生成的rootfs.ext4
可通过NFS、TFTP或烧录到存储设备(如eMMC、SD卡)供目标板使用。
根文件系统关键目录说明
目录 | 功能说明 |
---|---|
/bin |
基本命令(如sh 、ls ) |
/sbin |
系统管理命令(如ifconfig 、reboot ) |
/etc |
配置文件(如inittab 、fstab ) |
/dev |
设备文件(如/dev/ttyS0 为串口) |
/lib |
共享库文件(如libc.so.6 ) |
/usr |
用户程序(如/usr/bin 存放额外工具) |
引导程序配置与启动调试
目标板通常通过引导程序(如U-Boot)加载内核和根文件系统,需修改U-Boot的启动参数,确保能正确加载内核镜像、设备树及根文件系统。
U-Boot环境变量配置
通过U-Boot的setenv
命令设置启动参数:
setenv bootcmd 'tftp 0x82000000 zImage; tftp 0x83000000 board.dtb; bootz 0x82000000 - 0x83000000' # TFTP加载内核和设备树 setenv bootargs 'console=ttyS0,115200 root=/dev/mmcblk0p2 rw rootwait' # 启动参数,指定串口和根文件系统分区 saveenv # 保存环境变量
若使用NFS挂载根文件系统,bootargs
可修改为root=/dev/nfs nfsroot=192.168.1.100:/path/to/rootfs ip=192.168.1.101
。
启动调试
将编译好的zImage
、board.dtb
及根文件系统镜像通过TFTP、SD卡或烧录工具加载到目标板,启动后观察串口输出,若内核无法启动,需检查:
- 设备树是否正确(寄存器地址、中断号是否匹配);
- 启动参数是否正确(根文件系统分区、设备路径是否准确);
- 内核驱动是否开启(如串口驱动是否编译进内核)。
驱动与应用程序移植
驱动移植
若内核未包含目标板的外设驱动,需编写或修改驱动代码,步骤如下:
- 编写驱动代码:基于Linux驱动模型(platform驱动、字符设备等),实现
probe
、remove
等函数; - 修改设备树:在设备树中添加对应设备的节点,定义资源(如寄存器地址、中断号);
- 编译驱动:通过
make M=drivers/char ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules
编译驱动模块,生成.ko
文件; - 加载驱动:将
.ko
文件拷贝到目标板,通过insmod
加载,使用dmesg
查看驱动加载日志。
应用程序移植
使用交叉编译工具链编译用户程序,处理动态库依赖。
arm-linux-gnueabihf-gcc -o hello hello.c # 编译应用程序 arm-linux-gnueabihf-strip hello # 去除调试信息,减小体积
将编译好的程序拷贝到目标板根文件系统的/usr/bin/
目录,确保可执行权限(chmod +x hello
)。
相关问答FAQs
Q1:交叉编译环境搭建完成后,内核编译时提示“未定义的引用”错误,如何解决?
A:通常是由于交叉编译工具链与内核版本不匹配,或缺少必要的库文件,可尝试:
- 确认工具链架构与内核架构一致(如ARM 32位工具链编译ARM 32位内核);
- 检查内核配置中是否开启对应架构的支持(如“ARM system type”);
- 安装缺失的依赖库(如
libssl-dev
、libncurses-dev
等),确保编译环境完整。
Q2:根文件系统制作完成后,目标板启动时提示“VFS: Cannot open root device ‘mmcblk0p2’”,如何排查?
A:该错误表示内核无法找到根文件系统分区,排查步骤如下:
- 检查
bootargs
中的根设备路径是否正确(如mmcblk0p2
是否对应实际分区); - 确认存储设备(如eMMC)是否正确识别(通过
dmesg
查看内核日志,是否有mmcblk0
设备); - 若使用NFS,确认网络连接正常,且NFS服务器路径可访问;
- 检查根文件系统镜像是否正确制作(如
mkfs.ext4
是否成功,分区表是否损坏)。
原创文章,发布者:酷番叔,转转请注明出处:https://cloud.kd.cn/ask/15806.html