The second bullet of this week’s 2-Bullet Tuesday! Check out the first bullet here. Subscribe to receive the newsletter on the 2-Bullet Tuesday page!
Omega Tip
We’re continuing our series on cross-compiling programs for the Omega2. A couple weeks ago, we covered how to cross-compile a hello world C program. This week, we’ll be showing you how to cross-compile more complex C programs that make use of external libraries!
In this example, we will write and cross compile a program that will read and print the input value on a user-specified GPIO once a second for 20 seconds. Our program will use the ugpio
library to interact with the GPIOs. See our c-cross-compile-example repo on GitHub for the code.
You may ask, why do I need to cross-compile this program when I already know how to compile C programs on my Omega?
Well, as a space saving measure, header files for libraries that are not regularly part of the C standard library are not included on the Omega’s filesystem. So we are not be able to compile programs that make use of external libraries directly on the Omega, the compiler would complain that it can’t filnd the ugpio/ugpio.h
header file.
However, the Omega’s filesystem does include shared object files of many external libraries, including ugpio
(see /usr/lib
on your Omega). This means that compiled programs that use these libraries can be executed on the Omega, if they have been previously cross compiled on a system that has all of the required header files and shared object files.
Cross Compilation Process
Head to your omega2-source
Docker container and let’s dive in! Go to the /root
directory and we’ll start by cloning the repo that has the C code:
git clone https://github.com/OnionIoT/c-cross-compile-example.git
Now that you have all of the code, you’ll notice that there’s a makefile
as well as a xCompile.sh
script. The makefile
is fairly standard as far as makefiles go, it’s the xCompile.sh
script that makes all of the cross compilation magic happen. It’s responsible for invoking the makefile in such a way that:
- The compilers are set to the cross-compilers created by the LEDE build system
- The compilation and linking flags are set to allow compilation of programs that use external libraries
For more details on how the xCompile.sh
script works its magic, check out the README in the repo, or take a look at the script itself.
Since we love to write code that’s reusable, the script takes two arguments:
- The location of the LEDE build system (so it knows where to look for the cross-compiler and the header files & static object files for any external libraries)
- The names of any libraries that are used by the program
So, the script should be called like this:
sh xCompile.sh -buildroot ‹PATH TO BUILD SYSTEM› -lib ‹REQUIRED LIBRARY›
A Small but Important Note
We keep mentioning that the program will use the ugpio
library. In order for this to be possible, the library must first be compiled by LEDE build system.
If you’re using our omega2-source
Docker image or building based on our source
GitHub repo, you’re all good as it’s selected for compilation by default.
If not, you’ll have to run make menuconfig
in the build system to select the libugpio
package to be compiled and then compile it by running make
.
Back to Cross Compiling
Ok, let’s run our cross compilation script. If you’re following along in the omega2-source
Docker container, the following command is what you should run:
sh xCompile.sh -buildroot /root/source/ -lib ugpio
As you can see from the output, we now have a gpioRead
executable file. Let’s take a closer look at this file:
root@6cef4c9123cb:~/c-cross-compile-example# file gpioRead gpioRead: ELF 32-bit LSB executable, MIPS, MIPS32 rel2 version 1, dynamically linked, interpreter /lib/ld-musl-mipsel-sf.so.1, not stripped
Success! It’s a MIPS executable!
Getting the Program to the Omega
To get this program onto your Omega, transfer the gpioRead
binary executable file to https://transfer.sh/
and then download it on your Omega.
curl --upload-file ./gpioRead https://transfer.sh/gpioRead
It will upload the file and output a link you can use to download the file.
Now switch over to your Omega and we’ll download the executable using the wget
command:
root@Omega-F16B:~# wget https://transfer.sh/MVr7R/gpioRead --2017-10-10 15:48:25-- https://transfer.sh/MVr7R/ gpioRead Resolving transfer.sh... 51.15.75.10, 2001:bc8:4700:2000::4423 Connecting to transfer.sh|51.15.75.10|:443.. . connected. HTTP request sent, awaiting response... 200 OK Length: 9804 (9.6K) [] Saving to: 'gpioRead' gpioRead 100%[===== ============================== ============================== === ============================== =================>] 9.57K --.- KB/s in 0.005s 2017-10-10 15:48:27 (1.79 MB/s) - 'gpioRead' saved [9804/9804]
One last step, we’ll need to change the downloaded file’s permissions to make it executable:
chmod +x gpioRead
Another Small but Important Note
Our gpioRead
executable was compiled with the ugpio
library dynamically linked. So, when the gpioRead
program executes, it will be looking for the libugpio
shared object when it needs to execute code from the library.
What that means is that for the gpioRead
program to run properly, your Omega needs to have the libugpio
package installed. If you’re using an Onion firmware, you’re all good since it comes with libugpio
by default. If not, you’ll have to use opkg
to install it.
Running the Program
Back to the show: you’re all set to run your cross-compiled program! Select the GPIO that you would like to read and let’s run the program:
root@Omega-F16B:~# ./gpioRead 1 > setting to input > begin reading GPIO1 > Read GPIO1: value '1' > Read GPIO1: value '1' > Read GPIO1: value '0'
It will read the input value on the specified GPIO 20 times in a row and display it on the command line.
Try running a jumper wire from your GPIO to GND, starting the program, and then moving it from GND to 3.3V after a while.
You’ve Made It!
So now you’ve successfully cross compiled your second program, one that has a makefile
and uses an external library! Now, it’s your turn to make some awesome projects and share them with us! Try using some of the C Libraries we’ve made! Happy Hacking!
Thanks for reading & have a great week!
Have you seen the Omega2S, the smaller and surface-mount version of the Omega2 for high volume commercial and industrial OEMs? See our Omega2S page for more details!
Let us know what kind of stuff you would like to see featured on 2-Bullet Tuesday! Send a tweet to @OnionIoT with your suggestions!
P.S. We can still hardly believe it! The Omega2 family is now available on SparkFun!