2、开发环境搭建:交叉编译工具链、内核源码获取与配置、设备树基础、QEMU模拟环境搭建
好,咱们正式开始动手了。这一章我带你搭好开发环境。说实话,很多初学者卡就卡在这一步——工具链没配好,内核编不过,QEMU起不来,然后就没然后了。我当年也踩过不少坑,今天我把这些经验都摊开来讲。
2.1 交叉编译工具链:为什么需要它?
你想想看,你的电脑是x86架构,而嵌入式设备通常是ARM、RISC-V或者MIPS。x86的二进制程序,ARM芯片根本看不懂。所以我们需要交叉编译工具链——在x86主机上编译出ARM能运行的程序。
我个人习惯用Linaro提供的预编译工具链,稳定又省事。以ARM64(AArch64)为例:
# 下载ARM64交叉编译工具链
wget https://releases.linaro.org/components/toolchain/binaries/latest-7/aarch64-linux-gnu/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz
# 解压到 /opt 目录
sudo tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz -C /opt/
# 添加环境变量
export PATH=$PATH:/opt/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin
验证是否安装成功:
aarch64-linux-gnu-gcc --version
看到版本号就对了。嗯,这里要注意——工具链版本要和内核版本匹配。太老的gcc编新内核会报错,太新的gcc编老内核也可能出问题。我在项目中遇到过gcc 10编译Linux 4.19内核,结果一堆-Werror警告,折腾了半天。
2.2 内核源码获取与配置
源码从哪来?当然是kernel.org。但我建议你直接用LTS版本,长期支持,社区维护积极。
# 下载Linux 5.10 LTS内核
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.200.tar.xz
# 解压
tar -xvf linux-5.10.200.tar.xz
cd linux-5.10.200
配置内核有两种方式:
- make menuconfig:基于ncurses的图形界面,最常用
- make defconfig:使用默认配置,适合快速验证
对于Camera子系统,我们需要关注这些配置项:
| 配置项 | 说明 | 建议值 |
|---|---|---|
| CONFIG_MEDIA_SUPPORT | 多媒体框架支持 | y |
| CONFIG_MEDIA_CAMERA_SUPPORT | Camera设备支持 | y |
| CONFIG_V4L2 | Video4Linux2核心 | y |
| CONFIG_VIDEO_V4L2_SUBDEV_API | 子设备API | y |
配置命令:
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig
进入menuconfig后,按/键可以搜索配置项。比如搜"V4L2",所有相关选项就出来了。这个技巧很实用,我经常用。
2.3 设备树基础:硬件描述语言
设备树(Device Tree)说白了就是描述硬件信息的配置文件。以前内核把硬件信息硬编码在arch/arm/mach-xxx目录下,后来大家发现这样太乱了——换一个板子就要改内核代码。于是设备树诞生了。
设备树文件有两种:
- .dts:设备树源文件,人类可读的文本
- .dtb:编译后的二进制文件,内核直接使用
一个简单的Camera节点示例:
/dts-v1/;
/ {
model = "QEMU ARM64 Virtual Machine";
compatible = "qemu, virt";
soc {
#address-cells = <2>;
#size-cells = <2>;
camera@1c00000 {
compatible = "virtio,mmio";
reg = <0x0 0x1c00000 0x0 0x1000>;
interrupts = <0 42 4>;
status = "okay";
};
};
};
编译设备树:
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- dtbs
生成的dtb文件在arch/arm64/boot/dts/目录下。
2.4 QEMU模拟环境搭建
QEMU是我们最好的朋友。没有开发板?没关系,QEMU可以模拟ARM64硬件,跑完整的内核和根文件系统。
安装QEMU:
sudo apt-get install qemu-system-arm qemu-utils
编译内核和设备树:
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Image
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- dtbs
制作根文件系统(使用BusyBox):
# 下载BusyBox
wget https://busybox.net/downloads/busybox-1.36.0.tar.bz2
tar -xvf busybox-1.36.0.tar.bz2
cd busybox-1.36.0
# 配置并编译
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig
# 确保选中 "Build static binary (no shared libs)"
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc)
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- install
# 制作根文件系统镜像
cd _install
mkdir proc sys dev etc etc/init.d
cat > etc/init.d/rcS << EOF
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
/sbin/mdev -s
EOF
chmod +x etc/init.d/rcS
# 打包成cpio
find . | cpio -o --format=newc > ../rootfs.cpio
cd ..
gzip -c rootfs.cpio > rootfs.cpio.gz
启动QEMU:
qemu-system-aarch64 \
-machine virt \
-cpu cortex-a57 \
-kernel arch/arm64/boot/Image \
-initrd /path/to/rootfs.cpio.gz \
-append "console=ttyAMA0 root=/dev/ram rdinit=/sbin/init" \
-nographic \
-device virtio-gpu-pci \
-device virtio-mmio
看到内核启动日志,最后出现shell提示符,就说明环境搭建成功了。
-s -S参数可以启动GDB调试。在另一个终端运行aarch64-linux-gnu-gdb vmlinux,然后输入target remote :1234,就可以单步调试内核了。这个我在调试Camera驱动时用过无数次,非常管用。
2.5 验证Camera子系统是否启用
启动QEMU后,进入系统,执行以下命令检查V4L2设备:
# 查看V4L2设备列表
ls /dev/video*
# 查看设备信息
v4l2-ctl --list-devices
# 查看支持的格式
v4l2-ctl -d /dev/video0 --list-formats
如果能看到设备节点,说明我们的内核配置正确,Camera子系统已经就绪了。
CONFIG_VIRTIO相关选项,结果QEMU模拟的virtio设备内核根本不认。折腾了两天才发现是内核配置漏了。所以建议你用我上面给的配置表,逐项核对。
好,环境搭建就到这里。下一章我们开始深入V4L2框架,看看Camera设备在内核中是怎么被管理的。到时候我会结合代码,一步步带你分析。