3. 开发环境搭建:基于Docker的交叉编译环境配置,SDK安装与板卡连接(SSH/串口)

好,咱们进入实战环节的第一步——搭环境。

说实话,我见过太多人在这一步卡住。明明算法模型跑得挺好,一到板子上就各种报错。说白了,环境没配好,后面全是白费功夫。今天我就把我在几个车规芯片项目里积累的经验,一次性讲清楚。

3.1 为什么非要用Docker?

你可能会问:直接在Ubuntu上装SDK不行吗?

行,但你会后悔的。我经历过一次——项目做到一半,同事的Ubuntu从18.04升到20.04,结果交叉编译器炸了,整个组等了两天重新配环境。从那以后,我所有嵌入式项目都强制用Docker。

Docker的好处就三点:

  • 环境隔离——你搞烂了容器,删了重建就行,宿主机干干净净
  • 版本一致——团队里每个人pull同一个镜像,编译结果一模一样
  • 快速切换——不同芯片厂商的SDK互相不打架,各用各的容器

核心原则:宿主机只装Docker和驱动,所有开发工具链全部放在容器里。

3.2 基于Docker的交叉编译环境配置

3.2.1 宿主机准备

先确认你的机器。我建议用Ubuntu 20.04或22.04,64位系统。Windows用户可以用WSL2,但我个人还是推荐直接装Linux——少很多坑。

安装Docker,一行命令搞定:

curl -fsSL https://get.docker.com | bash -s docker
sudo usermod -aG docker $USER
# 退出终端重新登录,让用户组生效

嗯,这里要注意:usermod之后一定要重新登录,不然docker命令还得加sudo。我刚开始就犯过这个错,还以为是安装有问题。

3.2.2 构建交叉编译镜像

车规芯片的SDK通常基于Ubuntu 18.04或20.04。我习惯自己写Dockerfile,这样可控性更强。

下面是一个典型的Dockerfile,以地平线J5芯片为例:

FROM ubuntu:20.04

ENV DEBIAN_FRONTEND=noninteractive

