
1. 项目概述从零开始构建Hi3798MV100开发环境拿到一块搭载海思Hi3798MV100芯片的开发板或者机顶盒第一件要干的事是什么刷机跑Demo不对于开发者而言最基础也是最关键的一步是把官方的软件开发工具包SDK成功编译出来。这就像是拿到一块乐高你得先确保手头的说明书SDK和积木块源码是完整且能拼装起来的后续所有炫酷的模型应用程序都建立在这个基础之上。Hi3798MV100作为一款曾经在众多网络机顶盒、智能电视盒中广泛应用的芯片其SDK的编译是进入海思平台开发世界的“敲门砖”。这个过程看似只是敲几条命令实则涉及交叉编译工具链的配置、内核与文件系统的构建、以及海思特有媒体框架的整合任何一个环节出错都可能让你卡在起点。今天我就结合自己多次在Ubuntu系统上搭建Hi3798MV100 SDK编译环境的实战经验把从环境准备到最终生成烧录镜像的全流程以及其中最容易踩坑的细节给你掰开揉碎了讲清楚。2. SDK编译环境深度解析与准备2.1 理解海思SDK的典型结构在动手之前我们得先知道要面对的是什么。一份完整的Hi3798MV100 SDK通常不是一个简单的压缩包而是一个结构清晰的目录树。虽然不同版本或来源的SDK可能有细微差别但核心骨架大同小异。一个典型的目录结构可能包含以下部分osdrv/ 这是重中之重包含了操作系统驱动相关的所有内容。通常其下会有opensource开源软件包如busybox、内核等、pub编译输出的头文件、库文件、以及针对不同芯片的目录如hi3798mv100里面存放着内核配置、文件系统配置、编译脚本Makefile等。mpp/ 媒体处理平台Media Process Platform。这是海思芯片的灵魂包含了视频编解码H.264/H.265、音频处理、视频输入输出VI/VO、视频处理VPSS等所有媒体相关功能的样例代码、头文件和库。编译SDK通常也会编译这部分生成对应的静态库或动态库。sample/ 基于MPP的各种示例程序从最简单的视频采集播放到复杂的多路编解码是学习海思API的最佳起点。toolchain/ 交叉编译工具链存放处。这是让在x86电脑上编写的代码能生成在ARM架构的Hi3798芯片上运行的程序的关键。常见的是arm-hisivXXX-linux或aarch64-himixXXX-linux这样的工具链。注意很多从机顶盒固件中提取或从网络获取的SDK可能不包含工具链或者工具链不完整。你需要根据SDK文档的说明自行准备或下载指定版本的工具链这是编译成功的前提。2.2 宿主机系统与关键依赖安装海思SDK的编译对宿主机你的电脑环境有明确要求。经过多次实践Ubuntu 14.04 或 16.04 的64位版本是兼容性最好的选择。更高版本的Ubuntu如18.04, 20.04可能会因为库版本太新而导致编译错误需要额外处理。我强烈建议在虚拟机如VMware, VirtualBox或物理机上安装一个纯净的Ubuntu 16.04能避开至少50%的莫名奇妙的错误。系统装好后第一件事就是安装必要的编译工具和库。打开终端执行以下命令sudo apt-get update sudo apt-get install -y make libc6-i386 lib32z1 lib32stdc6 sudo apt-get install -y gcc g git wget sudo apt-get install -y ncurses-dev u-boot-tools sudo apt-get install -y bc flex bison这里解释几个关键包libc6-i386,lib32z1,lib32stdc6 因为交叉编译工具链很多是32位的在64位系统上运行需要这些32位兼容库。缺少它们执行arm-hisivXXX-linux-gcc时会报“找不到文件”或“格式错误”。ncurses-dev 编译内核时用于生成menuconfig图形化配置界面。u-boot-tools 提供制作U-Boot镜像的工具如mkimage。bc,flex,bison 内核编译过程中需要的工具。2.3 交叉编译工具链的配置与验证这是整个环境搭建中最容易出错的环节。假设你的SDK包里自带了工具链它可能位于sdk/toolchain/arm-hisiv400-linux/这样的路径下。你需要做两件事解压并设置权限 如果工具链是*.tar.gz格式将其解压到合适位置例如/opt/。sudo tar -zxvf arm-hisiv400-linux.tar.gz -C /opt/解压后检查/opt/arm-hisiv400-linux/下的bin目录是否有可执行文件并确保其有执行权限。设置环境变量 这是告诉系统“交叉编译器在哪里”的关键步骤。通常通过修改当前用户的~/.bashrc文件实现。echo export PATH/opt/arm-hisiv400-linux/bin:$PATH ~/.bashrc echo export ARCHarm ~/.bashrc echo export CROSS_COMPILEarm-hisiv400-linux- ~/.bashrc source ~/.bashrc这里CROSS_COMPILE的值就是你的交叉编译器前缀。编译时系统会自动在它后面加上gcc、ld等命令。验证工具链 执行以下命令如果成功显示编译器版本信息则配置基本正确。arm-hisiv400-linux-gcc -v如果报错“命令未找到”请检查PATH路径是否正确如果报错“无法执行二进制文件”通常是缺少32位兼容库回头检查上一节的依赖是否安装完整。3. 核心编译流程分步实操假设你的SDK根目录是/home/yourname/hi3798mv100_sdk。整个编译过程通常是分步骤、分模块进行的。3.1 第一步编译与配置Linux内核内核是系统的心脏。海思SDK的osdrv目录下通常有一个顶层的Makefile但更常见的做法是进入芯片特定目录进行操作。cd /home/yourname/hi3798mv100_sdk/osdrv/opensource/kernel/linux-3.18.y # 或者直接进入 osdrv/目录下芯片相关的kernel目录应用默认配置 海思会提供一个针对该芯片的基础配置文件config_hi3798mv100。使用它来初始化内核配置。make ARCHarm CROSS_COMPILEarm-hisiv400-linux- hi3798mv100_defconfig # 如果存在特定的defconfig文件命令可能是 # make ARCHarm CROSS_COMPILEarm-hisiv400-linux- hi3798mv100_xxx_defconfig自定义内核配置可选但重要 如果你需要增加或删除某些内核模块比如特定的文件系统、网络驱动、USB设备支持需要进行菜单配置。make ARCHarm CROSS_COMPILEarm-hisiv400-linux- menuconfig这会打开一个文本图形界面。在这里你可以按需修改。对于初次编译强烈建议先不要做任何修改直接保存退出确保基础编译能通过。等熟悉后再进行定制。开始编译内核make ARCHarm CROSS_COMPILEarm-hisiv400-linux- uImage -j4-j4表示使用4个线程并行编译可以加快速度数字可根据你的CPU核心数调整。编译成功后会在arch/arm/boot/目录下生成uImage文件这就是内核镜像。实操心得编译内核时最常见的错误是找不到某些头文件或依赖。这通常是因为内核源码树不干净或者之前编译的中间文件残留。如果遇到奇怪的错误尝试make distclean彻底清理再从头执行defconfig和编译步骤。但注意distclean会清除所有配置需谨慎使用。3.2 第二步制作根文件系统系统不能只有内核还需要一个包含基本命令和库的文件系统。海思SDK通常使用busybox来制作基础的根文件系统。编译busyboxcd /home/yourname/hi3798mv100_sdk/osdrv/opensource/busybox/busybox-1.xx.x make ARCHarm CROSS_COMPILEarm-hisiv400-linux- defconfig # 同样可以使用 menuconfig 进行定制例如添加你需要的命令 make ARCHarm CROSS_COMPILEarm-hisiv400-linux- menuconfig make ARCHarm CROSS_COMPILEarm-hisiv400-linux- install -j4编译安装后会在_install目录下生成基本的文件系统结构bin,sbin,usr等目录。构建完整的根文件系统目录 仅有busybox还不够我们需要创建一个完整的根文件系统目录例如rootfs并拷贝必要的文件。mkdir -p /home/yourname/rootfs cp -rf /path/to/busybox/_install/* /home/yourname/rootfs/ mkdir -p /home/yourname/rootfs/{lib, proc, sys, tmp, dev, mnt, etc, var}接下来需要从工具链中拷贝运行时库.so文件到rootfs/lib下。这是让动态链接的程序能在板子上运行的关键。cp -f /opt/arm-hisiv400-linux/arm-hisiv400-linux/lib/*.so* /home/yourname/rootfs/lib/ -d-d参数表示保持软链接关系。你可能会需要调整路径并选择性拷贝避免体积过大。制作文件系统镜像 最后将rootfs目录打包成板子能识别的镜像格式如ext4或jffs2。海思提供了mkfs.jffs2等工具通常在osdrv/tools/pc目录下。# 例如制作jffs2镜像 /path/to/sdk/osdrv/tools/pc/mkfs.jffs2 -d /home/yourname/rootfs -l -e 0x20000 -o rootfs.jffs2参数-e指定擦除块大小这个值必须和你的Flash芯片规格以及U-Boot中的设置完全一致否则系统无法挂载根文件系统。这是制作文件系统镜像时最大的一个“坑”。3.3 第三步编译海思媒体平台MPPMPP是应用开发的基础。其编译相对独立但依赖于内核编译生成的一些头文件。cd /home/yourname/hi3798mv100_sdk/mpp通常MPP目录下也有一个Makefile。在编译前你需要指定编译的目标平台和内核路径。配置平台 进入make目录找到对应的平台配置文件。可能是直接修改Makefile.param文件或者通过make OSDRV_ROOT/path/to/osdrv这样的命令来指定SDK路径。关键是要设置好KERNEL_ROOT指向你编译好的内核源码目录和CROSS_COMPILE。执行编译make -j4编译成功后在mpp/lib目录下会生成libhi_*.so或*.a等库文件在mpp/sample下会生成各个样例的可执行文件。你可以用file命令检查一下生成的可执行文件是否是ARM架构的。file sample/vio/vio_main # 应该显示类似ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked...4. 编译过程中的典型问题与实战排查即使步骤清晰编译过程也极少能一帆风顺。下面是我总结的几个最常见的问题及解决方法。4.1 工具链相关错误错误现象arm-hisiv400-linux-gcc: command not found排查执行echo $PATH检查工具链的bin目录是否在PATH中。检查~/.bashrc修改后是否执行了source ~/.bashrc。错误现象bash: /opt/arm-hisiv400-linux/bin/arm-hisiv400-linux-gcc: No such file or directory或无法执行二进制文件排查这几乎肯定是缺少32位运行库。在64位Ubuntu上请确保已安装libc6-i386,lib32z1,lib32stdc6。可以使用ldd命令检查工具链二进制文件的依赖ldd /opt/arm-hisiv400-linux/bin/arm-hisiv400-linux-gcc查看是否有not found的库。4.2 内核编译错误错误现象make: *** No rule to make target hi3798mv100_defconfig. Stop.排查说明在内核源码目录下找不到指定的默认配置文件。请仔细检查SDK文档确认正确的配置文件名称和位置。有时配置文件在arch/arm/configs/目录下命令需要写全路径或先进入该目录。错误现象error: unknown type name ‘xxx’或致命错误xxx.h没有那个文件或目录排查这通常是内核源码树不干净或者之前编译的配置与当前环境冲突。尝试执行make ARCHarm CROSS_COMPILEarm-hisiv400-linux- distclean然后从头开始配置和编译。如果问题依旧检查交叉编译工具链的版本是否与SDK要求严格一致。4.3 文件系统制作与MPP编译错误错误现象板子启动时卡在Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(x,y)排查这是根文件系统挂载失败。首先检查内核配置是否支持你制作的根文件系统类型如CONFIG_JFFS2_FSy。最关键的是检查制作镜像时使用的擦除块大小-e参数是否与Flash硬件以及U-Boot环境变量bootargs中的mtdparts设置一致。一个字节的差错都会导致挂载失败。错误现象编译MPP时报错找不到linux/ion.h或hi_comm_xxx.h等头文件。排查这表示MPP编译时找不到内核头文件。你需要确认Makefile.param或编译命令中的KERNEL_ROOT变量是否正确指向了已经编译过的内核源码目录即执行过make uImage的那个目录因为编译过程会生成一些头文件。仅仅指向内核源码目录是不够的必须确保已经执行过编译。4.4 版本与兼容性“玄学”问题海思SDK尤其是从各种设备中提取的版本对编译环境非常敏感。如果你在较新的Ubuntu版本如20.04上编译一个老SDK可能会遇到各种因GCC、Make、Bison等工具版本过高导致的语法错误。策略一推荐 老实用Ubuntu 14.04或16.04。这是最省事的办法。策略二 如果必须在高版本系统上编译可以尝试降低工具版本。例如安装特定版本的GCC和Gsudo apt-get install gcc-4.8 g-4.8 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 50 sudo update-alternatives --install /usr/bin/g g /usr/bin/g-4.8 50同时可能需要安装老版本的make、bison等。这是一个繁琐的调试过程。5. 编译完成后的验证与后续步骤当内核、文件系统、MPP都编译成功后你得到的是一堆散落的文件uImage,rootfs.jffs2,libhi_*.so以及MPP的样例程序。这还不是终点。整合烧录 你需要根据你的具体硬件开发板或机顶盒的烧录方式将这些镜像文件打包成最终的烧录包。这可能涉及使用海思的Hitool工具或者制作一个包含U-Boot、内核、文件系统的单一update.zip包。这个过程高度依赖具体硬件和原厂提供的打包脚本。运行测试 将编译好的MPP样例程序如sample_vio和所需的MPP动态库libhi_*.so拷贝到板子的文件系统中。在板子上运行前需要设置动态库路径export LD_LIBRARY_PATH/path/to/libs:$LD_LIBRARY_PATH ./sample_vio如果程序能正常运行并调用摄像头或进行编解码那恭喜你SDK编译和基础环境搭建就真正成功了。开启应用开发 至此你的开发环境才算是真正就绪。你可以开始深入研究mpp/include下的头文件了解海思的API。参考mpp/sample下的样例编写自己的应用程序。将应用程序添加到rootfs中重新制作文件系统镜像打造属于自己的定制化固件。编译Hi3798MV100的SDK是一个典型的嵌入式Linux系统构建过程。它考验的不仅是敲命令的熟练度更是对交叉编译、内核、文件系统、硬件驱动这一整套链条的理解。每一个错误信息都是通往更深理解的线索。我的建议是准备一个干净的Ubuntu 16.04环境严格按照SDK内可能存在的README或ReleaseDoc文档如果有的话操作并做好每一步都可能会遇到问题并需要搜索解决的心理准备。这个过程本身就是嵌入式开发入门最扎实的一课。当你第一次看到自己编译的系统在板子上跑起来并且能运行自己编译的程序时那种成就感会告诉你所有的折腾都是值得的。