“U-Boot - How to debug”的版本间的差异
(未显示同一用户的2个中间版本) | |||
第10行: | 第10行: | ||
默认情况下,U-Boot使用的宏 (debug(), pr_debug()...)不打印任何跟踪;要激活特定文件上的调试跟踪,需要启用 '''DEBUG''' 编译标志并更改文件的LOGLEVEL: | 默认情况下,U-Boot使用的宏 (debug(), pr_debug()...)不打印任何跟踪;要激活特定文件上的调试跟踪,需要启用 '''DEBUG''' 编译标志并更改文件的LOGLEVEL: | ||
− | * | + | * 在<file>.c文件包含任何之前定义调试 |
#define DEBUG | #define DEBUG | ||
#undef CONFIG_LOGLEVEL | #undef CONFIG_LOGLEVEL | ||
#define CONFIG_LOGLEVEL 8 | #define CONFIG_LOGLEVEL 8 | ||
− | * | + | * 使用 Makefile |
CFLAGS_<file>.o+= -DDEBUG -DCONFIG_LOGLEVEL=8 | CFLAGS_<file>.o+= -DDEBUG -DCONFIG_LOGLEVEL=8 | ||
第31行: | 第31行: | ||
== Debug with GDB == | == Debug with GDB == | ||
− | + | 在OpenSTLinux中,可以直接使用GDB脚本Setup.gdb: | |
* [[GDB#U-Boot_execution_phase]] | * [[GDB#U-Boot_execution_phase]] | ||
* [[GDB#U-Boot_boot_case]] | * [[GDB#U-Boot_boot_case]] | ||
− | + | 或者对于手动GDB连接,您需要: | |
− | # | + | # 获取U-Boot和/或SPL的[[U-Boot_overview#Output_files|elf files]] <br/>(构建目录中提供了u-boot和u-boot-spl) |
− | # | + | # 将[[GDB]]连接到目标 |
− | # | + | # 使用 gdb{{Highlight|"monitor reset halt"}}命令'''reset with attach'''复位目标:<br/>在ROM代码中或在FSBL执行开始时停止执行。 |
− | # | + | # 加载二进制文件的符号,以便在下一章中用可用的命令进行调试:<br/>[[#Load U-Boot symbol]], [[#Load SPL symbol]], [[#Load SPL code and debug]] |
− | # | + | # 使用 {{Highlight|"continue"}} 命令开始执行。 |
=== Load U-Boot symbol === | === Load U-Boot symbol === | ||
− | + | 使用[[U-Boot_overview#U-Boot_phases|U-Boot relocation]]时,符号更难加载。 | |
− | + | 请参阅 https://www.denx.de/wiki/DULG/DebuggingUBoot | |
− | + | 如果在运行的目标上连接GDB,则可以加载调试符号: | |
− | * | + | * 在使用 {{Highlight|"symbol-file"}} 命令进行重定位之前: |
{{GDB$}} {{Highlight|symbol-file u-boot}} | {{GDB$}} {{Highlight|symbol-file u-boot}} | ||
− | * | + | * 使用{{Highlight|"add-symbol-file"}} 命令重定位后,使用代码 offset = gd->relocaddr 重定位该符号: |
{{GDB$}} symbol-file u-boot {{Highlight|--> only for "gd_t" definition}} | {{GDB$}} symbol-file u-boot {{Highlight|--> only for "gd_t" definition}} | ||
{{GDB$}} set $offset = ((gd_t *)$r9)->relocaddr {{Highlight|--> get relocation offset}} | {{GDB$}} set $offset = ((gd_t *)$r9)->relocaddr {{Highlight|--> get relocation offset}} | ||
第59行: | 第59行: | ||
{{GDB$}} {{Highlight|add-symbol-file u-boot $offset}} | {{GDB$}} {{Highlight|add-symbol-file u-boot $offset}} | ||
− | + | 以下GDB示例脚本在{{Highlight|"monitor reset halt"}} 命令之后,在为编程板重定位前后自动加载U-Boot符号: | |
{{GDB$}} thbreak *0xC0100000 | {{GDB$}} thbreak *0xC0100000 | ||
第77行: | 第77行: | ||
> end | > end | ||
− | + | 当通过U-Boot入口点(CONFIG_SYS_TEXT_BASE = 0xC0100000)处的FSBL=TF-A或SPL将U-Boot代码加载到DDR中时,此脚本使用临时硬件断点{{Highlight|"thbreak"}} 加载符号。 | |
− | + | 它只允许在执行代码时加载符号,以避免在DDR初始化之前访问DDR。 | |
− | |||
− | |||
=== Load SPL symbol === | === Load SPL symbol === | ||
− | + | 要在闪存设备上使用GDB调试SPL,ROM代码加载二进制文件,GDB脚本只加载SPL符号: | |
{{GDB$}} symbol-file u-boot-spl | {{GDB$}} symbol-file u-boot-spl | ||
第89行: | 第87行: | ||
=== Load SPL code and debug === | === Load SPL code and debug === | ||
− | + | 有时,您需要在未编程的目标上调试SPL执行(例如,用于电路板启动),因此您可以使用GDB将SPL代码加载到嵌入式RAM中并执行。 | |
− | + | 在ROM代码中停止执行时,您需要执行{{Highlight|"load"}}命令,具体取决于 [[U-Boot_overview#Device_tree|U-Boot device tree]] 中定义的编译标志来加载SPL代码和关联的设备树: | |
− | * CONFIG_OF_SEPARATE = dtb | + | * CONFIG_OF_SEPARATE = dtb 附加在代码末尾,不存在于elf文件中(默认配置) |
{{GDB$}} file u-boot-spl | {{GDB$}} file u-boot-spl | ||
第100行: | 第98行: | ||
{{GDB$}} restore spl/dt.dtb binary $dtb | {{GDB$}} restore spl/dt.dtb binary $dtb | ||
− | * CONFIG_OF_EMBED = dtb | + | * CONFIG_OF_EMBED = dtb 嵌入elf文件中(调试配置) |
{{GDB$}} file u-boot-spl | {{GDB$}} file u-boot-spl | ||
第107行: | 第105行: | ||
=== Debug the first SPL instructions === | === Debug the first SPL instructions === | ||
− | + | 有时,在第一条指令之后,gdb命令 "monitor reset halt" 会停止SPL代码的执行。 | |
− | + | 要调试这部分代码,可以修改代码:在SPL代码中添加一个无限循环以等待gdb连接。 | |
− | + | 例如,在{{CodeSource | U-Boot | arch/arm/mach-stm32mp/spl.c}}中 : | |
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
第127行: | 第125行: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | 当连接gdb并加载SPL符号时,无限循环会因以下原因中断: | |
{{GDB$}} set var stop=1 | {{GDB$}} set var stop=1 | ||
− | + | 您可以通过gdb命令调试SPL first指令。 | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− |
2020年11月3日 (二) 15:07的最新版本
目录
Debug with console
跟踪和错误在设备树的chosen 节点中通过 stdout-path 字段定义的控制台上可用,例如在serial0 = uart4上:
chosen { stdout-path = " serial0:115200n8"; }; aliases { serial0 = &uart4; };
默认情况下,U-Boot使用的宏 (debug(), pr_debug()...)不打印任何跟踪;要激活特定文件上的调试跟踪,需要启用 DEBUG 编译标志并更改文件的LOGLEVEL:
- 在<file>.c文件包含任何之前定义调试
#define DEBUG #undef CONFIG_LOGLEVEL #define CONFIG_LOGLEVEL 8
- 使用 Makefile
CFLAGS_<file>.o+= -DDEBUG -DCONFIG_LOGLEVEL=8
如果在配置控制台之前(在执行U-Boot的第一阶段)U-Boot失败,则跟踪不可用。
在这种情况下,您需要:
- 用GDB调试 (请参阅下一章)
或,
- 激活调试UART功能:
- 在U-Boot configuration的defconfig中添加
- CONFIG_DEBUG_UART
- CONFIG_DEBUG_UART_STM32
- adpat 这个函数 board_debug_uart_init(): 在通过U-Boot驱动程序初始化之前配置所需的资源 (pad, clock)。
此功能需要针对您的主板进行调整。
- 在U-Boot configuration的defconfig中添加
Debug with GDB
在OpenSTLinux中,可以直接使用GDB脚本Setup.gdb:
或者对于手动GDB连接,您需要:
- 获取U-Boot和/或SPL的elf files
(构建目录中提供了u-boot和u-boot-spl) - 将GDB连接到目标
- 使用 gdb"monitor reset halt"命令reset with attach复位目标:
在ROM代码中或在FSBL执行开始时停止执行。 - 加载二进制文件的符号,以便在下一章中用可用的命令进行调试:
#Load U-Boot symbol, #Load SPL symbol, #Load SPL code and debug - 使用 "continue" 命令开始执行。
Load U-Boot symbol
使用U-Boot relocation时,符号更难加载。
请参阅 https://www.denx.de/wiki/DULG/DebuggingUBoot
如果在运行的目标上连接GDB,则可以加载调试符号:
- 在使用 "symbol-file" 命令进行重定位之前:
(gdb) symbol-file u-boot
- 使用"add-symbol-file" 命令重定位后,使用代码 offset = gd->relocaddr 重定位该符号:
(gdb) symbol-file u-boot --> only for "gd_t" definition (gdb) set $offset = ((gd_t *)$r9)->relocaddr --> get relocation offset (gdb) symbol-file --> clear previous symbol (gdb) add-symbol-file u-boot $offset
以下GDB示例脚本在"monitor reset halt" 命令之后,在为编程板重定位前后自动加载U-Boot符号:
(gdb) thbreak *0xC0100000 (gdb) commands > symbol-file u-boot > thbreak relocate_code > commands > print "RELOCATE U-Boot..." > set $offset = ((gd_t *)$r9)->relocaddr > print $offset > symbol-file > add-symbol-file u-boot $offset > thbreak boot_jump_linux > continue > end > continue > end
当通过U-Boot入口点(CONFIG_SYS_TEXT_BASE = 0xC0100000)处的FSBL=TF-A或SPL将U-Boot代码加载到DDR中时,此脚本使用临时硬件断点"thbreak" 加载符号。 它只允许在执行代码时加载符号,以避免在DDR初始化之前访问DDR。
Load SPL symbol
要在闪存设备上使用GDB调试SPL,ROM代码加载二进制文件,GDB脚本只加载SPL符号:
(gdb) symbol-file u-boot-spl
Load SPL code and debug
有时,您需要在未编程的目标上调试SPL执行(例如,用于电路板启动),因此您可以使用GDB将SPL代码加载到嵌入式RAM中并执行。
在ROM代码中停止执行时,您需要执行"load"命令,具体取决于 U-Boot device tree 中定义的编译标志来加载SPL代码和关联的设备树:
- CONFIG_OF_SEPARATE = dtb 附加在代码末尾,不存在于elf文件中(默认配置)
(gdb) file u-boot-spl (gdb) load (gdb) set $dtb = __bss_end (gdb) restore spl/dt.dtb binary $dtb
- CONFIG_OF_EMBED = dtb 嵌入elf文件中(调试配置)
(gdb) file u-boot-spl (gdb) load
Debug the first SPL instructions
有时,在第一条指令之后,gdb命令 "monitor reset halt" 会停止SPL代码的执行。
要调试这部分代码,可以修改代码:在SPL代码中添加一个无限循环以等待gdb连接。
例如,在arch/arm/mach-stm32mp/spl.c| |}} arch/arm/mach-stm32mp/spl.c 中 :
void board_init_f(ulong dummy)
{
struct udevice *dev;
int ret;
/* volatile is needed to avoid gcc optimization */
volatile int stop = 0;
/* infinite debug loop */
while ( !stop ) ;
arch_cpu_init();
当连接gdb并加载SPL符号时,无限循环会因以下原因中断:
(gdb) set var stop=1
您可以通过gdb命令调试SPL first指令。