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.
First we have to setup hardware:
- connect J-Link to target hardware using 20-pin plume (better to use original plume, not the du-pont wires shown on the photo)
- connect J-Link to host machine using USB-cable
- 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.
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.
Download j-link driver from here and install:
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:
Browse to u-boot sources and press Finish button.
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:
Then you have to modify already existing variable PATH by inserting following to the start of variable content:
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:
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:
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:
You can get everything described above just in few “clicks”:
and from container’s console:
Here is Eclipse packet in Docker container to get everything isolated and pre-configured. Repo is here.
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):
Then open u-boot/lib/fdtdec.c, navigate to fdtdec_setup() function and change:
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!
Dirty hack issue
Dirty hack with hardcoded address in source code is annoying and making unhappy. Research for workaround started with googling the fdtcontroladdr term. And this magic variable mentioned in U-boot documentation: “fdtcontroladdr” environment variable – is the hex address of the fdt binary blob. As it points to the __end looks like this fdt binary blob placed next to u-boot binary image. Let’s try to do that.
First we need to find that resulted fdt binary blob – and there is u-boot.dtb file exists. Reliable way to make sure that file is fdt blob is check for first four bytes of this file. Just open it using any hex editor and check that it starts with D0 0D FE ED:
Next we need to load that file to the memory of CPU somehow. GDB let’s you do that using following command:
Here 0x87882d68 is __end address taken from u-boot.map:
So let’s test it from command line first and if it works we will add same instruction to Eclipse somehow.
Running GDB server.
Starting GDB session
It is the path to U-boot sources.
And yeah, U-boot booted and log messages appeared in console!
The last thing to be done – add that command to Eclipse:
Don’t forget to remove ugly hardcoded fdt blob address in u-boot/lib/fdtdec.c, fdtdec_setup() function from:
and start debugging process again. It should boot as expected. Still not universal workaround. Still need to be investigated additionally but much better than hardcode in source code.
Don’t forget to enable debugging information and disable optimization by size of course:
and we still not get fully debuggable and controllable U-boot. Next chapter explains last thing we should learn to achieve it.