Sometimes there’s just no place like your desktop. You’ve already got your favorite development tools and references setup or installed and it’s a pain when you’re trying to work on an unfamiliar, or simply uncustomized, system. On your desktop everything is at your fingertips. If you want to search the web, the browser is just an alt-tab away. If you need a calculator, it’s right there to run. Your editor highlights syntax in your favorite colors already.

When developing on a Raspberry Pi, you leave all these creature comforts behind unless you spend the time to configure the Pi to your liking. Then it all gets wiped when you install a new distribution, like the recent change from Wheezy to Jessie. Even then it’s frustrating to switch back and forth between the desktop and the Pi because there is always something on the other system that you need. My usual comment is, “dirty word”, literally.

Cross-developing on your desktop is a very workable solution. We’re going to walk through setting up your desktop and a Pi to do this. This means loading a Pi ARM toolchain on your desktop and a debugging server on the Pi. This’ll let you develop and debug from in the comfort of your desktop. An added advantage is when you put that Pi in a robot you can debug over a wireless link.

Cross System Development

Cross-development is actually fairly common. You’ve already done it if you’ve compiled for the Arduino on your desktop. In the late 80s I used 80×86 based PCs to develop software for a STD bus system that used an 80286 processor. More recently for my 2013 NASA Sample Return Robot Competition entry I debugged my rovers, running XP on ITX PCs, over WiFi.

Cross-development is pretty natural approach for a Pi since it’s how Raspian gets built. I’ve been meaning to try this for a while and after the first pass on the Pi lidar project decided that the time was now.

Setting Up Cross Build Tools

I’m using Ubuntu 14.04 on my desktop and 15.04 on my laptop. I first setup the desktop for cross-development and then replicated the steps on the laptop to verify the process. This process should work okay on Linux and something similar can be done under Windows. Take care if you use an earlier distribution since the ARM development libraries may not be the ones used on the Pi.

The first step is to install the development tools on the desktop, or host system. From the command line run the following:

sudo apt-get install build-essential sudo apt-get install g++-arm-linux-gnueabihf sudo apt-get install gdb-multiarch

The first line installs the general build tools. The second installs the C and C++ compiler and build tools for the Pi’s ARM processor. The third installs a version of the gdb debugging tool that works with target systems regardless of the processor architecture. Make a note somewhere of the ARM architecture designation, arm-linux-gnueabihf-, because it is used as a prefix to distinguish the ARM tools from the host system tools. Be sure to get the dash at the end of the string.

To test if everything is working enter the following line, which should report the version of the G++ compiler installed, plus a lot of other information:

arm-linux-gnueabihf-g++ -v

Work back through the installation of the build tools if you get an error.

Hello World From Pi!!!

Your host system should now be ready to build a Raspberry Pi program. Let’s start with the ubiquitous Hello World with a little extra, in C++ of course. Create a file hello.cpp and enter this source code:

#include <iostream> using namespace std; int main() { cout << "!!!Hello World From Pi!!!" << endl; return 0; }

To build the program run these two command lines:

arm-linux-gnueabihf-g++ -O3 -g3 -Wall -c -o -fPIC "hello.o" "hello.cpp" arm-linux-gnueabihf-g++ -o "hello" hello.o

The first line compiled the file hello.cpp and the second linked the compiler output to build the executable hello. Assuming all goes well, enter the following command and you should see output similar to what is shown in italics:

file hello hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=bc5e0850c0dc9d88ba60887facf52c00222dc746, not stripped

This tells us that the file is built for an ARM processor and not for your host system. Copy that file to your Pi, set the execute and owner permission bits, execute it, and it will generate the “Hello World” message. You’re now all set to cross compile for the Pi.

While this is great, the ability to debug the software on the target Pi is missing. A lot can be done by tracing execution with output statements or logs, but nothing beats stepping through an ornery routine that just refuses to work.

Debugging Across Systems

Debugging with the GCC toolset is done using the program gdb. The last item we installed, gdb-multiarch, provides the debug capability on the host system. Now we need to install a debug server on the Pi target system that we can connect to from our the desktop and control execution on the target. Switch over to the Pi and run the following install to get the target’s version of gdb:

sudo apt-get install gdbserver

