Last edited 2 years ago

U-Boot - How to debug

Applicable for STM32MP13x lines, STM32MP15x lines

1. Debug with console[edit source]

See U-Boot Documentation or doc/develop/logging.rst for U-Boot logging details.

CONFIG_LOG is enable in OpenSTLinux.

By default, traces 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.

The ST boards use the default logging configuration:

  • CONFIG_LOG_DEFAULT_LEVEL = CONFIG_LOG_MAX_LEVEL = LOGL_INFO = 6
    the 'debug' macros used by U-Boot (log_debug(), debug(), pr_debug()...) are removed in the U-Boot binary.
  • CONFIG_LOGF_FILE, CONFIG_LOGF_LINE, CONFIG_LOGF_FUNC are not activated
    no debug information in log messages by default.

To enable all the debug traces in U-Boot you need to increase the max logging level with a major impact on U-Boot size; e.g. set CONFIG_LOG_MAX_LEVEL to LOGL_DEBUG by adding in your defconfig file the line:

 CONFIG_LOG_MAX_LEVEL=7

When the traces are present in U-Boot, you can change the default trace level with CONFIG_LOG_DEFAULT_LEVEL or you can use the log command (CONFIG_CMD_LOG) to dynamically configure and filter the output:

   log level 7
   log format all

1.1. Activate debug trace on one file[edit source]

To turn on this debug logging just in one file, you can define LOG_DEBUG and DEBUG for this file

  • add define before any include in the <file>.c file
 #define LOG_DEBUG
 #define DEBUG
  • with a Makefile
 CFLAGS_<file>.o+= -DLOG_DEBUG  -DDEBUG

1.2. Debug before console[edit source]

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
    • adapt 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 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 = u-boot 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
  5. start execution with the "continue" command

2.1. Load U-Boot symbol[edit source]

With U-Boot relocation, symbols are more difficult to load, see doc/README.arm-relocation for details.

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

  • Before relocation with "symbol-file" command:
  symbol-file u-boot
  • After relocation with "add-symbol-file" command to relocate the symbol with the code offset = gd->relocaddr:
  symbol-file u-boot                            --> only for "gd_t" definition
  set $offset = ((gd_t *)$r9)->relocaddr        --> get relocation offset
  symbol-file                                   --> clear previous symbol 
  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:

  thbreak *0xC0100000
  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 at the U-Boot entry point, CONFIG_SYS_TEXT_BASE =

  • 0xC0000000 for STM32MP13x lines More info.png
  • 0xC0100000 for STM32MP15x lines More info.png

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

3. References[edit source]

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