Friday, August 28, 2015

Compiling Arduino sketchs on Galileo/Edison from command line

For some time I've been playing around the idea of compiling and executing Arduino sketches right from the Galileo and Edison. In this post I'll detail out the method that I used to accomplish this task and will also note down the investigation that I had to do in order to do this.


Observe the logs:
In effect, what we are trying to do here is same as what the Intel Arduino IDE does but only that we are not really cross compiling the sketch, instead we will be directly compiling it on the Edison.
First thing to do is to get the Arduino IDE from here. Start the IDE and goto "File->preference" and enable "Show verbose output during: compilation"

From "Tools->Boards" select Edison.

Then clicked on the "verify" button to start the compilation process now the console window at the bottom will have all the logs. This is the process that has to be replicated on the Galileo/Edison.

The things to be inferred from the logs are:

  • A library file is created using files in the "Hardware/Arduino/" directory

    • These files contain function definitions that we can use in our sketches such as digitalWrite()...



  •  Also the pin defines are taken from a file located within "variants/edison_fab_c"

    • I believe that this the version of silicon that got released and all the required pin mux defines and pin configs are here

    • A "C" file implements board specific features in this folder



  • This log contains reference to sys root

    • I am not sure what this option does but I am assuming that this is to point to the general root FS for the target system since we are going to compile it on board, I've decided to remove this option and it seems to work fine.



  • Also the options passed to the GCC compiler was noted

  • The "main.cpp" is the application's entry point gets compiled into the library

    • Upon inspection, this function revealed that the "setup()" and "loop()" functions are called from here (within main).




I copied the "hardware" folder within the "arduino" directory onto by Edison's local directory called "arduino".
Once done, next step was to write a simple sketch and compile and run it.

Enter scons:
Instead of writing lengthy Makefiles to accomplish the above task, I chose to use scons. I had never used scons and saw this exercise as an opportunity to use scons. scons is like automake on steroids. It is real simple to use and did I say that you can use normal Python statements in this file and that would get executed?
Download scons from here extract it and copy the folder to your Galileo/Edison.
Install the scons from the source:

cd scons-2.3.6
python setup.py install


Following is the "SConstruct" file (scons' equivalent of Makefile of make) that I used:
https://gist.github.com/navin-bhaskar/4803f040c7f1d0bc22dc
The repo is located here: https://github.com/navin-bhaskar/arduino-sketch-on-GalileoEdison
Using the "board" variable you can specify your target board based on this, appropriate options and source files are selected for compilation.

If you need to add additional files for compilation, you can do that by naming the source files in the second argument list to env.Program().

env.Program('sketch.elf', [ c/c++ files here, 'libcore.a'], CCFLAGS=output, LIBS=['pthread', 'm'])
 


Once the compilation process is done, the final executable file, sketch.elf will be created you can execute it using the following command:

./sketch.elf

By default, blink.cpp will be compiled.
The executable created with this file should blink LED connected to port D5.
But if you were to run this executable, it would exit and you would see no blinking.
This is when I decided to use the tricks I learned from this cool talk and used strace.

strace ./sketch.elf

This will output the function calls and program operation in human readable form:


We already know that the sketch's entry point should be in "main.cpp" located in "hardware/arduino/x86[edison]/cores/arduino/main.cpp". Let's open it up and do a side by side comparission of the strace's output:

So it becomes evident here that the execution took this path and exited with status code. The condition for this to happen is if 'argc<2'. Now argc is the variable that holds number of command line arguments passed to the application. Further inspecting the code reveals that main.cpp expects two command line arguments which are the binary name and the serial port name ( port used to download binary from host as inferred from line 64 in main.cpp) since we are not bothered about these two args, let us just run the program with dummy args

./sketch.elf foo bar 

and indeed the LED blinks. You can exit this program by hitting ctrl-c;
of course I could have directly analyzed the source for getting around this but using strace helped me to pinpoint the problem more quickly and easily.
In case you were wondering where the "printf()"s of the main.cpp are going as you can see in the above snapshots that there are printf()s but you do not see any output at the console when you run the compiled sketch. These prints go to the file " /tmp/log.txt" the stdout is assigned to this file at the very beginning of the "main.cpp"

cat /tmp/log.txt

You can use "blink.cpp" as a template for writing your own sketches.

Difference from Arduino Galileo build:
The option "-mquark-strip-lock=yes" was not supported by the on board compiler I am not sure what this option does but I am assuming that this is related to the lock instruction bug in the quark. To proceed with compilation, I removed this option I have not yet encountered any issues due to this.
If some one can enlighten me on this, your help will be much appreciated.  

















1 comment:

  1. […] server being hosted by Edison from within the blockly interface, one should be able to upload and execute the generated Arduino […]

    ReplyDelete