How to debug u-boot

In previous two chapters: 1 and 2 we used Eclipse IDE to debug Embedded Linux user layer application. In that post we will use Eclipse as IDE to debug U-boot using usb debugger J-Link connected to target hardware using JTAG interface.

Hardware setup

First we have to setup hardware:

jlink Netsom

  1. connect J-Link to target hardware using 20-pin plume (better to use original plume, not the du-pont wires shown on the photo)
  2. connect J-Link to host machine using USB-cable
  3. power up target hardware, reboot device and enter U-boot console.

Pay attention for configuration flashed to target hardware. In a case of using configuration starting with audio_stream_ or alexa_ sharing JTAG pins with audio SAI interface you shouldn’t let U-boot to load kernel. E.g. you should type enter on power up sequence to stop U-boot count down and stay in U-boot console.

Next we need to install Eclipse IDE and compile toolchain to be used.
It is quite long procedure and if you wish to get fast setup scroll down to Dockerized setup chapter that automates everything to be installed just by typing few commands to the host console. Or check for Readme of that Docker image implemented as separate repository.

Toolchain compilation

$ mkdir /opt/eclipse/
$ cd /opt/elcipse/
$ git clone https://github.com/wireless-road/imx6ull-openwrt.git
$ cd imx6ull-openwrt
$ ./compile.sh flexcan_wifi

here better to use /opt/eclipse/¬†so all environment variable mentioned further in the text stays valid. Otherwise you have to modify them according to the path you selected to install toolchain and eclipse. Again, in a case of using Dockerized setup you don’t have to worry about it at all.

Drivers setup

Install gdb-multiarch:

$ sudo apt-get install gdb-multiarch

Download j-link driver from here and install:

$ dpkg -i /drivers/JLink_Linux_V754b_x86_64.deb

 

IDE setup

Download Eclipse IDE for Embedded C/C++ Developers and install it to /opt/eclipse so eclipse executable to have /opt/eclipse/eclipse/eclipse path and start it. It differs from Eclipse IDE used in previous chapters so better to move to Eclipse IDE for Embedded C/C++ Developers for user space applications development to have just single IDE for all needs.

Press File –> New Project and select C/C++ –> Makefile Project with Existing Code:

u-boot eclipse

 Browse to u-boot sources and press Finish button.

/opt/eclipse/imx6ull-openwrt/build_dir/target-arm_cortex-a7+neon-vfpv4_musl_eabi/u-boot-wirelessroad_ecspi3/u-boot-2017.07

Next we have to provide environment variables to configure IDE for cross-compilation using toolchain compiled on previous step to staging_dir sub-folder. Right click to the project and press Properties. Then navigate to C/C++ Build –> Environment tab and add following variables:

ARCH=arm
CROSS_COMPILE=arm-openwrt-linux-muslgnueabi-
STAGING_DIR=/opt/eclipse/imx6ull/imx6ull-openwrt/staging_dir/

Then you have to modify already existing variable PATH by inserting following to the start of variable content:

/opt/eclipse/imx6ull-openwrt/build_dir/target-arm_cortex-a7+neon-vfpv4_musl_eabi/linux-imx6ull_cortexa7/linux-4.14.199/scripts/dtc/:/opt/eclipse/imx6ull-openwrt/staging_dir/target-arm_cortex-a7+neon-vfpv4_musl_eabi/host/bin:/opt/eclipse/imx6ull-openwrt/staging_dir/hostpkg/bin:/opt/eclipse/imx6ull-openwrt/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-7.5.0_musl_eabi/bin:/opt/eclipse/imx6ull-openwrt/staging_dir/host/bin:/bin:

Here few path fot toolchain compiled before splitted by colon.
So you should get following:

Next we need disable default host headers (un-check CDT Cross GCC Built-in Compiler Settings):

and replace them with headers from our toolchain. Add following paths:

/opt/eclipse/imx6ull-openwrt/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-7.5.0_musl_eabi/arm-openwrt-linux-muslgnueabi/include/
/opt/eclipse/imx6ull-openwrt/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-7.5.0_musl_eabi/include/
/opt/eclipse/imx6ull-openwrt/staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-7.5.0_musl_eabi/lib/gcc/arm-openwrt-linux-muslgnueabi/7.5.0/include/

to C/C++ General –> Paths and Symbols –> Includes –> GNU C tab:

enable parallel build:

Let’s try to clean and compile project. Right click on the project –> Clean Project:

Right click on the project –> Build project:

Next make few changes to enable debugging.
First, enable CONFIG_TOOLS_DEBUG in .config file in the root folder:

CONFIG_TOOLS_DEBUG=y

If you don’t see hidden files you can enable them by pressing to filtering button:
and de-selecting .* resources option:
re-compile project to build image with debugging symbols included.

After that time to setup debug configuration. Press to Run –> Debug configuration, create new GDB SEGGER j-link Debugging configuration:


Dockerized setup

You can get everything described above just in few “clicks”:

$ git clone https://github.com/wireless-road/openwrt-ide.git
$ docker-compose run –name openwrt openwrt

and from container’s console:

$ ./setup_ide.sh
$ /opt/eclipse/eclipse/eclipse

Here is Eclipse packet in Docker container to get everything isolated and pre-configured. Repo is here.

Dirty hack

when I tried to debug first time it gave me nothing. Here is steps I passed to get it working. Finally got it working just by single line hard coding. Hope to avoid this in future but currently such ugly trick exists.

Type in U-boot console of running (not under debugger):

=> printenv fdtcontroladdr
fdtcontroladdr=8ef216d8

Then open u-boot/lib/fdtdec.c, navigate to fdtdec_setup() function and change:

gd->fdt_blob = &_end;

to:

gd->fdt_blob = (ulong *)0x8ef216d8;//&_end;

That’s it.

Debugging

Now everything is ready for debugging. Press Debug button, click OK to switch to Debug perspective and press Resume button to start application:


and… You should see U-boot log messages in console. Ok, it is running.

Let’s try to debug using breakpoints. So stop debugging, make power off-on cycle from hardware with j-link re-attaching. Add following break point to initcall_run_list function in debug configuration:

press Debug button and then Resume. Execution should stops at this function:

press to Step Over button few times:
Now we able to debug U-boot!
Hope to find workaround to replace dirty hack with something proper and next will try to debug kernel!