1. 项目概述与核心价值最近在折腾海思的SS928V100芯片准备用它来跑一些边缘侧的视觉算法。说实话从零开始搭建一套能编译、能调试、能烧录的完整开发环境是每个嵌入式Linux开发者的“入职第一课”也是劝退很多新手的第一个门槛。海思的平台尤其是像SS928这样较新的高性能芯片其SDK的庞大和环境的复杂性常常让人望而生畏。网上资料零散官方文档又往往语焉不详很多细节只能靠踩坑来积累。这篇文章我就结合自己从SD3403到SS928的实操经历把环境搭建这个“脏活累活”彻底讲透。目标很明确给你一份从纯净的Ubuntu系统开始到最终能成功编译出内核、文件系统并能通过HiTool进行烧录的完整、可复现的指南。我会重点解释每一步“为什么要这么做”而不仅仅是罗列命令同时分享那些官方手册里不会写的“坑点”和“骚操作”。无论你是刚接触海思平台还是从其他芯片如RK、Amlogic迁移过来这篇内容都能帮你节省大量摸索时间。2. 开发环境整体设计与思路拆解在动手敲命令之前我们必须先理清海思SDK开发环境的整体架构和依赖关系。盲目操作只会导致各种莫名其妙的错误。2.1 核心组件与工具链解析一套完整的海思Linux开发环境通常包含以下几个核心部分交叉编译工具链 (Cross-Compile Toolchain)这是最重要的基础。我们的开发主机Host通常是x86_64架构的PC而目标板Target是ARM架构的海思芯片。因此我们需要一个能在x86上运行但能生成ARM指令集代码的编译器、链接器等工具集合。海思会提供针对其芯片优化过的工具链例如arm-himix200-linux或aarch64-himix100-linux。SS928是64位Cortex-A55核心必须使用aarch64架构的工具链。海思SDK (Software Development Kit)这是海思提供的软件开发包是环境搭建的“原料”。它通常是一个庞大的压缩包里面包含了内核源码基于特定版本的Linux内核加入了海思的驱动、媒体处理框架如VPSS、VENC、VDEC、硬件加速模块等大量补丁。根文件系统可能是基于BusyBox的精简系统也可能是像Ubuntu Core这样的发行版。SDK里通常提供构建脚本和基础配置。硬件抽象层 (HAL) / 媒体处理平台 (MPP)的库和头文件这是调用海思芯片视频编解码、图像处理等专用功能的关键。烧录工具与配置如HiTool以及对应的烧录配置文件.xml。各种样例代码、编译脚本、文档。开发主机环境一个稳定的Linux操作系统是必须的。Ubuntu 18.04或20.04 LTS是经过广泛验证的版本社区资源最丰富。不推荐使用最新版本因为工具链和SDK可能依赖较老的系统库在新系统上容易出兼容性问题。烧录与调试工具HiTool海思官方的烧录工具运行在Windows上。我们需要通过它配合串口和网口将编译好的镜像烧写到板子的FlasheMMC或SPI NAND中。串口调试终端如MobaXterm、SecureCRT或Putty用于查看板子启动日志、进入Shell。这是开发初期最重要的调试手段。2.2 环境搭建的核心逻辑与路径规划理解了组件搭建的思路就清晰了在Ubuntu主机上安装工具链解压并配置SDK然后编译出内核、文件系统等镜像最后在Windows上用HiTool烧写到板子上。这里有一个关键决策点是否在虚拟机中搭建Ubuntu环境我强烈建议使用物理机安装Ubuntu或使用Windows的WSL2。原因如下性能内核编译非常消耗CPU和I/O资源虚拟机性能损耗大编译耗时可能成倍增加。文件共享虚拟机与主机间的文件共享有时会引发权限问题或文件损坏而编译过程对文件完整性极其敏感。USB设备透传虽然虚拟机可以透传USB转串口设备但稳定性不如物理机直接连接。如果必须用虚拟机请确保分配足够的CPU核心建议4核以上、内存8GB以上和磁盘空间100GB以上并使用桥接网络模式。注意整个SDK解压后可能超过30GB编译过程中产生的中间文件还会占用大量空间。请务必为你的Ubuntu系统分区预留充足的磁盘空间建议不少于150GB。3. 开发主机环境准备与依赖安装现在我们开始实操。假设你已经有了一台安装好Ubuntu 20.04 LTS的电脑物理机或WSL2。3.1 系统更新与基础工具安装首先更新软件源并安装一些后续步骤必需的通用工具。sudo apt-get update sudo apt-get upgrade -y # 安装编译、解压、版本控制等基础工具 sudo apt-get install -y git make gcc g cmake p7zip-full bzip2 \ libncurses5-dev libncursesw5-dev \ python2.7 python2.7-dev python3 python3-dev \ device-tree-compiler u-boot-tools \ gcc-aarch64-linux-gnu g-aarch64-linux-gnu \ sshpass rsync为什么需要这些包build-essential,make,gcc: 编译主机本地工具和脚本所需。libncurses5-dev: 用于make menuconfig配置内核时生成图形化界面。python2.7: 很多老的构建脚本包括海思的部分脚本仍然依赖Python 2.7。这是一个常见的坑即使系统默认是Python3也必须安装2.7版本。device-tree-compiler: 编译设备树源文件(.dts)为二进制文件(.dtb)。u-boot-tools: 包含制作U-Boot镜像的工具如mkimage。gcc-aarch64-linux-gnu: 这是Ubuntu源里的通用aarch64交叉编译器。注意我们主要使用海思提供的专用工具链但安装这个有时可以用于编译一些简单的第三方库或者作为备用验证。3.2 获取并部署海思专用工具链从海思官方或其授权渠道获取对应的工具链包通常是一个.tar.gz文件名称类似aarch64-himix100-linux.tar.gz。# 1. 创建一个统一的目录来存放所有开发环境相关的内容 mkdir -p ~/hisilicon/ss928 cd ~/hisilicon/ss928 # 2. 假设你将工具链包放到了当前目录进行解压 tar -xzf aarch64-himix100-linux.tar.gz # 3. 工具链会被解压到一个目录下进入并查看 cd aarch64-himix100-linux/ ls # 你应该能看到 bin/, lib/, aarch64-himix100-linux/ 等子目录 # 4. 将工具链路径添加到系统的环境变量中使其全局可用 # 编辑当前用户的bash配置文件 echo export PATH$PATH:~/hisilicon/ss928/aarch64-himix100-linux/bin ~/.bashrc echo export ARCHarm64 ~/.bashrc echo export CROSS_COMPILEaarch64-himix100-linux- ~/.bashrc # 5. 使环境变量立即生效 source ~/.bashrc # 6. 验证工具链是否安装成功 aarch64-himix100-linux-gcc -v如果命令成功执行并输出了gcc的版本信息恭喜你工具链安装成功了。CROSS_COMPILE这个环境变量非常重要后续在执行make编译内核或U-Boot时Makefile会自动使用$(CROSS_COMPILE)gcc来调用交叉编译器。实操心得不建议将工具链解压到/opt等系统目录除非你是多用户共享。放在家目录下权限管理简单备份和迁移也方便。另外如果同时开发多个不同架构的海思平台如arm-himix200和aarch64-himix100可以通过编写不同的shell脚本如setenv_himix200.sh,setenv_himix100.sh来动态切换环境变量避免混淆。4. SDK获取、解压与初步配置工具链就绪后接下来处理重头戏——SDK。4.1 解压SDK并处理可能的问题海思SDK通常是一个巨大的.tar.bz2或.7z文件解压需要时间和空间。cd ~/hisilicon/ss928 # 假设SDK包名为 HiSS928V100_SDK_V1.0.0.0.tgz tar -xzf HiSS928V100_SDK_V1.0.0.0.tgz # 解压后通常会生成一个 HiSS928V100_SDK_V1.0.0.0 目录进入 cd HiSS928V100_SDK_V1.0.0.0 ls你可能会看到类似osdrv,package,mpp,tools这样的目录结构。第一个大坑SDK中的二次解压包。很多海思SDK在首次解压后在osdrv目录下内核、U-Boot、文件系统的源码并不是直接可见的而是以*.tar.bz2的格式存在。你需要执行SDK自带的脚本进行“二次解压”。# 通常SDK根目录下有一个安装脚本 ./sdk.unpack # 或者 source ./sdk.unpack如果找不到就仔细阅读SDK根目录下的README或ReleaseNotes文件里面会明确说明解压步骤。这一步如果漏了后续编译根本找不到源码。4.2 目录结构解析与关键路径成功解压后熟悉目录结构对后续操作至关重要osdrv/:操作系统驱动这是核心。opensource/: 开源组件如内核kernel、U-Bootuboot、BusyBoxbusybox的源码包。pub/: 编译输出目录的预置位置以及一些预编译的二进制文件、根文件系统镜像等。tools/: 板端工具如pc目录下可能有用于制作根文件系统镜像的mkyaffs2image等工具。platform/: 与具体芯片平台相关的配置、补丁和脚本。mpp/:媒体处理平台包含音视频编解码、图像处理等样例源码和库文件。环境搭建阶段可以先不深入。package/: 可能包含一些第三方软件包。tools/(根目录下的): 可能包含一些Windows端的工具或文档。我们的编译工作将主要集中在osdrv目录下。5. 内核与U-Boot的编译实战这是环境搭建中最考验耐心和细心的环节。5.1 内核配置与编译cd ~/hisilicon/ss928/HiSS928V100_SDK_V1.0.0.0/osdrv/opensource/kernel # 进入内核源码目录目录名可能是 linux-4.19.y 或类似 cd linux-4.19.y # 1. 导入默认配置 # 海思会为特定板型提供默认配置文件通常在 arch/arm64/configs/ 或 SDK的 platform/ 目录下 # 例如复制一个名为 hi_ss928_defconfig 的配置 cp arch/arm64/configs/hi_ss928_defconfig .config # 2. 启动图形化配置界面可选但推荐 make ARCHarm64 CROSS_COMPILEaarch64-himix100-linux- menuconfig如果执行menuconfig时出错提示缺少ncurses库请确认前面是否已安装libncurses5-dev。在menuconfig界面中你可以根据需求增减内核模块。对于初次尝试强烈建议不要做任何修改直接保存退出。我们的首要目标是生成一个能启动的内核。# 3. 开始编译内核 # -j 后面的数字表示并行编译的作业数通常设置为CPU核心数的1-2倍以加快编译速度。 make ARCHarm64 CROSS_COMPILEaarch64-himix100-linux- -j8编译过程会持续一段时间十几分钟到半小时不等。如果成功最终会在arch/arm64/boot/目录下生成Image文件这就是压缩后的内核镜像。同时也会在对应目录下生成设备树二进制文件*.dtb。关键产物arch/arm64/boot/Image- 内核镜像arch/arm64/boot/dts/hisilicon/hi_ss928_xxx.dtb- 设备树文件5.2 U-Boot配置与编译U-Boot是板子上电后运行的第一段裸机程序负责初始化硬件、加载内核。cd ~/hisilicon/ss928/HiSS928V100_SDK_V1.0.0.0/osdrv/opensource/uboot # 进入U-Boot源码目录 cd u-boot-2020.01 # 1. 清理旧配置和编译结果如果是首次可跳过 make ARCHarm64 CROSS_COMPILEaarch64-himix100-linux- distclean # 2. 应用默认配置 # 海思会提供板级配置文件例如 hi_ss928_defconfig make ARCHarm64 CROSS_COMPILEaarch64-himix100-linux- hi_ss928_defconfig # 3. 启动配置界面可选 make ARCHarm64 CROSS_COMPILEaarch64-himix100-linux- menuconfig # 4. 编译 make ARCHarm64 CROSS_COMPILEaarch64-himix100-linux- -j8编译成功后会在源码根目录生成u-boot.bin纯二进制文件和u-boot.img带有U-Boot头部信息的镜像等文件。注意事项U-Boot的配置项比内核少但至关重要。特别是启动参数bootargs、启动命令bootcmd和DDR初始化参数。这些通常在板级配置的头文件如include/configs/hi_ss928.h或设备树中定义。对于初次编译绝对不要修改与内存DDR初始化相关的任何代码或配置错误的DDR参数会导致板子无法启动甚至变砖。使用SDK提供的默认配置是唯一安全的选择。6. 根文件系统的构建与打包内核启动后需要挂载根文件系统Rootfs来提供用户空间的环境。这里以构建最简单的BusyBox根文件系统为例。6.1 编译BusyBoxcd ~/hisilicon/ss928/HiSS928V100_SDK_V1.0.0.0/osdrv/opensource/busybox cd busybox-1.33.2 # 1. 导入默认配置BusyBox有海思修改过的配置 cp hi_ss928_defconfig .config # 2. 进入配置界面 make ARCHarm64 CROSS_COMPILEaarch64-himix100-linux- menuconfig在BusyBox的menuconfig中你可以选择需要编译进根文件系统的命令。同样初次尝试建议使用默认配置。# 3. 编译并安装到临时目录 make ARCHarm64 CROSS_COMPILEaarch64-himix100-linux- -j8 make ARCHarm64 CROSS_COMPILEaarch64-himix100-linux- install CONFIG_PREFIX../rootfs_tmpCONFIG_PREFIX指定了安装路径。编译后../rootfs_tmp目录下会生成bin,sbin,usr,linuxrc等基本结构。6.2 完善根文件系统一个可用的根文件系统还需要一些必要的目录和设备节点。cd ../rootfs_tmp # 创建必要的目录 mkdir -p dev proc sys tmp run var/log mnt home root etc/init.d # 创建最基本的设备节点在宿主机上创建板子启动后会由udev或mdev管理但基础的需要有 sudo mknod dev/console c 5 1 sudo mknod dev/null c 1 3 # 创建一个最简单的启动脚本 cat etc/init.d/rcS EOF #!/bin/sh mount -t proc none /proc mount -t sysfs none /sys mount -t tmpfs none /tmp /sbin/mdev -s echo HiSS928 RootFS is up. EOF chmod x etc/init.d/rcS6.3 制作根文件系统镜像根文件系统需要被打包成一种板子Bootloader能识别的镜像格式如ext4,squashfs, 或海思常用的yaffs2。# 回到osdrv目录使用海思提供的工具打包 cd ~/hisilicon/ss928/HiSS928V100_SDK_V1.0.0.0/osdrv # 假设使用 make 目标来打包具体命令需参考SDK中的 README 或 Makefile # 一种常见方式是使用 mkfs.yaffs2 工具可能在 osdrv/tools/pc 下 # 找到该工具路径例如 TOOL_PATHpwd/tools/pc/mkyaffs2image $TOOL_PATH rootfs_tmp rootfs.yaffs2 2048 # 参数 2048 表示页大小需要根据板子Flash类型确定务必查阅板级文档更常见的做法是SDK的osdrv目录下有一个顶层的Makefile可以通过指定参数一键编译所有内容。# 在 osdrv 目录下尝试执行 make BOOT_MEDIAspi AMP_TYPElinux all # 或 make BOOT_MEDIAemmc AMP_TYPElinux allBOOT_MEDIA指定启动介质spi nor/nand, emmcAMP_TYPE指定系统类型linux, liteos。请务必根据你的实际板型手册选择正确的参数执行成功后编译产物u-boot.bin,kernel.img,rootfs.img通常会集中输出到osdrv/pub/目录下。7. 烧录镜像与上电验证编译出三大镜像U-Boot, Kernel, Rootfs后就到了最激动人心的烧录环节。7.1 准备工作硬件连接将板子的串口通过USB转TTL模块连接到电脑。串口是“救命稻草”所有启动信息都从这里输出。将板子的网口与电脑用网线直连或者连接到同一局域网的路由器下。网口用于TFTP下载镜像或NFS挂载根文件系统后续调试用。准备好板子的电源。软件准备在Windows电脑上安装好HiTool工具。安装串口终端软件如MobaXterm配置好串口号在设备管理器中查看、波特率通常115200、数据位8、停止位1、无校验。将编译好的镜像文件从Ubuntu主机拷贝到Windows电脑上一个简单的路径下例如D:\ss928_images\。7.2 使用HiTool进行烧录打开HiTool选择芯片型号为HiSS928V100。选择“烧写eMMC”或“烧写SPI NAND”根据你的板子存储介质选择。在“烧写方式”中选择“串口”或“网口”。首次烧录或板子无系统时通常只能使用串口速度较慢但可靠。如果板子上已有U-Boot且网络已通可以使用“网口”加速。在分区表配置中加载或手动配置与你的板子和Flash匹配的.xml分区表文件。这个文件定义了eMMC或SPI NAND上各个分区如fastboot,kernel,rootfs的起始地址和大小。分区表必须绝对正确否则板子无法启动。通常SDK的tools/目录下会提供参考的xml文件。为每个分区选择对应的镜像文件fastboot分区 -u-boot.binboot或kernel分区 -Image(或打包后的kernel.img)rootfs分区 -rootfs.yaffs2(或rootfs.img)将板子设置为烧录模式。这通常是通过操作板上的启动拨码开关来实现的具体方法请查阅板子手册。常见模式是让板子从USB或UART启动而不是从Flash启动。给板子上电同时点击HiTool的“烧写”按钮。HiTool会等待串口连接然后开始擦除、烧写。整个过程会在HiTool的日志窗口显示。烧写完成后将板子拨码开关切换回正常启动模式从Flash启动然后重启板子。7.3 串口终端查看启动日志板子重启时立即打开串口终端软件。如果一切顺利你将看到U-Boot的启动日志然后是内核解压、启动最后是根文件系统挂载成功出现命令行提示符比如#或/ #。U-Boot 2020.01 ... DRAM: 1 GiB MMC: ... In: serial Out: serial Err: serial Net: eth0 Hit any key to stop autoboot: 0 ## Booting kernel from Legacy Image at 82000000 ... Loading Kernel Image Loading Device Tree to 0000000089f38000, end 0000000089f458b7 ... OK Starting kernel ... [ 0.000000] Booting Linux on physical CPU 0x0 ... (大量内核日志) ... [ 5.123456] VFS: Mounted root (yaffs2 filesystem) on device 31:3. [ 5.234567] Freeing unused kernel memory: 1024K / # ls bin etc linuxrc root sys usr dev home proc sbin tmp var / #看到这个熟悉的#提示符并且能执行ls等命令就标志着你的海思SS928开发环境搭建成功了8. 常见问题与排查技巧实录环境搭建过程极少一帆风顺以下是几个我踩过的坑和解决方案。8.1 编译阶段常见错误问题1make menuconfig时提示‘ncurses.h’ file not found原因缺少ncurses开发库。解决确保已执行sudo apt-get install libncurses5-dev libncursesw5-dev。问题2编译内核或U-Boot时出现arm-himix100-linux-gcc: not found原因交叉编译工具链路径未正确添加到PATH或者环境变量未生效。解决检查工具链bin目录的绝对路径是否正确echo $PATH。检查CROSS_COMPILE环境变量是否设置正确echo $CROSS_COMPILE应该输出aarch64-himix100-linux-。手动指定全路径编译一次测试make ARCHarm64 CROSS_COMPILE/home/yourname/hisilicon/ss928/aarch64-himix100-linux/bin/aarch64-himix100-linux- menuconfig确认.bashrc修改后是否在新的终端窗口执行或者执行了source ~/.bashrc。问题3编译过程中出现recipe for target ‘xxx’ failed等语法错误原因最常见的原因是主机Ubuntu系统的gcc版本过高。海思的SDK和工具链可能是在较老的gcc版本如gcc 5/7下测试的与Ubuntu 20.04/22.04默认的gcc 9/11存在兼容性问题。解决安装低版本的gcc/g并设置优先级。sudo apt-get install gcc-7 g-7 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 70 sudo update-alternatives --install /usr/bin/g g /usr/bin/g-7 70 # 如果需要切换回来可以使用 sudo update-alternatives --config gcc如果错误出现在某个特定的开源组件编译中可以尝试在SDK的osdrv/opensource目录下找到该组件的补丁文件夹查看是否有针对高版本gcc的补丁文件需要手动打入。8.2 烧录与启动阶段常见问题问题4HiTool连接失败一直显示“连接中...”原因串口号选择错误。板子未进入烧录模式启动拨码开关设置不对。串口线或USB转TTL模块有问题。板子未上电或电源异常。排查在Windows设备管理器中确认串口COM号。仔细阅读板子手册确认烧录模式的具体拨码开关状态这是最容易出错的一步。用串口终端软件如MobaXterm直接连接看是否有任何输出哪怕是乱码。如果有输出但HiTool连不上可能是波特率设置不对HiTool通常自动识别。尝试更换USB口或USB转TTL模块。问题5烧录成功但板子启动时卡在Starting kernel ...之后没有任何输出原因这是最棘手的问题之一可能性很多。内核镜像问题内核编译配置错误或设备树文件不对。内存DDR问题U-Boot传递给内核的DDR参数不对或者内核中的DDR驱动初始化失败。串口引脚复用问题内核使用的调试串口引脚与U-Boot阶段不同导致内核启动后输出到了别的引脚。排查确认镜像正确性核对烧录的Image和.dtb文件是否是为你的具体板型编译的。不同内存大小、不同外设的板子可能需要不同的设备树文件。检查U-Boot启动参数在U-Boot倒计时阶段按任意键进入命令行输入printenv查看bootargs和bootcmd。确保bootargs中的console参数指定的串口设备与硬件一致如consolettyAMA0,115200。尝试最简启动在U-Boot命令行中手动加载并启动内核排除烧录问题。# 假设内核镜像和设备树已通过TFTP加载到内存的 0x82000000 和 0x83000000 tftp 0x82000000 Image tftp 0x83000000 hi_ss928.dtb booti 0x82000000 - 0x83000000寻求官方或社区支持提供完整的U-Boot日志和你的板子具体型号往往能得到更直接的帮助。问题6内核启动后卡在VFS: Unable to mount root fs原因内核找不到或无法挂载根文件系统。排查检查bootargs中的root参数是否正确指定了根文件系统所在的设备和格式如root/dev/mtdblock3 rootfstypeyaffs2。确认烧录的根文件系统镜像格式与rootfstype指定的格式一致。确认根文件系统分区是否烧写成功。可以在U-Boot中用mmc read或nand read命令尝试读取分区数据验证。8.3 环境与配置问题问题7编译SDK顶层Makefile时提示找不到某个命令或包原因SDK的编译脚本可能依赖一些特定的工具这些工具没有安装在标准路径或者脚本中使用了硬编码的路径。解决仔细查看错误信息找到是哪个命令找不到。然后在Ubuntu中搜索或安装该命令对应的包。如果该命令是海思工具链的一部分检查脚本中调用该命令的路径可能需要手动修改脚本将路径改为你工具链的实际安装路径。修改任何脚本前请先备份问题8如何高效地进行后续开发和调试建议第一次成功启动后立即建立NFS网络文件系统调试环境。在Ubuntu主机上配置NFS服务器将你的根文件系统目录如rootfs_tmp共享出来。修改U-Boot的bootargs将root参数改为NFS挂载例如root/dev/nfs nfsroot192.168.1.100:/home/yourname/hisilicon/ss928/rootfs_tmp,v3,tcp,port2049,mountport2049 ipdhcp。这样每次在Ubuntu上修改了根文件系统里的文件如应用程序板子重启后就能立即生效无需重新烧录整个根文件系统镜像极大提升开发效率。环境搭建是万里长征的第一步也是最磨人但收获最大的一步。当你第一次看到自己编译的系统在板子上跑起来那种成就感是无与伦比的。这个过程里遇到的每一个错误和解决过程都会加深你对嵌入式系统启动流程、交叉编译、硬件对接的理解。希望这份超详细的指南能帮你平稳度过这个阶段把更多精力投入到后续有趣的应用开发中去。如果在实际操作中遇到这里没覆盖到的问题多查查板子手册多看看串口打印的日志那里面藏着所有问题的答案。