当前位置: 首页 > news >正文

rdk3 sdk 整理不完善的地方-->工具链

嵌入式BSP开发中最让人头疼的问题——同一套SDK内部,不同组件要求不同的工具链

第一部分 问题产生

一、问题的本质:不是“难搞”,是“设计如此”

RDK SDK 工具链设计哲学 │ ├── Bootloader (U-Boot) 用 aarch64-linux-gnu- │ ├── 来源:Linaro / 芯片厂商提供 │ ├── 特点:支持裸机程序编译 │ ├── 包含:完整的 libgcc(用于原子操作、浮点) │ └── 原因:U-Boot 需要编译出可在硬件上直接运行的代码 │ ├── Kernel 用 aarch64-none-linux-gnu- │ ├── 来源:ARM 官方嵌入式工具链 │ ├── 特点:专为 Linux 内核和嵌入式系统优化 │ ├── 包含:精简的 libc 头文件 │ └── 原因:内核编译需要特定的 Linux 内核头文件 │ └── 用户态应用 (Ubuntu/Debian) 用 aarch64-linux-gnu- └── 原因:需要完整的 glibc 支持

二、为什么 xbuild.sh 不设置 CROSS_COMPILE?

关键发现xbuild.sh确实没有设置CROSS_COMPILE,但mk_uboot.sh也没有设置

这意味着:地平线官方假设工具链已经在系统 PATH 中,或者依赖用户提前设置好环境变量。

验证方法

# 检查环境中是否有 aarch64-linux-gnu-gcc which aarch64-linux-gnu-gcc ​ # 如果没有,需要添加到 PATH export PATH=/opt/gcc-ubuntu-9.3.0-2020.03-x86_64-aarch64-linux-gnu/bin:$PATH export CROSS_COMPILE=aarch64-linux-gnu- ​ # 然后再尝试编译 cd source/bootloader/build ./mk_uboot.sh

三、解决方案:创建统一的环境脚本

借鉴 RK 平台的思路,创建一个顶层环境设置脚本set_build_env.sh

#!/bin/bash #============================================================================= # RDK SDK 统一编译环境设置脚本 # 使用方式: source set_build_env.sh #============================================================================= ​ # 检测并设置不同的工具链 setup_toolchain() { local component=$1 # uboot, kernel, app # 工具链路径(根据实际情况修改) local LINARO_TOOLCHAIN="/opt/gcc-ubuntu-9.3.0-2020.03-x86_64-aarch64-linux-gnu" local ARM_TOOLCHAIN="/opt/gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu" case $component in uboot|bootloader) # U-Boot 使用 Linaro 工具链 export PATH=$LINARO_TOOLCHAIN/bin:$PATH export CROSS_COMPILE=aarch64-linux-gnu- echo "Setting U-Boot toolchain: $CROSS_COMPILE" ;; kernel) # Kernel 使用 ARM 官方工具链 export PATH=$ARM_TOOLCHAIN/bin:$PATH export CROSS_COMPILE=aarch64-none-linux-gnu- echo "Setting Kernel toolchain: $CROSS_COMPILE" ;; app) # 应用使用 Linaro 工具链(完整 glibc) export PATH=$LINARO_TOOLCHAIN/bin:$PATH export CROSS_COMPILE=aarch64-linux-gnu- echo "Setting Application toolchain: $CROSS_COMPILE" ;; *) echo "Unknown component: $component" return 1 ;; esac export ARCH=arm64 } ​ # 编译 U-Boot build_uboot() { setup_toolchain uboot cd source/bootloader/build # 先选择板级配置 ./xbuild.sh lunch 0 # 根据实际情况选择 # 编译 U-Boot ./mk_uboot.sh # 打包 miniboot ./xbuild.sh cd - } ​ # 编译 Kernel build_kernel() { setup_toolchain kernel ./mk_kernel.sh } ​ # 使用说明 usage() { echo "Usage: source set_build_env.sh" echo "Then run: build_uboot or build_kernel" } ​ # 根据参数执行 if [ "${BASH_SOURCE[0]}" != "${0}" ]; then echo "Environment ready. Available commands:" echo " build_uboot - Build U-Boot and miniboot" echo " build_kernel - Build Linux kernel" echo " setup_toolchain <uboot|kernel|app> - Set toolchain" else usage fi

四、针对错误的快速修复

undefined reference to fdt_overlay_apply_verbose错误,最快的解决办法是:

方法1:直接修改源码

cd source/bootloader/uboot ​ # 编辑 common/fdt_support.c,在文件末尾添加: cat >> common/fdt_support.c << 'EOF' ​ #ifdef CONFIG_OF_LIBFDT_OVERLAY int fdt_overlay_apply_verbose(void *fdt, void *fdto) { return fdt_overlay_apply(fdt, fdto); } #endif EOF ​ # 重新编译 make clean make -j$(nproc)

方法2:禁用 dtoverlay(如果不需要)

