3、开发环境搭建:Linux BSP SDK获取、交叉编译工具链配置、内核驱动(sunxi-cedar)编译与加载、用户空间库(libcedar)安装

好,咱们正式开始动手了。这一章,说白了就是“把家伙事儿备齐”。

做嵌入式开发,最怕什么?最怕环境没搭好,折腾半天发现是工具链版本不对。我当年刚接触全志平台时,就吃过这个亏——编译出来的驱动死活加载不上,最后发现是交叉编译器跟内核版本不匹配。嗯,这种坑,咱们今天一次性填平。

3.1 Linux BSP SDK获取

全志官方提供的BSP(Board Support Package)SDK,是咱们开发的基础。它包含了U-Boot、Linux内核、文件系统以及各种驱动源码。

获取方式主要有两种:

  • 官方Git仓库:全志在GitHub上维护了H616的Linux SDK,地址是 https://github.com/allwinner-zh/linux-sunxi。我个人习惯用这个,因为能随时拉取最新补丁。
  • 开发板厂商提供:比如香橙派、芒果派,它们会提供定制化的SDK压缩包。如果你用的是这类板子,建议优先用厂商的,因为里面已经适配好了板级配置。
我的建议: 无论用哪种方式,下载后先检查 .repo/manifest.xml 文件,确认内核版本是否为5.4或更高。H616的cedar驱动对内核版本有依赖,太老的内核可能不支持。

下载命令很简单:

git clone https://github.com/allwinner-zh/linux-sunxi.git -b h616-v5.4
cd linux-sunxi
git submodule update --init --recursive

这个过程大概需要十几分钟,取决于你的网速。趁这个时间,咱们可以先把交叉编译工具链准备好。

3.2 交叉编译工具链配置

交叉编译,说白了就是在PC上编译出能在ARM芯片上跑的程序。H616是ARM Cortex-A53架构,64位,所以咱们需要aarch64的交叉编译器。

我推荐两种方案:

方案 工具链 适用场景
Linaro官方 gcc-arm-9.2-2019.12-x86_64_aarch64-linux-gnu 通用开发,稳定性好
Buildroot生成 自定义工具链 需要定制glibc版本时

我个人习惯用Linaro的,省事。下载并解压:

wget https://releases.linaro.org/components/toolchain/binaries/9.2-2019.12/aarch64-linux-gnu/gcc-arm-9.2-2019.12-x86_64_aarch64-linux-gnu.tar.xz
tar -xf gcc-arm-9.2-2019.12-x86_64_aarch64-linux-gnu.tar.xz -C /opt/

然后配置环境变量。我建议写到 ~/.bashrc 里,一劳永逸:

export PATH=/opt/gcc-arm-9.2-2019.12-x86_64_aarch64-linux-gnu/bin:$PATH
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-

记得 source ~/.bashrc 让它生效。验证一下:

aarch64-linux-gnu-gcc --version

如果看到版本信息,说明工具链配置成功。

注意: 我曾经遇到过一个问题——系统自带的gcc版本太高,跟Linaro工具链冲突。解决办法是:在编译内核时,明确指定 CC= 变量,或者在 Makefile 里强制覆盖。否则,你可能会编译出x86_64的内核,那可就尴尬了。

3.3 内核驱动(sunxi-cedar)编译与加载

cedar驱动,是全志视频解码引擎的核心。它位于内核源码的 drivers/media/platform/sunxi/cedar/ 目录下。

编译步骤:

  1. 配置内核:进入内核源码目录,执行 make sunxi_h616_defconfig。这个配置文件已经默认启用了cedar驱动。
  2. 确认驱动选项:运行 make menuconfig,检查以下选项是否开启:
    • Device Drivers → Multimedia support → Media drivers → Sunxi Cedar video decoder
    • 如果没找到,手动搜索 CONFIG_VIDEO_SUNXI_CEDAR
  3. 编译内核和模块
    make -j$(nproc) Image modules
    make modules_install INSTALL_MOD_PATH=./modules_install

编译完成后,你会得到 arch/arm64/boot/Image 内核镜像,以及 modules_install/lib/modules/ 下的驱动模块。

加载驱动:

把编译好的模块拷贝到开发板的 /lib/modules/ 目录下,然后执行:

depmod -a
modprobe sunxi-cedar

lsmod | grep cedar 检查是否加载成功。如果看到 sunxi_cedar 字样,说明驱动已经跑起来了。

避坑指南: 我曾经在加载驱动时遇到 Firmware: failed to load cedar_fw.bin 的错误。这是因为cedar驱动需要固件文件。解决办法是:从SDK的 firmware/ 目录下找到 cedar_fw.bin,拷贝到开发板的 /lib/firmware/ 目录下。没有这个文件,解码器是没法工作的。

3.4 用户空间库(libcedar)安装

驱动只是底层,真正给应用程序调用的,是用户空间的libcedar库。它封装了V4L2接口,提供了更友好的API。

获取源码:

libcedar的源码在SDK的 package/cedarx/ 目录下,或者从全志的GitHub单独拉取:

git clone https://github.com/allwinner-zh/cedarx.git

交叉编译:

cd cedarx
mkdir build && cd build
cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc \
         -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ \
         -DCMAKE_INSTALL_PREFIX=/usr/local/cedar
make -j$(nproc)
make install

编译完成后,你会得到 libcedar.so 和相关的头文件。把它们拷贝到开发板的 /usr/lib//usr/include/ 目录下。

验证安装:

写一个简单的测试程序,调用 cedar_open() 函数。如果能成功返回句柄,说明库安装正确。

#include <cedarx.h>
int main() {
    CedarHandle handle;
    if (cedar_open(&handle) == 0) {
        printf("Cedar initialized successfully!\n");
        cedar_close(handle);
    } else {
        printf("Failed to initialize Cedar.\n");
    }
    return 0;
}

编译时链接libcedar:

aarch64-linux-gnu-gcc test.c -lcedar -o test_cedar

我的经验: 如果你在运行测试程序时遇到 cannot open shared object file 的错误,八成是 LD_LIBRARY_PATH 没设置。执行 export LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH 即可。另外,libcedar依赖 libcedarx.solibcedarxalloc.so,记得一并拷贝过去。

好了,到这一步,你的开发环境就彻底搭好了。从SDK获取、工具链配置,到内核驱动编译加载,再到用户空间库安装,一条龙搞定。下一章,咱们就要开始真正接触cedar驱动的内部结构了——那才是解码方案的核心。