Monday 20 March 2017

How to Cross Compile for the Raspberry Pi 1, 2, and 3 in Linux.


Raspberry Pi cross compile

NOTICE: THIS BLOG HAS MOVE TO GRAFT ROBOTICS BLOG PAGE, AS PART OF THE NEWLY FORMED GRAFT ROBOTICS COMPANY.

If you usually compile your code directly on the raspberry pi, you can save a lot of time by setting up cross compiling. This basically means compiling your code on a different architecture (most commonly your desktop/laptop), but it will be run on a different architecture, specifically on the arm processor of the Raspberry Pi. Your desktop computer should be able to compile the code much faster than the pi, saving you a lot of time. I have tried a few ways of cross compiling, and I have found the following setup to be most useful. I have applied this method with the Raspberry Pi 1, but it should work for the Raspberry Pi 2 and 3. If you are interested in a low cost solution for controlling a GoPro while attached to a drone, RC car, camera trap, or for a custom home project using a Raspberry Pi, check out our FREE GoPie software.
What You Need
  • Laptop or desktop computer running some Linux based distro (I am using Lubuntu); this is known as your "host" for cross compiling.
  • Internet connection to your PC.
  • Raspberry Pi (I am using the Raspberry Pi B+)
  • Wifi or Ethernet connection between the PC and the Pi.
Software Overview
The cross compiling software that you will need consists of the following.
  • Pi toolchain: these are software development tools used on the Pi; such as GCC, binutils, glibc, etc.
  • Git: git is a version control repository service (it will be used to download the Pi toolchain)
  • SD card image: this is of the pi operating system; such as Raspbian. All the standard system libraries will be available on here.
  • Additional libraries: libraries required that are not within the sd card image.
Install Packages on your PC
Open up a terminal (Ctrl+Alt+t) and enter the following commands:
Git:
  • $ sudo apt-get install git
Create a Directory Structure
I use the following directory structure to hold all the cross compiling files. You can modify this to suit your own preferences. The structure is as follows:
/home/rasppi_xcompile: all the cross compile related files
/home/rasppi_xcompile/extra_libs_srcs: source files of additional libraries
/home/rasppi_xcompile/extra_libs_install: install files of additional libraries
/home/rasppi_xcompile/sd_card_images: pi operating system sd card images
/home/rasppi_xcompile/sysroot: holds the mounted sd card image
/home/rasppi_xcompile/tools: Pi toolchain files
You can create this directory structure by doing the following (note that the tools folder will be automatically created when downloading the toolchain):
  • open up a terminal
  • $ cd /home
  • $ sudo mkdir rasppi_xcompile
  • $ cd rasppi_xcompile
  • $ sudo mkdir extra_libs_srcs
  • $ sudo mkdir extra_libs_install
  • $ sudo mkdir sd_card_images
  • $ sudo mkdir sysroot
Toolchain
First download the Raspberry Pi toolchain (this will create the tools folder):
  • $ cd /home/rasppi_xcompile/
  • $ sudo git clone https://github.com/raspberrypi/tools
The Linux operating system on your PC needs to know where the pi toolchain is located in order to use it. This requires adding the directory of the pi toolchain to an environment variable called PATH. You can do this manually, but it is more convenient for it to be done every time a new shell is created. This is done by adding the following commands at the end of the file "/etc/bash.bashrc" (for a 32 bit PC remove the text "-x64"):
export PITOOLCHAIN=/home/rasppi_xcompile/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
export PATH=$PATH:$PITOOLCHAIN
Now when you open up a new terminal, the above commands will be applied. You can test it by opening a new terminal and typing in "arm" and then pressing tab twice to see if any further "arm.." options display in the terminal.
Mount the SD Card Image
First download the sd card image of the Raspberry Pi operating system (I used Raspbian Jesse Lite) and place it in the folder /home/rasppi_xcompile/sd_card_images (you should also be using this on the actual sd card of your pi):
  • $ cd /home/rasppi_xcompile/sd_card_images
  • $ sudo wget https://downloads.raspberrypi.org/raspbian_lite_latest
  • $ sudo unzip image_name.zip
Insert the zip image name in place of "image_name" above. Before mounting the image, you need to calculate an offset, which is used to mount only the operating system portion of the image.
  • $ cd /home/rasppi_xcompile/sd_card_images
  • $ fdisk -l image_name.img
