Remote cross debugging: Windows to Raspberry-Pi

In the past few days I’ve spent quite a lot of time on my new shining Raspberry-Pi. It’s an amazing little devil, worth every Euro I spent! Since I’ve planned to deploy a software component of my augmented reality system on this board, I needed to figure out how to remotely debug it in order to troubleshoot any issue I would run into. It took me some time, but thanks to the friends on Raspberry Pi Forum and to this awesome tutorial I finally made it: I can deploy my software to the raspberry-pi from Eclipse CDT and debug from my comfortable Windows 7 machine.

Step 1. The first thing you need to do is to setup a working Cygwin environment on your machine. I setup mine by following the advices from IanLinsdell and CopperPhil on the Raspberry Pi forum. Simply copy Cygwin installer to a folder (es. c:\cygwin) and execute it. Be sure to install the python package, the shell and the make tool.
Step 2. The next thing you need to do is to install the required cross-compilation toolchain. That is needed since we are on Windows and we need to compile and debug a software which will run on an ARM machine (our Raspberry Pi). Instead of building your own toolchain, you can download the ones built by a Raspberry Pi Forum user, IanLinsdell, available from his github account here. Since we want to cross-debug, download the hardfp version. Unpack the archive in c:/cygwin/opt/cross/x-tools so that the full path will look like this one c:/cygwin/opt/cross/x-tools/arm-unknown-linux-gnueabi.

Step 3. In order to upload the binaries we will compile to the Raspberry Pi, we need to enable an SSH server on the board. If you installed the Raspbian image, this operation is as easy as running the raspi-config command and selecting the ssh row. Once the server is running, you can use your username and password (default pi/raspberry) to access the Raspberry Pi from your Windows machine, using an SSH terminal.

Step 4. Download and install PUTTY (the full package), which is needed to talk to our Raspberry Pi using an SSH terminal. In order to upload our binaries to the Raspberry Pi and start the debugger, I thought of a little hack: I created a script which run as a post-build step in Eclipse (i.e. gets executed when the compilation successfully produces an artifact/binary) and uploads the file on the board using an SSH connection and executes a few commands after that (chmod and gdbserver). The following is the content of the BAT file, which you can save in a file and path of your choice. In my case I saved it to C:/Users/Dexter/Desktop/RaspberryPi/deploy_debug.bat, but any path will do.

[code gutter=”true”]@echo off

rem Check for a valid filename
IF "%1"=="" (
ECHO You have to provide a valid source file.

IF "%2"=="" (
ECHO You have to provide a valid destination path.

SET PUTTYSCP_BIN="C:\Program Files (x86)\PuTTY\pscp.exe"
SET PUTTY_BIN="C:\Program Files (x86)\PuTTY\putty.exe"
SET PASSWORD=raspberry

rem Upload the file to raspberry pi

rem Build a list of actions to do on the pi (chmod, execute GDB server)
if exist %~dp0%CMD_FILENAME% del %~dp0%CMD_FILENAME%
rem echo rm "%2" >> %~dp0%CMD_FILENAME%
echo chmod +x "%2" >> %~dp0%CMD_FILENAME%
echo gdbserver :3785 "%2" >> %~dp0%CMD_FILENAME%

rem Execute the action list on the raspberry pi

exit /b %ERRORLEVEL%[/code]

After saving the file, the following settings needs to be tweaked:

  • PUTTYSCP_BIN – The full path to pscp.exe, part of the Putty bundle, used to securely copy files over a SSH connection.
  • PUTTY_BIN – The full path to putty.exe, part of the Putty bundle, used to execute commands on a remote host over a SSH connection.
  • RASPBERRYPI_ADDR – The IP address of the Raspberry Pi
  • USERNAME – The username of the user who will authenticate on the Raspberry Pi
  • PASSWORD – The password 🙂
  • CMD_FILENAME – The name of the file which will contains all the commands to be executed on the Raspberry Pi. You don’t want to change that, it’s not really nedded.

Step 5. Download and install Eclipse IDE for C/C++ Developers (CDT). Create a sample “Hello World” project, let’s say its name is “RaspHelloWorld”. Open the project properties by right clicking on the project name inside the Project Explorer. Configure the project as follows.

C/C++ Build -> Environment

  • Add a variable named CYGWIN with value nodosfilewarning.
  • Append c:\cygwin\opt\cross\x-tools\arm-unknown-linux-gnueabi\bin;c:\cygwin\bin; to the beginning of the PATH variable.

C/C++ Build -> Tool Chain Editor

  • Select Cygwin GCC from Current toolchain dropbox.

C/C++ Build -> Settings -> Tool Settings

  • Set the Command field in Cygwin C++ Compiler to arm-unknown-linux-gnueabi-g++.
  • Add an include path in Includes which points to c:\cygwin\opt\cross\x-tools\arm-unknown-linux-gnueabi\arm-unknown-linux-gnueabi\sysroot\usr\include.
  • Set the Command field in Cygwin C Compiler to arm-unknown-linux-gnueabi-g++.
  • Add an include path in Includes which points to c:\cygwin\opt\cross\x-tools\arm-unknown-linux-gnueabi\arm-unknown-linux-gnueabi\sysroot\usr\include.
  • Set the Command field in Cygwin C++ Linker to arm-unknown-linux-gnueabi-g++.
  • Add a library search path in Libraries which points to c:\cygwin\opt\cross\x-tools\arm-unknown-linux-gnueabi\arm-unknown-linux-gnueabi\sysroot\usr\lib.

C/C++ Build -> Settings -> Build Steps

  • Set the Command field in Post-build steps to C:/Users/Dexter/Desktop/RaspberryPi/deploy_debug.bat $(OutDir)${ProjName}.a “/home/pi/projects/${ProjName}.a”.
  • Add a brief description inside the Description field.

C/C++ Build -> Settings -> Build Artifact

  • Set Artifact Extension to .a

Step 6. Compile your sample project. If everything went smoothly, your Console output in Eclipse should also print something about the binary uploading and command execution. Now it’s time to setup a Debug Configuration. Select Run -> Debug configurations from the top menu. Right click on C/C++ Remote Application and choose New to add a new configuration.

Main tab

  • Set the C/C++ Application field to the name of the produced binary (in my case to Debug/RaspHelloWorld.a).
  • Select Disable auto build.
  • Click on Select other…, near the left of the Apply button. From the newly opened window, choose GDB (DSF) Manual Remote Debugging Launcher and click ok.

Debugger tab

  • Set the GDB debugger field to the path of the gdb which is part of our downloaded tool chain, that is to say c:\cygwin\opt\cross\x-tools\arm-unknown-linux-gnueabi\bin\arm-unknown-linux-gnueabi-gdb.exe.
  • In the Connection sub tab, set the Type to TCP, the Host name or IP address field to the IP address of the Rapsberry Pi (the same you specified in the BAT settings) and Port number to 3785.

Click on Apply and then Debug. The debugger should start and Eclipse should switch to the Debug Perspective. We made it 😉 If you have any issue and it doesn’t work as expected, feel free to post a comment below!

Update 01/11/2012: As suggested in the comments (thanks Ivo), disabling the “Automate discovery of paths and symbols” option for the C and/or C++ compiler could fix the problem with missing cout or endl. This option can be found in the project properties “c/c++ Build/Discovery Option”. Once disable, click on the “Clear” button to remove all the unwanted include paths introduced into the project.


Alessio Placitelli