作为嵌入式开发者,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:
staticinlinevoidprint_eth_ip_addr(void){// 只保留eth0,删除eth1-eth5的条件编译print_eth(0);printf("IP addr = %sn",env_get("ipaddr"));}
步骤2:删除Flash相关打印
如果板卡无Flash,直接注释/删除print_bi_flash函数的调用(以ARM架构的do_bdinfo为例):
staticintdo_bdinfo(cmd_tbl_t*cmdtp,intflag,intargc,char*constargv[]){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);// ... 原有逻辑保留// ... 其余逻辑不变}
步骤3:关闭LCD/VIDEO相关打印
如果板卡无显示模块,删除帧缓冲打印:
// 【裁剪】注释掉FB base打印// print_num("FB base ", gd->fb_base);
裁剪核心原则
•优先用条件编译宏(如CONFIG_MY_BOARD_NO_FLASH)封装裁剪逻辑,便于后续开关:
print_bi_flash(bd);
•只删除“打印调用”,不删除底层函数(如print_bi_flash),避免影响其他架构/板卡复用。
三、实战2:功能扩展——新增自定义板级信息打印
这是最常用的定制场景:比如打印自研板卡的硬件版本、PMIC电压、传感器ID、自定义保留内存区域等。
适用场景
自研ARM板卡需要打印:
1.硬件版本号(存储在gd全局变量的自定义字段);
2.PMIC(电源管理芯片)的工作电压;
3.自研的安全分区内存地址。
扩展步骤
步骤1:定义自定义辅助打印函数
在bdinfo.c中新增适配自定义信息的打印函数(复用原厂的格式化风格,保持一致性):
// 新增:打印硬件版本__maybe_unusedstaticvoidprint_board_version(constchar*name, u32 version){// 格式对齐原厂:左对齐12字符,后接版本号(十进制)printf("%-12s= V%02d.%02dn", name, (version>>8)&0xFF, version&0xFF);}// 新增:打印PMIC电压(单位:mV)__maybe_unusedstaticvoidprint_pmic_voltage(constchar*name, u32 voltage_mv){printf("%-12s= %d mVn", name, voltage_mv);}// 新增:打印自定义保留内存__maybe_unusedstaticvoidprint_custom_reserve_mem(constchar*name,ulongstart,ulongsize){print_num(name, start);print_num("-> size", size);}
步骤2:在对应架构的do_bdinfo中添加调用
以ARM架构为例,在do_bdinfo函数中新增自定义打印(建议放在原有打印逻辑的末尾,便于查看):
staticintdo_bdinfo(cmd_tbl_t*cmdtp,intflag,intargc,char*constargv[]){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",0x90000000,0x100000);print_baudrate();// ... 其余原有逻辑保留return0;}
步骤3:用条件编译封装扩展逻辑
为了便于开关自定义打印,新增全局宏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",0x90000000,0x100000);
然后在板卡的configs/my_board_defconfig中添加:
CONFIG_MY_BOARD_CUSTOM_BDINFO=y
四、实战3:私有定制——适配自研调试工具
原厂bdinfo输出是“纯文本”,如果需要对接自研的调试解析工具(如自动解析参数的脚本),可以定制输出格式(如JSON、固定分隔符)。
适用场景
让bdinfo输出JSON格式,便于上位机脚本解析内存、波特率、自定义硬件版本等信息。
定制步骤
步骤1:修改核心打印函数为JSON格式
以print_num为例,修改为JSON键值对格式:
__maybe_unusedstaticvoidprint_num(constchar*name, ulong value){// 原厂格式:printf("%-12s= 0x%08lXn", name, value);// 定制为JSON格式(注意逗号分隔,最后一个字段无逗号)printf(" "%s": "0x%08lX",n", name, value);}// 同步修改自定义打印函数为JSON格式__maybe_unusedstaticvoidprint_board_version(constchar*name, u32 version){printf(" "%s": "V%02d.%02d"n", name, (version>>8)&0xFF, version&0xFF);}
步骤2:包裹整体输出为JSON结构
在do_bdinfo函数开头/结尾添加JSON首尾标识:
staticintdo_bdinfo(cmd_tbl_t*cmdtp,intflag,intargc,char*constargv[]){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");return0;}
定制后输出效果
{"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_detailvoidboard_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从“通用工具”变成贴合你自研板卡的“专属调试助手”!
-
嵌入式
+关注
关注
5209文章
20625浏览量
336764 -
u-boot
+关注
关注
0文章
135浏览量
39920 -
命令
+关注
关注
5文章
758浏览量
23914
发布评论请先 登录
嵌入式系统中U-Boot 基本特点及其移植方法
嵌入式系统中U-Boot 基本特点及其移植方法
U-Boot的启动及移植分析
嵌入式U-BOOT的启动流程及移植
基于u-boot的嵌入式系统实验板BSP研究
U-Boot在基于BF561的嵌入式Linux系统上的移植
u-boot学习指南
嵌入式Linux开发实用教程(试用)
如何在U-Boot中实现对Yaffs镜像的设计?
嵌入式Linux系统移植开发-(1)基于Yocto构建嵌入式u-boot,内核,文件系统
U-Boot架构浅析
创建自定义的u-boot命令
tiny4412编译与移植U-Boot
玩转U-Boot bdinfo:嵌入式bsp开发者的定制、扩展与裁剪实战指南
评论