Embedded linux development and remote debugging using Eclipse IDE

In previous post we explained ways to speed up embedded linux development process. By reducing source code compilation time (10x) and time to deliver changed code to target hardware we increased speed of development. 2-3 minutes to compile and deliver changes instead of 30-40 minutes gave us way not only grow up productivity but also made it possible to enjoy  development process since very long painful routine process that used to be real torture are now performed in a matter of minutes. But there are still lack in usability of tools used to develop embedded linux source code. Absence of  any IDE and ways to debug source code still makes it hard to build working processes efficient enough. In this post we describe steps we passed to start using Eclipse for C/C++ as IDE that let’s as develop source code for embedded linux and make debugging on remote hardware.

Our main repo will be used here as source code that we worked on during experiments with Eclipse. Distributive we are using is OpenWrt. But it should be quite similar for other commonly used embedded linux distributives.

So, we started from scratch. From simplest Hello world package.

Toolchain Preparation

But before it we need to get toolchain. We are compiling them from source code so clone them:

$ git clone https://github.com/wireless-road/imx6ull-openwrt.git
$ cd imx6ull-openwrt

and start compilation of any existing configuration with only goal — is compile toolchain that will be used later for compilation and debugging source code we will debug remotely:

$ ./compile.sh audio_stream_wifi
$ ls -la staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-7.5.0_musl_eabi/bin/

-rwxr-xr-x 1 al al 1130880 авг 6 16:27 arm-openwrt-linux-muslgnueabi-addr2line
-rwxr-xr-x 2 al al 1168544 авг 6 16:27 arm-openwrt-linux-muslgnueabi-ar
-rwxr-xr-x 2 al al 2071544 авг 6 16:27 arm-openwrt-linux-muslgnueabi-as
-rwxr-xr-x 2 al al 4619792 авг 6 16:30 arm-openwrt-linux-muslgnueabi-c++
-rwxr-xr-x 1 al al 1129960 авг 6 16:27 arm-openwrt-linux-muslgnueabi-c++filt
-rwxr-xr-x 1 al al 4613176 авг 6 16:30 arm-openwrt-linux-muslgnueabi-cpp
-rwxr-xr-x 1 al al 46256 авг 6 16:27 arm-openwrt-linux-muslgnueabi-elfedit
-rwxr-xr-x 2 al al 4619792 авг 6 16:30 arm-openwrt-linux-muslgnueabi-g++
-rwxr-xr-x 2 al al 4609384 авг 6 16:30 arm-openwrt-linux-muslgnueabi-gcc

-rwxr-xr-x 1 al al 1130816 авг 6 16:27 arm-openwrt-linux-muslgnueabi-strings
-rwxr-xr-x 2 al al 1287552 авг 6 16:27 arm-openwrt-linux-muslgnueabi-strip

That utilities will be used for cross compilation.

Hello world from command line

Let’s create simple helloworld program:

$ mkdir package/helloworld/src
$ touch package/helloworld/helloworld.c
$ cd package/helloworld/src

Then open helloworld.c using any editor and enter following:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char **argv) {
fprintf(stdout, «Hello world! \r\n»);
return 0;
}

Then compile source code and run it:

$ gcc -c -o helloworld.o helloworld.c -Wall
$ gcc -o helloworld helloworld.o
$ ./helloworld
Hello world!

Next we will compile it for target hardware:

$ export STAGING_DIR=/home/al/imx6ull/imx6ull-openwrt/staging_dir/
$ ../../../staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-7.5.0_musl_eabi/bin/arm-openwrt-linux-muslgnueabi-gcc -c -o helloworld.o helloworld.c -Wall
$ ../../../staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-7.5.0_musl_eabi/bin/arm-openwrt-linux-muslgnueabi-gcc -o helloworld helloworld.o

Except and environment variable the only difference between compilation for host and cross compilation is usage of specific toolchain. Copy resulted executable to target machine using scp:

$ scp helloworld root@192.168.31.99:/

where 192.168.31.99 — is IP address of target and run it from target machine’s console:

# /helloworld
Hello world

Looks pretty simple.

So next step is do same things using Eclipse IDE.

Hello world using Eclipse

Open eclipse and create simple C/C++ Project:

embedded linux development

Select Cross GCC toolchain enter project name and press Next:

embedded linux development

Enter arm-openwrt-linux-muslgnueabi- to prefix field and path to staging_dir/toolchain-arm_cortex-a7+neon-vfpv4_gcc-7.5.0_musl_eabi/bin folder we got on previous chapter:

embedded linux development using eclipse

In generated project create src folder and helloworld.c file. Then type same code from previous chapter and compile project by pressing Project —> Build All:

embedded linux development using eclipse

Again, no STAGING_DIR environment variable is defined.

Make mouse right click on the project root folder  then: Properties —>  C/C++ Build —> Environment —> Add to add STAGING_DIR variable with same path to staging_dir folder in source code we cloned before:

embedded linux development using eclipse

Try to recompile the project again. Now it should be ok:

embedded linux development using eclipse

Copy resulted executable to target hardware and run it same way we did it before:

$ scp helloworld root@192.168.31.99:/

 

# /helloworld
Hello world

Great! Next we have to integrate resulted binary delivery to target hardware in Eclipse. But we have to recompile kernel image on target device to include sftp server and gdbserver in device image.

Image recompilation

type in the root folder of source code we cloned before:

$ make menuconfig

and enable openssh-sftp-server:

embedded linux development using eclipse

embedded linux development using eclipse

embedded linux development using eclipse

by pressing Y.

Then we have to enable gdbserver:

embedded linux development using eclipse

embedded linux development using eclipse

Exit and save changes.

Then recompile image:

$ make

Here we call make instead of ./compile.sh to keep changes we made in .config file used as configuration file during compilation process. After that you have to update firmware on target device using one of the possible ways: sysupgrade utility or nfs.

After that everything ready for final steps of integration Eclipse with remote device.

Eclipse configuration. SFTP.

First we will configure Eclipse to run resulted executable right on remote hardware by accessing it using SFTP. Press Run —> Run Configurations for that:

Then create C/C++ Remote Application by double click to C/C++ Remote Application row:

and connection to target device by pressing to New button in front of connection option:

Select SSH as connection type and provide IP address of target device. Select password based authentification (no password by default in our source code) and press Finish:

Next we need to provide path on remote hardware application executable to be copied to. Press to Browse button:

and select path.

So now we can press to Run button to run application on target machine. You should see something like this in Console window of Eclipse:

Switch to target console. Application binary file is there:

 

Eclipse configuration. Remote debugging.

Install gdb-multiarch utility on host machine:

$ sudo apt-get install gdb-multiarch

Then open Debug configuration window in eclipse:

It should be pre-configured on previous steps. So you just have to switch to Debugger tab:

Here you need just set GDB debugger field to gdb-multiarch and clean GDB command file field. Everything is ready. Press to Debug button. Eclipse should ask for switching to Debug perspective:

It is working! We can walk through the code line by line!

In next chapter we will debug Makefile based OpenWrt’s package.