bin2bmp 工具¶
工具简介¶
bin2bmp 是一个把显存原始二进制数据直接还原为 BMP 图片的调试小工具,常用于以下场景:
屏幕显示异常时,直接查看 LVGL 实际写入 framebuffer 的内容,确认问题出在 LVGL 渲染 还是 LCD 驱动/屏本身
没有截屏接口的板子上,把当前屏幕内容"抓"出来作为图片保存
验证双 buffer 切换、部分刷新(partial refresh)等逻辑是否符合预期
工具位于 SDK 的 tools/bin2bmp/ 目录下,包含三个文件:
文件 |
作用 |
|---|---|
|
BMP 图片生成与像素格式转换的核心库 |
|
离线方式:把已有的 |
|
在线方式:通过 J-Link 直接从板子内存 dump framebuffer,再转 BMP |
工作原理¶
整个流程可以理解为"内存 → bin 文件 → BMP 图片"两步:
┌──────────┐ J-Link/SWD ┌────────────┐ bin2bmp ┌─────────┐
│ 板子内存 │ ────────────▶ │ xxx.bin │ ──────────▶ │ xxx.bmp │
│ framebuffer│ (savebin) │ (原始数据) │ (像素解码) │ (图片) │
└──────────┘ └────────────┘ └─────────┘
jlinkbin2bmp.py一键完成上面两步:先调用JLink.exe的savebin命令把指定地址的内存保存为.bin,再调用bmp.py把.bin解码成.bmp并自动打开bin2bmp.py只做第二步,用于已经手上已经有.bin文件的情况(比如之前 dump 下来的、或别人发过来的)
支持的颜色格式¶
工具支持 framebuffer 中常见的像素格式,必须与当前工程实际使用的格式一致,否则解出来的图会是杂色条纹。
格式 |
位深 (bit) |
每像素字节数 |
说明 |
|---|---|---|---|
|
8 |
1 |
8 位 alpha,单色(默认红色)加透明度 |
|
4 |
0.5 |
4 位 alpha,2 像素/字节 |
|
2 |
0.25 |
2 位 alpha,4 像素/字节 |
|
8 |
1 |
R3G3B2 |
|
16 |
2 |
R5G6B5 |
|
16 |
2 |
B5G6R5 |
|
24 |
3 |
A8 + R5G6B5 |
|
24 |
3 |
R8G8B8 |
|
32 |
4 |
A8R8G8B8 |
|
32 |
4 |
R8G8B8A8 |
|
16 |
2 |
YUV 4:2:2 packed (Y0 U Y1 V) |
|
16 |
2 |
YUV 4:2:2 packed (U Y0 V Y1) |
使用准备¶
Python 3:直接
python xxx.py即可运行,无需安装额外依赖(只用标准库)J-Link:使用
jlinkbin2bmp.py时需要安装 SEGGER J-Link 并保证JLink.exe在 PATH 中板子已通过 SWD 连接 J-Link,并且固件处于运行状态
下面以 SDK 自带的 example/multimedia/lvgl/watch 例程(板型 sf32lb58-lcd_a128r32n1,屏幕 390×450,RGB888)为例,完整走一遍流程。
方式一(推荐):jlinkbin2bmp.py 在线 dump¶
这是最常用的方式,一条命令搞定,dump 完成后会自动打开生成的 BMP。
步骤 1:从 map 文件找到 framebuffer 地址¶
编译完成后,在工程的 build 目录下会生成 main.map,里面记录了所有全局/静态变量的链接地址。framebuffer 变量命名规则如下:
变量名 |
位置 |
用途 |
|---|---|---|
|
L1 SRAM(0x2000xxxx) |
LVGL 部分刷新用的绘制 buffer,高度由 |
|
L2 PSRAM(0x62xxxxxx) |
全屏 framebuffer,用于 RAMLESS 屏或 |
想看"屏幕上完整的画面",应该 dump
buf2_1/buf2_2;buf1_x只是 LVGL 的绘制 staging buffer,只能看到当前正在刷新的几行。
在 watch 例程的 main.map 中搜索 frambuf 关键字,可以看到:
.bss.l1_non_ret_bss_frambuf
0x2000ef50 0x3ed78 .../middleware/lvgl/lv_drivers/lv_lcd.o
...
.bss.l2_non_ret_bss_anim_frambuf
0x62000000 0x101148 .../middleware/lvgl/app_mem.o
*fill* 0x62101148 0x38
.bss.l2_non_ret_bss_frambuf
0x62101180 0x101164 .../middleware/lvgl/lv_drivers/lv_lcd.o
解读:
buf2_1 起始地址 =
0x62101180(l2_non_ret_bss_frambuf 段的起始地址就是 buf2_1)段总大小 0x101164 = 1053028 字节 ≈ 2 个 390×450×3 的全屏 buffer 加对齐填充
buf2_2 紧跟在 buf2_1 之后(64 字节对齐),偏移 =
ALIGN(390*450*3, 64)= 0x808C0,因此 buf2_2 =0x62101180 + 0x808C0=0x62181A40
备注
不同工程、不同屏幕分辨率、不同颜色格式,地址都不一样。每次重新编译后地址都可能变化,请以当前 build 目录下最新的 main.map 为准。
步骤 2:确认颜色格式和分辨率¶
打开 build 目录下的 .config 文件,搜索以下关键字:
CONFIG_LCD_HOR_RES_MAX=390 # 屏幕水平分辨率
CONFIG_LCD_VER_RES_MAX=450 # 屏幕垂直分辨率
CONFIG_LV_COLOR_DEPTH_24=y # 24bit = RGB888,每像素 3 字节
# CONFIG_LV_COLOR_DEPTH_16 is not set
LV_COLOR_DEPTH |
对应 jlinkbin2bmp 颜色格式参数 |
|---|---|
16 |
|
24 |
|
32 |
|
本例:分辨率 390×450,颜色格式 rgb888。
步骤 3:执行 dump 命令¶
进入 SDK 的 tools/bin2bmp/ 目录,执行:
cd tools/bin2bmp
python jlinkbin2bmp.py "-if SWD -speed 12000" rgb888 390 450 62101180
参数说明:
参数 |
含义 |
|---|---|
第 1 个参数 |
传给 J-Link 的连接参数,本地 USB 连接用 |
第 2 个参数 |
颜色格式(小写) |
第 3 / 4 个参数 |
宽 / 高(像素) |
第 5 个参数 |
framebuffer 起始地址(十六进制,不带 |
执行过程会输出 J-Link 的连接日志,最后 Reading 526500 bytes from addr 0x62101180 into file...O.K. 表示 dump 成功,随后脚本会自动调用系统默认图片查看器打开生成的 BMP。
步骤 4:查看结果¶
下面两张图就是跑 example/multimedia/lvgl/watch 例程的板子,依次 dump buf2_1 和 buf2_2 拿到的结果——正是手表 demo 的主菜单界面:
图 1 buf2_1(地址 0x62101180)内容:手表主菜单¶
图 2 buf2_2(地址 0x62181A40)内容:与 buf2_1 一致(静态画面时双 buffer 内容相同)¶
备注
静态画面下两个 buffer 内容一致;动画/滑动过程中两个 buffer 会一新一旧交替,这是正常现象,正好可以用这个工具观察双 buffer 切换时机。
方式二:bin2bmp.py 离线转换¶
如果手上已经有 dump 好的 .bin 文件(比如之前保存的、或同事发过来的),直接用 bin2bmp.py 转换:
python bin2bmp.py hcpu_ram.bin rgb565 454 454 2000
参数说明:
参数 |
含义 |
|---|---|
第 1 个参数 |
bin 文件路径 |
第 2 个参数 |
颜色格式 |
第 3 / 4 个参数 |
宽 / 高(像素) |
第 5 个参数(可选) |
偏移量(十六进制字符串,如 |
生成的 BMP 文件名格式为 <bin文件名>_offset0x<偏移>_<宽>x<高>_<格式>.bmp,会自动用系统默认看图工具打开。
常见问题¶
解出来全是杂色条纹¶
颜色格式填错:例如实际是 RGB565 却填了 rgb888,每像素字节数对不上,整个画面会错乱。请回到
.config确认LV_COLOR_DEPTH分辨率填错:宽高任意一个不对都会出现斜条纹。请确认
.config中的LCD_HOR_RES_MAX/LCD_VER_RES_MAX
图像整体左右/上下偏移¶
地址没对准 buffer 起始地址:检查 map 文件中的地址是否抄错;如果 dump 的是 buf2_2,要确认是否算上了 64 字节对齐的填充
解出来全黑 / 全白 / 全 0¶
该 buffer 当前没有被使用。比如工程配置为单 buffer(
LV_FB_ONE_NOT_SCREEN_SIZE),buf1_2就不存在;或双 buffer 中当前只有一块在被刷新屏幕当前确实显示纯黑/纯白画面(比如息屏、启动 logo 阶段)
图像上下颠倒¶
BMP 文件本身按"底向上"存储像素,工具已经做了翻转处理。如果仍然颠倒,多半是把部分 buffer 的高度填错了,请检查 LV_FB_LINE_NUM 与实际使用方式。
J-Link 连接失败¶
检查 SWD 连线、板子是否上电
检查是否有其他程序(Ozone、J-Flash、Keil 调试器等)占用了 J-Link
远程场景下确认 UsartServer 已启动并监听对应端口
提示与技巧¶
想看动画中间帧:在动画播放过程中执行 dump,buf2_1 和 buf2_2 的内容会不一样,分别代表"正在显示的"和"正在绘制的"那一帧
想看部分刷新区域:dump
buf1_1(高度为LV_FB_LINE_NUM行),可以看到 LVGL 当前正在合成的那一段画面批量保存分析:
jlinkbin2bmp.py每次都会生成<地址>_<宽>x<高>_<格式>.bmp,文件名自带参数,方便归档对比
相关工具¶
SFTool —— 烧录与串口日志
UsartServer —— UART 转 J-Link 远程调试(56x/52x 平台)
图形转换工具 —— 离线图片/视频资源转换