“U-Boot - How to debug”的版本间的差异

来自百问网嵌入式Linux wiki
(创建页面,内容为“== Debug with console == Trace and error are available on the console defined in the '''chosen''' node of the device tree by the '''stdout-path''' field, for example…”)
 
第1行: 第1行:
 
== Debug with console ==
 
== Debug with console ==
Trace and error are available on the console defined in the '''chosen''' node of the device tree by the '''stdout-path''' field, for example on serial0=uart4:
+
跟踪和错误在设备树的'''chosen''' 节点中通过 '''stdout-path''' 字段定义的控制台上可用,例如在serial0 = uart4上:
  
 
   chosen {
 
   chosen {
第9行: 第9行:
 
   };
 
   };
  
By default, the macros used by U-Boot (debug(), pr_debug()...) do not print any trace; to activate the debug traces on a specific file, you need to enable the '''DEBUG''' compilation flag and change the LOGLEVEL for the file:
+
默认情况下,U-Boot使用的宏 (debug(), pr_debug()...)不打印任何跟踪;要激活特定文件上的调试跟踪,需要启用 '''DEBUG''' 编译标志并更改文件的LOGLEVEL:
 
* define DEBUG before any include in the <file>.c file
 
* define DEBUG before any include in the <file>.c file
 
   #define DEBUG
 
   #define DEBUG
第18行: 第18行:
 
   CFLAGS_<file>.o+= -DDEBUG -DCONFIG_LOGLEVEL=8
 
   CFLAGS_<file>.o+= -DDEBUG -DCONFIG_LOGLEVEL=8
  
If U-Boot fails before the console configuration (in the first stage of U-Boot execution), trace is not available.
+
如果在配置控制台之前(在执行U-Boot的第一阶段)U-Boot失败,则跟踪不可用。
  
In this case, you need to:
+
在这种情况下,您需要:
* debug with GDB (see the next chapter)
+
* 用GDB调试 (请参阅下一章)
or,
+
,
* activate the debug UART feature:
+
* 激活调试UART功能:
** add in defconfig of [[U-Boot_overview#U-Boot_configuration|U-Boot configuration]]
+
** [[U-Boot_overview#U-Boot_configuration|U-Boot configuration]]的defconfig中添加
 
*** {{Highlight|CONFIG_DEBUG_UART}}
 
*** {{Highlight|CONFIG_DEBUG_UART}}
 
*** {{Highlight|CONFIG_DEBUG_UART_STM32}}
 
*** {{Highlight|CONFIG_DEBUG_UART_STM32}}
** adpat the function {{Highlight|board_debug_uart_init()}}: that configures the required resources (pad, clock) before initialization by the U-Boot driver.<br/>This function needs to be adapted for your board.
+
** adpat 这个函数 {{Highlight|board_debug_uart_init()}}: 在通过U-Boot驱动程序初始化之前配置所需的资源 (pad, clock)<br/>此功能需要针对您的主板进行调整。
  
 
== Debug with GDB ==
 
== Debug with GDB ==

2020年11月3日 (二) 14:43的版本

Debug with console

跟踪和错误在设备树的chosen 节点中通过 stdout-path 字段定义的控制台上可用,例如在serial0 = uart4上:

 chosen {
 	stdout-path = " serial0:115200n8";
 };
 aliases {
 	serial0 = &uart4;
 };

默认情况下,U-Boot使用的宏 (debug(), pr_debug()...)不打印任何跟踪;要激活特定文件上的调试跟踪,需要启用 DEBUG 编译标志并更改文件的LOGLEVEL:

  • define DEBUG before any include in the <file>.c file
 #define DEBUG
 #undef CONFIG_LOGLEVEL
 #define CONFIG_LOGLEVEL 8
  • with a 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)。
      此功能需要针对您的主板进行调整。

Debug with GDB

With OpenSTLinux, you can directly use GDB script Setup.gdb:

Or for manual GDB connection, you need to:

  1. get the elf files for U-Boot and/or SPL
    (u-boot and u-boot-spl available in the build directory)
  2. connect GDB to the target
  3. reset with attach the target with the gdb "monitor reset halt" command:
    execution is stopped in ROM code or at the beginning of FSBL execution.
  4. load the symbols of the binary to be debugged with commands available in next chapter:
    #Load U-Boot symbol, #Load SPL symbol, #Load SPL code and debug
  5. start execution with the "continue" command

Load U-Boot symbol

With U-Boot relocation, symbols are more difficult to load.

See https://www.denx.de/wiki/DULG/DebuggingUBoot

If you connect GDB on running target, you can load the debug symbols:

  • Before relocation with "symbol-file" command:
 (gdb) symbol-file u-boot
  • After relocation with "add-symbol-file" command to relocate the symbol with the code 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

The following GDB example script automatically loads the U-Boot symbol before and after relocation for a programmed board, after "monitor reset halt" command:

 (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

This script uses a temporary hardware breakpoint "thbreak" to load the symbol when U-Boot code is loaded in DDR by FSBL = TF-A or SPL at the U-Boot entry point (CONFIG_SYS_TEXT_BASE = 0xC0100000).

It allows the symbol to be loaded only when code is executed to avoid DDR access before DDR initialization.

Load SPL symbol

To debug SPL with GDB on a Flashed device, ROM code loads the binary and the GDB script just loads the SPL symbols:

 (gdb) symbol-file u-boot-spl

Load SPL code and debug

Sometimes you need to debug SPL execution on an unprogrammed target (for example for board bring-up), so you can use GDB to load the SPL code in embedded RAM and execute it.

When execution is stopped in ROM code, you need to execute the "load" commands, depending on the compilation flags defined in U-Boot device tree to load the SPL code and the associated device tree:

  • CONFIG_OF_SEPARATE = dtb appended at the end of the code, not present in the elf file (default configuration)
 (gdb) file u-boot-spl
 (gdb) load
 (gdb) set $dtb =  __bss_end
 (gdb) restore spl/dt.dtb binary $dtb
  • CONFIG_OF_EMBED = dtb embedded in the elf file (debug configuration)
 (gdb) file u-boot-spl
 (gdb) load

Debug the first SPL instructions

Sometime the SPL code execution is stopped by the gdb command "monitor reset halt" after the first instructions.

To debug this part, you can modify the code: add a infinite loop in SPL code to wait the gdb connection.

For example in 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();

when gdb is attached and the SPL symbols are loaded, the infinite loop is interrupted by :

 (gdb) set var stop=1

And you can debug the SPL first instruction by gdb commands. <securetransclude src="ProtectedTemplate:PublicationRequestId" params="12894 | 2019-08-01 |"></securetransclude>