As before, insert the unzipped image name in place of "image_name" above. The last command will provide you with something like this:


The second internal image is of the operating system, which you should mount. Calculate the offset by multiplying its start value by the sector size (for the above image 98304*512 = 50331648). The image can then be mounted as follows:
  • $ sudo mount -o loop,offset= image_name.img
In my case this resulted in:
  • $ sudo mount -o loop,offset=70254592 /home/rasppi_xcompile/sd_card_images/2016-05-27-raspbian-jessie-lite.img /home/rasppi_xcompile/sysroot/
The image needs to be mounted during the compilation process. To do it automatically at startup of your PC, you will need to create a startup script in /home/rasppi_xcompile/. I called mine sdmount.sh with the following contents:
#!/bin/sh
mount -o loop,offset=70254592 /home/rasppi_xcompile/sd_card_images/2016-05-27-raspbian-jessie-lite.img /home/rasppi_xcompile/sysroot/
Give the file permissions:
  • $ sudo chmod +x mystartup.sh
Most recent linux operating systems use systemd, which requires a service file for startup scripts. Create the file sdmount.service in the directory /lib/systemd/system/ with the following contents:
[Unit]
Description=Raspberry Pi SD card mounting service
After=multi-user.target
[Service]
Type=idle
ExecStart=/home/rasppi_xcompile/sdmount.sh
[Install]
WantedBy=multi-user.target
Activate the startup script:
  • $ sudo systemctl daemon-reload
  • $ sudo systemctl enable sdmount.service
Reboot for the changes to take place.
Additional Libraries
There are a few options for dealing with additional libraries. In every option you will need the header and the static (.a) or shared object (.so) files. The header and library files should then be placed in the directory /home/rasppi_xcompile/extra_libs_install. You can also compress the library and header files separately as backups. The quickest options are listed first.
Option 1: Install on the pi and copy to PC
You can apt-get install the libraries directly on the Raspberry Pi. The .so and .a files should be located on the pi in the directories /usr/local/lib or /usr/lib, and the header files should be found in /usr/local/include or /usr/include. Copy these to your PC in the directory /home/rasppi_xcompile/extra_libs_install.
Option 2: Cross compile
You can download the library source files and then cross compile them to generate the library and header files. Most cross compiling methods have an install directory option, which you can set as /home/rasppi_xcompile/extra_libs_install.
Option 3: Compile on the Pi
You can download the source code onto the Pi and then compile it. This option will obviously take longer to compile.
Compiling
The following compilation example is for a test program written in C++. Usually a makefile system is used to handle the make process, but this will be simplified to a test program and compiling it via terminal commands. First create a test program in the file main.cpp, in any directory, with the following contents:
#include <iostream>
int main()
{
std::cout << "Hello world" << std::endl;
return 0;
}
Cross compile the program:
"arm-linux-gnueabihf-g++" is the gcc arm compiler followed by a number of flags. From "-std=c++11" to "-L/rasppi_xcompile/extra_libs_install/" are compiler flags based on the directory structure we created earlier, and the architecture of the Raspberry Pi 1; you will need to modify these for the Pi 2 and 3.  At this point any additional library names should be added (eg. -lwiringPi), but none are used in this test program. "-o testprog main.cpp" specifies the name of the resulting binary and that main.cpp is the source file.
Testing
The final step is copying all the necessary files onto the Raspberry Pi and running the compiled program.  You can use the sftp command as follows:
  • $ sudo sftp <pi username>@<pi ip address>
  • eg. $ sudo sftp pi@192.168.8.100
  • $ mput <list of files>
  • eg. $ mput *.h
Copy the header files from your PC in /home/rasppi_xcompile/extra_libs_install to the Pi in /usr/local/include. Copy the library files from your PC in /home/rasppi_xcompile/extra_libs_install to the Pi in /usr/local/lib. Copy the test program from your PC to some directory on the Pi. Create a shell session to the pi and run the test program:
  • $ sudo ssh <pi username>@<pi ip address>
  • eg. $ sudo ssh pi@192.168.8.100
  • $ ./testprog
And that is it!

Labels: , , , , ,

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home