ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Hi3516CV610海思SDK编译环境搭建实战:交叉工具链与rootfs构建

Hi3516CV610海思SDK编译环境搭建实战:交叉工具链与rootfs构建 写这篇东西的起因是我手头拿到一块基于Hi3516CV610的板子。这颗芯片是海思针对智能视觉IoT场景推的一路H.265/H.264编解码、内置算力、低功耗做网络摄像机和带屏门铃这类产品很合适。但真要把SDK跑起来第一步就卡在编译环境上。网上关于这颗料的信息少SDK解压完一堆脚本和文档新手很容易在工具链、库依赖、内核配置这些环节反复折腾。这篇就把我从零搭建Hi3516CV610海思SDK编译环境、部署交叉工具链的过程完整记录下来包括每一步的操作、参数、坑点和排错思路给正在搞这颗芯片的朋友做个参考。1. 项目概述与整体设计思路1.1 标题背后的真实需求解析Hi3516CV610这个型号核心是定位轻量级、低功耗的视觉处理。它和以前Hi3516CV500那一代比编码性能和算力都有变化但SDK的组织方式、编译思路是一脉相承的。拿到SDK后你会发现它不是一个开箱即用的IDE工程而是一整套Linux下的源码包U-Boot、内核、rootfs、MPPMedia Processing Platform库、以及一堆编译脚本和文档。这里有个很多人没想明白的点海思SDK默认是按“在x86主机上交叉编译ARM目标”来设计的。你的编译主机是Ubuntu目标是ARM架构的Hi3516CV610中间靠交叉工具链连接。所以搭建编译环境本质上是三件事准备一台干净、版本正确的Ubuntu编译主机。正确解压并理解海思SDK的目录结构和脚本逻辑。部署匹配的交叉编译工具链让“编译目标”指向ARM。这三件事哪一件做不对都会在你执行make的时候用报错来提醒你而且报错信息往往不直白。1.2 从零到能编译的整体规划我不建议拿到SDK就直接开敲命令。先把路线理清楚能省掉一半的返工时间。我的规划是这样第一步环境准备。搞定Ubuntu尽量用SDK文档里验证过的版本避免在系统库上踩坑。第二步SDK解压与目录分析。搞清楚每个文件夹是干什么的尤其注意osdrv和tools这两个。第三步工具链部署。安装交叉编译器配置PATH验证能否编译最简单的C程序。第四步编译一个最小系统。从内核或者rootfs开始实际跑通编译流程。第五步烧录验证。把产物烧到板子上确认环境从“能编译”变成“能跑”。这个顺序有个好处每一步都有明确的验收标准。比如工具链部署完能不能编译hello world就是硬指标不需要等到烧录才发现工具链有问题。2. 环境准备与关键工具选型2.1 编译主机系统与虚拟机配置建议海思官方文档对Ubuntu版本有推荐。根据我查到的资料和实际操作经验Hi3516CV610的SDK建议使用Ubuntu 14.04或16.04 64位系统。但现实情况是大部分人手头的电脑是Windows或者已经是Ubuntu 20.04、22.04这些新版本直接装老系统不现实。我实测下来的方案是在Windows上用VMware Workstation装Ubuntu 16.04 64位。为什么选16.04而不是更新的版本关键点是老内核的SDK在编译时可能会用到一些旧版系统库的路径和头文件比如/usr/include/i386-linux-gnu、/usr/lib/i386-linux-gnu这些东西新系统往往移除了或者版本不一致。虽然理论上可以手动补齐但折腾成本高。虚拟机配置上我建议CPU至少4核否则编译内核时会等到怀疑人生。内存建议8GB起步编译时并行任务多内存不够容易OOM。硬盘至少100GB。SDK解压后就有几GB编译中间产物和rootfs镜像会继续堆空间留足余量。注意如果只有16GB内存的物理机虚拟机分配8GB就够了。千万别全部分配给虚拟机否则宿主机卡死虚拟机也跟着遭殃。2.2 SDK整包获取与文件校验Hi3516CV610的SDK一般是从开发板厂商或者海思官方渠道获取通常是类似Hi3516CV610_SDK_Vx.x.x.x.tgz这样的压缩包。拿到后别急着解压先做两件事第一用md5sum校验文件完整性。SDK压缩包体积不小网络传输或拷贝过程中可能损坏务必比对官方提供的md5值。第二确认压缩包属性。用ls -l查看确保有读权限。校验命令很简单md5sum Hi3516CV610_SDK_Vx.x.x.x.tgz2.3 工具链版本选型的核心考量Hi3516CV610的工具链从SDK包里解压出来后通常是类似arm-mix410-linux-gnueabi或arm-gcc这样的命名。这个前缀就是交叉编译器的“target triple”决定了它生成的代码是给哪个架构、哪种系统使用的。工具链版本选择有个铁律优先用SDK自带的工具链不要去官网下载最新版GCC。因为海思SDK里的U-Boot、内核和MPP库都是针对特定工具链版本验证过的工具链版本变化可能导致编译失败或运行异常。老版本GCC编译出来的代码在性能上和兼容性上可能没问题但新版本GCC的警告级别、默认标准变了经常会出现源码能编译但工具链升级后报错的情况。我在SDK自带的工具链路径上还遇到了32位库的问题。早期海思工具链是32位程序在64位系统上运行需要32位兼容库。解决办法是安装lib32z1 lib32stdc6 lib32ncurses5这类包。Hi3516CV610的工具链是不是纯64位需要具体看包内容。反正如果执行arm-mix410-linux-gnueabi-gcc时报No such file or directory大概率就是缺32位库用file命令看下工具链文件的位数就能确认。3. SDK目录结构与核心技术组件解析3.1 解压SDK后的目录全景把SDK压缩包解压后你会看到一系列目录和脚本。以海思一贯的组织方式核心目录大概是这些osdrv这个是最核心的目录里面是U-Boot、内核、rootfs的源码和编译脚本。绝大多数编译操作都在这。mpp海思媒体处理平台库包含VENC、VDEC、VPSS、VI、VO等模块的库文件和头文件。docs开发文档一定要仔细看。tools烧录工具、调试工具等。scripts一些辅助脚本。这里最容易犯的错是直接进到某个子目录单独编译结果发现依赖关系一团糟。海思SDK的编译入口通常是osdrv目录下的顶层Makefile它会按依赖关系依次编译U-Boot、内核、rootfs。3.2 交叉工具链的安装路径与PATH配置工具链一般会放在SDK目录内也可能需要从osdrv/tools/linux/toolchain下解压出来。安装的流程应该是找到工具链压缩包比如arm-mix410-linux-gnueabi-xxx.tar.gz。解压到固定目录我是放在/opt/hisi-linux/x86-arm/保证路径没有防火墙和权限问题。把bin目录加到当前用户的PATH里。以下是解压和PATH配置示例mkdir -p /opt/hisi-linux/x86-arm tar -xvf arm-mix410-linux-gnueabi-xxx.tar.gz -C /opt/hisi-linux/x86-arm/ export PATH/opt/hisi-linux/x86-arm/arm-mix410-linux-gnueabi/bin:$PATH但export只在当前终端会话有效。为了永久生效建议写进~/.bashrc然后用source ~/.bashrc刷新。3.3 编译环境变量与目录权限风险海思SDK编译时对环境变量有几个硬性要求尤其是PATH里必须能找到交叉编译器但同时又不能影响到主机自己的gcc。说得更具体一点交叉编译器的名字是arm-mix410-linux-gnueabi-gcc主机的编译器是gcc二者不会冲突但如果你把交叉编译器的bin目录放在PATH最前面又恰好有个脚本写了不带前缀的gcc那它会优先找到ARM版gcc结果就是在x86主机上编译出ARM目标链接时必定失败。另外一个容易踩的坑是权限。SDK里的编译脚本可能会创建临时文件、修改脚本权限。我建议整个SDK目录用非root用户操作但工具链安装到/opt需要root权限。实践做法是工具链用root放到/optSDK目录用普通用户维护。这样既避免工具链被误删也避免总是以root编译导致文件归属混乱。4. 工具链部署与编译器自测4.1 交叉编译器安装实操步骤我用一个实际例子走一遍工具链部署。假设SDK解压在/home/user/Hi3516CV610_SDK工具链压缩包在osdrv/tools/linux/toolchain/下。第一步查看压缩包内容确认目录结构tar -tzf arm-mix410-linux-gnueabi-xxx.tar.gz | head -20如果压缩包顶层是一个目录直接解压到/opt/hisi-linux/x86-arm/即可。第二步解压并设置家乡路径cd /opt/hisi-linux/x86-arm tar -xvf /home/user/Hi3516CV610_SDK/osdrv/tools/linux/toolchain/arm-mix410-linux-gnueabi-xxx.tar.gz解压完成确认bin目录下有以下关键文件ls /opt/hisi-linux/x86-arm/arm-mix410-linux-gnueabi/bin/至少要看到arm-mix410-linux-gnueabi-gcc、arm-mix410-linux-gnueabi-g、arm-mix410-linux-gnueabi-ld、arm-mix410-linux-gnueabi-strip这几个缺了后续会有麻烦。第三步写环境变量。我喜欢在~/.bashrc里单独加一段便于注释和修改# Hisi Hi3516CV610 toolchain export PATH/opt/hisi-linux/x86-arm/arm-mix410-linux-gnueabi/bin:$PATH然后生效source ~/.bashrc4.2 用一段C代码验证整条编译链路工具链配置完毕最直接有效的验证方式就是交叉编译一个C程序然后确认生成的ELF文件架构。写一个hello_hi3516.c#include stdio.h int main(void) { printf(Hello Hi3516CV610\n); return 0; }执行arm-mix410-linux-gnueabi-gcc -o hello_hi3516 hello_hi3516.c如果没报错用file命令看产物类型file hello_hi3516终端会识别出类似ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV)的信息。看到ARM字样说明工具链工作正常看到x86-64说明这里用的编译器根本不是交叉编译器。还有一个细节静态编译rootfs里的busybox时可能会需要-static参数。可以用下面的命令验证工具链是否支持静态链接arm-mix410-linux-gnueabi-gcc -static -o hello_static hello_hi3516.c file hello_static4.3 工具链与SDK版本匹配的经验关于工具链有一个反面教材我见过太多次了开发者在官网下载最新版ARM GCC编译内核时报出一堆错误回头还抱怨SDK不好。其实不是SDK不好是工具链和SDK版本不匹配。原因在于U-Boot、内核源码都有特定的“工具链版本容忍范围”。比如某些很老的内核3.x、4.x在使用GCC 9以上编译时会因为-fno-common默认变化、头文件包含顺序变化等问题报错。Hi3516CV610的内核版本没那么老但依然建议用SDK绑定的工具链版本这是最稳的。判断工具链版本arm-mix410-linux-gnueabi-gcc --version如果版本和SDK文档一致那基本就稳了。5. 内核编译与根文件系统制作实操5.1 内核配置与编译核心参数工具链就绪后就可以进osdrv正式编译了。正式编译前先把编译脚本和Makefile看一遍重点关注变量名是CROSS_COMPILE还是CROSS_COMPILE_HI3516CV610不同版本SDK这个变量名可能不同。以“基于SDK自带配置编译内核”为例子完整命令大概是这样的cd /home/user/Hi3516CV610_SDK/osdrv make kernel但这个make kernel能成功前提是Makefile里已经把CROSS_COMPILE指向了正确的前缀。如果脚本里没有写或者你想手动指定可以这样make ARCHarm CROSS_COMPILEarm-mix410-linux-gnueabi- hi3516cv610_defconfig make ARCHarm CROSS_COMPILEarm-mix410-linux-gnueabi- -j4这里有个关键点CROSS_COMPILE必须以短横线结尾。因为内核构建系统会自动拼接gcc、ld这些命令所以填arm-mix410-linux-gnueabi-而不是arm-mix410-linux-gnueabi。编译过程中会有大量.o文件和中间产物磁盘空间消耗很快。如果编译到一半提示磁盘满把osdrv目录下的中间文件清理掉比如make clean再重新编。5.2 busybox构建根文件系统内核编译只是第一步。一个能启动的系统还需要rootfs。海思SDK的osdrv里一般会带busybox源码通过脚本自动编译成最小根文件系统。busybox的构建逻辑不复杂但有几个细节第一busybox默认用动态链接这样busybox体积小但依赖glibc的动态库。在制作rootfs时必须把相应的.so库复制到lib目录。否则启动时会报/bin/sh: not found其实就是动态库找不到。第二如果不想处理动态库拷贝可以静态编译。配置busybox时在Busybox Settings - Build Options中勾选Build BusyBox as a static binary。这样生成的busybox不依赖任何动态库拷进rootfs就能跑对新手来说省心很多。第三步用busybox的make install生成_install目录make ARCHarm CROSS_COMPILEarm-mix410-linux-gnueabi- menuconfig make ARCHarm CROSS_COMPILEarm-mix410-linux-gnueabi- -j4 make ARCHarm CROSS_COMPILEarm-mix410-linux-gnueabi- install生成的_install目录就是最小根文件系统的骨架里面已经自动生成了bin、sbin、usr目录和linuxrc。你还需要手动补充etc、dev、proc、sys、tmp等目录以及最基本的/etc/inittab等配置文件。5.3 制作可烧录镜像的关键细节根文件系统目录准备好后要打成可用烧录的镜像格式。海思平台常见的是rootfs.ext4、rootfs.squashfs或rootfs.cramfs。具体用哪种取决于你的flash类型nor还是nand。我以最常用的ext4为例。用genext2fs或make_ext4fs工具把目录打包成镜像make_ext4fs -l 32M -s rootfs.img rootfs_dir/这里-l 32M指定镜像大小上限为32MB-s表示生成稀疏镜像。大小不能拍脑袋定要结合你板子flash分区表来。比如分区表里rootfs分区是32M你做成64M的镜像烧录时要么截断要么失败。查分区表最直接的办法是看uboot的bootargs和SDK文档里的partition参数。还要注意文件权限尤其是/etc/inittab、/etc/init.d/rcS这些文件必须带执行权限。打包前用fakeroot或者root用户改好权限。5.4 SDK自带脚本的灵活使用如果你的SDK版本比较完整osdrv目录下会有类似build.sh的脚本可以把整个流程串起来。我只建议在环境完全匹配的情况下用一键脚本。环境稍有差异脚本可能因为某个软件没装就报错退出你还要去修脚本反而不如手动一步步来好排查。6. 烧录与首次启动调试6.1 通过串口和网口烧录镜像编译产物基本齐了之后就要烧录到板子上了。Hi3516CV610开发板常见的方式有两种串口烧录和网口烧录。串口烧录需要准备USB转串口模块连接板子的调试串口。开发板进入U-Boot命令行后用himd或者flwrite这类命令配合烧录工具来下载镜像这种方式速度慢适合烧uboot。网口烧录相对快常见的是通过tftp把镜像拉下来再写入flash。具体命令取决于板卡的U-Boot版本和分区设计。以我调试时用的U-Boot为例烧内核镜像到kernel分区setenv serverip 192.168.1.100 setenv ipaddr 192.168.1.10 tftp 0x82000000 uImage nand erase 0x800000 0x800000 nand write 0x82000000 0x800000 0x800000这些地址和大小必须和你的分区表严格对齐不能照抄。nand读写是风险操作一旦写错bootloader可能起不来要用串口线SD卡或JTAG才能恢复操作前务必仔细看分区表。6.2 首次启动日志的关键检查项烧录完成后给板子上电把串口终端波特率调到115200具体看U-Boot配置观察启动日志。我有几次调环境编译都能过但板子就是起不来最后都是靠启动日志定位到rootfs或内核的问题的。重点检查几个地方U-Boot是否正常启动能否打印Hit any key to stop autoboot。内核是否开始解压Uncompressing Linux... done, booting the kernel是否出现。内核挂载rootfs时是否报错比如VFS: Cannot open root device mtdblock2。是否成功执行/sbin/init或linuxrc最后是否出现/bin/sh的提示符。常见的启动失败原因里“找不到rootfs”占了一大半。要么是bootargs里的root参数和实际分区不符要么是rootfs镜像格式内核不支持。6.3 MPP库测试与编码基础验证环境起来后别急着关串口先跑一下SDK自带的MPP样例确认编译出来的库和内核驱动配合正常。比如mpp/sample/venc下的编码用例可以验证H.264/H.265编码的硬件通路。这里有个提示海思的MPP库分两个测例等级——静态库和动态库。测试样例通常默认链接静态库。如果你确认编码功能正常说明从工具链到内核再到MPP整个链路都是通的接下来就可以开始自己的业务开发了。7. 常见问题与排查技巧实录7.1 高频报错速查表我整理了一份自己在搭建过程中遇到的、以及我在社区里看到的高频问题清单每个问题都附上了排查思路和解决办法。报错/现象可能原因排查命令/解决方法arm-mix410-linux-gnueabi-gcc: Command not found工具链不在PATH中或未安装检查which arm-mix410-linux-gnueabi-gcc重新export PATHarm-mix410-linux-gnueabi-gcc: No such file or directory但文件存在工具链是32位程序系统缺32位库安装lib32z1 lib32stdc6 lib32ncurses5fatal error: sys/types.h: No such file or directory系统缺少libc-dev包或工具链与libc不匹配安装系统libc-devsudo apt install libc6-dev-i386按系统execstack: command not foundSDK脚本调用了execstack命令系统未安装用sudo apt install execstack安装如果源里有或修改脚本跳过该步骤编译内核时大量error: implicit declaration of function工具链版本过新内核源码跟不上改用SDK自带工具链或调整内核里的CFLAGSCannot find -lpthread缺少线程库确认交叉工具链lib/下有libpthread或添加-L指定lib路径cannot find -lc缺少libc库同理确认工具链自带libc库是否完整U-Boot烧入后无输出波特率不对或烧录地址错检查串口波特率、分区表、烧录工具设置内核启动后VFS: Cannot open root devicebootargs的root参数与rootfs实际位置不符检查bootargs尤其是root/dev/mtdblockN和mtdparts7.2 链路排查方法论上面这些报错表面上看起来五花八门但排查思路是一致的——逐层剥离。我的方法论是这样的第一层确认工具链本身可用。就是前面说的file hello确认能编译出ARM ELF。这一步能过滤掉工具链安装、PATH配置、32位库、架构不匹配等大部分低级问题。第二层确认SDK的编译入口能加载工具链。进osdrv目录执行make kernel看第一行的编译命令里是否有arm-mix410-linux-gnueabi-前缀。如果没有说明CROSS_COMPILE变量没传进去。第三层确认目标系统能跑起来。就是烧录后看启动日志哪一步卡住就排查哪一步U-Boot卡住查串口和bootargs内核卡住查镜像格式和rootfs。这一套流程走下来百分之九十的问题都能在半小时内定位。剩下的百分之十多半是硬件接触不良、电源电流不够或者flash分区损坏。7.3 别忘了文档和社区海思SDK里其实藏着很多经验docs目录下的《SDK安装及升级使用说明》《开发环境搭建》这些文档都是前人踏过坑后的文字沉淀。我发现很多开发者拿到SDK第一件事就是找代码完全不看文档遇到问题了又回头翻文档这顺序是反的。好习惯是解压SDK后先把docs目录下的PDF和readme文件通读一遍把环境相关的章节标黄。官方文档虽然有些地方写得含混但版本匹配、依赖包列表这些关键信息是准确的。最后说点我自己的体会Hi3516CV610这套SDK环境搭建本质上不是“会不会装工具链”的问题而是有没有耐心去理解SDK的构建逻辑。我见过不少人卡在工具链上其实工具链只是引子内核和rootfs的联动才是核心。静态编译一个busybox配好bootargs让板子串口里出现shell提示符的那一刻整个开发环境的信任感才真正建立起来。如果一次编译没过别急着换电脑换系统换工具链。先冷静下来用file命令和启动日志这两大法宝做判断。它们在绝大多数情况下能准确地告诉你问题出在哪一层。搞定了环境后面无论是调MPP编码还是集成算法都会顺畅得多。
返回列表