第二章 开发环境搭建:交叉编译工具链安装、QEMU模拟器配置、Yocto Project构建最小车规级Linux系统、TFTP/NFS网络启动设置
各位同学,欢迎来到第二章。
上一章我们聊了车规级Linux驱动开发的整体框架。这一章,咱们得先把家伙事儿备齐了。说白了,就是搭建开发环境。
我刚开始做车规级驱动那会儿,光搭环境就折腾了两天。不是工具链版本不对,就是QEMU死活起不来。后来我总结了一个经验:环境搭得稳,开发省一半心。今天我就把这几年的踩坑经验,一股脑儿倒给你们。
2.1 交叉编译工具链安装
车规级芯片,比如NXP的S32V、TI的TDA4,它们的CPU架构通常是ARM Cortex-A系列或者RISC-V。咱们的PC是x86架构,没法直接在PC上编译出能在ARM芯片上跑的程序。所以,需要交叉编译工具链。
工具链的选择,我个人习惯用Linaro GCC。它针对ARM架构优化得比较好,而且社区活跃,遇到问题容易找到解决方案。
核心思路:在x86主机上,用交叉编译器生成ARM架构的二进制文件。
2.1.1 下载与安装
我建议直接去Linaro官网下载预编译好的工具链。别自己从源码编译,太费时间了。我记得有一次为了省空间,自己编译了一个精简版,结果链接阶段各种报错,查了两天才发现是少了某些库。
# 以ARM Cortex-A72为例,下载gcc-linaro-7.5.0
wget https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
# 解压到 /opt 目录
sudo tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz -C /opt/
# 添加环境变量
export PATH=/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin:$PATH
小提示:把export命令加到 ~/.bashrc 文件里,这样每次打开终端就不用重新设置了。
2.1.2 验证安装
安装完,咱们得验证一下。运行下面这条命令:
arm-linux-gnueabihf-gcc --version
如果能看到版本信息,说明安装成功了。你想想看,如果这一步报错,大概率是环境变量没配好,或者下载的版本跟你的系统架构不匹配。
2.2 QEMU模拟器配置
做驱动开发,不可能每次都在真车上调试。成本高不说,烧写一次系统就要好几分钟。所以,我们需要QEMU。它可以在PC上模拟一个ARM开发板。
我选QEMU,主要是因为它支持virt平台。这个平台很灵活,可以自定义内存、CPU数量、外设等。对于咱们学习来说,完全够用了。
2.2.1 安装QEMU
# Ubuntu/Debian系统
sudo apt-get install qemu-system-arm
# 验证安装
qemu-system-arm --version
2.2.2 启动一个最小系统
我们需要一个内核镜像和一个根文件系统。这里我直接用Yocto构建出来的(后面会讲)。假设你已经有了 zImage 和 core-image-minimal-qemuarm64.ext4。
qemu-system-aarch64 \
-machine virt \
-cpu cortex-a72 \
-smp 4 \
-m 2G \
-kernel zImage \
-drive file=core-image-minimal-qemuarm64.ext4,if=none,format=raw,id=hd0 \
-device virtio-blk-device,drive=hd0 \
-append "root=/dev/vda rw console=ttyAMA0" \
-nographic
注意:这里用的是 qemu-system-aarch64,如果你是32位ARM,要用 qemu-system-arm。我曾经因为搞混这两个命令,浪费了半小时。
启动后,你会看到一个串口终端。输入 root 登录(默认无密码)。嗯,到这里,你的第一个虚拟车规级环境就跑起来了。
2.3 Yocto Project构建最小车规级Linux系统
Yocto Project,说白了就是一个嵌入式Linux构建系统。它可以根据你的配置,生成一个包含内核、根文件系统、bootloader的完整镜像。
车规级项目里,Yocto几乎是标配。为什么?因为它能精确控制每一个软件包的版本,还能打上安全补丁。这在车规认证(比如ISO 26262)中非常重要。
2.3.1 初始化Yocto环境
# 克隆poky(Yocto的参考发行版)
git clone git://git.yoctoproject.org/poky.git -b dunfell
# 进入目录
cd poky
# 初始化构建环境
source oe-init-build-env build
这一步会创建一个 build 目录,并切换到该目录。你想想看,Yocto的构建过程其实很像一个“食谱”:它告诉你需要哪些原料(源码包),以及怎么烹饪(编译、打包)。
2.3.2 配置目标平台
编辑 build/conf/local.conf 文件:
# 指定目标机器,这里用qemuarm64
MACHINE ??= "qemuarm64"
# 添加一些常用的工具
IMAGE_INSTALL_append = " strace gdb"
# 使用最小的根文件系统
EXTRA_IMAGE_FEATURES ?= "debug-tweaks"
2.3.3 开始构建
bitbake core-image-minimal
第一次构建会非常慢,因为要下载所有源码包并编译。我建议你晚上睡觉前跑上,第二天早上就好了。我记得我第一次构建,用了整整6个小时,中间还因为网络问题断了一次,气得我差点砸电脑。
加速技巧:配置一个本地 sstate-cache 和 downloads 目录,这样下次构建就不用重新下载了。
2.4 TFTP/NFS网络启动设置
在开发阶段,我们经常需要修改内核或驱动。如果每次都烧写到Flash里,效率太低了。所以,我们用TFTP来加载内核,用NFS来挂载根文件系统。
说白了,就是让开发板通过网络,从你的PC上启动系统。这样你改了代码,只需要重新编译,然后重启开发板就行了。
2.4.1 搭建TFTP服务器
# 安装TFTP服务器
sudo apt-get install tftpd-hpa
# 配置TFTP目录
sudo mkdir -p /srv/tftp
sudo chmod 777 /srv/tftp
# 编辑配置文件 /etc/default/tftpd-hpa
# 修改 TFTP_DIRECTORY="/srv/tftp"
把编译好的 zImage 和 设备树文件 复制到 /srv/tftp 目录下。
2.4.2 搭建NFS服务器
# 安装NFS服务器
sudo apt-get install nfs-kernel-server
# 创建NFS共享目录,并解压根文件系统
sudo mkdir -p /srv/nfs/rootfs
sudo tar -xvf core-image-minimal-qemuarm64.tar.bz2 -C /srv/nfs/rootfs
# 编辑 /etc/exports,添加:
/srv/nfs/rootfs *(rw,sync,no_subtree_check,no_root_squash)
# 重启NFS服务
sudo systemctl restart nfs-kernel-server
2.4.3 U-Boot启动参数设置
在U-Boot命令行中,设置如下环境变量:
setenv serverip 192.168.1.100 # 你的PC IP
setenv ipaddr 192.168.1.101 # 开发板 IP
setenv netmask 255.255.255.0
setenv bootcmd 'tftp 0x40000000 zImage; tftp 0x48000000 your-board.dtb; bootz 0x40000000 - 0x48000000'
setenv bootargs 'console=ttyAMA0,115200 root=/dev/nfs nfsroot=${serverip}:/srv/nfs/rootfs rw ip=${ipaddr}'
saveenv
boot
避坑指南:我曾经遇到过NFS挂载失败,原因是防火墙没关。记得检查一下 sudo ufw disable 或者开放NFS端口(2049)。另外,开发板和PC必须在同一个网段,这个很容易忽略。
好了,到这里,你的开发环境就全部搭建完成了。从交叉编译工具链,到QEMU模拟,再到Yocto构建,最后是网络启动。这一套流程,是车规级Linux驱动开发的基本功。
下一章,我们会正式开始写第一个驱动——一个简单的GPIO控制驱动。到时候,咱们就在这个环境里调试。
公众号:蓝海资料掘金营,微信deep3321