ARTICLE DETAIL

资讯详情

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

Hi3798MV100 SDK编译环境搭建与嵌入式Linux系统构建全流程指南

Hi3798MV100 SDK编译环境搭建与嵌入式Linux系统构建全流程指南 1. 从零开始的Hi3798MV100 SDK编译环境搭建最近在折腾一块基于海思Hi3798MV100芯片的机顶盒板子型号是创维E900V21C。这玩意儿在海鲜市场很常见几十块钱就能淘到硬件配置对于学习嵌入式Linux开发来说性价比极高。我拿到手的第一件事就是想把官方的SDK编译环境给搭起来毕竟这是后续所有开发工作的基石。但这个过程远比想象中要“复古”和“折腾”。如果你也正准备入坑Hi3798MV100或者任何一款老版本海思芯片的开发这篇笔记或许能帮你避开我踩过的那些坑。Hi3798MV100是一颗经典的机顶盒SoC虽然现在看其CPU性能和外围接口不算突出但胜在资料相对丰富以海思的标准而言社区也有不少玩家在研究。编译它的SDK核心目的就是为了生成三个关键的东西U-Boot引导程序、Linux内核以及根文件系统。有了它们你才能让板子真正跑起来并在此基础上进行应用开发或系统定制。整个编译过程强烈依赖于一个特定的、老旧的交叉编译工具链和一套定制化的构建脚本对宿主机的Linux发行版和软件版本有近乎苛刻的要求。网上很多教程直接跳到编译命令但环境没配好一切都是徒劳。所以我们从头说起。2. 宿主机操作系统与软件版本的精确选择这是整个过程中最至关重要的一步选错了系统后面会寸步难行。根据官方SDK通常版本号类似Hi3798MV100R001C01SPCxxx的文档和无数前辈的血泪教训最兼容、问题最少的宿主机系统是Ubuntu 14.04 64位。是的你没看错是2014年发布的那个版本。为什么必须是它原因在于SDK内置的交叉编译工具链通常是arm-hisiv300-linux或arm-hisiv400-linux是在特定的glibc库版本下构建的。在新版本的Ubuntu如18.04, 20.04上系统的动态链接库版本过高会导致工具链无法运行报各种“No such file or directory”或“versionGLIBC_2.xx not found”的错误。试图去升级工具链或修改系统库复杂度极高极易失败。那么有没有其他选择有但都是妥协方案使用Docker容器这是目前最优雅的解决方案。创建一个基于Ubuntu 14.04镜像的Docker容器在容器内进行所有编译工作。这样既能保持宿主机系统的洁净和现代又能满足SDK的古老需求。我强烈推荐这种方式。使用老旧的物理机或虚拟机老老实实安装一个Ubuntu 14.04的虚拟机。VMware或VirtualBox都可以。确保分配足够的磁盘空间建议40GB以上和内存4GB以上。尝试在较新系统上“打补丁”有人通过手动安装旧版本的libc6:i386等32位兼容库或者使用chroot构造一个旧环境让工具链跑起来。这个过程非常繁琐不推荐新手尝试。我的选择是Docker方案。接下来所有步骤都基于在Ubuntu 14.04 Docker容器内操作来展开。如果你用虚拟机操作完全一致。3. 获取SDK与交叉编译工具链海思的SDK通常不是公开下载的需要一定的渠道获取。对于Hi3798MV100这类消费级芯片SDK可能会随着某些开发板流出或者在相关的技术社区找到分享链接请注意版权风险。假设你已经拿到了一个名为Hi3798MV100R001C01SPCxxx.tgz的SDK包。第一步准备Docker环境宿主机为现代Linux或Windows WSL2在宿主机上拉取Ubuntu 14.04镜像并启动一个容器。# 拉取镜像 docker pull ubuntu:14.04 # 运行容器将本地SDK目录挂载到容器内并创建一个用于编译的用户 docker run -it --name hi3798mv100-build \ -v /path/to/your/sdk:/home/sdk \ -v /path/to/your/output:/home/output \ ubuntu:14.04 /bin/bash进入容器后首先更新软件源并安装一些基础工具比如vim,make,gcc,g注意这是宿主机的gcc用于编译一些本地工具以及git等。apt-get update apt-get install -y vim make gcc g git wget cpio python第二步解压SDK在容器内进入挂载的目录。cd /home/sdk tar -xzf Hi3798MV100R001C01SPCxxx.tgz解压后你会看到一个复杂的目录结构通常包含以下关键部分pub/ 存放公版镜像、文档等。source/ 最核心的源码目录包含bootU-Boot、kernelLinux内核和rootfs根文件系统构建脚本和配置。tools/ 包含交叉编译工具链、PC端工具如mkimage。build/ 存放编译脚本如build.sh。第三步安装交叉编译工具链工具链通常在tools/linux/toolchain/目录下。对于Hi3798MV100常见的是arm-hisiv300-linux或arm-hisiv400-linux。cd /home/sdk/tools/linux/toolchain/ # 假设工具链包是 arm-hisiv300-linux.tar.gz tar -xzf arm-hisiv300-linux.tar.gz -C /opt/解压到/opt目录后需要将工具链路径加入到系统的PATH环境变量中。通常SDK的build目录下会有一个env_setup.sh之类的脚本。如果没有需要手动设置。# 编辑当前用户的bashrc文件 vim ~/.bashrc # 在文件末尾添加 export PATH/opt/arm-hisiv300-linux/bin:$PATH export ARCHarm export CROSS_COMPILEarm-hisiv300-linux- # 使环境变量生效 source ~/.bashrc # 验证工具链是否安装成功 arm-hisiv300-linux-gcc -v如果成功输出gcc版本信息恭喜你最困难的环境部分已经完成了一大半。4. 编译U-Boot引导程序U-Boot相当于嵌入式板子的BIOS负责初始化硬件、加载内核。海思的U-Boot通常经过了深度定制。第一步进入U-Boot源码目录并配置cd /home/sdk/source/boot/u-boot-2010.06 # 先执行一次清理 make distclean # 应用默认配置文件不同板子配置不同常见 hi3798mv100_defconfig make hi3798mv100_defconfig这里的defconfig文件定义了该板型的所有编译选项。如果你是从其他板型移植可能需要基于一个相近的配置进行修改。关键配置位于.config文件中但通常通过make menuconfig来调整。不过海思的U-Boot菜单配置可能被简化很多关键参数如DDR初始化参数、寄存器配置直接写死在板级头文件或boards.cfg里。第二步编译生成U-Boot镜像make -j4-j4表示使用4个线程并行编译可以加快速度。编译成功后在源码目录下会生成关键的镜像文件通常名为u-boot.bin。但海思平台通常还需要一个步骤就是用tools目录下的mkboot.sh或sign工具对这个u-boot.bin进行打包和签名特别是高安芯片生成最终的u-boot-xxx.bin。这里有一个大坑Hi3798MV100有高安Secure Boot和非高安Non-Secure Boot版本。你手里的板子如果是运营商的定制版很可能是高安版直接用普通编译的U-Boot是启动不了的。创维E900V21C这类盒子很多是非高安版相对简单。务必确认你的芯片版本。实操心得编译U-Boot时最常见的错误是找不到交叉编译工具链。请反复检查CROSS_COMPILE环境变量是否正确以及工具链的bin目录是否在PATH中。另一个常见错误是缺少某些头文件比如asm/arch/xxx.h这通常是因为源码目录结构不对或者没有正确应用海思提供的补丁。确保你是从海思提供的完整source目录开始编译而不是从官方的U-Boot官网下载代码。5. 编译Linux内核内核编译的步骤相对标准但海思的内核源码树里集成了大量的海思平台专用驱动和模块。第一步内核配置cd /home/sdk/source/kernel/linux-3.18.y # 清理 make distclean # 导入默认配置海思通常提供 .config 文件或者通过 defconfig cp arch/arm/configs/hi3798mv100_defconfig .config # 启动图形化配置界面需要容器内安装 libncurses5-dev apt-get install libncurses5-dev make ARCHarm CROSS_COMPILEarm-hisiv300-linux- menuconfig在menuconfig中你需要根据你的板子硬件情况调整配置。关键点包括系统类型System Type确保选中Hisilicon Hi3798MV100系列。设备驱动Device Drivers重点关注MMC/SD/SDIO card support、USB support、Network device support特别是以太网PHY驱动如Hisilicon Gigabit Ethernet、Graphics supportGPU驱动如Mali或PowerVR但海思可能用自家的hi_fb。文件系统File systems确保支持你根文件系统将要使用的格式如ext2/3/4,squashfs,jffs2等。海思特有的驱动如HISILICON VPU视频编解码、HISILICON GPIO等通常已经以模块M或内置*形式配置好。对于初次编译如果你不确定可以直接保存默认配置退出。第二步编译内核与模块# 编译内核镜像和模块 make ARCHarm CROSS_COMPILEarm-hisiv300-linux- uImage -j4 # 编译设备树文件如果使用 make ARCHarm CROSS_COMPILEarm-hisiv300-linux- dtbs -j4 # 编译所有模块 make ARCHarm CROSS_COMPILEarm-hisiv300-linux- modules -j4编译成功后关键产出在arch/arm/boot/uImage 压缩的内核镜像U-Boot可以直接引导。arch/arm/boot/dts/hi3798mv100-xxx.dtb 设备树二进制文件如果使用设备树。各个模块文件.ko散落在各驱动目录。第三步安装模块到临时目录为了后续打包进根文件系统需要将编译好的模块安装到一个临时目录。# 创建一个临时目录 mkdir -p /home/output/rootfs_modules # 安装模块INSTALL_MOD_PATH指定安装路径 make ARCHarm CROSS_COMPILEarm-hisiv300-linux- modules_install INSTALL_MOD_PATH/home/output/rootfs_modules执行后模块会被安装到/home/output/rootfs_modules/lib/modules/3.18.xx/目录下。踩坑记录内核版本与工具链的匹配我遇到过最诡异的问题是编译内核时一切顺利但编译某些外设驱动特别是第三方驱动时提示函数未定义或内核头文件不匹配。这往往是因为内核源码版本与交叉编译工具链所依赖的内核头文件版本不一致。海思SDK提供的工具链和内核源码是匹配的但如果你尝试升级内核版本就必须同步使用匹配的新工具链或者手动指定工具链内的-I头文件路径。对于新手强烈建议不要轻易修改内核版本就用SDK里提供的那个。6. 构建根文件系统根文件系统包含了Linux启动后所有的用户态程序、库文件和配置文件。海思SDK通常提供两种构建方式一种是基于busybox制作最小根文件系统另一种是使用buildroot或yocto构建更复杂的系统。这里以最常见的busybox方式为例。第一步编译BusyBoxBusyBox是一个集成了上百个常用Linux命令的单一可执行文件是嵌入式根文件系统的核心。cd /home/sdk/source/rootfs/busybox-1.xx.x # 清理 make distclean # 导入海思提供的默认配置通常叫 hi3798mv100_defconfig make hi3798mv100_defconfig # 可以进行自定义配置 make ARCHarm CROSS_COMPILEarm-hisiv300-linux- menuconfig在menuconfig中主要关注Settings - Build Options - Build BusyBox as a static binary 是否编译为静态链接。静态链接的BusyBox不依赖动态库更简单但体积稍大。动态链接则需要将工具链的动态库复制到根文件系统。在Settings - Installation Options中确认Don‘t use /usr被选中这样安装时会直接安装到_install目录而不是系统的/usr下。 配置完成后开始编译和安装make ARCHarm CROSS_COMPILEarm-hisiv300-linux- -j4 make ARCHarm CROSS_COMPILEarm-hisiv300-linux- install编译安装后当前目录下会生成一个_install目录里面就是BusyBox生成的所有命令的链接。第二步组装根文件系统骨架我们需要创建一个目录作为根文件系统的根。mkdir -p /home/output/rootfs cd /home/output/rootfs # 复制BusyBox的内容 cp -r /home/sdk/source/rootfs/busybox-1.xx.x/_install/* . # 创建Linux系统必需的目录 mkdir -p proc sys dev etc/init.d tmp var/lib mnt home root lib第三步复制动态库如果你的BusyBox是动态链接的或者你后续要运行动态链接的应用程序就必须将交叉工具链里的动态库复制过来。# 找到工具链的动态库路径通常在 /opt/arm-hisiv300-linux/arm-hisiv300-linux/libc/lib cp -d /opt/arm-hisiv300-linux/arm-hisiv300-linux/libc/lib/*.so* ./lib/ # -d 参数保持软链接第四步添加内核模块将之前编译好的内核模块复制过来。cp -r /home/output/rootfs_modules/lib/modules ./lib/第五步创建基本的配置文件最重要的文件是etc/inittab和etc/init.d/rcS。etc/inittab 定义系统启动后要运行的进程。# 内容示例 ::sysinit:/etc/init.d/rcS ::respawn:-/bin/sh ttyAMA0::askfirst:-/bin/sh ::ctrlaltdel:/sbin/rebootetc/init.d/rcS 系统初始化脚本需要赋予可执行权限。#!/bin/sh # 内容示例 mount -t proc none /proc mount -t sysfs none /sys mount -t tmpfs none /tmp echo /sbin/mdev /proc/sys/kernel/hotplug mdev -s # 设置网络如果需要 ifconfig lo 127.0.0.1 up # 加载必要的内核模块 insmod /lib/modules/3.18.xx/kernel/drivers/xxx.ko第六步制作根文件系统镜像最后需要将这一堆目录和文件打包成一个镜像文件方便烧录。常见的格式有ext4和squashfs。# 制作ext4格式镜像可读写 cd /home/output dd if/dev/zero ofrootfs.ext4 bs1M count64 # 创建一个64MB的空文件 mkfs.ext4 rootfs.ext4 mkdir -p mnt_point sudo mount -o loop rootfs.ext4 mnt_point sudo cp -r rootfs/* mnt_point/ sudo umount mnt_point # 制作squashfs格式镜像只读压缩率高 mksquashfs rootfs rootfs.squashfs -comp xzsquashfs镜像体积更小适合存储空间有限的SPI NAND Flash。ext4则适合eMMC或SD卡。7. 整合与烧录生成最终固件现在我们有了三个核心部件u-boot.bin、uImage内核和rootfs.img根文件系统镜像。但通常机顶盒的烧录文件是一个完整的.img包它包含了分区表以及各个分区bootloader、kernel、rootfs等的映像。海思SDK的tools目录下通常提供了打包工具比如mkimage或专门的pack脚本。第一步了解分区表Hi3798MV100的典型NAND Flash分区可能如下bootargs 启动参数分区。boot 存放U-Boot的分区。kernel 存放Linux内核镜像的分区。rootfs 存放根文件系统的分区。misc、recovery等。你需要一个描述分区大小和布局的配置文件有时叫partition.xml或直接在打包脚本里定义。第二步使用打包脚本进入SDK的build或tools/pack目录通常能找到build.sh或mkimage.sh。cd /home/sdk/build # 修改脚本中的路径指向你编译好的文件 # 通常需要设置环境变量或修改脚本里的路径变量例如 # export UBOOT_PATH/home/output/u-boot.bin # export KERNEL_PATH/home/output/uImage # export ROOTFS_PATH/home/output/rootfs.squashfs ./build.sh执行成功后会在output或image目录下生成最终的Hi3798MV100R001C01SPCxxx.img文件。第三步烧录到板子烧录方式取决于板子的启动模式和接口串口烧录最常用板子通过串口连接电脑进入U-Boot命令行。使用tftp或xmodem协议将镜像下载到内存然后使用nand write或mmc write命令写入存储。USB烧录海思提供了Hitool工具通过USB OTG口进行烧录。你需要将板子设置为USB Burning模式通常通过短接Flash引脚或按特定按键上电然后在Windows电脑上用Hitool选择镜像文件进行烧写。SD卡烧录将镜像写入SD卡插入板子设置从SD卡启动板子会自动将SD卡中的镜像烧写到内部Flash。最后的忠告备份原机固件在第一次烧录你自己编译的固件前务必先通过Hitool或其他方式完整地读取并备份原机的整个Flash内容。这是你救砖的最后保障。一旦新固件无法启动你可以通过短接Flash进入强制烧录模式将原厂固件写回去。整个Hi3798MV100的SDK编译流程就像在操作一个精密的古董仪器每一步都需要严格按照“手册”来对版本极度敏感。但一旦走通这个流程你对嵌入式Linux从源码到镜像的构建全过程会有一个非常扎实的理解。这不仅仅是敲几个命令更是对工具链、内核配置、根文件系统组织、固件打包这一整套工具链的熟悉。
返回列表