U-Boot - How to debug
目录
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指令。