3、开发环境搭建:Linux开发机配置、交叉编译工具链安装、TFTP/NFS服务器搭建、串口与JTAG调试环境
说实话,做机顶盒嵌入式开发,环境搭建这一步要是没弄好,后面全是坑。我见过太多新手一上来就急着写代码,结果编译都过不了,或者烧录进去跑不起来,最后回过头来查环境问题,白白浪费好几天。
这一章,我就把我在多个机顶盒项目里积累的搭建经验,掰开了揉碎了讲给你听。你跟着我的步骤走,基本能一次搞定。
3.1 Linux开发机配置:选对工具,事半功倍
机顶盒的芯片方案,像海思、晶晨、瑞芯微这些,它们的SDK(软件开发包)几乎都是基于Ubuntu的。我个人习惯用Ubuntu 18.04 LTS或20.04 LTS。为什么?因为很多老芯片的编译器只支持glibc 2.27左右的版本,你装个最新的Ubuntu 22.04,反而会碰到各种库不兼容的问题。
嗯,这里要注意:千万别用虚拟机里的Ubuntu做日常编译。机顶盒的源码动不动几十个G,全量编译一次可能要半小时到一小时。虚拟机磁盘IO性能太差,你会等到怀疑人生。我建议直接装双系统,或者搞一台专门的编译服务器。
硬件配置上,我的建议是:
- CPU:至少4核,8核以上更佳。编译时能开多线程,省时间。
- 内存:16GB起步。我遇到过32GB内存编译大型Android TV源码时,都差点爆掉。
- 硬盘:必须用SSD,容量至少500GB。机顶盒的SDK解压后,加上编译中间文件,轻松吃掉200GB。
- 文件系统:建议用ext4,别用NTFS或FAT32。交叉编译时,符号链接和文件权限经常出问题,NTFS根本hold不住。
settop,然后把SDK放在/home/settop/work下。这样权限隔离,不会污染系统环境。
3.2 交叉编译工具链安装:别用错版本
交叉编译,说白了就是在你的x86电脑上,编译出能在ARM芯片上跑的程序。工具链就是那个“翻译官”。
机顶盒芯片厂商一般都会提供配套的工具链。比如海思的arm-hisiv300-linux-gcc,晶晨的aarch64-linux-gnu-gcc。你千万别自己去网上下个通用的ARM gcc,那大概率编译出来的程序跑不起来。
安装步骤其实很简单,但有个坑我必须提醒你:
# 1. 解压工具链(假设是海思的)
tar -xvf arm-hisiv300-linux-gcc-4.9.2-20150629.tar.bz2
# 2. 移动到标准目录
sudo mv arm-hisiv300-linux /opt/
# 3. 配置环境变量(一定要加到 ~/.bashrc 里)
echo 'export PATH=$PATH:/opt/arm-hisiv300-linux/bin' >> ~/.bashrc
source ~/.bashrc
# 4. 验证安装
arm-hisiv300-linux-gcc --version
我曾经犯过一个错:只把环境变量加到了当前终端,结果一关窗口,重新打开就找不到编译器了。所以一定要写到~/.bashrc或~/.profile里,让它永久生效。
sudo apt install lib32z1 lib32ncurses5 就能解决。如果你遇到“No such file or directory”但文件明明存在,多半就是这个问题。
验证工具链是否正常,我一般会写个最简单的hello world:
// hello.c
#include <stdio.h>
int main() {
printf("Hello, STB World!\n");
return 0;
}
// 编译
arm-hisiv300-linux-gcc -o hello hello.c
// 查看文件信息
file hello
// 输出应该是:ELF 32-bit LSB executable, ARM, ...
看到“ARM”字样,说明交叉编译成功了。这个文件在x86电脑上是跑不了的,得放到机顶盒上才能执行。
3.3 TFTP/NFS服务器搭建:开发板的“快递员”和“共享文件夹”
开发板不像你的电脑,它没有硬盘,也没有显示器。那你怎么把编译好的程序传上去?怎么调试?这就轮到TFTP和NFS出场了。
3.3.1 TFTP服务器:快速传输内核和镜像
TFTP(简单文件传输协议)常用于在uboot阶段,把内核镜像(uImage)和设备树文件(.dtb)从电脑传到开发板。它没有认证,速度也一般,但胜在简单。
搭建步骤:
# 安装TFTP服务器
sudo apt install tftpd-hpa
# 配置(编辑 /etc/default/tftpd-hpa)
# 把 TFTP_DIRECTORY 改成你的共享目录,比如 /srv/tftp
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure"
# 创建目录并设置权限
sudo mkdir -p /srv/tftp
sudo chmod 777 /srv/tftp
# 重启服务
sudo systemctl restart tftpd-hpa
在开发板的uboot里,你只需要这样操作:
# 设置开发板IP和服务器IP
setenv ipaddr 192.168.1.100
setenv serverip 192.168.1.10
# 下载内核镜像
tftp 0x82000000 uImage
# 启动内核
bootm 0x82000000
嗯,这里要注意:TFTP的根目录权限一定要给够。我遇到过因为目录权限是755,导致文件传不过去,折腾了半天才发现是权限问题。
3.3.2 NFS服务器:让开发板挂载你的电脑目录
NFS(网络文件系统)比TFTP强大得多。开发板可以通过网络,直接访问你电脑上的某个目录。这样你编译完程序,不用反复烧录,直接在开发板上运行就行。调试效率提升一大截。
搭建步骤:
# 安装NFS服务器
sudo apt install nfs-kernel-server
# 配置(编辑 /etc/exports)
# 共享 /home/settop/nfsroot 目录,允许开发板读写
/home/settop/nfsroot *(rw,sync,no_subtree_check,no_root_squash)
# 创建目录
sudo mkdir -p /home/settop/nfsroot
sudo chmod 777 /home/settop/nfsroot
# 重启服务
sudo systemctl restart nfs-kernel-server
在开发板的uboot或内核启动参数里,加上NFS挂载命令:
# 在uboot中设置启动参数
setenv bootargs 'console=ttyS0,115200 root=/dev/nfs nfsroot=192.168.1.10:/home/settop/nfsroot rw ip=192.168.1.100'
# 或者在内核启动后手动挂载
mount -t nfs -o nolock 192.168.1.10:/home/settop/nfsroot /mnt
3.4 串口与JTAG调试环境:开发板的“眼睛”和“手术刀”
开发板没有显示器,你怎么看它打印的信息?怎么输入命令?串口就是干这个的。而JTAG,则是更底层的调试工具,可以单步执行、查看寄存器。
3.4.1 串口调试:最基础的交互方式
机顶盒开发板上一般都会有一个4针的串口接口(TX、RX、GND、VCC)。你需要一根USB转串口线(比如PL2303或CH340),连接到电脑。
连接方式:
- 开发板的TX -> 串口线的RX
- 开发板的RX -> 串口线的TX
- GND -> GND
- VCC一般不接,或者接3.3V(看板子要求)
电脑端,我推荐用MobaXterm或PuTTY。设置如下:
# 查看串口设备
ls /dev/ttyUSB* # 一般是 /dev/ttyUSB0
# 使用 screen 命令(临时用)
sudo screen /dev/ttyUSB0 115200
# 或者用 minicom(更稳定)
sudo minicom -D /dev/ttyUSB0 -b 115200
波特率一般是115200,8位数据位,1位停止位,无校验。如果打印出乱码,多半是波特率不对,或者TX/RX接反了。
3.4.2 JTAG调试:深入骨髓的调试手段
JTAG主要用于uboot阶段或内核早期的调试。当系统还没跑起来,串口都没输出时,JTAG就是唯一的救命稻草。
常用的JTAG调试器有J-Link、OpenOCD配合FT2232等。机顶盒芯片大多支持ARM的SWD(串行线调试)模式,只需要两根线(SWDIO和SWCLK)就能调试。
以OpenOCD为例,配置文件大概长这样:
# stb.cfg
source [find interface/ftdi/ft2232.cfg]
source [find target/hi3536.cfg]
# 设置传输速率
adapter speed 1000
# 连接目标板
init
targets
reset halt
启动OpenOCD后,再用GDB连接:
arm-hisiv300-linux-gdb u-boot
(gdb) target remote localhost:3333
(gdb) monitor reset halt
(gdb) load
(gdb) continue
说实话,JTAG调试在日常开发中用得不多。但一旦遇到uboot起不来、DDR初始化失败这种硬核问题,你就知道它的好了。我有个同事,曾经靠JTAG单步调试,发现是某颗电阻虚焊导致时钟信号异常,省了返厂维修的时间。
3.5 环境验证:跑一个完整的启动流程
所有环境搭好后,我建议你跑一个完整的流程,验证每个环节是否通畅:
- 在电脑上编译uboot和内核。
- 通过TFTP把镜像传到开发板。
- 开发板启动后,通过NFS挂载根文件系统。
- 在串口终端里,输入命令,看到正常的shell提示符。
- 写一个简单的测试程序,交叉编译后,放到NFS目录里,在开发板上运行。
如果以上5步都能顺利完成,恭喜你,开发环境搭建成功了。你可以安心地进入下一章,开始真正的驱动开发了。