cd source/bootloader/uboot ​ # 修改配置 make menuconfig # 取消勾选: Device Tree Control -> Enable DT overlay support # 取消勾选: Command line interface -> dtoverlay ​ # 重新编译 make clean make -j$(nproc)

方法3:设置正确的工具链后重试

# 设置工具链 export PATH=/opt/gcc-ubuntu-9.3.0-2020.03-x86_64-aarch64-linux-gnu/bin:$PATH export CROSS_COMPILE=aarch64-linux-gnu- ​ # 检查是否设置正确 echo $CROSS_COMPILE # 应该显示 aarch64-linux-gnu- ​ # 进入 U-Boot 目录 cd source/bootloader/uboot ​ # 完全清理 make distclean ​ # 配置(根据板子选择) make xj3_perf_ubuntu_defconfig ​ # 编译 make -j$(nproc) 2>&1 | tee build.log

五、理解后的总结

┌─────────────────────────────────────────────────────────────────────────────┐ │ 关键理解要点 │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ 1. 工具链不一致是设计,不是 bug │ │ - U-Boot 需要裸机编译能力(Linaro 工具链) │ │ - Kernel 需要 Linux 内核头文件(ARM 官方工具链) │ │ │ │ 2. xbuild.sh 不设置 CROSS_COMPILE 的原因 │ │ - 地平线假设用户在系统 PATH 中已配置好 │ │ - 或者依赖用户在调用前手动 export │ │ │ │ 3. 当前错误的根本原因 │ │ - 不是工具链的问题! │ │ - 是 U-Boot 源码版本不一致:dtoverlay.c 新,libfdt 旧 │ │ │ │ 4. 最佳实践 │ │ - 创建顶层 build.sh 统一管理不同组件的工具链 │ │ - 或在每个编译脚本中显式设置 CROSS_COMPILE │ │ │ └─────────────────────────────────────────────────────────────────────────────┘

“为什么官方不统一工具链”,嵌入式 BSP 开发中,接受这个现实,然后建立自己的构建封装,才是最高效的做法。创建一个顶层脚本统一管理,以后只需要运行./build.sh uboot即可。

第二部分fdt_overlay_apply_verbose函数深度解析

一、这个函数的作用

一个"包装函数"(wrapper function),它的作用是:

fdt_overlay_apply_verbose (详细版) │ ├── 输入:两个设备树二进制文件 │ ├── fdt - 主设备树(base device tree) │ └── fdto - 覆盖设备树(overlay device tree) │ ├── 处理:什么都不做,只是转发调用 │ └── return fdt_overlay_apply(fdt, fdto) │ └── 输出:返回覆盖应用的结果(成功0,失败负数)

简单说:这个函数就是调用了另一个函数fdt_overlay_apply,然后把结果原样返回。

二、为什么要写这样一个"多余"的函数?

为了向后兼容(backward compatibility)和API设计。

2.1 历史原因

U-Boot 设备树覆盖功能的演进 │ ├── 早期版本(2017年前) │ └── 只有 fdt_overlay_apply() - 静默失败,不输出错误信息 │ ├── 2017年9月,Pantelis Antoniou 提交补丁 │ ├── 新增 fdt_overlay_apply_verbose() │ ├── 功能:在失败时打印详细错误信息 │ └── 原因:开发者调试 overlay 时不知道哪里出错 │ └── 现状 ├── 新代码调用 fdt_overlay_apply_verbose()(要错误信息) ├── 旧代码继续调用 fdt_overlay_apply()(保持兼容) └── 如果 CONFIG_OF_LIBFDT_OVERLAY_VERBOSE 未开启, 则 fdt_overlay_apply_verbose = fdt_overlay_apply

2.2 这段代码的作用

这段代码,实际上是手动实现了这个兼容层

// 原本缺失的函数 int fdt_overlay_apply_verbose(void *fdt, void *fdto) { // 简单转发到实际存在的函数 return fdt_overlay_apply(fdt, fdto); }

效果

  • 链接器现在能找到fdt_overlay_apply_verbose的实现了

  • 编译可以通过

  • 功能上等价于没有详细错误信息的版本

三、设备树覆盖(DT Overlay)是什么?

为了理解这个函数的用途,需要先了解什么是设备树覆盖:

设备树覆盖概念 │ ├── 主设备树(base.dtb) │ └── 描述板子的基本硬件(如 CPU、内存、UART) │ ├── 覆盖设备树(overlay.dtbo) │ └── 描述扩展硬件(如插入的摄像头、显示屏) │ └── 动态应用 ├── 系统运行时可以动态加载/卸载 overlay ├── 不需要重新编译内核或重启 └── 常用于:HAT 板、PCIe 设备、USB 转接板

实际应用场景

# 例如:在树莓派上动态加载一个 RTC 模块 sudo dtoverlay ds1307.dtbo ​ # 内核会调用 fdt_overlay_apply() 来合并设备树 # 如果失败,verbose 版本会打印: # "Error: Fragment 1: Node name /soc/i2c@1 not found"

四、完整的 fdt_overlay_apply_verbose 实现

官方完整版本应该是这样的:

