4. 算法移植环境搭建:交叉编译、DSP SDK 与原型验证平台

环境搭建这事儿,说难不难,说简单也真能卡你三天。我见过不少同事,算法在 PC 上跑得飞起,一到板子上就各种“找不到库”、“链接失败”、“DSP 加载崩溃”。说白了,就是环境没搭对。这一章,我把 SA8295/SA8255 的交叉编译环境、Hexagon DSP SDK 的安装,还有原型验证平台的搭建,一步步拆开讲清楚。

4.1 交叉编译环境配置

高通平台的交叉编译器,官方推荐的是 aarch64-oe-linux-gcc,这套工具链包含在 LE (Linux Embedded) 包里面。我个人习惯用 SA8295 的 LE 1.2 版本,比较稳定。

4.1.1 工具链安装步骤

  1. 解压 SDK 包:将下载的 SA8295.LE.1.2.tar.gz 放到工作目录,执行 tar -xzf SA8295.LE.1.2.tar.gz。
  2. 设置环境变量:在 ~/.bashrc 中添加以下内容:
    export TOOLCHAIN_DIR=/opt/sa8295/le-1.2/toolchain
    export PATH=$TOOLCHAIN_DIR/bin:$PATH
    export CROSS_COMPILE=aarch64-oe-linux-
    export CC=${CROSS_COMPILE}gcc
    export CXX=${CROSS_COMPILE}g++
    export LD=${CROSS_COMPILE}ld
    export AR=${CROSS_COMPILE}ar
  3. 验证安装:运行 aarch64-oe-linux-gcc --version,看到版本号输出就对了。
避坑指南:我曾经在 SA8255 上用过一套较老的工具链,结果编译出来的 OpenCV 库在板子上跑 segmentation fault。后来发现是工具链的 glibc 版本与板子上的不匹配。所以,一定要用芯片配套的 LE 包,别自己从网上下通用工具链。

4.1.2 关键依赖库的交叉编译

算法移植通常需要 OpenCV、Eigen、TinyXML 等库。这里以 OpenCV 为例,展示交叉编译的 CMake 配置:

cmake -DCMAKE_SYSTEM_NAME=Linux \
      -DCMAKE_SYSTEM_PROCESSOR=aarch64 \
      -DCMAKE_C_COMPILER=aarch64-oe-linux-gcc \
      -DCMAKE_CXX_COMPILER=aarch64-oe-linux-g++ \
      -DCMAKE_FIND_ROOT_PATH=/opt/sa8295/le-1.2/sysroot \
      -DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER \
      -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY \
      -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY \
      -DWITH_IPP=OFF \
      -DWITH_TBB=OFF \
      -DBUILD_opencv_world=ON ..
make -j8

注意 CMAKE_FIND_ROOT_PATH 指向 sysroot,这样 cmake 才会去板子的根文件系统里找头文件和库,而不是去 PC 的 /usr/include 里找。

4.2 Hexagon DSP SDK 安装

双摄融合和夜景模式里,很多像素级操作(比如对齐、融合)会跑到 DSP 上执行。Hexagon DSP SDK 就是用来开发这些 DSP 代码的。

4.2.1 SDK 版本选择

芯片 推荐 SDK 版本 Hexagon 架构 备注
SA8295 Hexagon SDK 5.0.2 V73 支持 HVX 双向量模式
SA8255 Hexagon SDK 5.1.0 V75 新增了部分图像处理指令

4.2.2 安装与配置

  1. 安装 SDK:运行 ./Qualcomm_Hexagon_SDK_5_0_2.bin,按提示完成安装。
  2. 设置环境变量:
    export HEXAGON_SDK_ROOT=/opt/qualcomm/hexagon_sdk/5.0.2
    export HEXAGON_TOOLS_ROOT=$HEXAGON_SDK_ROOT/tools
    export PATH=$HEXAGON_TOOLS_ROOT/qaic/1.8.0/bin:$PATH
    export PATH=$HEXAGON_TOOLS_ROOT/hexagon-clang/8.5.07/bin:$PATH
  3. 验证 DSP 编译器:运行 hexagon-clang++ --version,确认输出中包含 Hexagon 字样。
