第二章 开发环境搭建:交叉编译工具链安装、SDK包结构解析、Ubuntu开发机配置
说实话,搭建开发环境这件事,看着简单,但坑是真不少。我见过太多新手卡在这一步,一卡就是好几天。今天我就把我在Hi3559A上折腾出来的经验,一次性说清楚。
2.1 交叉编译工具链安装
为什么要用交叉编译?说白了,你的开发机是x86架构,但Hi3559A是ARM架构。你不可能在ARM芯片上直接写代码、编译吧?那太慢了。所以我们在PC上编译,生成ARM能跑的可执行文件,再传过去运行。
2.1.1 获取工具链
海思官方提供的工具链是 arm-himix200-linux。你可以在SDK包里的 toolchain 目录找到它。我个人习惯把它放在 /opt/hisi 下,方便管理。
# 解压工具链
tar -xvf arm-himix200-linux.tar.bz2 -C /opt/hisi/
# 进入解压后的目录
cd /opt/hisi/arm-himix200-linux
# 运行安装脚本
./install.sh
安装脚本会自动设置环境变量。不过,我建议你手动检查一下。为什么?因为有时候脚本执行不完整,你后面编译时会报一些莫名其妙的错。
source /etc/profile,让环境变量生效。
2.1.2 验证安装
验证很简单,执行以下命令:
arm-himix200-linux-gcc --version
如果能看到版本信息,说明安装成功。我曾经遇到过一个问题:明明显示安装成功,但编译时提示找不到编译器。后来发现是 PATH 变量没加对。你想想看,系统都不知道去哪找这个编译器,它当然报错。
~/.bashrc 里,这样每次打开终端都不用重新设置。
echo 'export PATH=/opt/hisi/arm-himix200-linux/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
2.2 SDK包结构解析
拿到海思的SDK包,第一眼感觉就是:东西真多。别慌,我来帮你理一理。SDK包的核心目录结构大致如下:
| 目录/文件 | 说明 |
|---|---|
osdrv/ |
操作系统驱动,包含内核、文件系统、uboot等 |
mpp/ |
媒体处理平台,这是Hi3559A的核心,包含视频编解码、AI推理等 |
smp/ |
多核通信相关,Hi3559A是大小核架构,这个目录很重要 |
toolchain/ |
交叉编译工具链,刚才我们已经装过了 |
doc/ |
开发文档,建议先看这里 |
我个人建议,刚开始不要一头扎进代码里。先花半小时把 doc/ 目录下的 Hi3559A__xxx_Release_Notes.pdf 翻一遍。里面会告诉你SDK版本、支持的特性、已知问题。嗯,这一步能帮你省下不少排查问题的时间。
2.2.1 mpp目录详解
mpp/ 是重中之重。它的结构是这样的:
mpp/
├── component/ # 组件层,封装了底层API
├── include/ # 头文件,开发时主要参考这里
├── lib/ # 编译好的库文件
├── sample/ # 示例代码,学习利器
└── Makefile # 编译脚本
我在项目中遇到过最头疼的事,就是自己写代码调用了某个API,结果编译报错说找不到函数。后来发现是头文件路径没加对。所以,include/ 目录下的文件,建议你至少扫一遍,知道每个头文件是干什么的。
sample/ 目录下的示例代码,是你入门最快的方式。比如你想做视频采集,直接看 sample_vio;想做AI推理,看 sample_nnie。把示例跑通了,再改自己的逻辑。
2.3 Ubuntu开发机配置
开发机推荐用 Ubuntu 18.04 或 20.04。为什么?因为海思的工具链和库,在这两个版本上测试最充分。我试过用 Ubuntu 22.04,结果编译时一堆依赖问题,折腾了两天才搞定。所以,别跟自己过不去。
2.3.1 安装必要依赖
以下是我整理的最小依赖列表,缺一不可:
sudo apt-get update
sudo apt-get install -y \
build-essential \
libncurses5-dev \
zlib1g-dev \
libssl-dev \
flex \
bison \
u-boot-tools \
device-tree-compiler \
python3 \
python3-pip
这里有个坑:libncurses5-dev 在 Ubuntu 20.04 上可能装不上,因为默认是 libncurses-dev。我曾经在这卡了半小时,后来发现直接装 libncurses-dev 就行。
gcc-arm-linux-gnueabihf 这个交叉编译器。别问我怎么知道的,问就是吃过亏。
2.3.2 配置NFS和TFTP
开发过程中,你肯定需要把编译好的文件传到开发板上。我推荐用NFS挂载根文件系统,用TFTP下载内核。这样调试起来非常方便。
NFS配置:
sudo apt-get install nfs-kernel-server
sudo mkdir -p /srv/nfs
sudo chown nobody:nogroup /srv/nfs
echo "/srv/nfs *(rw,sync,no_subtree_check,no_root_squash)" | sudo tee -a /etc/exports
sudo systemctl restart nfs-kernel-server
TFTP配置:
sudo apt-get install tftpd-hpa
sudo mkdir -p /srv/tftp
sudo chmod 777 /srv/tftp
echo "TFTP_DIRECTORY=\"/srv/tftp\"" | sudo tee -a /etc/default/tftpd-hpa
sudo systemctl restart tftpd-hpa
配置好之后,把编译好的内核镜像 uImage 放到 /srv/tftp 下,把根文件系统放到 /srv/nfs 下。开发板启动时,直接从网络加载,省去了反复烧写SD卡的麻烦。
/srv/nfs 下建一个 app/ 目录,专门放编译好的应用程序。这样开发板上直接 mount -t nfs 挂载后,就能运行最新的程序,不用每次都拷贝。
2.3.3 串口调试工具
串口是嵌入式开发的生命线。我推荐用 minicom 或 screen。我个人更习惯用 screen,因为它轻量、稳定。
sudo apt-get install screen
# 连接串口,假设设备是 /dev/ttyUSB0,波特率115200
screen /dev/ttyUSB0 115200
断开串口时,按 Ctrl+A 然后按 K,再按 Y 确认。嗯,这个快捷键我刚开始老记不住,后来贴了个便签在显示器上。
2.4 验证环境是否搭建成功
环境搭没搭好,跑一个最简单的Hello World就知道了。
// hello.c
#include <stdio.h>
int main() {
printf("Hello, Hi3559A!\n");
return 0;
}
# 交叉编译
arm-himix200-linux-gcc hello.c -o hello
# 查看文件信息,确认是ARM架构
file hello
# 输出应该包含:ELF 32-bit LSB executable, ARM
如果能看到 ARM 字样,恭喜你,环境搭建成功了。把这个文件传到开发板上,运行一下,看到打印信息的那一刻,你会觉得前面所有的折腾都值了。
好了,环境搭建就讲到这里。下一章我们开始真正接触Hi3559A的硬件,聊聊它的核心架构和内存布局。到时候你会发现,理解了硬件,写代码才有底气。