Last edited 2 months ago

U-Boot - How to debug


1. Debug with console[edit | edit source]

Trace and error are available on the U-Boot console which use stdout-path defined in the chosen node of the Linux kernel device tree as described in the Linux kernel binding[1].

See page How to configure U-Boot for your board for configuration details.

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:

  • 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

For details, see doc/README.log .

If U-Boot fails before the console configuration (in the first stage of U-Boot execution), trace is not available.

In this case, you need to:

  • debug with GDB (see the next chapter)

or,

  • activate the debug UART feature:
    • add in defconfig of U-Boot configuration
      • CONFIG_DEBUG_UART
      • CONFIG_DEBUG_UART_STM32
    • adpat the function board_debug_uart_init(): that configures the required resources (pad, clock) before initialization by the U-Boot driver.
      This function needs to be adapted for your board.

2. Debug with GDB[edit | edit source]

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

2.1. Load U-Boot symbol[edit | edit source]

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.

3. Debug SPL with GDB[edit | edit source]

SPL is also supported with "stm32mp15_basic_defconfig" but only for U-Boot_SPL:_DDR_interactive_mode.


4. References[edit | edit source]

  1. Documentation/devicetree/bindings/chosen.txt the Linux kernel binding for chosen node