Tag Archives: toolchain

LinkIt Smart 7688 Toolchain with OpenWRT

My last post was about how to get the LinkIt Smart 7688 embedded Linux module running and updating the firmware. This post in the series is going to explain the next step in the embedded development sequence, getting a cross compiler GCC toolchain working for the target to start developing software in C and C++.

A cross compiling toolchain is a crucial piece in any embedded development effort. While the LinkIt has programming languages built in such as python, lua, and node, many times system programmers need a native C/C++ toolchain to program low level fast systems. Many embedded platforms, such as the RaspberryPi, come with a toolchain already built and running on the system. This is handy for quick development but you are limited to compiling on the target processor, in this case 580MHz which can be a slow and painful process. A cross compiler is a compiler that runs on a PC and generates binary programs that run on a different machine. The LinkIt is a MIPS processor, so we need a compiler that runs on a typical PC (Most likely x86_64) and generates programs that run on MIPS.

The OpenWRT SDK Toolchain

OpenWRT’s build system is based on Buildroot, a set of tools for generating embedded Linux systems. The Buildroot system downloads all the packages needed for a system, compiles them for the target and builds an image. To compile the packages Buildroot downloads and makes a cross compiler toolchain which we can use for our system! OpenWRT does a great job of putting all the toolchain pieces together in an SDK when the image is built. Because the LinkIt is based on the ramips target of the 15.01 Chaos Calmer, the SDK is available on the build root servers. You can find the packages here: https://archive.openwrt.org/chaos_calmer/15.05.1/ramips/mt7688/ . On a 64bit Linux system, simply download the OpenWrt-SDK-15.05.1-ramips-mt7688_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64.tar.bz2 file and decompress it. Windows cross compilers do exist or can be built but are outside of the scope of this post.

The OpenWRT SDK contains the GCC compiler, plus all the other tools needed to link and package binary files. The SDK also contains all the libraries required to link a Linux application such as the C library (LibC), pthreads, librt, etc. You will find the tools in the following locations in the bz2 package:

  • GCC Compiler: staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/bin
  • GCC libraries (RFS): staging_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2

Using the Toolchain

Lets make a ‘hello world’ application for the LinkIt with the OpenWRT SDK toolchain. Create a test file:

#include
int main(int argc, char ** argv)
{
printf(“Hello world\n”);
return 0;
}

Now compile the test program with the toolchain from the SDK:

<PATHTOBIN>/mipsel-openwrt-linux-gcc -c test.c -o test.bin

There should be no errors or warnings when you do the compile, and the output will be test.bin, an application that will only run on the LinkIt. The compiler also wanted the STAGING_DIR environment variable set with ‘export STAGING_DIR=<PATHTOSTAGINGDIR>’. You can confirm that the binary is for MIPS with the ‘file’ command:

file test.bin

Simply copy the binary file to the Linkit /root/ directory and run with ./test.bin. If your Linkit is connected to the network you can copy using scp.

scp test.bin root@<IP_ADDRESS>:/root/

Running the binary with ./test.bin from the /root/ directory and you should see the “Hello world” output.

Cross compile for Raspberry Pi, VideoCore, MMAL

I have a project which requires full control of the camera board on a Raspberry Pi from a custom C application, so I recently started looking into getting a toolchain and code running on the Pi. The Raspberry Pi is actually a really powerful and advanced SBC, with a full Broadcom VideoCore GPU and a connection to a 5MP camera that can do full 1080 HD video at 30 FPS. The project I am working on takes a single picture from the camera and saves it to the flash. I could use the raspistill application and some bash scripting, however I want full control over the camera and since eventually I will be processing video from a camera, the access should be as fast as possible by using the GPU. The first step was to build a tool chain and cross compiler to get things working, and then make a test application that uses the Multi-Media Abstraction Layer (mmal) library to access the VideoCore (VC) pipeline. I followed these two articles on how to use crosstool-ng to make a crosscompiler for the Pi. The next step was to make a simple application with some hooks into mmal and link it against the mmal libraries. It turns out the easiest way to build the mmal libraries is to clone the userland code for the Pi and build it locally using your new crosscompiler. I modified the cmake file in the makefile/cmake/toolchain/ directory to point to my custom crosstool-ng compiler rather than the compiler from git (Here are my modified buildme and cmake files).

Everything built successfully and the final step was to add in some mmal variables and function calls and build against the mmal libraries. This was more of a pain than I thought it was going to be. There are like 6 libraries that need to be preferences and 5 include paths for the VideoCore and mmal paths. After a few hours of searching and trial and error I found the correct include paths and library paths for GCC and the linker. One really annoying part was the fact that you have to explicitly add ALL libraries to the ld command, even if they are dependencies of libraries and the .so file is in the same directory as an already linked .so file. Take a look at this image and you will get the idea, all was fixed when I added -l entries for each missing lib. Here is what you need to build and link against if you want to access the camera on the Pi via mmal using VideoCore.

Include paths:
-I ../userland/
-I ../userland/build/inc/interface/vcos/
-I ../userland/host_applications/linux/apps/raspicam/
-I ../userland/host_applications/linux/libs/bcm_host/include/
-I ../userland/interface/vmcs_host/linux/
-I ../userland/interface/vcos/pthreads/
-I ../userland/interface/vcos/

Library include path:
-L ../userland/build/lib

Libraries to link:
-lmmal_core
-lmmal
-lmmal_util
-lvcos
-lcontainers
-lbcm_host
-lmmal_vc_client
-lmmal_components
-lvchiq_arm