玩转U-Boot bdinfo:嵌入式bsp开发者的定制、扩展与裁剪实战指南

电子说

1.4w人已加入

描述

 

 

 

作为嵌入式开发者,U-Boot 是我们调试、适配板卡的核心工具,而 bdinfo 命令更是板级信息调试的利器”——它能直观打印内存布局、Flash 信息、网络配置、时钟频率等核心参数。但原厂的 bdinfo.c 往往是大而全的通用实现,适配自研板卡时,要么冗余打印拖慢调试效率,要么缺少我们需要的自定义硬件信息。

 

 

今天就结合bdinfo.c 的核心逻辑,手把手教你做功能裁剪、扩展、私有定制,让bdinfo 完全贴合自研板卡的调试需求!

命令

一、先理清:bdinfo.c 核心价值与定制思路

 

 

bdinfo.c 的核心是实现bdinfo 命令,通过封装各类打印函数(print_num/print_mhz/print_eth 等),基于bd_t(板级信息结构体)和全局gd 指针,按不同架构(ARM/RISC-V/PPC 等)差异化打印硬件参数。

 

 

我们的定制思路围绕 3 个核心需求:

 

 

裁剪:删掉自研板卡用不到的打印逻辑,减小 U-Boot 镜像体积;

 

 

扩展:新增自研板卡的自定义硬件信息打印(如硬件版本、PMIC 状态);

 

 

定制:修改输出格式,适配自研调试工具(如 JSON 格式、固定分隔符)。

 

 

二、实战 1:功能裁剪——精简冗余打印,减小镜像体积

 

 

自研板卡往往是极简设计:比如只有单网口、无外置 Flash、不需要多 DRAM Bank 打印,这些冗余代码不仅增加镜像体积,还会在调试时输出无关信息,干扰判断。

 

 

适用场景

 

 

自研 ARM 板卡只有 eth0,不需要 eth1-eth5 打印;

 

 

板卡无 Flash 芯片,无需 Flash 起始地址/大小打印;

 

 

不需要 LCD/VIDEO 相关的帧缓冲(FB base)打印。

 

 

裁剪步骤(以 ARM 架构为例)

 

 

步骤 1:精简以太网打印

 

 

