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

好,咱们正式开始动手了。

这一章,说白了就是给你的开发机“装上武器”。没有交叉编译工具链,你写的代码在PC上跑得再欢,ARM板子也看不懂。没有SSH和NFS,你每次改个文件都要插拔SD卡,那效率低得让人抓狂。我当年刚入行时,就吃过这个亏——代码改了一整天,烧录进去发现有个小bug,又得重新编译、烧录、重启……来回折腾了十几遍。后来搭好了NFS,才真正体会到什么叫“丝滑开发”。

2.1 交叉编译工具链:为什么需要它?

你想想看,你的PC是x86架构,而嵌入式板子通常是ARM架构。x86的编译器编译出来的程序,ARM根本看不懂。所以我们需要一个“跨平台”的编译器——在x86上运行,但生成ARM能执行的机器码。这就是交叉编译工具链。

我个人习惯用Linaro提供的工具链,稳定且社区支持好。当然,你也可以用芯片厂商提供的SDK里的工具链,比如NXP的、TI的,本质都一样。

2.1.1 安装步骤(以ARM Cortex-A7为例)

  1. 下载工具链
    去Linaro官网下载 gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz。别下错了版本,注意是arm-linux-gnueabihf,带硬浮点优化的。
  2. 解压到指定目录
sudo mkdir -p /opt/toolchains
sudo tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz -C /opt/toolchains/
  1. 配置环境变量
    编辑 ~/.bashrc,在末尾添加:
export PATH=$PATH:/opt/toolchains/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin
export CROSS_COMPILE=arm-linux-gnueabihf-
export ARCH=arm

然后 source ~/.bashrc 使其生效。

  1. 验证安装
arm-linux-gnueabihf-gcc --version

如果看到版本信息,恭喜你,第一步走通了。

我的小技巧: 我习惯把工具链路径写在 /etc/profile 里,这样所有用户都能用。但如果你只是个人开发,改 ~/.bashrc 就够了,避免污染系统环境。

2.2 Linux系统配置:让开发机更顺手

嗯,这里要注意。很多新手拿到Ubuntu第一件事就是装IDE,其实先把基础环境配好,后面能省一半时间。

2.2.1 安装必要软件包

sudo apt update
sudo apt install -y build-essential git vim ssh nfs-kernel-server minicom

这几个包的作用:

  • build-essential:编译必备,gcc、make等
  • git:版本管理,你总不想代码丢了重写吧
  • vim:编辑器,我习惯用vim,但用nano也行
  • ssh:远程登录,后面调试全靠它
  • nfs-kernel-server:网络文件系统,共享目录用
  • minicom:串口工具,调试板子必备

2.2.2 配置静态IP(开发机)

为什么用静态IP?因为你的板子每次启动都要通过NFS挂载你的目录,如果IP变了,板子就找不到你了。我曾经在实验室里因为路由器重启导致IP变了,板子挂载失败,排查了半天……后来老老实实配了静态IP。

编辑 /etc/netplan/01-netcfg.yaml(Ubuntu 18.04+):

network:
  version: 2
  ethernets:
    eth0:
      dhcp4: no
      addresses:
        - 192.168.1.100/24
      gateway4: 192.168.1.1
      nameservers:
        addresses: [8.8.8.8, 114.114.114.114]

然后 sudo netplan apply 生效。

注意: 开发机和板子要在同一个网段。比如开发机是192.168.1.100,板子就设192.168.1.101。网关和DNS可以一样。

2.3 SSH网络调试环境

SSH,说白了就是让你能远程登录板子,像操作本地终端一样。我调试时,通常开三个终端:一个SSH到板子看日志,一个本地编译代码,一个用SCP传文件。效率很高。

2.3.1 板子端开启SSH服务

大多数嵌入式Linux系统默认不带SSH服务,需要自己移植。但如果你用的是Buildroot或Yocto构建的系统,可以在配置时勾选openssh包。

手动安装方法(以ARM板为例):

  1. 下载openssh源码,交叉编译
  2. 将编译好的 sshdsshssh-keygen 等二进制文件拷贝到板子的 /usr/sbin//usr/bin/
  3. 生成密钥对:ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
  4. 启动服务:/usr/sbin/sshd

