2. 开发环境搭建:SDK安装、交叉编译工具链配置、ADB调试与性能分析工具

说实话,做嵌入式图形开发,环境搭建往往是第一道坎。很多人觉得不就是装个软件嘛,但我在高通平台上折腾了这么多年,踩过的坑真不少。这一章,我就把那些容易出问题的地方,一个一个给你讲清楚。

2.1 SDK安装:别小看这一步

高通8155的SDK,官方叫LE(Linux Embedded)SDK。我个人习惯,拿到SDK第一件事不是急着装,而是先看Release Notes。为什么?因为里面会写明依赖的Ubuntu版本、Python版本、还有哪些已知的bug。

注意:我遇到过有人用Ubuntu 22.04去装老版本的SDK,结果编译链死活跑不起来。后来发现,官方只支持18.04和20.04。所以,先看文档,别头铁。

安装步骤其实不复杂,但有几个关键点:

  1. 解压SDK包:通常是一个.tar.gz.bin文件。如果是.bin,记得先给执行权限。
  2. 运行安装脚本:比如./setup.sh。它会自动检测你的系统环境,缺什么会提示你装。
  3. 设置环境变量:安装完成后,脚本一般会提示你把SDK路径加到~/.bashrc里。
# 解压SDK
tar -xzf qcom_8155_sdk_v2.0.tar.gz

# 进入目录
cd qcom_8155_sdk_v2.0

# 运行安装
./setup.sh

# 安装完成后,添加环境变量
echo "export QCOM_SDK=/opt/qcom/8155" >> ~/.bashrc
echo "export PATH=$PATH:$QCOM_SDK/tools/bin" >> ~/.bashrc
source ~/.bashrc

嗯,这里要注意:SDK安装路径尽量不要有中文或空格。我有个同事把SDK装在了/home/张三/我的SDK/下面,结果编译时各种路径解析错误,折腾了一下午。

2.2 交叉编译工具链配置

交叉编译,说白了就是在你的x86电脑上,编译出能在ARM架构的8155上跑的程序。工具链就是那个「翻译官」。

高通提供的工具链一般是基于GCC的。我建议你直接用官方提供的,别自己从源码编译——那是个无底洞。

核心配置:

  • CC:C编译器,通常是aarch64-linux-gnu-gcc
  • CXX:C++编译器,aarch64-linux-gnu-g++
  • AR:静态库打包工具
  • STRIP:去除调试符号,减小体积

配置好工具链后,我一般会写一个toolchain.cmake文件,方便CMake项目直接调用:

# toolchain.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)

set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)

set(CMAKE_FIND_ROOT_PATH /opt/qcom/8155/sysroot)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

你想想看,如果没有这个文件,每次编译都要手动指定编译器,多麻烦。而且容易出错。

小技巧:我曾经在编译OpenGL ES的测试程序时,发现链接器报错说找不到libGLESv2.so。后来发现是sysroot路径没配对。记住:CMAKE_FIND_ROOT_PATH一定要指向SDK里的sysroot目录,而不是你本机的/usr/lib

2.3 ADB调试:你的远程控制台

ADB(Android Debug Bridge)是连接你电脑和8155开发板的桥梁。虽然8155跑的是Linux,但高通在底层保留了ADB的支持,这对调试来说太方便了。

配置ADB其实很简单:

  1. 安装ADB工具:sudo apt install adb
  2. 用USB线连接开发板
  3. 运行adb devices,看看设备是否识别
# 检查设备
adb devices
# 输出示例:
# List of devices attached
# 1234567890abcdef    device

# 进入shell
adb shell

# 推送文件到开发板
adb push ./test_app /data/local/tmp/

# 拉取文件到电脑
adb pull /data/local/tmp/log.txt ./

我个人习惯,在~/.bashrc里加几个别名,能省不少事:

alias adb-push='adb push'
alias adb-pull='adb pull'
alias adb-shell='adb shell'
alias adb-log='adb logcat -c && adb logcat | grep -E "GPU|GL|EGL"'
注意:有时候ADB会提示unauthorized。这是因为开发板上的ADB服务需要授权。你需要在开发板的屏幕上确认授权,或者通过串口执行adb kill-server && adb start-server重新启动服务。

