3、开发环境搭建:SDK获取与目录结构、交叉编译工具链配置、NFS/TFTP调试环境搭建

好,咱们直接进入正题。这一章是动手干活的基础,说白了就是把你手里的电脑和开发板“打通”。我见过太多人卡在这一步,SDK 下错了版本,或者工具链没配好,折腾一整天连个灯都点不亮。咱们今天就把这些坑一个个填平。

3.1 SDK 获取与目录结构

MTK8678 的 SDK,官方一般会通过 NDA 或者合作伙伴渠道发放。你拿到的通常是一个压缩包,名字类似 MTK8678_ETH_SDK_V2.1.0.tar.gz。我个人习惯拿到手先做两件事:校验 MD5,然后解压到不带空格的路径下。

注意: 路径里千万别有中文或空格。我有个同事曾经把 SDK 解压到 "我的文档" 下,结果编译时各种奇葩报错,查了半天才发现是路径问题。

解压后,你会看到这样的目录结构:

MTK8678_ETH_SDK/
├── build/              # 编译脚本和配置文件
├── docs/               # 技术文档和 datasheet
├── kernel/             # Linux 内核源码(4.19 LTS 版本)
├── u-boot/             # 引导加载程序
├── app/                # 上层应用示例
├── toolchain/          # 交叉编译工具链(有的版本会单独提供)
├── scripts/            # 辅助脚本
├── Makefile            # 顶层 Makefile
└── README.md           # 必读!

嗯,这里要特别提一下 build/ 目录。里面有个 configs/ 子目录,存放了不同硬件版本的默认配置。比如 mt8678_evb_defconfig 就是官方评估板的配置。你拿到自己的板子后,大概率要基于这个改。

3.2 交叉编译工具链配置

交叉编译,说白了就是在你的 x86 电脑上编译出能在 ARM 架构上跑的程序。MTK8678 用的是 ARM Cortex-A76 核心,所以工具链必须是 aarch64 的。

我建议你直接用 SDK 里自带的工具链。如果单独下载,记得选 gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu 这个版本。为什么?我在项目里试过 gcc 10 以上的版本,链接时偶尔会出一些奇怪的符号错误,9.2 是最稳的。

配置步骤其实就三步:

  1. 解压工具链/opt/toolchains/ 目录下
  2. 设置环境变量,把工具链的 bin 目录加到 PATH 里
  3. 验证一下,跑个简单的 hello world

具体命令如下:

# 解压
sudo tar -xzf gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu.tar.xz \
  -C /opt/toolchains/

# 设置环境变量(建议写到 ~/.bashrc 里)
export PATH=/opt/toolchains/gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu/bin:$PATH
export CROSS_COMPILE=aarch64-none-linux-gnu-
export ARCH=arm64

# 验证
aarch64-none-linux-gnu-gcc --version
小技巧: 我习惯在项目根目录下创建一个 setenv.sh 脚本,把环境变量都放进去。每次打开新终端,直接 source setenv.sh 就行,省得每次都要 export。

验证通过后,你可以写个简单的 C 文件测试一下:

// hello.c
#include <stdio.h>

int main() {
    printf("Hello from MTK8678!\n");
    return 0;
}

// 编译
aarch64-none-linux-gnu-gcc -o hello hello.c

// 查看文件信息
file hello
// 输出应该包含 "ELF 64-bit LSB executable, ARM aarch64"

看到 "ARM aarch64" 这几个字,就说明工具链配好了。我曾经遇到有人用 file 命令看到的是 x86-64,结果折腾半天发现是 PATH 没生效——嗯,这种低级错误我也犯过。

3.3 NFS/TFTP 调试环境搭建

开发阶段,你不可能每次改个代码就烧录一次固件。太慢了。所以我们需要搭建网络调试环境。这里主要用两个协议:NFS 和 TFTP。

3.4.1 TFTP:快速传输内核和设备树

TFTP 说白了就是一个极简的文件传输协议,没有认证,没有加密,但胜在轻量。我们用它来从电脑传内核镜像(Image)和设备树(.dtb)到开发板。

在 Ubuntu 上搭建 TFTP 服务器:

# 安装
sudo apt-get install tftpd-hpa

# 配置
sudo vim /etc/default/tftpd-hpa

# 内容如下:
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"        # 这就是你的文件存放目录
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="-l -c -s"

# 创建目录并设置权限
sudo mkdir -p /srv/tftp
sudo chmod 777 /srv/tftp

# 重启服务
sudo systemctl restart tftpd-hpa

然后把编译好的 Imagemt8678-evb.dtb 复制到 /srv/tftp/ 下。在开发板的 U-Boot 里,你就可以这样加载:

# 在 U-Boot 命令行中
setenv serverip 192.168.1.100    # 电脑 IP
setenv ipaddr 192.168.1.50       # 开发板 IP
tftp 0x40000000 Image
tftp 0x48000000 mt8678-evb.dtb
booti 0x40000000 - 0x48000000
注意: 开发板和电脑要在同一个网段。我遇到过有人把电脑 IP 设成 192.168.1.x,开发板却设成 10.0.0.x,结果 TFTP 一直超时。网络基础一定要打牢。

3.4.2 NFS:挂载根文件系统

TFTP 只能传文件,但你的程序跑起来后,总得有个文件系统吧?NFS 就是干这个的。开发板的根文件系统直接放在电脑上,开发板通过网络挂载。这样你改代码、编译、运行,一气呵成。

搭建 NFS 服务器:

# 安装
sudo apt-get install nfs-kernel-server

# 配置
sudo vim /etc/exports

# 添加一行(假设你的根文件系统在 /srv/nfs/rootfs)
/srv/nfs/rootfs *(rw,sync,no_subtree_check,no_root_squash)

# 创建目录并解压根文件系统
sudo mkdir -p /srv/nfs/rootfs
sudo tar -xzf buildroot-2020.02-output.tar.gz -C /srv/nfs/rootfs

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

然后在开发板的 U-Boot 里设置内核启动参数:

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

这里 nfsroot 的格式是 服务器IP:路径,后面的 ip 参数依次是:开发板IP、服务器IP、网关、子网掩码。我第一次配的时候,把网关写错了,结果板子能 ping 通电脑,但挂载 NFS 就是失败。查了半小时才发现是网关的问题。

调试小贴士: 如果 NFS 挂载失败,先在开发板上用 ping 192.168.1.100 确认网络通不通。如果 ping 不通,检查网线、IP 配置。如果 ping 得通但挂载失败,多半是 /etc/exports 的权限或者路径写错了。

3.5 验证环境是否打通

全部配置好后,我们来个完整的启动流程验证:

  1. 开发板上电,进入 U-Boot
  2. 用 TFTP 下载内核和设备树
  3. 用 NFS 挂载根文件系统
  4. 系统启动后,执行 ifconfig 确认网络正常
  5. 在开发板上 mount | grep nfs,应该能看到挂载信息

如果一切顺利,你会看到开发板的终端上出现了熟悉的 Linux 登录提示符。那一刻,说实话,挺有成就感的。

嗯,这一章的内容就到这里。环境搭建是枯燥了点,但这是后面所有实验的基础。下一章我们开始真正接触 MTK8678 的以太网 MAC 层,到时候你会感谢今天把环境配好的自己。