第二章:嵌入式Linux开发环境搭建
说实话,搭建开发环境这件事,看着琐碎,但却是整个嵌入式Linux学习的基石。我见过太多新手,一上来就急着写代码,结果编译报错半天找不到原因——最后发现是工具链没装对。嗯,咱们今天就把这事一次性搞定。
2.1 交叉编译工具链安装
先说说交叉编译。你想想看,你的PC是x86架构,但嵌入式板子通常是ARM架构。PC上编译的程序,ARM板子跑不了。怎么办?就得用交叉编译工具链。
我个人习惯用Linaro提供的工具链,稳定且社区活跃。安装其实就三步:
- 下载对应架构的压缩包(比如gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz)
- 解压到指定目录,比如/opt/toolchains/
- 配置环境变量
# 解压
sudo tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz -C /opt/toolchains/
# 配置环境变量(加到~/.bashrc里)
export PATH=$PATH:/opt/toolchains/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
# 验证
arm-linux-gnueabihf-gcc --version
2.2 TFTP/NFS服务配置
开发过程中,你肯定不想每次改个驱动都重新烧写整个系统。TFTP和NFS就是干这个的——一个用来快速下载内核和设备树,一个用来挂载根文件系统。
2.2.1 TFTP服务器配置
TFTP说白了就是个轻量级的文件传输协议。U-Boot里用它来加载内核镜像。
# 安装TFTP服务器
sudo apt-get install tftpd-hpa
# 配置文件 /etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/tftpboot"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="-l -c -s"
# 创建目录并设置权限
sudo mkdir -p /tftpboot
sudo chmod 777 /tftpboot
# 重启服务
sudo systemctl restart tftpd-hpa
2.2.2 NFS服务器配置
NFS用来共享根文件系统。开发阶段把根文件系统放在主机上,板子通过网络挂载,改完代码直接生效,不用反复烧写。
# 安装NFS服务器
sudo apt-get install nfs-kernel-server
# 编辑 /etc/exports,添加共享目录
/opt/rootfs *(rw,sync,no_subtree_check,no_root_squash)
# 重启服务
sudo systemctl restart nfs-kernel-server
板子端U-Boot里设置启动参数:
setenv bootargs 'console=ttyS0,115200 root=/dev/nfs nfsroot=192.168.1.100:/opt/rootfs rw ip=192.168.1.101:192.168.1.100:192.168.1.1:255.255.255.0::eth0:off'
2.3 U-Boot与内核编译
U-Boot和内核的编译,流程其实差不多。我建议你养成一个好习惯:每次编译前先清理,避免旧文件干扰。
2.3.1 U-Boot编译
# 下载源码
git clone https://github.com/u-boot/u-boot.git
cd u-boot
# 配置(以STM32MP157为例)
make stm32mp15_defconfig
# 编译
make -j4
# 编译完成后,会在当前目录生成u-boot.bin
这里有个坑:不同板子的配置文件不一样。你最好先查一下板子的官方文档,确认defconfig的名字。我刚开始做的时候,随便选了个配置,结果U-Boot起不来,折腾了两天。
2.3.2 Linux内核编译
# 下载内核源码
git clone https://github.com/torvalds/linux.git
cd linux
# 配置内核
make ARCH=arm stm32mp1_defconfig
# 如果需要自定义配置
make ARCH=arm menuconfig
# 编译内核和设备树
make ARCH=arm zImage -j4
make ARCH=arm dtbs -j4
# 编译内核模块
make ARCH=arm modules -j4
make ARCH=arm modules_install INSTALL_MOD_PATH=/opt/rootfs
2.4 根文件系统制作
根文件系统,说白了就是Linux启动后挂载的第一个文件系统。它里面包含了init程序、库文件、配置文件等。制作根文件系统,主流有两种方式:Buildroot和Yocto。
2.4.1 Buildroot方式
Buildroot适合快速出系统。配置简单,编译快,适合中小型项目。
# 下载Buildroot
git clone https://github.com/buildroot/buildroot.git
cd buildroot
# 配置
make stm32mp157_dk_defconfig
# 自定义配置
make menuconfig
# 编译(第一次编译会比较慢)
make -j4
# 编译完成后,output/images/目录下会生成rootfs.tar
我个人习惯用Buildroot做原型验证。有一次客户要三天出demo,我用Buildroot一天就把系统跑起来了,剩下两天调应用。效率确实高。
2.4.2 Yocto方式
Yocto功能更强大,但学习曲线陡峭。适合需要高度定制化的产品级项目。
# 下载Yocto
git clone git://git.yoctoproject.org/poky.git
cd poky
# 初始化构建环境
source oe-init-build-env
# 配置
bitbake-layers add-layer ../meta-openembedded/meta-oe
bitbake-layers add-layer ../meta-st-stm32mp
# 编译
bitbake core-image-minimal
# 编译完成后,tmp/deploy/images/目录下会生成根文件系统镜像
2.5 开发环境验证
环境搭好了,怎么验证?我一般会写个简单的Hello World程序,交叉编译后放到板子上跑一下。
// hello.c
#include <stdio.h>
int main() {
printf("Hello, Embedded Linux!\n");
return 0;
}
// 交叉编译
arm-linux-gnueabihf-gcc -o hello hello.c
// 通过TFTP传到板子
tftp 192.168.1.101 -c put hello
// 板子上执行
./hello
如果能看到"Hello, Embedded Linux!"输出,恭喜你,开发环境搭建成功了。