原厂代码会遍历 eth0-eth5,但我们只有单网口,直接修改 print_eth_ip_addr 函数,只保留 eth0

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
static inline void print_eth_ip_addr(void){#if defined(CONFIG_CMD_NET)    // 只保留eth0,删除eth1-eth5的条件编译print_eth(0);printf("IP addr     = %sn"env_get("ipaddr"));#endif}

步骤 2:删除 Flash 相关打印

 

 

如果板卡无 Flash,直接注释/删除 print_bi_flash 函数的调用(以 ARM 架构的 do_bdinfo 为例):

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
static int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc,char * const argv[]){bd_t *bd = gd->bd;print_num("arch_number",bd->bi_arch_number);print_bi_boot_params(bd);print_bi_dram(bd);    // 【裁剪】删除Flash打印(板卡无Flash)    // print_bi_flash(bd);#ifdef CONFIG_SYS_MEM_RESERVE_SECURE    // ... 原有逻辑保留#endif    // ... 其余逻辑不变}

步骤 3:关闭 LCD/VIDEO 相关打印

 

 

如果板卡无显示模块,删除帧缓冲打印:

 

 

  •  
  •  
  •  
  •  
#if defined(CONFIG_LCD) || defined(CONFIG_VIDEO)    // 【裁剪】注释掉FB base打印// print_num("FB base  ", gd->fb_base);#endif

裁剪核心原则

 

 

优先用条件编译宏(如CONFIG_MY_BOARD_NO_FLASH)封装裁剪逻辑,便于后续开关:

 

 

  •  
  •  
  •  
#ifndef CONFIG_MY_BOARD_NO_FLASHprint_bi_flash(bd);#endif

只删除打印调用,不删除底层函数(如 print_bi_flash),避免影响其他架构/板卡复用。

 

 

三、实战 2:功能扩展——新增自定义板级信息打印

 

 

这是最常用的定制场景:比如打印自研板卡的硬件版本、PMIC 电压、传感器 ID、自定义保留内存区域等。

 

 

适用场景

 

 

自研 ARM 板卡需要打印:

 

 

1.硬件版本号(存储在gd 全局变量的自定义字段);

 

 

2.PMIC(电源管理芯片)的工作电压;

 

 

3.自研的安全分区内存地址。

 

 

扩展步骤

 

 

步骤 1:定义自定义辅助打印函数

 

 

bdinfo.c 中新增适配自定义信息的打印函数(复用原厂的格式化风格,保持一致性):

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
// 新增:打印硬件版本__maybe_unusedstatic void print_board_version(const char *name, u32 version){    // 格式对齐原厂:左对齐12字符,后接版本号(十进制)printf("%-12s= V%02d.%02dn", name, (version>>8)&0xFF, version&0xFF);}// 新增:打印PMIC电压(单位:mV)__maybe_unusedstatic void print_pmic_voltage(const char *name, u32 voltage_mv){printf("%-12s= %d mVn", name, voltage_mv);}// 新增:打印自定义保留内存__maybe_unusedstatic void print_custom_reserve_mem(const char *name, ulong start, ulong size){print_num(name, start);print_num("-> size", size);}

步骤 2:在对应架构的 do_bdinfo 中添加调用

 

 

 ARM 架构为例,在 do_bdinfo 函数中新增自定义打印(建议放在原有打印逻辑的末尾,便于查看):

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
static int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc,char * const argv[]){bd_t *bd = gd->bd;// ... 原有打印逻辑(arch_number、DRAM、eth等)保留    // 【扩展】新增自定义硬件信息打印    // 1. 打印硬件版本(假设gd->arch.board_version是自定义字段)    print_board_version("Board Ver", gd->arch.board_version);    // 2. 打印PMIC核心电压(模拟读取PMIC寄存器)    u32 core_volt = read_pmic_reg(PMIC_CORE_VOLT_REG); // 自研PMIC读取函数    print_pmic_voltage("PMIC Core", core_volt);    // 3. 打印安全分区内存    print_custom_reserve_mem("Secure Area"0x900000000x100000);print_baudrate();// ... 其余原有逻辑保留return 0;}

步骤 3:用条件编译封装扩展逻辑

 

 

为了便于开关自定义打印,新增全局宏CONFIG_MY_BOARD_CUSTOM_BDINFO

 

 

  •  
  •  
  •  
  •  
  •  
  •  
#ifdef CONFIG_MY_BOARD_CUSTOM_BDINFO    // 自定义打印逻辑    print_board_version("Board Ver", gd->arch.board_version);    print_pmic_voltage("PMIC Core", core_volt);    print_custom_reserve_mem("Secure Area"0x900000000x100000);#endif

然后在板卡的configs/my_board_defconfig 中添加:

 

 

  •  
CONFIG_MY_BOARD_CUSTOM_BDINFO=y

四、实战 3:私有定制——适配自研调试工具

 

 

原厂bdinfo 输出是纯文本,如果需要对接自研的调试解析工具(如自动解析参数的脚本),可以定制输出格式(如 JSON、固定分隔符)。

 

 

适用场景

 

 

bdinfo 输出 JSON 格式,便于上位机脚本解析内存、波特率、自定义硬件版本等信息。

 

 

定制步骤

 

 

步骤 1:修改核心打印函数为 JSON 格式

 

 

print_num 为例,修改为 JSON 键值对格式:

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
__maybe_unusedstatic void print_num(const char *name, ulong value){    // 原厂格式:printf("%-12s= 0x%08lXn", name, value);    // 定制为JSON格式(注意逗号分隔,最后一个字段无逗号)printf("  "%s": "0x%08lX",n", name, value);}// 同步修改自定义打印函数为JSON格式__maybe_unusedstatic void print_board_version(const char *name, u32 version){printf("  "%s": "V%02d.%02d"n", name, (version>>8)&0xFF, version&0xFF);}

步骤 2:包裹整体输出为 JSON 结构

 

 

do_bdinfo 函数开头/结尾添加 JSON 首尾标识:

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
static int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc,char * const argv[]){bd_t *bd = gd->bd;    // JSON开头    printf("{n");print_num("arch_number",bd->bi_arch_number);print_bi_boot_params(bd);print_bi_dram(bd);    // ... 其余打印逻辑(含自定义)    print_board_version("Board Ver", gd->arch.board_version);    // JSON结尾    printf("}n");return 0;}

定制后输出效果

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
{  "arch_number": "0x00000000",  "boot_params": "0x80000100",  "DRAM bank": "0x00000000",  "-> start": "0x80000000",  "-> size": "0x10000000",  "Board Ver": "V01.02"}

五、定制扩展的最佳实践

 

 

1.优先用条件编译,避免硬改:所有定制逻辑都用CONFIG_MY_BOARD_XXX 宏封装,便于不同板卡复用、开关;

 

 

2.复用原厂函数风格:新增打印函数时,对齐原厂的格式化规则(如%-12s 左对齐),保持输出可读性;

 

 

3.利用 __weak 函数扩展:如果需要修改架构级的核心逻辑(如 PPC 的 board_detail),优先用__weak 重写,而非直接修改原厂函数:

 

 

  •  
  •  
  •  
  •  
  •  
// 自研板卡重写board_detailvoid board_detail(void){    print_num("Custom Param"0x12345678);}

4.编译测试验证

 

 

编译:make my_board_defconfig && make,确保无编译错误;

 

 

烧录:将新 U-Boot 烧录到板卡;

 

 

验证:执行bdinfo 命令,检查打印内容是否符合预期。

 

 

六、总结

 

 

bdinfo.c  U-Boot 板级调试的窗口,通过裁剪冗余代码、扩展自定义信息、定制输出格式,既能减小 U-Boot 镜像体积,又能让调试信息精准匹配自研板卡的需求。

 

 

核心要点回顾:

 

 

1.裁剪:聚焦自研板卡的硬件特性,删除无关打印,用宏控制开关;

 

 

2.扩展:复用原厂打印风格,新增自定义辅助函数,在对应架构的do_bdinfo 中调用;

 

 

3.定制:适配调试工具的输出格式(如 JSON),兼顾可读性和自动化解析。

 

 

掌握这些技巧,让bdinfo 通用工具变成贴合你自研板卡的专属调试助手

 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分