wiki:Debugging/OpenOCD/BeagleBoneBlack

Version 2 (modified by Chris Johns, on 04/16/18 at 00:06:19) (diff)

--

OpenOCD Support for BeagleBone Black

OpenOCD supports the BeagleBone Black board that use the TI AM3358 SOC. The support is in the OpenOCD source and you can you can create a suitable environment. At the time of writing this page I am using the latest GIT version of OpenOCD.

The BeagleBone Black board as shipped has pad on the underside for JTAG. You need to solder a header on to the board so a suitable JTAG cable can be connected. It does require a small level of soldering skill but do not be put off by this.

The main OpenOCD page details how to build OpenOCD from GIT.

Flyswatter2 for the BeagleBone Black

Tincan Tools provides a BeagleBone Black JTAG Adapter Kit and detailed instructions on their wiki describing how to install the JTAG Adapter Kit. The kit and the Flyswatter2 pod provide an accessible way to get JTAG debugging.

BeagleBone Initialization

An RTEMS application runs in the DDR memory and in production the uBoot bootloader initializes the AM3358 SOC device and the connected hardware before loading the executable from local storage or over the network into the DDR memory and passing control to RTEMS entry point. JTAG needs to emulate the bootloader process and there are a number of ways this can be done.

  1. Directly access the SOC registers to initialize the hardware
  2. Use uBoot to perform initialize the hardware

Directly accessing the SOC is fast and direct however it requires you detail all the set up required. This can often be more than writing the DDR controller registers to enable the DDR memory, it can also require the configuration of clocks and bus configuration hardware. Getting this right can be time consuming and complex.

uBoot contains all the required SOC set up however uBoot is designed to boot the processor so while loading and executing uBoot is easy, it can often be tricky stopping after the hardware is initialized to regain control. There are couple of methods that can be used, the first is to make sure uBoot cannot load any executable so it runs and stops. You can load the first stage of uBoot and start it executing, wait a while then halt the target. The second method is to have a look into uBoot and find a suitable place to stop it and to set a breakpoint. This requires a little investigation because the location can be different for each uBoot.

There is another small complication with the AM3358 SOC. The hardware watchdog is enabled after reset and this means resetting the SOC via JTAG will result in the SOC resetting after approximately 6 seconds. The watchdog device needs to be disabled and this can be done 2 ways, the first is in the OpenOCD BBB support where the watchdog registers are updated to disable the watchdog or you can let the SOC ROM based initialization code run which also disables the watchdog.

Once the watchdog reset has been disabled and the DDR memory is initialized you can load the RTEMS ELF executable using GDB and start it executing.

OpenOCD Configuration

Tincan tools provides a TCL configuration file to use with OpenOCD. Download !BeagleBone Black Config File from Tincan Tool's wiki and save. Create a configuration file with an editor containing:

source [find interface/ftdi/flyswatter2.cfg]
source [find ti_beaglebone_with_fs2.cfg]

telnet_port 4445
tcl_port    6667
gdb_port    3334

proc bbb_restart { } {
  reset halt
  bp 0x402f0400 4 hw
  reset run
  sleep 300
  rbp 0x402f0400
}

init

The script defines bbb_restart which executes the SOC's ROM code disabling the watchdog. The address 0x402f0400 is the entry the ROM code calls once it has finished it's initialization and it has loaded uBoot's MLO first stage loader.

Start OpenOCD with:

# sudo openocd -f bbb-fs.cfg

Initializing with uBoot

The following details how to initialize the SOC using uBoot. For this you need to get uBoot from git and to build it for the BeagleBone Black. The initialization is done by GDB calling OpenOCD's monitor interface. This approach lets you provide a personal specific initialization which is useful if you are sharing hardware on a network with a team.

In your home directory create or edit your .gdbinit file adding:

def target-connect-fs
  echo JTAG FS\n
  set $TARGET_JTAG = 1
  set $TARGET_REMOTE = "kaka:3333"
end

def target-connect
  target remote $TARGET_REMOTE
end

def bbb-restart
 if $TARGET_JTAG
  mon echo "] BBB Restart..."
  mon cortex_a dacrfixup on
  mon cortex_a maskisr on
  mon reset halt
  mon bp 0x402f0400 4 hw
  mon reset run
  mon sleep 1000
  mon rbp 0x402f0400
  mon echo "] Loading MLO"
  # EDIT to a path for your uBoot MLO loader
  mon load_image /opt/src/rtems/beagle/black/u-boot-spl-nodtb.bin 0x402f0400 bin
  mon bp 0x402f1424 4 hw
  mon resume 0x402f0400
  mon sleep 1000
  # EDIT to match your uBoot
  mon rbp 0x402f1424
 end
end

The first GDB script function added is target-connect-fs. This is called by your application's generic .gdbinit script. It is a simple way to manage team access to shared debugging resources without polluting your application's repository with network specific debugging configurations. The remote target in my configuration is kaka:3333, this is the server on my networking the Flyswatter2 pod is connected to and is running OpenOCD. The port is the OpenOCD default GDB server port of 3333 and that matches the OpenOCD configuration above.

The second GDB script function restarts the BBB. GDB passes mon commands to the target monitor.

The first two monitor commands are important when debugging RTEMS. The first command is mon cortex_a dacrfixup on and it tells OpenOCD to enable all domains in the Domain Access Control registers. Without this OpenOCD will get data aborts when writing to the DDR after RTEMS has enabled the MMU. The second command mon cortex_a maskisr on tells OpenOCD that RTEMS can vector to an interrupt handler when a step is taken. Without this command a step will result in you stepping into highest priority interrupt and that gets a little boring when the timer interrupt is enabled.

The following monitor commands:

  1. Reset and halt the SOC
  2. Run the SOC's ROM code to disable the watchdog and perform any other low level initialization
  3. Load uBoot's MLO first stage loader, which is called SPL in uBoot source and build
  4. Set a break to the instruction after the function TODO find function name.
  5. Run uBoot's MLO until the breakpoint
  6. Remove the breakpoint

Once this has run the hardware is ready to load an RTEMS application.

GDB Configuration

GDB is initialized with the following script:

target-connect-fs
target-connect

bbb-restart

echo ] Loading RTEMS exe ...\n
load

# Catch any exit paths
b exit
b _exit
b bsp_reset
b bsp_fatal_extension

# Uncomment if Init is the entry point
tb Init
# Uncomment if main is the entry point
#tb main

c