Note that when gdbserver is running it creates a big security hole on the Pi. That’s not likely to be exploited since you’re running on your local network but don’t set it up to run on startup and then deploy the system in the wild.

Now determine where on the Pi you want to put the executable file. I created a directory remote which you’ll see in the examples. To run the server we’ll just use this simple command line, as follows, but there are options you should explore:

gdbserver --multi mysticlakelinux:2001

This command starts the server and tells it to run continuously. The computer name, or IP address, is that of the host computer. In my case it is mysticlakelinux. Finally, 2001 is the port that the host and target will use for communication. Be sure to remember it because it’s needed for debugging on the host.

We’re done with the Pi at the moment but leave the SSH terminal running. Besides keeping the server running it will display error messages and, when finally all is working, the output from the program. Now switch back to the host, open a terminal, and change to the directory of the “Hello World” program so we can start debugging.

The program gdb-multiarch is an interactive program. There are a host of commands that can be entered. It also takes a large number of command line options including the ability to read the interactive commands from a text file. We’ll just do enough to demonstrate it running the program because there is a plethora of options and capabilities.

On the host, enter the command:

gdb-multiarch

You should get a bunch of output followed by the prompt (gdb). In the future you might want to add the option -q to the command line. That stifles the introductory information. At the prompt, using the name of your Pi, enter the following commands and you should see the responses, as shown in italics here:

target extended-remote pizero.local:2001 Remote debugging using pizero.local:2001 set remote exec-file remote/hello [[no response]] file hello Reading symbols from hello...done.

The target command tells gdb the name of the target system, pizero, and the port, 2001, to use. If it worked, you’ll get the response shown; otherwise a timeout message. The set remote line specifies the file location to use on the Pi target system. Remember that the executable needs to be copied onto the target system every time it is changed. We’ll see how to do that from within gdb, below. The last command, file, is the path and filename on the host computer. This can be a directory other than where the debugger is running. Now, type the following and get the response as shown:

run Starting program: /home/rmerriam/development/ws/pi/hello/Debug/hello [[ a bunch more lines, some warnings and stuff to ignore for now ]] [Inferior 1 (process 1532) exited normally]

If it works you’ll see that last line. Now switch to the SSH terminal connected to the Pi and you’ll see a couple of lines of status, the output from the program, a blank line, and a line reporting the exit status of the program. If all this doesn’t work check the error message from the server. It should explain what is happening. Often there is a mismatch between what you told gdb and the location of the executable.

The debugger provides a large number of commands for manipulating breakpoints, continuing execution, listing the program, etc. For instance, type in main and the program stops when main() is reached. A ‘c’ runs the program after a breakpoint. To help with debugging, there is an interesting mode, the Terminal User Interface, or tui. You can access and leave it by typing in Ctrl-x, Ctrl-a. This mode provides windows that show the source, registers, assembly language, and other information.

One unfortunate aspect of gdb is it doesn’t automatically copy new versions of the executable, or at least not that I could find. This can be handled by entering an ‘escaped’ command in gdb, which is a normal Linux command run on the host but outside of the debugger. The scp command will copy files from one system to another. Here’s what I tried and the response:

!scp hello pi@pizero.local:/home/pi/remote/hello pi@pizero.local's password: hello 100% 69KB 68.7KB/s 00:00

This wouldn’t be bad except it asks for the password every time. The way around it is to use sshpass like this:

!sshpass -p 'password' scp hello pi@pizero.local:/home/pi/remote/hello

Once you start gdb and get everything set up you don’t want to have to reenter all the setup commands. One solution is to add them all to a text file and run them inside gdb using the source command. The other option is to never leave gdb. Typing a ‘!’ at the beginning of a line passes the command off to a shell to run and return. Type in the ‘!’ by itself and you’re at the host system command line. You can work in the terminal environment until ready to go back to debugging. Just like any other terminal, type exit, and you’re back in gdb.

Wrap Up

If you are happy with using the command line for debugging then you’ll need to explore the details of working with gdb. You can set breakpoints, step through programs, and display information about the program. I’ve used similar command line tools in the past for embedded systems work. No thank you, I’m going back to using Eclipse, and in the next article I’ll cover that process. That article will also revisit the Lidar project and another Pi library, pigpio. See you then!