JTAG is a useful tool that allows customers additional debugging options. Segger was kind enough to send us a J-Link Plus probe for us to test. This blog post will describe how to setup your environment and use the J-Link to debug during both U-Boot and Kernel development.
Note that all of the instructions below would work for all other J-Link probes.
Environment setup
Basic software setup
This blog post will focus on Linux installation but Windows setup should be very similar.
First, you need to install the J-Link tools from Segger website:
https://www.segger.com/downloads/jlink
From there you need to download the J-Link Software and Documentation Pack for your OS.
The version v6.10m was used for this blog post, which is the latest version at the time of this writing.
If you use an Ubuntu/Debian distro, the installation is very simple:
Once installed, several tools and documentation will be installed, here are the important ones:
UM08001_JLink.pdf: User Manual (located under /opt/SEGGER/JLink_V610m/Doc/)
JLinkExe: J-Link Commander tool that can be used for
verifying proper installation of the USB driver
verifying the connection to the target CPU
updating the firmware (automatically)
JLinkGDBServer: GDB remote server
for GDB to connect to and communicate with the target
The latter tool is the most important since it will be used for every GDB debugging session. In our case, we want to use debug on ARM targets, so we need a cross ARM toolchain and GDB.
For Ubuntu/Debian, you can simply install the following packages:
Another solution is to use a toolchain from Linaro which includes the cross GDB binary:
gcc-linaro-5.3.1-2016.05-x86_64_arm-linux-gnueabihf.tar.xz
The tools above are sufficient to start debugging using GDB manually.
Graphical IDE setup
If you wish to use a graphical IDE instead of entering GDB commands manually, there are some open-source solutions.
For this blog post, we chose the most commonly used IDE: Eclipse. Although it was primarly made for Java developement, it now exists in different flavors.
The version we are interested for U-Boot/Kernel development is the C/C++ one:
http://www.eclipse.org/downloads/packages/eclipse-ide-cc-developers/neon1a
Once the tarball downloaded, you can extract to the folder of your choice.
You then need to install the GNU ARM Eclipse plug-in which contains J-Link debugging features. The plugin website explains the installation procedure in details:
http://gnuarmeclipse.github.io/plugins/install/
Make sure to select J-Link Debugging when installing the plugin.
ARM Plugin Install
The J-Link part of the plugin is also well explained here.
Hardware setup
As you might have noticed, our boards have a tiny JTAG connector which is (much) smaller than the standard 20-pin connector.
In order to connect the J-Link probe you threrefore need the following adaptation board:
NIT6X_JTAG
This board comes with several jumpers. Make sure to place them on J3, J4 and J6 so the JTAG can properly communicate with the CPU.
Also, make sure that the pin 1 (white dot) of the adaptation board matches the pin 1 of the board connector.
Here is what it should look like for the BD-SL-iMX6.
BDSL + J-Link
At this point, if the board is powered, the JLinkExe tool should detect a CPU is connected.
U-Boot debugging
In this section, it is assumed your board doesn’t boot to U-Boot automatically. That means that the procedure below will explain how to initialize the DDR using the JTAG.
In order to make sure that the board won’t boot on its own, you can configure the boot DIP switch like for USB recovery. You can look at our unbricking blog post in order to see how to position the switch.
Before debugging, you need to build your U-Boot binary. It is assumed that you’ve already read our article on that subject.
Here is an example for the Nitrogen6x/BD-SL-i.MX6 (SabreLite):
Note that the output ELF binary ready to be debugged is named u-boot.
Using GDB manually
First the GDB server needs to be started.
The i.MX6SoloX requires a specific script for the server to be able to communicate with the CPU. It can be found here:
https://wiki.segger.com/index.php?title=I.MX6_SoloX_Support
script needs to be specified with the -scriptfile option
Then a GDB session can attach to our local server (to the J-Link) in order to load the ELF binary.
As said previously, the RAM needs to be initialized first before. In order to do so, a gdb init script must be provided to set the clocks and DDR registers like the DCD table would do.
Such GDB init scripts have been created for all our boards:
http://linode.boundarydevices.com/jlink/
For BD-SL-i.MX6 (Sabre-Lite), the nitrogen6x one must be used. The GDB command therefore looks like:
At this stage, the DDR and clocks are properly initialized. You now can load the ELF binary and start debugging. Here is an example.
If you are not familiar with GDB, we highly recommend this article.
Using Eclipse IDE
Disclaimer: this section will only detail how to debug U-Boot from the IDE. If you wish to build U-Boot from eclipse, we recommend you to read this pdf.
First, go to File > Import and select C/C++ Executable. Then enter the u-boot binary path into the Select Executable field.
Then the project is ready, the debug configuration now needs to be created. Go to Run > Debug Configurations and create a new GDB Segger J-Link Debugging profile.
In the Debugger tab, adjust the settings to match the picture below (Device, Endianness, Connection etc..).
Finally, in the Startup tab, copy the memU32 values from the GDB init script mentioned above to the box below.
That’s it, you can hit Debug and start debugging your U-Boot source code.
Linux kernel debugging
Unlike the U-Boot setup above, the assumption of this section is that the kernel (and its device tree) is loaded from U-Boot. This eases the setup quite a lot, the JTAG just needs to connect to the target and is ready to debug.
For debugging purposes, we recommend using TFTP/NFS setup to load the kernel/device tree/OS.
Before debugging, the kernel must be built. Here are the latest instructions to do so:
If you use TFTP, don’t forget to copy the zImage and dtb file to the root directory of your TFTP server.
The ELF binary that will be used for debugging is called vmlinux
Using GDB manually
Same as before, the GDB server needs to be started.
Note that 1 JLinkGDBServer can only connect to 1 core, so if you want to debug several cores, you need to start as many GDB servers as cores. Each GDB server instance must use different ports than the other instances. Here is the command to connect to the Core1 for instance:
Then a GDB session can attach to our local server (to the J-Link) in order to load the ELF binary.
At this stage, the DDR and clocks are properly initialized. You now can load the ELF binary and start debugging. Here is an example.
Now that we have set our breakpoints, we can load the kernel from U-Boot. Here is an example using TFTP.
Then you should see the breakpoints on the GDB console.
Using Eclipse IDE
Just like the U-Boot procedure, go to File > Import and select C/C++ Executable. Then enter the vmlinux binary path into the Select Executable field.
Then the project is ready, the debug configuration now needs to be created. Go to Run > Debug Configurations and create a new GDB Segger J-Link Debugging profile.
As said before, if you want to debug multiple cores, you need to create several debug configurations. Below is the core0 setup.
Note the difference with the U-Boot setup, here the Connect to running target is checked.
Same here, note that the Initial Reset and Halt is unchecked.
For other cores, the only differences are in the Debugger tab where you need to specify a scriptfile that you can find here. Also the ports must be different, see the Core1 setup below.
Then you can create a Launch Group that would start the debugging session on all the cores at once.
Finally you can start debugging all the cores.
The post Debugging using Segger J-Link JTAG appeared first on Boundary Devices.