小技巧:我习惯在 ~/.bashrc 里写一个函数 dspsetup,一键切换不同版本的 SDK 环境。毕竟项目多了,SA8295 和 SA8255 的 SDK 版本不一样,来回改环境变量太容易出错了。

4.3 算法原型验证平台搭建

环境搭好了,怎么验证算法移植得对不对?你不能每次都烧固件跑吧?太慢了。我们需要一个 原型验证平台,在 PC 上模拟板子的行为,快速迭代。

4.3.1 平台架构

下面这张图是我自己设计的验证平台结构,你可以参考:

算法原型验证平台架构 输入层 RAW / YUV 图像序列 预处理层 BLC / LSC / 去噪 算法核心层 融合 / 夜景 / HDR 输出层 融合后图像 / 指标 验证对比模块 PSNR / SSIM / 耗时 DSP 模拟器 Hexagon Simulator 平台工作流程 1. 输入 RAW/YUV 图像,经过预处理后送入算法核心层 2. 算法核心层可同时输出到 DSP 模拟器和输出层 3. 输出层结果与验证对比模块比对,评估移植精度 4. DSP 模拟器用于验证 Hexagon 代码的功能正确性

4.3.2 搭建步骤

  1. 准备 PC 端测试框架:我推荐用 Python + OpenCV 写一个简单的 pipeline,读取图像、调用算法库、显示结果。这样调试效率最高。
  2. 编译算法为 ARM64 动态库:用 4.1 节配置的交叉编译器,把你的算法(比如双摄融合的 warp + blend)编译成 .so 文件。
  3. 编写 JNI 封装层:如果算法库是用 C++ 写的,而测试框架是 Python,可以用 ctypes 或 pybind11 封装一下。我个人更倾向 pybind11,类型转换更省心。
  4. 集成 DSP 模拟器:Hexagon SDK 自带 hexagon-sim,可以加载你的 DSP 可执行文件(.do 文件)进行仿真。在测试框架里通过 subprocess 调用模拟器,获取 DSP 处理后的结果。
核心思路:原型验证平台的目标是 在 PC 上复现板子上的行为。ARM64 库模拟 CPU 侧行为,Hexagon Simulator 模拟 DSP 侧行为。两边结果对比,误差在 1% 以内,就可以放心往板子上搬了。

4.3.3 一个典型的验证流程

假设你要移植一个双摄融合算法:

  1. PC 端用 OpenCV 读取左右两张 RAW 图。
  2. 调用交叉编译好的 ARM64 库,执行特征点匹配和单应性矩阵计算。
  3. 将 warp 参数传给 DSP 模拟器,执行像素级 warp 和 blend。
  4. 对比 DSP 模拟器输出与 PC 端 OpenCV 参考实现的 PSNR。
  5. 如果 PSNR > 40dB,说明移植精度达标。
注意:DSP 模拟器的速度比实际硬件慢很多,一个 1080p 的 warp 操作在模拟器上可能要跑几十秒。所以验证时建议用 小图(比如 640x480) 先调通逻辑,再用大图做精度验收。

4.4 环境验证清单

环境搭完,别急着写代码。先跑一遍这个清单,确认所有环节都通了:

检查项 验证方法 预期结果
交叉编译器 编译一个 hello world 生成 ARM64 可执行文件,file 命令显示 ELF 64-bit LSB
OpenCV 交叉编译 编译一个读取图片并显示尺寸的程序 在板子上运行正常,输出正确尺寸
Hexagon SDK 编译 SDK 自带的 example 生成 .do 文件,hexagon-sim 加载无报错
原型验证平台 跑一个简单的图像处理 pipeline ARM64 库结果与 PC 参考结果一致

嗯,环境搭建这部分就这些。别嫌麻烦,这一步做好了,后面算法移植会顺畅很多。我见过太多人急着写代码,结果环境没配好,浪费了整整一周在定位“编译器版本不对”这种低级问题上。磨刀不误砍柴工,对吧?