2.4 性能分析工具:找到瓶颈在哪

做图形优化,没有工具就是盲人摸象。高通平台上有几个我常用的工具,今天都给你列出来。

2.4.1 Snapdragon Profiler

这是高通官方的性能分析工具,功能非常强大。它可以实时抓取GPU的负载、频率、带宽、温度等数据。

使用步骤:

  1. 在电脑上安装Snapdragon Profiler(Windows/Linux都支持)
  2. 用ADB连接开发板
  3. 打开Profiler,选择你的设备
  4. 点击「Start Capture」,开始采集数据

我记得有一次,一个客户说他们的UI滑动卡顿。我用Profiler一看,GPU负载才30%,但CPU的一个核心跑满了。原来是UI线程在做大量的位图解码,占用了CPU。后来改成GPU硬件解码,问题就解决了。

2.4.2 命令行工具

有时候不方便用图形界面,命令行工具就派上用场了。

工具名 用途 示例命令
top 查看CPU占用 adb shell top -d 1
dumpsys 查看系统服务状态 adb shell dumpsys gfxinfo
cat /sys/class/kgsl/kgsl-3d0/gpuclk 查看GPU当前频率 adb shell cat /sys/class/kgsl/kgsl-3d0/gpuclk
cat /sys/class/kgsl/kgsl-3d0/gpubusy 查看GPU繁忙率 adb shell cat /sys/class/kgsl/kgsl-3d0/gpubusy

避坑指南:我曾经在调试一个渲染性能问题时,发现GPU频率一直上不去。后来查了资料才知道,高通GPU有功耗管理策略,如果温度过高会自动降频。所以,看性能数据时,一定要同时看温度:cat /sys/class/kgsl/kgsl-3d0/temp

2.4.3 帧率分析

做图形开发,帧率是最直观的指标。我一般用两种方法:

  • SurfaceFlinger的帧率统计adb shell dumpsys SurfaceFlinger --latency
  • 自己写一个简单的帧率计算器:在渲染循环里记录时间戳,计算FPS
// 简单的FPS计算代码片段
static uint64_t last_time = 0;
static int frame_count = 0;
static float fps = 0.0f;

void calculate_fps() {
    frame_count++;
    uint64_t current_time = get_current_time_ms();
    if (current_time - last_time >= 1000) {
        fps = frame_count * 1000.0f / (current_time - last_time);
        frame_count = 0;
        last_time = current_time;
        LOGI("Current FPS: %.2f", fps);
    }
}

嗯,这个代码虽然简单,但很实用。我在项目里一直用这个方法来快速验证优化效果。

2.5 环境验证:确保一切就绪

所有东西都装好后,我建议你跑一个简单的测试程序,验证整个链路是否通畅。

// test_gpu.c
#include <stdio.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>

int main() {
    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if (display == EGL_NO_DISPLAY) {
        printf("Failed to get EGL display\n");
        return -1;
    }
    
    EGLint major, minor;
    if (!eglInitialize(display, &major, &minor)) {
        printf("Failed to initialize EGL\n");
        return -1;
    }
    
    printf("EGL version: %d.%d\n", major, minor);
    printf("GPU environment is ready!\n");
    
    eglTerminate(display);
    return 0;
}

编译命令:

aarch64-linux-gnu-gcc test_gpu.c -o test_gpu \
    -I/opt/qcom/8155/sysroot/usr/include \
    -L/opt/qcom/8155/sysroot/usr/lib \
    -lEGL -lGLESv2

adb push test_gpu /data/local/tmp/
adb shell /data/local/tmp/test_gpu

如果看到「GPU environment is ready!」,恭喜你,环境搭建成功了。

说实话,环境搭建这一步虽然繁琐,但基础打好了,后面的开发才会顺利。我见过太多人因为环境没配好,浪费了大量时间在排查「低级错误」上。希望这一章能帮你少走弯路。