嗯,这里要注意。第一次启动时,板子可能没有 /var/empty 目录,需要手动创建:

mkdir -p /var/empty
chmod 755 /var/empty

2.3.2 从开发机SSH登录板子

ssh root@192.168.1.101

第一次登录会提示确认指纹,输入yes即可。如果提示“Permission denied”,检查板子上 /etc/ssh/sshd_config 是否允许root登录:

PermitRootLogin yes
避坑指南: 我曾经遇到过SSH连上后几秒就断开的情况。后来发现是板子的时钟不对,导致密钥验证失败。解决办法:在板子上运行 date -s "2025-01-15 10:30:00" 设置正确时间,或者配置NTP同步。

2.4 NFS网络调试环境

NFS,网络文件系统。它的作用是把开发机上的一个目录共享给板子,板子启动时直接挂载这个目录作为根文件系统。这样你改代码、编译、运行,全在开发机上操作,板子实时看到更新。不用烧录、不用重启,爽不爽?

2.4.1 开发机端配置NFS服务器

  1. 创建共享目录
sudo mkdir -p /srv/nfs/rootfs
sudo chmod 777 /srv/nfs/rootfs
  1. 编辑导出文件
    编辑 /etc/exports,添加一行:
/srv/nfs/rootfs 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)

参数说明:

  • rw:读写权限
  • sync:同步写入,保证数据一致性
  • no_subtree_check:提高性能
  • no_root_squash:允许板子上的root用户拥有完整权限。这个很重要,否则板子上创建的文件属主会变成nobody
  1. 重启NFS服务
sudo exportfs -a
sudo systemctl restart nfs-kernel-server
  1. 验证共享是否生效
showmount -e localhost

应该能看到 /srv/nfs/rootfs 被列出。

2.4.2 板子端挂载NFS

在板子的U-Boot启动参数中,设置根文件系统为NFS。以常见的 bootargs 为例:

setenv bootargs 'console=ttyS0,115200 root=/dev/nfs nfsroot=192.168.1.100:/srv/nfs/rootfs rw ip=192.168.1.101:192.168.1.100:192.168.1.1:255.255.255.0::eth0:off'

参数解释:

  • root=/dev/nfs:告诉内核根文件系统在NFS上
  • nfsroot=服务器IP:共享目录
  • ip=板子IP:服务器IP:网关:子网掩码::网卡名:off

保存并启动板子。如果一切正常,板子会从NFS启动,你可以在开发机上修改 /srv/nfs/rootfs 下的文件,板子立即生效。

注意: 如果板子启动时卡在“VFS: Unable to mount root fs”,先检查网络通不通:在板子的U-Boot里用 ping 192.168.1.100 测试。如果不通,检查网线、IP配置、防火墙。我遇到过最坑的一次是Windows防火墙把NFS端口给拦了,关掉就好了。

2.5 实战:验证整个环境

好,环境搭好了,我们来写个简单的“Hello World”验证一下。

  1. 在开发机上编写代码
cd /srv/nfs/rootfs
vim hello.c
#include <stdio.h>

int main() {
    printf("Hello from ARM board!\n");
    return 0;
}
  1. 交叉编译
arm-linux-gnueabihf-gcc -o hello hello.c
  1. SSH登录板子,运行程序
ssh root@192.168.1.101
cd /
./hello

如果看到 Hello from ARM board!,恭喜你,整个开发环境搭建成功!

总结一下: 交叉编译工具链让你能在PC上编译ARM程序,SSH让你远程操作板子,NFS让你免去烧录的烦恼。这三样东西配齐了,你的嵌入式开发效率至少提升三倍。我到现在做项目,第一件事就是搭环境,磨刀不误砍柴工嘛。

下一章,我们会开始写第一个真正的嵌入式程序——点亮LED。别小看这个,它背后涉及GPIO控制、寄存器操作、设备树配置,是嵌入式开发的“Hello World”。准备好了吗?