I have decided to write about the usage of Raspberry pi as both wireless programmer/debugger and tool for automated testing for Cortex-M MCUs. There are few articles and tutorials but still, this topic's online coverage is rather poor considering its usefulness.

Please consider this as more of an inspiration than complete tutorial.

 

You can use any Raspberry Pi as a standalone programmer/debugger plus also write debugging script which can do some form of low-level automated testing.

 

OpenOCD

Most debugging setups are server-client based. We have a server which is taking care of interfacing with our HW programmer/debugger and then client which is used for actual debugging - it asks the server to set breakpoints, read memory, etc...

We will use OpenOCD as our server but if we wish to use raspberry GPIO port as an SWD debugger we need to recompile it with its support turned on you can use Adafrauit's tutorial for this step: https://learn.adafruit.com/programming-microcontrollers-using-openocd-on-raspberry-pi

 

Also, OpenOCD can be used with most programmers and development boards by finding proper config scripts in the interface or target folder and editing your config file.

 

You can define events in your config file to customize what happens when for example client connects and disconnects like this:

$_TARGETNAME configure -event gdb-attach {
  halt
}

$_TARGETNAME configure -event gdb-detach {
  resume
}

 

Depending on your target MCU and interface setting up OpenOCD can be as easy as it gets or rather complicated (Mainly in cases of newer MCUs which need some flash or security setup and there is no config script supplied by openocd)

 

Also by default OpenOCD is binding only to a localhost address if you want to be able to connect to it from other computers you need to add "bindto 0.0.0.0" to your config file.

Beware that it's not secured so anybody from your network can connect to it. The best solution would be to leave it bound only on to a localhost and create SSH tunnel

 

After successfully running openocd its output can look something like this:

Info : BCM2835 GPIO JTAG/SWD bitbang driver
Info : JTAG and SWD modes enabled
Info : clock speed 4061 kHz
Info : SWD DPIDR 0x2ba01477
Info : lpc17xx.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : lpc17xx.cpu: external reset detected
Info : Listening on port 3030 for gdb connections
    TargetName         Type       Endian TapName            State
--  ------------------ ---------- ------ ------------------ ------------
 0* lpc17xx.cpu        cortex_m   little lpc17xx.cpu        running
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections

GDB

Now to be able to connect to your OpenOCD server you need a client. GDB is something you would almost always use in this setup. If you have your standard arm gcc tools installed you can use arm-none-eabi-gdb.

 

You can use it from the command line like this:

arm-none-eabi-gdb ./YourELFBinary.elf //run gdb with your binary also its good not to move your binary from a place where it was compiled so gdb can parse track symbols to their place in a source code.

//now you are in a gdb console
target extended-remote 192.168.0.10:3333 //you can connect to your server like this

//if you want to load binary into device
load

//show value of variable
p var

//continue program
cont

//reset MCU
monitor reset

//show stack
info stack

//you can break program at any time by pressing ctrl+c

 

This is example of some basic usage, you can use almost any IDE to debug using GDB, if you use eclipse look for GNU ARM C/C++ OpenOCD Debugging package.

 

GDB Scripts

But more interesting and useful usage for me is to use it for automated testing. You can write scripts for GDB using GDB internal interpreter or you can use python.

 

Let say we want to check if some variable isn't set to zero and if it is we want to know from where exactly.

target extended-remote 192.168.0.10:3333

watch var_pointer

catch signal SIGTRAP
commands
  if var_pointer != 0
    cont
  else
    print "var_pointer is set to 0 from:"
    info stack
  end
end

 

Or something more simple print something every time breakpoint gets hit:

target extended-remote 192.168.0.10:3333

rbreak Radio.cpp:.*receive*
commands
    silent
    printf "radio beacon from address: %d\n", beacon.source_address
    cont
end

continue

 

You can run those scripts like this:

arm-none-eabi-gdb -batch --command=./script.gdb .\binary.elf

You can, for example, take your Raspberry pi, set up build tool-chain on it, and every time changes get committed to your source code Raspberry can build it, load it into MCU through SWD and then run gdb scripts and send you results on email etc..

And as you can see all of this costs only one Raspberry pi. (and a little bit of time while learning it all)