2、调试环境搭建:交叉编译工具链配置、内核源码树准备、NFS/TFTP网络启动环境搭建、串口终端(minicom/Putty)设置、逻辑分析仪与示波器基础操作
调试环境搭建,说白了就是给你的开发板配齐「吃饭的家伙」。我见过太多新手,代码写得挺溜,结果卡在环境配置上好几天。其实这步搞定了,后面调试会顺很多。
2.1 交叉编译工具链配置
机顶盒芯片大多是 ARM 或 MIPS 架构,你的 PC 是 x86 架构。所以你得用交叉编译工具链——在 PC 上编译出能在机顶盒上跑的程序。
工具链的选择,我一般看芯片厂商的 SDK 里带了什么。比如海思的 HiLinux、晶晨的 Android 源码包,里面都有现成的工具链。我个人习惯用 Linaro 的 GCC 工具链,稳定且社区活跃。
配置步骤:
- 下载对应架构的工具链(arm-linux-gnueabihf- 或 mips-linux-gnu-)
- 解压到
/opt/toolchains/目录 - 添加环境变量到
~/.bashrc
export PATH=$PATH:/opt/toolchains/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin
export CROSS_COMPILE=arm-linux-gnueabihf-
export ARCH=arm
配置完记得 source ~/.bashrc。然后跑一下 arm-linux-gnueabihf-gcc --version,看到版本号就说明成了。
小技巧:我曾经在某个项目里,工具链版本和内核版本不匹配,编译出来的驱动模块 insmod 时直接报错。后来发现是 GCC 版本太新,内核头文件不兼容。建议用芯片厂商推荐的工具链版本,别盲目追新。
2.2 内核源码树准备
驱动调试离不开内核源码树。说白了,就是你要编译驱动模块,得有内核的头文件和 Makefile 结构。
两种常见做法:
- 完整内核源码:从芯片厂商拿到内核包,解压后配置编译一遍。这样最保险,但耗时长。
- 仅内核头文件:如果只是调试驱动模块,可以只安装内核头文件包。但要注意版本必须完全一致。
我一般用第一种。拿到源码后,先配置内核:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- xxx_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage -j4
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules -j4
编译完内核和模块后,把 arch/arm/boot/zImage 和 arch/arm/boot/dts/ 下的设备树文件拷贝出来备用。
注意:内核源码树路径不要有中文或空格。我见过有人把源码放在「我的文档」里,结果编译时各种奇葩错误。老老实实用 /home/user/kernel/ 这种路径。
2.3 NFS/TFTP 网络启动环境搭建
调试驱动时,最烦的就是每次改代码都要重新烧写固件。用网络启动就方便多了——内核和文件系统都放在服务器上,开发板通过网络加载。
TFTP 服务器(传输内核和设备树)
TFTP 用来传内核镜像和设备树文件。配置很简单:
sudo apt install tftpd-hpa
sudo vim /etc/default/tftpd-hpa
配置文件里指定 TFTP_DIRECTORY="/srv/tftp",然后把 zImage 和 .dtb 文件丢进去。
开发板 U-Boot 里设置:
setenv serverip 192.168.1.100
setenv ipaddr 192.168.1.10
setenv bootcmd 'tftp 0x82000000 zImage; tftp 0x83000000 board.dtb; bootz 0x82000000 - 0x83000000'
saveenv
boot
NFS 文件系统(挂载根文件系统)
NFS 让开发板把服务器上的目录当作根文件系统来用。这样你改完驱动,重启开发板就能看到效果。
sudo apt install nfs-kernel-server
sudo vim /etc/exports
添加一行:
/srv/nfs/rootfs 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)
然后在 U-Boot 里设置内核启动参数:
setenv bootargs 'console=ttyS0,115200 root=/dev/nfs nfsroot=192.168.1.100:/srv/nfs/rootfs rw ip=192.168.1.10'
避坑指南:我曾经在调试网卡驱动时,NFS 死活挂不上。折腾了半天,发现是开发板和服务器的网段不一致。还有一次是防火墙没关。记住:调试阶段先把防火墙关了,省得自己坑自己。
2.4 串口终端(minicom/Putty)设置
串口是嵌入式调试的「生命线」。内核打印、驱动日志、甚至紧急 shell,都靠它。
minicom(Linux 下常用)
sudo minicom -s
进入配置界面,设置:
- 串口设备:
/dev/ttyUSB0(看你的 USB 转串口设备) - 波特率:
115200 - 数据位:
8 - 停止位:
1 - 无校验
- 硬件流控:
No
Putty(Windows 下常用)
选 Serial,填上 COM 口和波特率。注意 Windows 下 COM 口编号可以在设备管理器里查到。
关键设置:流控一定要关掉!我见过太多人开着硬件流控,结果串口只能收不能发,或者乱码。另外,如果出现乱码,先检查波特率是否匹配,再检查电平是否一致(3.3V vs 1.8V)。
2.5 逻辑分析仪与示波器基础操作
软件调试搞不定的时候,就得请出硬件工具了。逻辑分析仪看时序,示波器看波形。
逻辑分析仪
调试 I2C、SPI、UART 这些协议时,逻辑分析仪是神器。我常用的有 Saleae Logic 和国产的梦源。
基本操作:
- 把通道夹子接到要测的信号线上(记得共地)
- 设置采样率(一般 24MHz 够用,高速信号要更高)
- 设置触发条件(比如 I2C 的 START 条件)
- 点击开始采集,然后让开发板跑相关操作
举个例子,调试 I2C 驱动时,用逻辑分析仪抓一下 SCL 和 SDA 的波形。如果看到 START 条件后没有 ACK,那多半是设备地址错了或者从设备没上电。
示波器
示波器看模拟信号更在行。比如调试 HDMI 输出、音频信号、电源纹波。
基础操作:
- 探头补偿:用示波器自带的 1kHz 方波信号校准探头
- 垂直档位:根据信号幅度调整(一般先设 1V/div)
- 水平时基:根据信号频率调整(比如 1MHz 信号设 500ns/div)
- 触发设置:边沿触发最常用,触发电平设在信号中间
安全提醒:示波器探头的地线夹子一定要接开发板的 GND,千万别接到 VCC 上,否则直接短路烧板。我刚开始用示波器时就犯过这错,烧了一块价值 2000 块的开发板……嗯,从那以后我每次接线都先确认一遍。
小结
调试环境搭建看起来琐碎,但每一步都关系到后续调试效率。工具链配好了,编译不报错;网络启动配好了,迭代速度快;串口调通了,能看到内核日志;逻辑分析仪和示波器会用,硬件问题也能定位。
我个人建议,把这套环境搭好后,写个脚本一键配置。下次换项目或者换电脑,直接跑脚本就行,省得重复劳动。