Tag: #follow

Following the Kernel #3 – Debugging environment

In this part, I will show you how to configure your debug environment to start following the kernel on BeagleBone Black board. My laptop uses Ubuntu 18.04 LTS distribution. As the debugging interface, I will use the JLink device, connected with BBB Compact TI JTAG via an adapter prepared by myself (link to the project below). The connector is placed in the bottom of the BBB and is normally not soldered. Things, which are needed (except JLink and our BeagleBone Black) are listed below.

OpenOCD

The most important software part gdbserver, controlling the JLink device. Like almost everything in this series, I will use open-sourced OpenOCD, which you can download from the git repository and install locally:

$ git clone git://git.code.sf.net/p/openocd/code openocd
$ cd openocd
$ ./bootstrap # only if you cloned git repo (like me)
$ mkdir install # local install directory (we don't want to polute system)
$ ./configure --prefix=`pwd`/install --enable-jlink
$ make && make install

Probably you will need to install some missing dependencies. OpenOCD README says about these:

- make
- libtool
- pkg-config >= 0.23 (or compatible)
- autoconf >= 2.64
- automake >= 1.14
- texinfo >= 5.0
U-Boot

The next thing is building our MLO image, which is a part of the U-Boot repository. I assume, that you have arm-linux-gnueabihf- toolchain after reading the previous part and you know how to use it with Kbuild. So just do the following:

$ git clone https://github.com/u-boot/u-boot.git
$ cd u-boot
$ export ARCH=arm
$ export CROSS_COMPILE=arm-linux-gnueabihf- # should be in PATH
$ make am335x_defconfig # like omap2plus_defconfig previously
$ make

After building it MLO binary should be placed in the root folder. The ELF file (needed to debug) is placed in the spl subfolder.

SD Card

I described the early boot process in the first part of this series. We end up searching for a file called MLO in the FAT16 partition. We have to prepare it, and after building U-Boot we have all we need.

Enter the SD card to the slot. It should be detected as /dev/mmcblkX device. In my case, it is /dev/mmcblk0. After that run these commands:

$ sudo dd if=/dev/zero of=/dev/mmcblk0 bs=512 # not mandatory - clear card
$ echo -e "2048,98304,0x0E,*\n" | sudo sfdisk /dev/mmcblk0 # create MBR entry with offset 2048, size 98304, type 0x0E (FAT16), marked to boot (*)
$ sudo mkfs.vfat /dev/mmcblk0p1 # Prepare file system
$ sudo mount /dev/mmcblk0p1 /mnt
$ sudo cp MLO /mnt/ 

sfdisk is a utility similar to fdisk. Of course, you can use a more interactive fdisk and pass similar parameters. The most important is choosing the right file system and marking it to boot.

Remember that the SD card slot is the second device examined during the boot process. If you are not sure if eMMC is empty, press the S2 button during start. If your eMMC is not empty, run Linux on it and clear mmcblk0 device like on the upper listing (remember it will remove all your data from BeagleBone :-)).

cTI JTAG adapter

Unfortunately, BeagleBone Black has no port, matching the JLink device. However, it is pretty easy to adapt the existing Compact TI JTAG connector and connect it with an adapter, or simple wiring. Here you can find my Kicad adapter project – https://github.com/rafalo235/jlink-cti-adapter.

If you don’t want to make it on your own with, for example with toner transfer technique. You can order it from a PCB manufacturer, or simply wire it together according to the schematics.

Run

If you are done (JLink connected to the adapter, SD card in a slot, BBB power up) we can start debugging. First, run the OpenOCD. If you passed the same commands as I did, go to the openocd/install/bin directory and run this command:

$ ./openocd -f interface/jlink.cfg -f board/ti_beaglebone_black.cfg -c init -c "reset init"
Open On-Chip Debugger 0.11.0+dev-00035-g8d6f7c922-dirty (2021-06-01-22:31)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
Info : J-Link V10 compiled Oct  6 2017 16:37:55
Info : Hardware version: 10.10
Info : VTarget = 3.425 V
Info : clock speed 1000 kHz
Info : JTAG tap: am335x.jrc tap/device found: 0x1b94402f (mfg: 0x017 (Texas Instruments), part: 0xb944, ver: 0x1)
Info : JTAG tap: am335x.tap enabled
Info : am335x.cpu: hardware has 6 breakpoints, 2 watchpoints
Info : starting gdb server for am335x.m3 on 3333
Info : Listening on port 3333 for gdb connections
Info : starting gdb server for am335x.cpu on 3334
Info : Listening on port 3334 for gdb connections
Info : JTAG tap: am335x.jrc tap/device found: 0x1b94402f (mfg: 0x017 (Texas Instruments), part: 0xb944, ver: 0x1)
Info : JTAG tap: am335x.tap enabled
Error: Debug regions are unpowered, an unexpected reset might have happened
Error: JTAG-DP STICKY ERROR
Warn : am335x.cpu: ran after reset and before halt ...
Info : am335x.cpu rev 2, partnum c08, arch f, variant 3, implementor 41
Error: MPIDR not in multiprocessor format
target halted in Thumb state due to debug-request, current mode: Supervisor
cpsr: 0x600001b3 pc: 0x0002412a
MMU: disabled, D-Cache: disabled, I-Cache: disabled
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections

OpenOCD connects to the JTAG interface on BBB via JLink and opens a port for a gdb connection. Now we have to run arm-linux-gnueabihf-gdb. Open a new terminal window and go to the u-boot directory.

To ease connecting gdb, I prepared a gdbinit script. Please copy it to a file, you will refer to it on debugger start.

# Connect to OpenOCD
target extended-remote :3334

# Create normal breakpoint
b _start

# Restart device and halt it
monitor reset halt
monitor sleep 2000 # we must wait for completion after each command

# Create hardware breakpoint in the starting point of shadowed MLO (check part 1)
monitor bp 0x402f0400 4 hw
monitor sleep 2000

# Restart BBB once again, we will stop on upper breakpoint
monitor reset run
monitor sleep 2000

# We have already stopped, remove this hardware breakpoint
monitor rbp 0x402f0400
# Disable watchdog!
monitor disable_watchdog
monitor sleep 2000

continue

I’m not sure why separate b _start (which is placed on 0x402f0400) and monitor bp 0x402f0400 4 hw is needed. But from many combinations, this one works. I will try to find out why this happens. If you have any idea, please add a comment.

Now we can run the debugger:

$ arm-linux-gnueabihf-gdb spl/u-boot-spl --command=~/Documents/gdbinit-bbb
GNU gdb (Linaro_GDB-2018.05) 8.1.0.20180612-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-unknown-linux-gnu --target=arm-linux-gnueabihf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from spl/u-boot-spl...done.
0x00024126 in ?? ()
Breakpoint 1 at 0x402f0400: file arch/arm/lib/vectors.S, line 87.
JTAG tap: am335x.jrc tap/device found: 0x1b94402f (mfg: 0x017 (Texas Instruments), part: 0xb944, ver: 0x1)
JTAG tap: am335x.tap enabled
Debug regions are unpowered, an unexpected reset might have happened
JTAG-DP STICKY ERROR
am335x.cpu: ran after reset and before halt ...
am335x.cpu rev 2, partnum c08, arch f, variant 3, implementor 41
target halted in Thumb state due to debug-request, current mode: Supervisor
cpsr: 0x000001b3 pc: 0x00024136
MMU: disabled, D-Cache: disabled, I-Cache: disabled
jtag_flush_queue_sleep [sleep in ms]
sleep milliseconds ['busy']

breakpoint set at 0x402f0400

JTAG tap: am335x.jrc tap/device found: 0x1b94402f (mfg: 0x017 (Texas Instruments), part: 0xb944, ver: 0x1)
JTAG tap: am335x.tap enabled
Debug regions are unpowered, an unexpected reset might have happened
JTAG-DP STICKY ERROR
am335x.cpu rev 2, partnum c08, arch f, variant 3, implementor 41
target halted in ARM state due to breakpoint, current mode: Supervisor
cpsr: 0x40000193 pc: 0x402f0400
MMU: disabled, D-Cache: disabled, I-Cache: disabled
am335x.cpu rev 2, partnum c08, arch f, variant 3, implementor 41

Breakpoint 1, _start () at arch/arm/lib/vectors.S:87
87		ARM_VECTORS
(gdb)

Voila, we finally are ready to debug the MLO code. We will cover this in the next chapter. I recommend check the configuration with console-based gdb and then configure more interactive IDE like Eclipse or VSCode.