2、开发环境搭建:交叉编译工具链安装、嵌入式Linux系统构建、SSH与NFS服务配置

好,咱们正式开始动手了。这一章要解决一个核心问题:怎么让你的电脑和嵌入式板子“对上话”

说白了,你不可能在板子上直接写代码、编译代码——那玩意儿资源太有限了。所以我们的工作模式是:在PC上写代码、交叉编译,然后把生成的可执行文件扔到板子上跑。这就是嵌入式开发的常态。

我个人习惯把环境搭建分成三步走:
1. 装交叉编译工具链(让PC能编译出ARM架构的程序)
2. 构建嵌入式Linux系统(让板子能跑起来)
3. 配置SSH和NFS(让PC和板子能方便地传文件、调试)

嗯,咱们一个一个来。

2.1 交叉编译工具链安装

先问个问题:为什么需要交叉编译?

因为你的PC是x86架构,而嵌入式板子通常是ARM架构。x86的编译器编译出来的程序,ARM芯片看不懂。所以我们需要一个在x86上运行、但能生成ARM机器码的编译器——这就是交叉编译工具链。

我在项目中遇到过最坑的事:有人直接拿gcc编译,然后拷到板子上,跑起来直接Segmentation Fault。嗯,那场面,挺尴尬的。

2.1.1 获取工具链

常用的交叉编译工具链有几种:

  • Linaro GCC:ARM官方推荐的,支持ARMv7、ARMv8
  • Buildroot生成的工具链:自己定制,更灵活
  • 芯片厂商提供的SDK:比如NXP的Yocto、TI的Processor SDK

我个人习惯用Linaro的预编译工具链,省事。下载命令如下:

# 以ARM 32位为例
wget https://releases.linaro.org/components/toolchain/binaries/latest-7/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz

# 解压到指定目录
tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz -C /opt/

# 添加环境变量
export PATH=$PATH:/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin
小提示:建议把环境变量写到 ~/.bashrc 里,这样每次打开终端就不用重新export了。我刚开始学的时候老忘,后来直接写进文件里,省心。

2.1.2 验证工具链

装完之后,验证一下:

arm-linux-gnueabihf-gcc --version

如果能看到版本信息,说明装好了。然后写个最简单的Hello World试试:

# 编写测试文件
echo '#include <stdio.h>
int main() {
    printf("Hello Embedded World!\n");
    return 0;
}' > test.c

# 交叉编译
arm-linux-gnueabihf-gcc -o test test.c

# 查看生成的文件类型
file test

你会看到输出类似:ELF 32-bit LSB executable, ARM, version 1 (SYSV)。这说明编译出来的确实是ARM架构的程序。

注意:千万不要在PC上直接运行这个test文件!它是ARM架构的,x86跑不了。我曾经见过有人双击执行,然后一脸懵地问“为什么没反应”……嗯,你懂的。

2.2 嵌入式Linux系统构建

板子要跑起来,光有交叉编译工具链还不够。你还需要一个完整的嵌入式Linux系统,包括:

  • Bootloader(引导程序)
  • Linux内核
  • 根文件系统(rootfs)

这三件套,缺一不可。

2.2.1 构建方式选择

构建嵌入式Linux系统,常见的有三种方式:

方式 特点 适用场景
Buildroot 轻量级,配置简单,生成速度快 中小型项目,快速原型
Yocto 功能强大,定制性强,但学习曲线陡 大型项目,需要深度定制
手动构建 完全可控,但繁琐 学习目的,或特殊需求

我个人建议初学者先用Buildroot。为什么?因为快。你想想看,Yocto第一次构建可能要几个小时,Buildroot半小时搞定。我刚开始学的时候,用Yocto编译了一下午,结果报错……心态直接崩了。

2.2.2 使用Buildroot快速构建

步骤很简单:

# 下载Buildroot
git clone https://git.buildroot.net/buildroot
cd buildroot

# 配置(以树莓派3为例)
make raspberrypi3_defconfig

# 进入菜单配置界面(可选)
make menuconfig

# 开始构建
make

构建完成后,在 output/images/ 目录下会生成:

  • zImage:内核镜像
  • rootfs.ext4:根文件系统
  • *.dtb:设备树文件
核心要点:构建过程中,Buildroot会自动下载并编译所有依赖包。你只需要耐心等待。如果网络不好,可以提前下载好源码包放到 dl/ 目录下。

2.2.3 烧录到板子

把生成的镜像烧录到SD卡或eMMC:

# 查看SD卡设备(假设是 /dev/sdb)
lsblk

# 烧录镜像
sudo dd if=output/images/sdcard.img of=/dev/sdb bs=1M status=progress

# 同步并卸载
sync
sudo eject /dev/sdb
警告:dd命令非常危险!一定要确认 /dev/sdb 是你的SD卡,而不是硬盘。我曾经手滑把电脑硬盘给覆盖了……嗯,那是一个悲伤的故事。

2.3 SSH与NFS服务配置

系统跑起来了,板子也连上网了。接下来要解决的是:怎么方便地和板子交互

两个服务必不可少:

  • SSH:远程登录,传文件
  • NFS:网络文件系统,共享目录

2.3.1 配置SSH服务

在Buildroot配置中,确保开启了SSH:

make menuconfig
# 进入 Target packages → Networking applications
# 选中 openssh

板子启动后,用网线连接路由器或交换机。查看板子的IP地址:

ifconfig eth0

然后在PC上通过SSH登录:

ssh root@192.168.1.100

默认密码通常是空,或者 root。登录成功后,你就可以像操作普通Linux一样操作板子了。

小技巧:如果不想每次都输密码,可以配置SSH密钥登录。在PC上执行 ssh-keygen 生成密钥,然后把公钥拷贝到板子的 ~/.ssh/authorized_keys 里。我项目里都是这么干的,省事。

2.3.2 配置NFS服务

NFS的作用是:把PC上的一个目录共享给板子。这样你在PC上编译好的程序,板子直接就能访问,不用每次都scp拷贝。

PC端配置(Ubuntu为例):

# 安装NFS服务器
sudo apt-get install nfs-kernel-server

# 创建共享目录
sudo mkdir -p /srv/nfs/rootfs

# 配置导出文件
sudo vim /etc/exports
# 添加一行:
/srv/nfs/rootfs 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)

# 重启NFS服务
sudo systemctl restart nfs-kernel-server

板端配置:

# 挂载NFS共享目录
mount -t nfs -o nolock 192.168.1.10:/srv/nfs/rootfs /mnt

# 验证
ls /mnt

如果能看到PC上的文件,说明NFS配置成功了。

为什么用NFS?因为开发过程中,你可能会频繁修改代码、重新编译。每次都用scp拷贝,效率太低。NFS相当于让板子直接访问PC的硬盘,修改代码后立即可见。我当年做HMI项目时,一天要编译几十次,没有NFS的话,光传文件就能把人逼疯。

2.3.3 常见问题排查

配置过程中,可能会遇到一些问题。我列几个常见的:

  • SSH连不上:检查板子IP是否正确,防火墙是否开放22端口
  • NFS挂载失败:检查PC端的exports配置,确认网络互通
  • 权限问题:no_root_squash选项很重要,否则板子上的root用户没有写权限

嗯,环境搭建这部分就到这里。说实话,第一次搭建确实有点繁琐,但这是必经之路。你想想看,后面30章的代码都要在这个环境上跑,基础打牢了,后面才顺畅。

下一章,咱们开始真正接触HMI的底层驱动开发。到时候你会感谢今天认真搭环境的自己。