# 安装基础工具
RUN apt-get update && apt-get install -y \
    build-essential \
    cmake \
    git \
    vim \
    ssh \
    net-tools \
    iputils-ping \
    python3 \
    python3-pip \
    libgtk2.0-dev \
    pkg-config \
    && rm -rf /var/lib/apt/lists/*

# 安装交叉编译工具链(以aarch64为例)
RUN apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu

# 创建工作目录
WORKDIR /workspace

CMD ["/bin/bash"]

构建镜像:

docker build -t cross-compile:latest .

我的习惯:把Dockerfile和项目代码放在同一个Git仓库里。这样新同事clone下来,直接docker build就能干活,不用看十几页的环境搭建文档。

3.2.3 启动容器并挂载代码

启动容器时,最关键的是挂载你的代码目录:

docker run -it --rm \
    -v $(pwd):/workspace \
    -v /dev:/dev \
    --privileged \
    --network host \
    --name my_dev_env \
    cross-compile:latest

解释一下几个参数:

  • -v $(pwd):/workspace:把当前目录挂到容器里,代码在宿主机编辑,在容器里编译
  • --privileged:给容器访问设备的权限,后面连板卡要用
  • --network host:用宿主机网络,方便SSH连接板卡

为什么要用--network host?我曾经用默认的bridge模式,结果容器里ping不通板卡,排查了半天才发现是网络隔离的问题。用host模式,一劳永逸。

3.3 SDK安装

不同芯片厂商的SDK安装方式大同小异。我以地平线J5和瑞萨R-CAR为例,讲一下通用流程。

3.3.1 地平线J5 SDK安装

地平线的SDK叫hobot-sdk,解压后直接安装:

# 在容器内操作
cd /workspace
tar -xzf hobot-sdk-xj3-*.tar.gz
cd hobot-sdk

# 安装依赖
pip3 install -r requirements.txt

# 设置环境变量
echo "export HOBOT_SDK_PATH=/workspace/hobot-sdk" >> ~/.bashrc
echo "export PATH=\$PATH:\$HOBOT_SDK_PATH/toolchain/bin" >> ~/.bashrc
source ~/.bashrc

验证安装:

hobot_model_tool --version

如果输出版本号,说明SDK装好了。

3.3.2 瑞萨R-CAR SDK安装

瑞萨的SDK稍微麻烦一点,需要先安装Yocto环境:

# 安装Yocto依赖
apt-get install -y gawk wget git diffstat unzip texinfo \
    gcc-multilib build-essential chrpath socat cpio \
    python3 python3-pip python3-pexpect xz-utils debianutils \
    iputils-ping python3-git python3-jinja2 libegl1-mesa libsdl1.2-dev

# 解压SDK
tar -xjf rcar-sdk-*.tar.bz2
cd rcar-sdk

# 设置环境
source poky/oe-init-build-env

注意:瑞萨的SDK对Ubuntu版本很敏感。我曾在Ubuntu 22.04上折腾了两天,最后发现官方只支持Ubuntu 20.04。所以Dockerfile里用Ubuntu 20.04作为基础镜像,就是为了避免这种问题。

3.4 板卡连接:SSH与串口

环境配好了,SDK装好了,接下来就是连板卡。车规芯片的调试接口通常有两种:SSH(网络)和串口(UART)。

3.4.1 SSH连接

SSH是最常用的方式。前提是板卡和开发机在同一个局域网内。

先确认板卡的IP地址。一般板卡启动后会在串口输出IP,或者通过路由器管理界面查看。

连接命令:

ssh root@192.168.1.100

默认密码通常是root123456,具体看芯片厂商的文档。

为了方便,我习惯配置SSH免密登录:

# 在宿主机生成密钥(如果还没有)
ssh-keygen -t rsa -b 4096

# 复制公钥到板卡
ssh-copy-id root@192.168.1.100

之后登录就不用输密码了。这在频繁调试时能省不少时间。

避坑指南:我曾经遇到过SSH连上后,执行命令特别慢的情况。后来发现是板卡的DNS解析超时。解决办法是在/etc/ssh/sshd_config里加上UseDNS no,然后重启SSH服务。

3.4.2 串口连接

串口是最后的保底手段。当板卡网络不通、系统起不来的时候,串口是你唯一的窗口。

硬件连接:

  • USB转串口模块(推荐FT232或CP2102)
  • 板卡上的UART接口,通常是3.3V电平
  • 接线:GND接GND,TX接RX,RX接TX

软件配置:

# 查看串口设备
ls /dev/ttyUSB*

# 安装minicom或screen
apt-get install -y minicom

# 启动串口终端(波特率通常为115200)
minicom -D /dev/ttyUSB0 -b 115200

或者用screen:

screen /dev/ttyUSB0 115200

退出screen:按Ctrl+A,然后按K,再按Y确认。

重要提醒:串口接线时,千万不要把TX和TX直接连在一起。我见过有人把板卡的TX接到USB转串口的TX上,结果烧了串口芯片。记住:TX接RX,RX接TX。

3.4.3 在Docker容器内访问串口和SSH

前面启动容器时加了--privileged--network host,就是为了让容器能直接访问硬件设备和网络。

在容器内测试串口:

# 检查串口设备是否可见
ls -la /dev/ttyUSB*

# 如果看不到,可能是权限问题
# 在宿主机上执行(不要在容器内):
sudo chmod 666 /dev/ttyUSB*

测试SSH:

# 在容器内ping板卡
ping 192.168.1.100

# SSH连接
ssh root@192.168.1.100

如果一切正常,恭喜你——开发环境搭建完毕。

3.5 验证环境

最后,写一个简单的Hello World程序,交叉编译后传到板卡上运行,验证整个链路是否通畅。

在宿主机上创建测试文件:

// hello.c
#include <stdio.h>

int main() {
    printf("Hello from J5 board!\n");
    return 0;
}

在容器内交叉编译:

aarch64-linux-gnu-gcc hello.c -o hello

# 查看文件信息,确认是ARM架构
file hello
# 输出:hello: ELF 64-bit LSB executable, ARM aarch64, ...

传到板卡并运行:

scp hello root@192.168.1.100:/root/
ssh root@192.168.1.100 ./hello

如果看到Hello from J5 board!,说明整个环境全部打通。

总结一下:Docker容器做编译,SSH/串口做调试,SDK提供工具链。这三样配齐了,后面部署模型就是水到渠成的事。下一章,我们开始讲模型转换和量化——这才是真正有意思的部分。