4. 开发环境搭建与交叉编译

NVIDIA DRIVE 平台的开发与普通 x86 服务器开发有一个根本差异:代码在主机(Host,通常是 x86_64 Ubuntu 工作站)上编写和编译,但最终运行在目标板卡(Target,DRIVE AGX 上的 ARM64 SoC,如 Orin 系列)上。因此整个环境搭建的核心,是建立一条从主机到目标板的可靠通路,并让编译产物、系统镜像、调试手段都能在这条通路上正确流动。本节围绕主机环境、目标板连接、交叉编译工具链、DriveOS 刷写与启动流程四件事展开。

主机开发环境配置

主机推荐使用 Ubuntu 20.04 或 22.04 LTS,内核版本与 NVIDIA SDK Manager 要求保持一致。基础依赖包括构建工具、设备访问工具和镜像处理工具:

sudo apt update
sudo apt install -y build-essential git cmake ninja-build \
  python3 python3-pip device-tree-compiler \
  libusb-1.0-0-dev usbutils picocom minicom \
  qemu-user-static binfmt-support

# 安装 NVIDIA SDK Manager(用于刷写与组件管理)
sudo apt install -y ./sdkmanager_*.deb
sdkmanager --version

SDK Manager 负责下载 DriveOS 组件、生成刷写镜像并驱动刷写流程。首次运行需要 NVIDIA 开发者账号登录,登录后它会拉取与目标板卡型号匹配的 BSP(Board Support Package)。主机磁盘建议预留 100 GB 以上,因为 DriveOS 的完整 BSP 与交叉工具链体积较大。此外,主机需要能通过 USB 与目标板通信,因此要确认当前用户属于 plugdev 组,否则刷写阶段会出现权限拒绝。

目标板卡连接与访问方式

DRIVE AGX 开发套件通常提供多种连接通道,用途各不相同:

  • USB Type-C / Micro-USB 调试口:连接后主机出现 /dev/ttyUSB* 或 /dev/ttyACM*,用于串口控制台,可观察 UEFI、内核和启动日志。
  • 以太网口:刷写完成后通过 SSH 登录系统,进行应用部署与调试。
  • DisplayPort / HDMI:用于查看图形界面与推理可视化结果。
  • 电源与散热:DRIVE 板卡功耗较高,需使用配套电源并保证散热,否则高负载推理时会触发降频。

串口控制台是排障的第一入口。连接示例:

# 查看串口设备
ls /dev/ttyUSB*
# 以 115200 波特率打开控制台
sudo picocom -b 115200 /dev/ttyUSB0

刷写完成后,目标板默认 IP 常为 192.168.1.100 一类地址,主机需配置同网段静态 IP,例如主机设为 192.168.1.10/24,然后 ssh nvidia@192.168.1.100 登录。若无法登录,应先用串口确认系统是否真正启动到用户态。

交叉编译工具链

交叉编译的关键是让主机上的编译器生成 ARM64 可执行文件。NVIDIA 在 DriveOS BSP 中提供了配套的 aarch64 工具链,通常位于 toolchains/ 目录下。使用前先设置环境变量:

export CROSS_COMPILE=/opt/nvidia/toolchains/aarch64--glibc--stable/bin/aarch64-linux-gnu-
export CC=${CROSS_COMPILE}gcc
export CXX=${CROSS_COMPILE}g++
export SYSROOT=/opt/nvidia/toolchains/aarch64--glibc--stable/aarch64-linux-gnu/sysroot

# 验证
${CC} --version
${CC} -dumpmachine   # 应输出 aarch64-linux-gnu

编译时通过 --sysroot 指向目标板根文件系统,确保链接到的是目标板的库而非主机的库。以 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_SYSROOT      /opt/nvidia/toolchains/aarch64--glibc--stable/aarch64-linux-gnu/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)

配置时使用 cmake -DCMAKE_TOOLCHAIN_FILE=aarch64.cmake ..。编译完成后用 file 命令确认产物架构:

file ./infer_demo
# 期望输出:ELF 64-bit LSB executable, ARM aarch64 ...

如果输出仍是 x86-64,说明工具链未生效,应检查 CMake 缓存是否残留了主机编译器路径,必要时删除 CMakeCache.txt 重新配置。对于依赖 CUDA、TensorRT 的推理程序,交叉编译时还需把目标板的 CUDA/TensorRT 头文件与库路径加入 sysroot,否则链接阶段会报找不到 libnvinfer.so。

DriveOS 刷写与系统启动流程

刷写是把 DriveOS 镜像写入目标板存储的过程。典型流程是:主机通过 SDK Manager 选择目标板型号与 DriveOS 版本,下载并生成镜像;将目标板置于恢复模式(Recovery Mode),通常需要按住恢复按键再上电;主机识别到 USB 设备后开始刷写。刷写完成后板卡自动重启,进入启动流程。

启动过程大致分为几个阶段:BootROM 加载引导程序,UEFI 初始化硬件并选择启动设备,随后加载内核与设备树,挂载根文件系统,最后启动用户态服务。串口日志是判断启动是否正常的主要依据。常见异常与判断方式如下:

现象可能原因处理方向
串口无任何输出未进入恢复模式或串口参数错误检查按键时序、波特率 115200
卡在 UEFI 阶段启动设备或镜像损坏重新刷写,确认镜像版本匹配
内核 panic设备树或根文件系统不匹配核对 BSP 与板卡型号
启动后无法 SSH网络未配置或服务未起串口登录后检查网络配置

刷写与启动的完整链路可以用下面的图来理解,它把主机侧操作、目标板状态变化和观察点对应起来:

DriveOS 刷写与启动链路 主机 (x86_64 Ubuntu) SDK Manager 选择板卡 与 DriveOS 版本 下载 BSP 并生成 刷写镜像 USB 连接目标板 执行刷写 串口 / SSH 观察 启动日志 交叉编译产物 scp 部署到板卡 目标板 (DRIVE AGX ARM64) Recovery Mode 等待刷写 BootROM → UEFI 硬件初始化 加载内核与设备树 挂载根文件系统 用户态服务启动 网络 / SSH 可用 运行推理程序 GPU / TensorRT 执行 USB 刷写镜像 启动加载 串口日志回传 scp 部署可执行文件 关键观察点:串口日志 / file 架构 / SSH 连通 三者同时正常,才说明环境搭建闭环

判断环境是否真正搭好,可以按三个观察点确认:串口能看到完整启动日志并进入登录提示;file 检查交叉编译产物为 ARM aarch64;SSH 能登录目标板并执行部署的程序。三者同时满足,说明主机、工具链、板卡和系统镜像已经形成闭环,可以进入后续的推理部署与性能优化阶段。

建议把工具链路径、目标板 IP、串口设备号记录在项目 README 或环境脚本中,避免每次重新查找。例如编写 env.sh 统一导出 CROSS_COMPILE、SYSROOT 和 TARGET_IP,团队协作时可直接复用。
刷写过程中不要断电或拔除 USB,否则可能造成板卡存储损坏,需要重新进入恢复模式刷写。若刷写失败,先确认 SDK Manager 中选择的板卡型号与 DriveOS 版本是否与实际硬件一致,版本不匹配是刷写失败最常见的原因。