2. 开发环境搭建:交叉编译工具链安装、TFTP/NFS服务器配置、串口终端与ADB调试
做嵌入式开发,第一步就是把“窝”搭好。环境配不对,后面全是坑。我见过不少新手,代码写得挺漂亮,结果卡在编译不过、烧录失败上,一查全是工具链版本不对、服务器没配好这类基础问题。
这一章,咱们就把全志T113的开发环境从头捋一遍。说白了,就四件事:交叉编译工具链、TFTP/NFS服务器、串口终端、ADB调试。每样我都会结合自己的踩坑经历来讲。
2.1 交叉编译工具链安装
T113是ARM Cortex-A7内核,你的PC是x86架构。在x86上编译出ARM能跑的程序,就得靠交叉编译工具链。说白了,就是一套“跨架构的编译器+库+头文件”。
2.1.1 获取工具链
全志官方推荐的是 gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf 这个版本。我个人习惯用Linaro的版本,稳定,社区支持好。
核心要点:工具链版本必须与内核版本匹配。T113的官方BSP基于Linux 5.4,用gcc 7.5最稳。我曾经试过用gcc 9.x编译,结果内核模块加载时直接报Unknown symbol,折腾了两天才发现是工具链ABI不兼容。
安装步骤很简单,就三步:
- 下载:从Linaro官网或全志网盘获取压缩包。
- 解压:放到
/opt/目录下。 - 配置环境变量:加到
~/.bashrc里。
# 解压到 /opt
sudo tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz -C /opt/
# 编辑 ~/.bashrc,在末尾添加
export PATH=$PATH:/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin
export CROSS_COMPILE=arm-linux-gnueabihf-
export ARCH=arm
# 使生效
source ~/.bashrc
# 验证
arm-linux-gnueabihf-gcc --version
小技巧:我习惯在项目根目录下放一个 setenv.sh 脚本,每次开新终端就 source setenv.sh,避免多个项目环境变量冲突。
2.1.2 验证工具链
写一个最简单的Hello World,交叉编译后放到板子上跑,这是最直接的验证方式。
// hello.c
#include <stdio.h>
int main(void)
{
printf("Hello from T113!\n");
return 0;
}
// 编译
arm-linux-gnueabihf-gcc -o hello hello.c
// 查看文件信息
file hello
// 输出: hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), ...
看到 ARM 字样,说明编译出来的确实是ARM架构的可执行文件。嗯,这一步别跳过,我见过有人配了半天,结果 file 一看还是x86的。
2.2 TFTP/NFS服务器配置
开发阶段,你不可能每次修改都重新烧录整个镜像。TFTP用来网络加载内核和设备树,NFS用来挂载根文件系统。这两个配好了,开发效率能翻一倍。
2.2.1 TFTP服务器
TFTP说白了就是一个极简的文件传输协议,Uboot用它从主机拉取内核镜像。
# 安装
sudo apt-get install tftp-hpa tftpd-hpa
# 创建tftp根目录
sudo mkdir -p /tftpboot
sudo chmod 777 /tftpboot
# 配置文件 /etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/tftpboot"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="-l -c -s"
# 重启服务
sudo systemctl restart tftpd-hpa
sudo systemctl enable tftpd-hpa
注意:防火墙要放行UDP 69端口。我在项目中遇到过Ubuntu的ufw默认开启,结果TFTP一直超时,查了半天才发现是防火墙拦了。执行 sudo ufw allow 69/udp 即可。
测试方法:在 /tftpboot 下放一个文件,然后在板子的Uboot中执行:
# Uboot端
setenv serverip 192.168.1.100 # 主机IP
setenv ipaddr 192.168.1.50 # 板子IP
tftp 0x42000000 zImage
能正常下载,说明TFTP通了。
2.2.2 NFS服务器
NFS用于挂载根文件系统。这样你修改了文件系统内容,板子重启后直接生效,不用反复烧录。
# 安装
sudo apt-get install nfs-kernel-server
# 创建导出目录,比如 /home/t113/rootfs
sudo mkdir -p /home/t113/rootfs
# 配置文件 /etc/exports,添加一行
/home/t113/rootfs *(rw,sync,no_subtree_check,no_root_squash)
# 重启服务
sudo systemctl restart nfs-kernel-server
sudo exportfs -av
避坑指南:no_root_squash 这个参数很重要。不加的话,板子上的root用户会被映射成nobody,很多操作会权限不足。我曾经因为这个,折腾了一下午才发现是权限问题。
板端挂载测试:
# 板子上执行
mount -t nfs -o nolock 192.168.1.100:/home/t113/rootfs /mnt
ls /mnt
能列出文件,说明NFS配置成功。
2.3 串口终端与ADB调试
这两个是调试的“眼睛”和“手”。串口看日志,ADB传文件、跑命令。
2.3.1 串口终端配置
T113的调试串口默认是UART0,通常用3.3V电平的USB转串口模块连接。波特率一般是 115200,8N1。
主机端我用 minicom 或 screen,个人更推荐 screen,轻量、稳定。
# 安装
sudo apt-get install screen
# 查看串口设备
ls /dev/ttyUSB* # 或 /dev/ttyACM*
# 连接
sudo screen /dev/ttyUSB0 115200
# 退出:Ctrl+A 然后按 K,再按 Y 确认
关键参数:波特率115200、数据位8、停止位1、无校验、无流控。这五个参数错一个,出来的就是乱码。我刚开始做驱动时,有次串口全是乱码,还以为是硬件坏了,结果发现是minicom的流控没关。
板子上电后,串口应该能输出Uboot的启动信息,然后是内核的log。如果没有任何输出,先检查:
- TX/RX有没有接反?
- GND有没有共地?
- 电平是不是3.3V?
2.3.2 ADB调试
ADB(Android Debug Bridge)本来是Android的调试工具,但全志的Linux BSP也集成了ADB守护进程。有了ADB,你可以通过USB传输文件、执行shell命令,比串口快得多。
主机端安装:
sudo apt-get install adb
# 查看设备
adb devices
# 进入shell
adb shell
# 传输文件
adb push local_file /target_path
adb pull /remote_file local_path
我的习惯:调试驱动时,我通常开两个终端:一个串口看内核log,一个ADB shell用来insmod/rmmod模块、测试应用。串口负责“看”,ADB负责“做”,分工明确。
如果 adb devices 找不到设备,检查:
- USB线是不是数据线?有些充电线只能充电。
- 板子上有没有启动ADB守护进程?执行
adbd &。 - 主机有没有添加USB设备权限?可以
sudo adb kill-server然后sudo adb start-server。
2.4 环境验证清单
所有配置完成后,我建议你按这个表格逐项检查。每一项都确认通过,再开始写代码。
| 序号 | 验证项 | 验证方法 | 预期结果 |
|---|---|---|---|
| 1 | 交叉编译工具链 | arm-linux-gnueabihf-gcc --version |
显示版本号,无报错 |
| 2 | TFTP下载 | Uboot中执行 tftp 0x42000000 zImage |
下载成功,显示传输速率 |
| 3 | NFS挂载 | 板端执行 mount -t nfs ... /mnt |
挂载成功,能列出文件 |
| 4 | 串口输出 | 板子上电,观察串口终端 | 正常显示Uboot和内核log |
| 5 | ADB连接 | adb devices |
显示设备序列号 |
重要提醒:开发主机的IP地址建议设置为静态IP,比如 192.168.1.100。板子的IP也固定下来。DHCP虽然方便,但每次重启IP一变,Uboot里的serverip就得改,很烦。我吃过这个亏,后来一律用静态IP。
环境搭好了,后面写驱动、调bug才能顺风顺水。嗯,这一章的内容就这些,都是实打实的操作。你跟着配一遍,遇到问题再回头看,基本都能解决。