You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过xgdb实现主机镜像128*64嵌入式单色屏及修改目标端打印函数?

实现XMOS目标设备128*64单色屏的xgdb镜像调试方案

一、目标端代码实现

针对128*64单色显示屏,帧缓冲区大小为 128*64/8 = 1024字节(每字节存储8个单色像素)。以下两种方案可实现帧缓冲区的调试输出:

方案1:通过printf输出帧数据(无需xgdb内存访问权限)

添加调试专用的帧缓冲区dump函数,利用现有printf通道输出标准化格式的帧数据,方便主机端解析:

#include <stdio.h>
#include <stdint.h>

// 调试用帧缓冲区dump函数,输出带标记的十六进制帧数据
void fb_debug_dump(uint8_t *framebuffer, int width, int height) {
    const int byte_count = (width * height) / 8;
    // 帧数据起始标记,附带屏幕尺寸
    printf("[FB_START] %d %d\n", width, height);
    // 按每行16字节输出十六进制数据
    for (int i = 0; i < byte_count; i++) {
        printf("%02X", framebuffer[i]);
        if ((i + 1) % 16 == 0) printf("\n");
    }
    // 帧数据结束标记
    printf("\n[FB_END]\n");
}

在图形库的显示屏更新逻辑末尾调用fb_debug_dump(fb_ptr, 128, 64),即可在xgdb窗口输出帧数据。

方案2:直接让xgdb读取目标内存(更高效)

若帧缓冲区地址固定(或可通过符号获取),无需修改目标端代码,直接通过xgdb的内存访问功能读取。例如通过p &display_framebuffer命令获取帧缓冲区的地址。

二、主机端xgdb Python脚本优化

针对单色屏幕特性,优化AI提供的脚本,添加实时显示、日志记录功能,并适配xgdb的使用场景:

优化后的dump_fb.py

import gdb
from PIL import Image, ImageTk
import tkinter as tk
import datetime

# 全局变量:浮动显示窗口和日志文本框
fb_window = None
log_text = None

def init_windows():
    """初始化浮动显示窗口和日志窗口"""
    global fb_window, log_text
    # 帧缓冲镜像显示窗口
    fb_window = tk.Toplevel()
    fb_window.title("Display Mirror")
    # 日志记录窗口
    log_window = tk.Toplevel()
    log_window.title("FB Dump Log")
    log_text = tk.Text(log_window, width=60, height=20)
    log_text.pack(padx=5, pady=5)

def dump_framebuffer(addr, width=128, height=64, save_to_file=True):
    """读取目标端单色帧缓冲区,实现实时显示与日志记录"""
    byte_count = (width * height) // 8
    try:
        # 从目标内存读取帧缓冲原始数据
        mem = gdb.selected_inferior().read_memory(addr, byte_count)
        mem_bytes = bytes(mem)
        
        # 生成单色图像(适配1位像素格式)
        img = Image.new('1', (width, height))
        pixels = img.load()
        for y in range(height):
            for x in range(width):
                byte_idx = (y * width + x) // 8
                bit_idx = 7 - ((y * width + x) % 8)
                pixel_val = (mem_bytes[byte_idx] >> bit_idx) & 1
                # 根据显示屏极性调整黑白反转(此处1为黑色,0为白色)
                pixels[x, y] = 0 if pixel_val else 255
        
        # 在浮动窗口显示放大后的镜像
        if fb_window is None:
            init_windows()
        img_tk = ImageTk.PhotoImage(img.resize((width*2, height*2)))
        label = tk.Label(fb_window, image=img_tk)
        label.image = img_tk
        label.pack()
        
        # 记录dump日志
        timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        log_entry = f"[{timestamp}] Framebuffer dumped from 0x{addr:x}\n"
        if log_text:
            log_text.insert(tk.END, log_entry)
            log_text.see(tk.END)
        
        # 保存为单色PPM格式文件
        if save_to_file:
            filename = f"fb_{timestamp.replace(':', '_')}.ppm"
            with open(filename, "wb") as f:
                f.write(f"P5\n{width} {height}\n1\n".encode())
                f.write(mem_bytes)
            log_entry += f"  Saved to {filename}\n"
            if log_text:
                log_text.insert(tk.END, log_entry)
                log_text.see(tk.END)
                
    except Exception as e:
        error_msg = f"Error dumping framebuffer: {str(e)}\n"
        print(error_msg)
        if log_text:
            log_text.insert(tk.END, error_msg)
            log_text.see(tk.END)

# 注册xgdb自定义命令,简化调用
class DumpFBCommand(gdb.Command):
    """自定义xgdb命令:dump-fb <帧缓冲区地址> [宽度=128] [高度=64]"""
    def __init__(self):
        super(DumpFBCommand, self).__init__("dump-fb", gdb.COMMAND_USER)
    
    def invoke(self, args, from_tty):
        args = gdb.string_to_argv(args)
        if len(args) < 1:
            print("Usage: dump-fb <framebuffer_addr> [width=128] [height=64]")
            return
        addr = int(args[0], 16)
        width = int(args[1]) if len(args)>=2 else 128
        height = int(args[2]) if len(args)>=3 else 64
        dump_framebuffer(addr, width, height)

DumpFBCommand()

使用步骤

  1. 安装依赖:pip install pillow
  2. 在xgdb中加载脚本:source dump_fb.py
  3. 调用自定义命令:dump-fb 0xXXXXXX(替换为实际帧缓冲区地址)
  4. 自动弹出浮动显示窗口和日志窗口,实时查看屏幕镜像与dump记录

三、兼容性保障

  • 目标端:添加的fb_debug_dump为独立调试代码,可通过#ifdef DEBUG宏开关控制是否编译进生产版本,不依赖xgdb特定版本,无兼容性风险。
  • 主机端:脚本基于标准GDB Python API开发,xgdb作为GDB的衍生版本,完全兼容这些API,即使xgdb更新,只要保留GDB的Python扩展支持,脚本即可正常运行。

四、目标端主动控制输出

若需从目标端触发dump或切换输出模式,可通过以下方式实现:

  1. 目标端添加触发函数,输出标准化指令:
void fb_trigger_dump(int log_only) {
    // log_only=1仅记录日志,log_only=0显示+记录
    printf("[TRIGGER_FB_DUMP] %d\n", log_only);
}
  1. 主机端脚本添加输出监听,自动响应目标端指令:
# 添加xgdb输出监听,解析目标端触发指令
class FBOutputHandler:
    def handle_output(self, line):
        if "[TRIGGER_FB_DUMP]" in line:
            parts = line.split()
            log_only = int(parts[1]) if len(parts)>=2 else 0
            # 通过符号获取帧缓冲区地址
            addr = int(gdb.parse_and_eval("&display_framebuffer"))
            dump_framebuffer(addr, save_to_file=True, display=(log_only==0))
            return True
        return False

gdb.events.before_prompt.connect(FBOutputHandler().handle_output)

目标端调用fb_trigger_dump(0)即可主动触发主机端的屏幕镜像显示。


内容的提问来源于stack exchange,提问作者Øyvind Teig

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 21:44:49