First commit with working display
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
import gdb
|
||||
|
||||
from .core import DumpObj
|
||||
from .display import DumpDisplayBuf
|
||||
from .draw import InfoDrawUnit
|
||||
from .misc import InfoStyle, DumpCache
|
||||
from .debugger import Debugger
|
||||
from .drivers import Lvglobal
|
||||
|
||||
__all__ = []
|
||||
|
||||
# Set pagination off and python print-stack full
|
||||
gdb.execute("set pagination off")
|
||||
gdb.write("set pagination off\n")
|
||||
gdb.execute("set python print-stack full")
|
||||
gdb.write("set python print-stack full\n")
|
||||
|
||||
|
||||
# Debugger
|
||||
Debugger()
|
||||
|
||||
# Dumps
|
||||
DumpObj()
|
||||
DumpDisplayBuf()
|
||||
DumpCache()
|
||||
|
||||
# Infos
|
||||
InfoStyle()
|
||||
InfoDrawUnit()
|
||||
|
||||
# Drivers
|
||||
Lvglobal()
|
||||
@@ -0,0 +1,5 @@
|
||||
from .lv_obj import DumpObj
|
||||
|
||||
__all__ = [
|
||||
"DumpObj",
|
||||
]
|
||||
@@ -0,0 +1,64 @@
|
||||
import argparse
|
||||
import gdb
|
||||
|
||||
from lvglgdb.lvgl import curr_inst
|
||||
from lvglgdb.lvgl import LVObject, dump_obj_info
|
||||
from lvglgdb.value import Value
|
||||
|
||||
|
||||
class DumpObj(gdb.Command):
|
||||
"""dump obj tree from specified obj"""
|
||||
|
||||
def __init__(self):
|
||||
super(DumpObj, self).__init__(
|
||||
"dump obj", gdb.COMMAND_USER, gdb.COMPLETE_EXPRESSION
|
||||
)
|
||||
|
||||
def dump_obj(self, obj: LVObject, depth=0, limit=None):
|
||||
if not obj:
|
||||
return
|
||||
|
||||
# dump self
|
||||
print(" " * depth, end="")
|
||||
dump_obj_info(obj)
|
||||
|
||||
if limit is not None and depth >= limit:
|
||||
return
|
||||
|
||||
# dump children
|
||||
for child in obj.children:
|
||||
self.dump_obj(child, depth + 1, limit=limit)
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
parser = argparse.ArgumentParser(description="Dump lvgl obj tree.")
|
||||
parser.add_argument(
|
||||
"-L",
|
||||
"--level",
|
||||
type=int,
|
||||
default=None,
|
||||
help="Limit the depth of the tree.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"root",
|
||||
type=str,
|
||||
nargs="?",
|
||||
default=None,
|
||||
help="Optional root obj to dump.",
|
||||
)
|
||||
try:
|
||||
args = parser.parse_args(gdb.string_to_argv(args))
|
||||
except SystemExit:
|
||||
return
|
||||
|
||||
if args.root:
|
||||
root = gdb.parse_and_eval(args.root)
|
||||
root = LVObject(Value(root))
|
||||
self.dump_obj(root, limit=args.level)
|
||||
else:
|
||||
# dump all displays
|
||||
depth = 0
|
||||
for disp in curr_inst().displays():
|
||||
print(f"Display {hex(disp)}")
|
||||
for screen in disp.screens:
|
||||
print(f'{" " * (depth + 1)}Screen@{hex(screen)}')
|
||||
self.dump_obj(screen, depth=depth + 1, limit=args.level)
|
||||
@@ -0,0 +1,75 @@
|
||||
import argparse
|
||||
|
||||
import gdb
|
||||
|
||||
|
||||
class Debugger(gdb.Command):
|
||||
"""Start debugpy server or connect to a debug server, so we can debug python code from IDE like PyCharm/VSCode"""
|
||||
|
||||
def __init__(self, host="localhost", port=11451):
|
||||
self.__host = host
|
||||
self.__port = port
|
||||
super().__init__("debugger", gdb.COMMAND_USER)
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
parser = argparse.ArgumentParser(description=Debugger.__doc__)
|
||||
parser.add_argument(
|
||||
"--host",
|
||||
type=str,
|
||||
help="Server listening host",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-p",
|
||||
"--port",
|
||||
type=int,
|
||||
help="Server listening port",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-t",
|
||||
"--type",
|
||||
choices=["pycharm", "vscode", "eclipse"],
|
||||
help="Debugger type",
|
||||
required=True,
|
||||
)
|
||||
|
||||
try:
|
||||
args = parser.parse_args(gdb.string_to_argv(args))
|
||||
except SystemExit:
|
||||
return
|
||||
|
||||
if args.host:
|
||||
self.__host = args.host
|
||||
|
||||
if args.port:
|
||||
self.__port = args.port
|
||||
|
||||
if args.type == "pycharm":
|
||||
self.connect_to_pycharm()
|
||||
elif args.type == "vscode":
|
||||
self.connect_to_vscode()
|
||||
elif args.type == "eclipse":
|
||||
self.connect_to_eclipse()
|
||||
|
||||
def connect_to_pycharm(self):
|
||||
try:
|
||||
import pydevd_pycharm
|
||||
except ImportError:
|
||||
print("pydevd_pycharm module not found. Please install it using pip.")
|
||||
return
|
||||
|
||||
pydevd_pycharm.settrace(
|
||||
self.__host, port=self.__port, stdoutToServer=True, stderrToServer=True
|
||||
)
|
||||
|
||||
def connect_to_vscode(self):
|
||||
try:
|
||||
import debugpy
|
||||
except ImportError:
|
||||
print("debugpy module not found. Please install it using pip.")
|
||||
return
|
||||
|
||||
debugpy.listen((self.__host, self.__port))
|
||||
debugpy.wait_for_client()
|
||||
|
||||
def connect_to_eclipse(self):
|
||||
print("Eclipse is not implemented yet")
|
||||
@@ -0,0 +1,5 @@
|
||||
from .lv_display import DumpDisplayBuf
|
||||
|
||||
__all__ = [
|
||||
"DumpDisplayBuf",
|
||||
]
|
||||
@@ -0,0 +1,54 @@
|
||||
import argparse
|
||||
import gdb
|
||||
|
||||
from lvglgdb.lvgl import curr_inst
|
||||
from lvglgdb.lvgl import LVDrawBuf
|
||||
|
||||
|
||||
class DumpDisplayBuf(gdb.Command):
|
||||
"""dump display buf to image"""
|
||||
|
||||
def __init__(self):
|
||||
super(DumpDisplayBuf, self).__init__(
|
||||
"dump display", gdb.COMMAND_USER, gdb.COMPLETE_EXPRESSION
|
||||
)
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
parser = argparse.ArgumentParser(description="Dump display draw buffer.")
|
||||
parser.add_argument(
|
||||
"-p",
|
||||
"--prefix",
|
||||
type=str,
|
||||
default="",
|
||||
help="prefix of dump file path",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-f",
|
||||
"--format",
|
||||
type=str,
|
||||
choices=["bmp", "png"],
|
||||
default=None,
|
||||
help="dump file format (bmp or png)",
|
||||
)
|
||||
|
||||
try:
|
||||
args = parser.parse_args(gdb.string_to_argv(args))
|
||||
except SystemExit:
|
||||
return
|
||||
|
||||
display = curr_inst().disp_default()
|
||||
if not display:
|
||||
print("Error: Invalid display pointer")
|
||||
return
|
||||
buffers = {
|
||||
"buf_1": display.buf_1,
|
||||
"buf_2": display.buf_2,
|
||||
}
|
||||
|
||||
for buf_name, buf_ptr in buffers.items():
|
||||
if buf_ptr is not None:
|
||||
draw_buf = LVDrawBuf(buf_ptr)
|
||||
filename = f"{args.prefix}{buf_name}.{args.format.lower() if args.format else 'bmp'}"
|
||||
draw_buf.data_dump(filename, args.format)
|
||||
else:
|
||||
print(f"Warning: {buf_name} buffer is None, skipping.")
|
||||
@@ -0,0 +1,5 @@
|
||||
from .lv_draw import InfoDrawUnit
|
||||
|
||||
__all__ = [
|
||||
"InfoDrawUnit",
|
||||
]
|
||||
@@ -0,0 +1,50 @@
|
||||
import gdb
|
||||
|
||||
from lvglgdb.value import Value
|
||||
from lvglgdb.lvgl import curr_inst
|
||||
|
||||
|
||||
class InfoDrawUnit(gdb.Command):
|
||||
"""dump draw unit info"""
|
||||
|
||||
def __init__(self):
|
||||
super(InfoDrawUnit, self).__init__(
|
||||
"info draw_unit", gdb.COMMAND_USER, gdb.COMPLETE_EXPRESSION
|
||||
)
|
||||
|
||||
def dump_draw_unit(self, draw_unit: Value):
|
||||
# Dereference to get the string content of the name from draw_unit
|
||||
name = draw_unit.name.string()
|
||||
|
||||
# Print draw_unit information and the name
|
||||
print(f"Draw Unit: {draw_unit}, Name: {name}")
|
||||
|
||||
# Handle different draw_units based on the name
|
||||
def lookup_type(name):
|
||||
try:
|
||||
return gdb.lookup_type(name)
|
||||
except gdb.error:
|
||||
return None
|
||||
|
||||
types = {
|
||||
"DMA2D": lookup_type("lv_draw_dma2d_unit_t"),
|
||||
"NEMA_GFX": lookup_type("lv_draw_nema_gfx_unit_t"),
|
||||
"NXP_PXP": lookup_type("lv_draw_pxp_unit_t"),
|
||||
"NXP_VGLITE": lookup_type("lv_draw_vglite_unit_t"),
|
||||
"OPENGLES": lookup_type("lv_draw_opengles_unit_t"),
|
||||
"DAVE2D": lookup_type("lv_draw_dave2d_unit_t"),
|
||||
"SDL": lookup_type("lv_draw_sdl_unit_t"),
|
||||
"SW": lookup_type("lv_draw_sw_unit_t"),
|
||||
"VG_LITE": lookup_type("lv_draw_vg_lite_unit_t"),
|
||||
}
|
||||
|
||||
type = types.get(name, lookup_type("lv_draw_unit_t"))
|
||||
print(
|
||||
draw_unit.cast(type, ptr=True)
|
||||
.dereference()
|
||||
.format_string(pretty_structs=True, symbols=True)
|
||||
)
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
for unit in curr_inst().draw_units():
|
||||
self.dump_draw_unit(unit)
|
||||
@@ -0,0 +1,5 @@
|
||||
from .nuttx import Lvglobal
|
||||
|
||||
__all__ = [
|
||||
"Lvglobal",
|
||||
]
|
||||
@@ -0,0 +1,5 @@
|
||||
from .nuttx import Lvglobal
|
||||
|
||||
__all__ = [
|
||||
"Lvglobal",
|
||||
]
|
||||
@@ -0,0 +1,55 @@
|
||||
# GDB script to get lvgl global pointer in NuttX.
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
import gdb
|
||||
|
||||
|
||||
class Lvglobal(gdb.Command):
|
||||
"""Set which lvgl instance to inspect by finding lv_global pointer in task TLS data."""
|
||||
|
||||
def __init__(self):
|
||||
super(Lvglobal, self).__init__("lvglobal", gdb.COMMAND_USER)
|
||||
|
||||
def set_lvgl_instance(self, inst):
|
||||
from lvglgdb.lvgl import curr_inst
|
||||
|
||||
curr_inst().reset()
|
||||
curr_inst().ensure_init(inst)
|
||||
|
||||
def invoke(self, arg, from_tty):
|
||||
parser = argparse.ArgumentParser(description=self.__doc__)
|
||||
parser.add_argument("-p", "--pid", type=int, help="Optional process ID")
|
||||
try:
|
||||
args = parser.parse_args(gdb.string_to_argv(arg))
|
||||
except SystemExit:
|
||||
return
|
||||
try:
|
||||
from nxgdb import utils
|
||||
except ImportError:
|
||||
print("nxgdb is not installed, can't find lvgl global pointer.")
|
||||
return
|
||||
|
||||
lv_global = utils.gdb_eval_or_none("lv_global")
|
||||
if lv_global:
|
||||
print(f"Found single instance lv_global@{hex(lv_global.address)}")
|
||||
self.set_lvgl_instance(lv_global)
|
||||
return
|
||||
|
||||
# find the lvgl global pointer in tls
|
||||
if not args.pid:
|
||||
print("LVGL is in multi-process mode; please provide --pid.")
|
||||
return
|
||||
lv_key = utils.gdb_eval_or_none("lv_nuttx_tlskey")
|
||||
if lv_key is None:
|
||||
lv_key = utils.gdb_eval_or_none("lv_global_default::index")
|
||||
if lv_key is None:
|
||||
print("Can't find lvgl tls key in multi-process mode.")
|
||||
return
|
||||
lv_global = utils.get_task_tls(args.pid, lv_key)
|
||||
if lv_global:
|
||||
print(f"Found lv_global@{hex(lv_global)}")
|
||||
self.set_lvgl_instance(lv_global)
|
||||
else:
|
||||
print(f"\nCan't find lv_global with tlskey@{hex(lv_key)}.")
|
||||
@@ -0,0 +1,4 @@
|
||||
from .lv_style import InfoStyle
|
||||
from .lv_cache import DumpCache
|
||||
|
||||
__all__ = ["InfoStyle", "DumpCache"]
|
||||
@@ -0,0 +1,40 @@
|
||||
import argparse
|
||||
import gdb
|
||||
|
||||
|
||||
class DumpCache(gdb.Command):
|
||||
"""dump cache info for specified cache"""
|
||||
|
||||
def __init__(self):
|
||||
super(DumpCache, self).__init__(
|
||||
"dump cache", gdb.COMMAND_USER, gdb.COMPLETE_EXPRESSION
|
||||
)
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
parser = argparse.ArgumentParser(description="Dump lvgl cache info.")
|
||||
parser.add_argument(
|
||||
"cache",
|
||||
type=str,
|
||||
choices=["image", "image_header"],
|
||||
default="image",
|
||||
help="cache to dump.",
|
||||
)
|
||||
|
||||
from lvglgdb import curr_inst
|
||||
|
||||
try:
|
||||
args = parser.parse_args(gdb.string_to_argv(args))
|
||||
except SystemExit:
|
||||
return
|
||||
|
||||
cache = None
|
||||
if args.cache == "image":
|
||||
cache = curr_inst().image_cache()
|
||||
elif args.cache == "image_header":
|
||||
cache = curr_inst().image_header_cache()
|
||||
|
||||
if not cache:
|
||||
print("Invalid cache: ", args.cache)
|
||||
return
|
||||
|
||||
cache.print_entries()
|
||||
@@ -0,0 +1,40 @@
|
||||
import argparse
|
||||
import gdb
|
||||
|
||||
from lvglgdb.value import Value
|
||||
from lvglgdb.lvgl import LVObject
|
||||
from lvglgdb.lvgl import dump_style_info
|
||||
|
||||
|
||||
class InfoStyle(gdb.Command):
|
||||
"""dump obj style value for specified obj"""
|
||||
|
||||
def __init__(self):
|
||||
super(InfoStyle, self).__init__(
|
||||
"info style", gdb.COMMAND_USER, gdb.COMPLETE_EXPRESSION
|
||||
)
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
parser = argparse.ArgumentParser(description="Dump lvgl obj local style.")
|
||||
parser.add_argument(
|
||||
"obj",
|
||||
type=str,
|
||||
help="obj to show style.",
|
||||
)
|
||||
|
||||
try:
|
||||
args = parser.parse_args(gdb.string_to_argv(args))
|
||||
except SystemExit:
|
||||
return
|
||||
|
||||
obj = gdb.parse_and_eval(args.obj)
|
||||
if not obj:
|
||||
print("Invalid obj: ", args.obj)
|
||||
return
|
||||
|
||||
obj = Value(obj)
|
||||
|
||||
# show all styles applied to this obj
|
||||
for style in LVObject(obj).styles:
|
||||
print(" ", end="")
|
||||
dump_style_info(style)
|
||||
Reference in New Issue
Block a user