int fdt_overlay_apply_verbose(void *fdt, void *fdto) { int ret; // 1. 检查参数有效性 if (!fdt || !fdto) { printf("ERROR: NULL pointer in fdt_overlay_apply\n"); return -1; } // 2. 检查 FDT 魔术字(验证是否是有效的设备树) if (fdt_magic(fdt) != FDT_MAGIC) { printf("ERROR: Invalid magic in main FDT (0x%08x)\n", fdt_magic(fdt)); return -2; } if (fdt_magic(fdto) != FDT_MAGIC) { printf("ERROR: Invalid magic in overlay FDT (0x%08x)\n", fdt_magic(fdto)); return -3; } // 3. 尝试应用覆盖 ret = fdt_overlay_apply(fdt, fdto); // 4. 如果失败,打印详细错误信息(这就是 verbose 的精髓) if (ret < 0) { printf("ERROR: fdt_overlay_apply failed: %s (err=%d)\n", fdt_strerror(ret), ret); // 进一步打印哪个 fragment 失败了 if (ret == -FDT_ERR_NOTFOUND) { printf(" Hint: A node or property referenced in overlay was not found\n"); } } return ret; }

五、简化版本 vs 完整版本

特性简化版本完整版本(官方)
参数检查❌ 无✅ 有
魔术字验证❌ 无✅ 有
错误信息打印❌ 无✅ 详细输出
调试帮助❌ 无✅ 提示可能原因
功能正确性✅ 可以工作✅ 可以工作
代码大小很小较大

六、uboot整理思路

"fdt_overlay_apply_verbose是 U-Boot 中用于应用设备树覆盖(Device Tree Overlay)的函数,它的verbose后缀表示会在失败时打印详细错误信息。

添加的这段代码是一个简化实现,直接调用底层fdt_overlay_apply函数。之所以需要这个函数,是因为地平线 SDK 中的cmd/dtoverlay.c调用了它,但libfdt库中没有提供实现,导致链接失败。

这段代码的作用:

  1. 解决链接错误(undefined reference

  2. 提供函数入口,让程序能够正常链接

  3. 功能上等价于不打印详细错误信息的普通版本

更根本的理解:这个函数的存在体现了设备树覆盖机制的设计——允许系统在运行时动态修改硬件描述。这对于需要支持热插拔外设的嵌入式系统非常有用。

为什么官方代码会缺失:这通常是 SDK 整合时的版本不一致导致的。dtoverlay.c来自较新的 U-Boot,但libfdt来自旧版本。添加这个 wrapper 是最小侵入性的修复方案。"

http://www.jsqmd.com/news/616396/

相关文章:

  • 创意无限:用圣女司幼幽模型生成不同风格的角色场景图
  • OpenClaw智能监控:Qwen3-32B实现服务器异常自动告警
  • 后悔没早看!敏感肌日常修护全攻略,轻松养出健康厚脸皮✨
  • 20230508直播录播-
  • OpenClaw异常处理机制:千问3.5-27B任务失败自动回滚
  • 编程语言的本质是什么?从“动态性“三维模型重新理解你写的每一行代码
  • 品牌设计没头绪?专业公司来帮你!
  • 2026年怎么部署OpenClaw?阿里云超简单5步喂奶级教程
  • Phi-3-mini-4k-instruct-gguf完整指南:GGUF模型加载机制与llama-cpp内存优化原理
  • Entity Framework Core 10向量搜索深度实践(从NuGet包冲突到ANN精度调优全链路拆解)
  • 前端学习笔记-vue3基础
  • TOP3化妆学校,究竟哪家强?
  • 20230709直播实录
  • 基于STM32的多功能温室大棚环境监测系统:实时显示、远程监控与智能调节温湿度
  • Gradio UI定制化:修改SenseVoice-Small webui.py实现多语言切换+结果导出功能
  • 20230908直播录播回放
  • VOOHU沃虎单对以太网(SPE)技术白皮书:原理、标准、应用与选型
  • 2026化工行业高仓(6~12 米)条码采集方案:海雅达HDT500“12米中远距扫描”的5寸手持终端PDA
  • GTE-Base-ZH镜像体验:可视化界面+API,双模式交互更便捷
  • 2026企业用工数字化:如何选择适合自己的企业培训系统?
  • PHP 8.9 JIT开启后反而变慢?深度剖析opcache.jit_buffer_size与CPU缓存行对齐的隐性冲突
  • 直播带货系统源码开发需要哪些功能?电商直播平台搭建详解
  • 20230930直播实录
  • sp-html2canvas-render在iOS中跨域问题
  • 长沙这个酒吧好玩到让你不想回家!
  • Vue 2 与 Vue 3 的区别
  • Windows Terminal 文本出现黑色背景问题解决方法
  • java项目(附资料)-基于SpringBoot+Vue前后端分离的在线商城系统设计与实现
  • Windows 11系统优化完全指南:从卡顿到流畅的专业解决方案
  • AdMergeX 斩获信通院铸基计划双项权威认可