Getting Started with Yocto on the Raspberry Pi

Introduction

I’ve been wanting to have a play with Yocto so decided to have a go at getting an image running on a Raspberry Pi. I found plenty of references but no step by step that just worked. This post just covers my notes on how to get going.

Development Machine

The Yocto Project Quick Start states “In general, if you have the current release minus one of the following distributions, you should have no problems”, then lists several distros including Ubuntu. I originally tried using Ubuntu 16.04, and had problems, I think because of the later version of gcc.

I used a clean install of Ubuntu 14.04 desktop running on a virtual machine, the rest of the process was actually pretty straight forward

Firstly I made sure that Ubuntu was fully patched

sudo apt-get update
sudo apt-get upgrade

Then following the Yocto Project Quick Start  I installed the required packages

sudo apt-get install gawk wget git-core diffstat unzip texinfo gcc-multilib build-essential chrpath socat libsdl1.2-dev xterm

I then disabled the dash shell in favour of the bash shell ( I did this because I saw it advised, not sure if this is required)

sudo dpkg-reconfigure dash

Getting the code and Building

At the time of writing krogoth is the latest version of Yocto, hence I am working with that branch. The raspberrypi meta data is not currently branched so I am working with the master branch. The first step is to clone yocto and meta-raspberrypi

mkdir yocto
cd yocto
git clone -b krogoth git://git.yoctoproject.org/poky.git poky
cd poky
git clone -b master git://git.yoctoproject.org/meta-raspberrypi

Now generate the default configuration files into the default directory build.

. oe-init-build-env build

Now we need to edit the build configuration. Firstly edit yocto/poky/build/conf/local.conf add these lines

MACHINE ?= "raspberrypi2"
GPU_MEM = "16"

MACHINE could also be set to raspberrypi, or to raspberrypi3 depending on your target hardware (The raspberrypi2 image should also run on an RPI3). The GPU_MEM setting allocates the minimum amount of memory to the GPU leaving the rest for the ARM processor. See the READEME in meta-raspberrypi for details of these and other options.
Secondly edit 
yocto/poky/build/conf/bblayers.conf and add meta-raspberrypi, mine looks like this

# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly
POKY_BBLAYERS_CONF_VERSION = "2"
BBPATH = "${TOPDIR}"
BBFILES ?= ""
BBLAYERS ?= " 
/home/david/yocto/poky/meta 
/home/david/yocto/poky/meta-poky 
/home/david/yocto/poky/meta-yocto-bsp 
/home/david/yocto/poky/meta-raspberrypi 
"

Now it’s time to build, it’s worth noting that the command oe-init-build-env doesn’t just create the configuration files and build directory – it also sets up the environment including the path, so if you build in a  new shell, or having logged in you need to re-run oe-init-build-env. It won’t overwrite the changes you’ve made to the configuration. So to build I cd to the poky directory and then

. oe-init-build-env build
bitbake rpi-basic-image

The build takes a long time the first time, potentially hours, numerous packages are fetched, when I build the first time I had a package fail to download because the git repository was unavailable, and the build failed. Just re-run the bitbake command. Assuming everything succeeds you should see output that looks like this

Parsing recipes: 100% |#########################################| Time: 00:00:22
Parsing of 891 .bb files complete (0 cached, 891 parsed). 1321 targets, 67 skipped, 0 masked, 0 errors.
NOTE: Resolving any missing task queue dependencies
Build Configuration:
BB_VERSION = "1.30.0"
BUILD_SYS = "x86_64-linux"
NATIVELSBSTRING = "universal"
TARGET_SYS = "arm-poky-linux-gnueabi"
MACHINE = "raspberrypi2"
DISTRO = "poky"
DISTRO_VERSION = "2.1.1"
TUNE_FEATURES = "arm armv7ve vfp thumb neon vfpv4 callconvention-hard cortexa7"
TARGET_FPU = "hard"
meta 
meta-poky 
meta-yocto-bsp = "krogoth:f5da2a5913319ad6ac2141438ba1aa17576326ab"
meta-raspberrypi = "master:2745399f75d7564fcc586d0365ff73be47849d0e"
NOTE: Preparing RunQueue
NOTE: Executing SetScene Tasks
NOTE: Executing RunQueue Tasks
NOTE: Tasks Summary: Attempted 2167 tasks of which 911 didn't need to be rerun and all succeeded.

The resultant sdcard image is found beneath the build directory, flash it to SDCard as you would any other image

tmp/deploy/images/raspberrypi2/rpi-basic-image-raspberrypi2.rpi-sdimg

Testing

Insert the media into your raspberry pi, attach keyboard and monitor, power on…

Screen Shot 2016-08-09 at 20.10.02

ssh is also available in this image, access is available as root with no password. Before doing anything else tighten up security.

Have fun…

VPN bridge from home network to AWS VPC with Raspberry Pi

Introduction and disclaimer

I wanted to extend my home network to a Virtual Private Cloud (VPC) within Amazon Web Services (AWS), primarily for use as a jenkins build farm. I have achieved this using a Raspberry Pi as my Customer Gateway device. This post covers the process of configuring the raspberry pi from scratch and AWS from scratch. I’m posting as a reminder to myself, hopefully others will find this useful.

NOTE: I found this post by Pahud Hsieh on hackmd.io very helpful while developing this. I have also relied heavily on the excellent documentation at http://aws.amazon.com/documentation/

I have a fairly standard home network on 192.168.0/24 with a router provided by my ISP.  This post uses a Raspberry Pi, on a static IP address within my home network as a VPN gateway. Allowing any devices on my home network to communicate with EC2 instances (virtual machines), running within my VPC.

Network Diagram

Network Diagram

Prerequisite

  • Raspberry Pi on a static IP address (in this example 192.168.0.30)
  • Home gateway IP address of you home network is static (My ISP doesn’t offer static IP addresses, however the address has not changed for years).
  • AWS account (I suggest also running some tutorials, the free tier is sufficient).

I’m starting with a clean install of Raspbian Jessie Lite, although other distributions of Linux should work.

Configuring VPC

Login to AWS, and select Services->VPC, this takes you to the VPC dashboard. Start the VPC Wizard

Screen Shot 2016-07-11 at 14.24.36

Choose VPC with a Private Subnet Only and Hardware VPN access and click Select.

Screen Shot 2016-07-11 at 14.27.49

 

Screen Shot 2016-07-11 at 14.33.15

 

Screen Shot 2016-07-11 at 14.37.54

Wait for the VPN to be created

Screen Shot 2016-07-11 at 14.41.53

Now on the left towards the bottom find the VPN Connections page and click the Download Configuration button at the top of the page

Screen Shot 2016-07-11 at 15.04.56

In the downloaded configuration file find the tunnel groups under the IKE section

!
! The tunnel group sets the Pre Shared Key used to authenticate the 
! tunnel endpoints.
!
tunnel-group <TUNNEL1_IP> type ipsec-l2l
tunnel-group <TUNNEL1_IP> ipsec-attributes
pre-shared-key <PSKEY_STRING>

You will need the <TUNNEL1_IP> and <PSKEY_STRING> values later, note them down.

Ensure that the static route to your home network exists in the VPN, Opne VPN Connections and select the Static Routes tab, it should show the CIDR for your home network. If not (my setup didn’t) click Edit and type in the CIDR.

Screen Shot 2016-07-12 at 10.17.03

 

 

 

Configure the Raspberry Pi

Enable the Random Number Generator

Edit /boot/config.tx and append

# Enable random number generator
dtparam=randon=on

Reboot and then install the random number generator tools

sudo apt-get install rng-tools

Install Openswan

sudo apt-get install -y openswan lsof

During package installation you get prompted about using X.509 certificates. I’m sure AWS supports these, for now I’m skipping for simplicity.

Screen Shot 2016-07-11 at 15.24.15

IPSec configuration

Edit /etc/ipsec.conf and set the content as shown below. NOTE this is including configuration files from /etc/ipsec.c/*.conf, this allows different files for different connections.

# /etc/ipsec.conf - Openswan IPsec configuration file
#
# Manual: ipsec.conf.5
#
# Please place your own config files in /etc/ipsec.d/ ending in .conf
version 2.0 # conforms to second version of ipsec.conf specification
# basic configuration
config setup
# Debug-logging controls: "none" for (almost) none, "all" for lots.
# klipsdebug=none
# plutodebug="control parsing"
# For Red Hat Enterprise Linux and Fedora, leave protostack=netkey
protostack=netkey
nat_traversal=yes
virtual_private=
oe=off
# Enable this if you see "failed to find any available worker"
# nhelpers=0
#You may put your configuration (.conf) file in the "/etc/ipsec.d/" and uncomment this.
include /etc/ipsec.d/*.conf

Create a configuration file for this connection, edit /etc/ipsec.d/home_to_aws.conf

conn home-to-aws
   type=tunnel
   authby=secret
   #left=%defaultroute
   left=192.168.0.30
   leftid=123.123.123.123
   leftnexthop=%defaultroute
   leftsubnet=192.168.0.0/24
   right=<TUNNEL1_IP>
   rightsubnet=10.0.0.0/16
   pfs=yes
   auto=start

Where

left – The IP address of your Raspberry Pi on your home network

leftid – The IP address of your home gateway

leftsubnet – the CIDR of your home network

right – the IP address of Tunnel1 in your AWS gateway.

right subnet – The CIDR of your VPC

Input the pre-shared key

edit/var/lib/openswan/ipsec.secrets.inc and set the content as below

123.123.123.123 <TUNNEL1_IP> : PSK "<PSKEY_STRING>"

Edit /etc/sysctl.conf

Append the following lines

net.ipv4.ip_forward=1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.default.accept_redirects = 0

Then run sysctl -p to reload it.

Check IPSec status

$ sudo ipsec verify
Checking your system to see if IPsec got installed and started correctly:
Version check and ipsec on-path [OK]
Linux Openswan U2.6.38/K4.4.11-v7+ (netkey)
Checking for IPsec support in kernel [OK]
SAref kernel support [N/A]
NETKEY: Testing XFRM related proc values [OK]
 [OK]
 [OK]
Hardware RNG detected, testing if used properly [OK]
Checking that pluto is running [OK]
Pluto listening for IKE on udp 500 [OK]
Pluto listening for NAT-T on udp 4500 [OK]
Checking for 'ip' command [OK]
Checking /bin/sh is not /bin/dash [WARNING]
Checking for 'iptables' command [OK]
Opportunistic Encryption Support [DISABLED]

 

Restart IPSec

sudo service ipsec restart

Check IPsec status

make sure an active connection is running

$ sudo service ipsec status
● ipsec.service - LSB: Start Openswan IPsec at boot time
Loaded: loaded (/etc/init.d/ipsec)
Active: active (running) since Mon 2016-07-11 17:56:40 UTC; 8min ago
Process: 1660 ExecStop=/etc/init.d/ipsec stop (code=exited, status=0/SUCCESS)
Process: 1746 ExecStart=/etc/init.d/ipsec start (code=exited, status=0/SUCCESS)
CGroup: /system.slice/ipsec.service
├─1840 /bin/sh /usr/lib/ipsec/_plutorun --debug --uniqueids yes --...
├─1841 logger -s -p daemon.error -t ipsec__plutorun
├─1842 /bin/sh /usr/lib/ipsec/_plutorun --debug --uniqueids yes --...
├─1845 /bin/sh /usr/lib/ipsec/_plutoload --wait no --post
├─1846 /usr/lib/ipsec/pluto --nofork --secretsfile /etc/ipsec.secr...
├─1853 pluto helper # 0 
├─1854 pluto helper # 1 
├─1855 pluto helper # 2 
└─1974 _pluto_adns
Jul 11 17:56:41 vpc pluto[1846]: "home-to-aws" #1: STATE_MAIN_I2: sent MI2,...R2
Jul 11 17:56:41 vpc pluto[1846]: "home-to-aws" #1: NAT-Traversal: Result us...ed
Jul 11 17:56:41 vpc pluto[1846]: "home-to-aws" #1: transition from state ST...I3
Jul 11 17:56:41 vpc pluto[1846]: "home-to-aws" #1: STATE_MAIN_I3: sent MI3,...R3
Jul 11 17:56:41 vpc pluto[1846]: "home-to-aws" #1: Main mode peer ID is ID_...4'
Jul 11 17:56:41 vpc pluto[1846]: "home-to-aws" #1: transition from state ST...I4
Jul 11 17:56:41 vpc pluto[1846]: "home-to-aws" #1: STATE_MAIN_I4: ISAKMP SA...8}
Jul 11 17:56:41 vpc pluto[1846]: "home-to-aws" #2: initiating Quick Mode PS...8}
Jul 11 17:56:42 vpc pluto[1846]: "home-to-aws" #2: transition from state ST...I2
Jul 11 17:56:42 vpc pluto[1846]: "home-to-aws" #2: STATE_QUICK_I2: sent QI2...e}
Hint: Some lines were ellipsized, use -l to show in full.

Start on reboot

sudo update-rc.d ipsec defaults

reboot the Raspberry pi and recheck the ipsec service status

Check VPC connection in the VPC console

Make sure Tunnel1 is UP

Screen Shot 2016-07-11 at 19.40.12

Redundancy

For increased reliability, add the second tunnel configuration to the RPI configuration

 

Create an EC2 Instance

To test the configuration Launch an EC2 instance into your VPC. As an example I’m launching the free tier Ubuntu server.

From the EC2 Dashboard select Launch Instance, select Ubuntu Server 14.04 LTS (HVM), SSD Volume Type, select t2.micro (Free Tier Eligible) then click Next: Configure Instance Details. Select your VPC as the Network.

Screen Shot 2016-07-12 at 09.31.01

Click Next: Add Storage, Next: Tag Instance, Next: Configure Security Group, Create a new security group and add the rules you require, the example below adds SSH and ICMP (ping) from my home subnet.

Screen Shot 2016-07-12 at 09.38.33

Click Review and Launch, Launch, create a new key-pair (or use existing if you prefer), Download the Key Pair and keep them safe. Launch and then View Instance. Wait for the Status Checks to complete.

Screen Shot 2016-07-12 at 09.48.25

Note the private IP address – in this example 10.0.1.19

From your Raspberry Pi you should now be able to ping the instance

$ ping 10.0.1.19
PING 10.0.1.19 (10.0.1.19) 56(84) bytes of data.
64 bytes from 10.0.1.19: icmp_seq=1 ttl=64 time=200 ms
64 bytes from 10.0.1.19: icmp_seq=2 ttl=64 time=204 ms

Adding local Routes

Devices on your home network that are to access the VPC need to have a static route added that identifies the Raspberry Pi as the gateway to use for 10.0.0.0/16.

On Linux based devices (including macs)

sudo route -n add 10.0.0.0/16 192.168.0.30

ssh access

copy the key file that you previously downloaded to the machine you want to open an ssh session from. Ensure the pen file has read only permissions.

chmod 400 jenkins_aws.pem

Open an ssh session using the key

ssh -i jenkins_aws.pem ubuntu@10.0.1.19

All being well you are now logged in to your EC2 instance.

 

Install Raspberry Pi img using OSX

Up to now I have used win32Diskimager.exe in a windows VM to program images onto SDCards for the Raspberry Pi. For some reason having not done this for a while it has stopped working for me, so I decided to program using OSX directly.

Downloading

Firstly I downloaded and unzipped the raspbian image in my Downloads folder, the image I downloaded and unzipped contained 2016-02-09-raspbian-jessie.img.
In the terminal on the mac

cd ~/Downloads
ls -l *.img

this showed
rwx—— 1 davidcozens staff 4127195136 20 Feb 13:11 2016-02-09-raspbian-jessie.img

Programming the SDCard

I inserted the SDCard into a USB card reader (The internal reader on my MBP didn’t recognise the card), then to identify which device OSX had mounted this as

diskutil list

The output looked like

/dev/disk0 (internal, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *1.0 TB     disk0
   1:                        EFI EFI                     209.7 MB   disk0s1
   2:          Apple_CoreStorage Macintosh HD            999.7 GB   disk0s2
   3:                 Apple_Boot Recovery HD             650.1 MB   disk0s3
/dev/disk1 (internal, virtual):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:                  Apple_HFS Macintosh HD           +999.3 GB   disk1
                                 Logical Volume on disk0s2
                                 A8176DD4-96DB-4F64-B013-EAA7D075A63B
                                 Unencrypted
/dev/disk2 (external, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *8.0 GB     disk2
   1:             Windows_FAT_32 boot                    62.9 MB    disk2s1
   2:                      Linux                         4.1 GB     disk2s2
/dev/disk3 (disk image):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        +1.6 TB     disk3
   1:                        EFI EFI                     209.7 MB   disk3s1
   2:                  Apple_HFS Time Machine Backups    1.6 TB     disk3s2
/dev/disk6 (external, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:                                                   *613.9 KB   disk6
Now BE VERY CAREFUL to identify the device corresponding to the SDCard. Using the wrong device name in the commands below could erase all of the data on your MAC. Look for the size that matches your SDCard. In my case /dev/disk2 is the SDCard, disk0 and disk1 are the internal HD on my MAC and disk6 is may backup device.
In the commands below I use /dev/diskx to represent the SDCard device name.
Unmount the SDCard

diskutil unmountDisk /dev/diskx

zero out the partition table

sudo dd if=/dev/zero of=/dev/rdiskx bs=1024 count=1

Program the SDcard

sudo dd if=2016-02-09-raspbian-jessie.img of=/dev/rdiskx bs=4m

ensure all data is synced

sync

You should now be safe to remove and use the SDCard.

Starting with CODESYS on the Raspberry Pi – Update

Last May I blogged about Starting with CODESYS on the Raspberry Pi. Since then I have found it a great teaching platform to help others learn CODESYS. My getting started tutorial is now a little out of date, so I thought I would reproduce it using current versions of software. This blog walks through the steps of installing CODESYS under Windows 10, installing the CODESYS for Raspberry Pi plugin, Installing the CODESYS runtime Raspbian and establishing communications.
Thanks to 3S the process is now much easier.

Installing CODESYS on Windows 10

Download CODESYS from https://www.codesys.com/download/  (You need to register, but then the download is free). Run the installer accepting all defaults

Installing CODESYS for Raspberry Pi

Download CODESYS for Raspberry Pi from the CODESYS Store http://store.codesys.com/codesys-control-for-raspberry-pi-sl.html. Again you have to register first, everything is contained within a single .package file
Installation is a two stage process, firstly installing the package within CODESYS, and then subsequently installing CODESYS on the Raspberry Pi.

Installing the CODESYS Package

Launch the CODESYS IDE, Tools->Package Manager… then Install…, browse to the Package previously downloaded. Accept the license and then accept the default on every menu in the installer. The package should install as shown, and CODESYS then needs to be restarted.

Preparing the Raspberry Pi

Ensure that you have the latest version of Raspbian installed on your Raspberry Pi.

New Install

3S give links on their download page http://store.codesys.com/codesys-control-for-raspberry-pi-sl.html and the First Steps pdf tells you how to setup the RPi for various different peripherals

Upgrade Raspbian

If you choose to upgrade, be careful of anything important, perform backups before you start. On the Raspberry Pi issue these commands to upgrade, then continue to install CODESYS as instructed below.

sudo apt-get updatesudo apt-get dist-upgradesudo rpi-update

Installing CODESYS on the Raspberry Pi

Launch CODESYS and then select Tools->Update RaspberryPi, enter the password for the Raspberry Pi, click scan.
If your RPi is found then select the IP Address from the dialog and click OK.
If your RPi is not found, it is possible to enter the IP Address manually, then click OK on the Update Raspberry Pi dialog – this will install the CODESYS runtime on your Raspberry Pi. Progress is reported in the bottom left corner of the CODESYS window.
The update only takes a few seconds, on completion check for messages

There should be a single message saying the Update has finished

Login the the Raspberry Pi and reboot it – now you are ready to test your installation.

Testing The Installation

Launch CODESYS and select New Project…
Select Standard Project and give the project a name, click OK.
Select the Device: as CODESYS Control for Raspberry Pi and the programming language to use, click OK. A project is then created with this content.
Double click on PLC_PRG (PRG) and create a simple program
Now try to login (Online->Login),
Click Yes to start a network scan. (For me this didn’t work – probably because I am running Windows in a virtual machine, if that happens manually type the IP address of your RPi into the box representing the device and hit Enter, your device should then be found).
Select Online->Login again, this time login and download should succeed, the program will be in the STOP state. Switch to the PLC_PRG tab and you should see your program and Variables at their starting values.
Select Debug->Start and the application will start running, you will ten see the variables changing.
Have fun…

Cross development using eclipse and GCC for the RPi

Introduction

When I decided to use eclipse to do some cross development for the Raspberry Pi hosted on windows I was surprised to find that I found lots of useful posts elsewhere that gave a part of the solution, or worked well on a Linux host. I found both of the sites below to be particularly helpful. http://www.gurucoding.com/en/raspberry_pi_eclipse/index.php
http://gnutoolchains.com/raspberry/tutorial/
My blog post Using google test with CDT in eclipse gives details on how to install eclipse CDT, which is an assumed starting point for this post.

Install GCC Cross compiler

It is possible to build your own GCC cross compiler, however this is a complex process and prebuilt versions are available. I choose to download from http://gnutoolchains.com/raspberry/, and selected raspberry-gcc4.6.3.exe to match wheezy raspbian. Installation was as simple as running the executable and accepting the terms of the license.

Synchronise header file and library versions

This step is required to ensure that the versions of headers and libraries used on the Raspberry Pi match those used by the cross compiler.
Run c:SysGCCRaspberryTOOLSUpdateSysroot.exe
Press Select… and setup a new SSH connection to your Raspberry PI (Mine is running a newly installed image and has the default username and password).
Click Connect and then save the key when prompted, then click Synchronize, wait while the headers and libraries are copied (This takes a few minutes).
NOTE: Whenever you update your RPi it is a good idea to resynchronize to ensure that your development environment remains in step with your target.

Configure eclipse for cross compilation

Open eclipse and in the Project Explorer right click and select New…->C++ Project. Select the Hello World C++ Project and Cross GCC, give the project a name.
Click Next> and customise as you wish
Click Next>
Click Next> and specify the cross-compiler prefix as arm-linux-gnueabihf- and cross-compiler path as C:SysGCCRaspberrybin.
Click Finish and then build the project, there should be no errors.

Configure RPi for gdb

Run SmarTY.exe from C:SysGCCRaspberryTOOLSPortableSmartty, and open the connection to your RPi.
Enter these commands
mkdir remote-debugging
Verify that gdbserver is on the path and the version of gdbserver that is installed
gdbserver --version

To automate the use of gdb on the target RPi it needs to have the DataStore server running. 
 
Download the server from http://download.eclipse.org/tm/downloads/index.php, I used the 3.6M4 release and downloaded rseserver-linux-3.6-M4.tar to the /tmp directory on the RPi. Following the install advice from the eclipse help I executed these commands on the RPi

sudo mkdir /opt/rseservercd /opt/rseserversudo tar xf /tmp/rseserver-linux-3.6-M4.tar

The daemon needs to be run as root, so it can be manually started by

sudo su
cd /opt/rseserver
perl ./daemon.pl &

To have it start automatically each time the RPi reboots, edit /etc/rc.local and just before the exit 0 at the end of the default file launch the server

cd /opt/rseserver
perl ./daemon.pl &

When the RPi reboots you should see a message that says

Daemon running on: raspberry, port: 4075 

Configure eclipse for Cross debugging

Right click on the HelloWorld project in the project explorer and New->File, set the name to .gdbinit and click Finish.
In the file set sys root to point to the cross tools set sysroot C:SysGCCRaspberryarm-linux-gnueabihfsysroot
 

In the project explorer right click on the HelloWorld project and select Debug As->Debug Configurations…, then select C/C++ Remote Application and click the New button (circled).

In the Debug Configurations Dialog the first step is to configure a connection to the Raspberry Pi, to do this, next to Connection: click New…
 
Select a Remote System type of Linux, and click Next>
Enter the IP address of your RPi in Host name:, name the connection and set a description, then Next>.
Click Next>

 

Click Finish, ensure that the Connection: is set to your new connection
Then click Browse… under Remote Absolute File Path for C/C++ Application:

 

Then try to expand My Home, you will be prompted for user credentials and certificates

 

 

 

Select the remote-debugging directory and click OK.

 

When the binary is transferred to the raspberry pi we need to ensure that it has execute permissions set, so in the Commands to execute before application enter chmod 777 /home/pi/remote-debugging/HelloWorld
Now in the Debug Configurations dialog select the Debugger tab and on the Main sub-tab browse to the arm-linux-gnueabihf-gdb.exe debugger.
Now select the Gdbserver Settings sub-tab, the default settings worked for me and looked like this.
Apply these settings, and Close.
Click Window->Perspective->Open Perspective->Other... select Remote System Explorer, and click OK.
In the Remote Systems tab right click on your connection and select Connect. (I found if I didn’t connect to the RPi before launching the debugger the launch would fail, retrying usually worked – but this is cleaner).
Now select Run->Debug Configurations, ensure your configuration is selected (it should be) and click Debug. You will be prompted to confirm the perspective switch, tick to Remember your decision and click Yes.

You should then see your application stopped on the first line and ready to be debugged

I have tested this setup with setting breakpoints, viewing disassembly, stepping into and out of functions and inspecting variables. It all seems to work, however I have not yet diagnosed the error Cannot access memory at address 0x0. I will update this post if/when I get to the bottom of it.

Clean error

If you don’t have rm.exe on your path you will see an error like this when you clean the project.
This can be resolved by downloading rm.exe as part of MinGW, find the path to rm.exe, (with a default install it is C:MinGWmsys1.0bin). Add this to the end of your windows PATH and restart eclipse.

Further Reading

If you find this tutorial helpful you may find my previous postings on eclipse helpful too
Unit testing with googletest
Code coverage with Gcov
Static analysis with CppCheck
I develop for RPi by having a unit test project that compiles and runs on my PC for speed, and then a cross compiled project that shares the same source code and runs on the RPi.
 
 




Backup and Restore Raspberry Pi to Synology DiskStation

Introduction

There are many articles on how to backup Raspery Pi systems, up to now I have relied on taking card images and storing these on a machine that is backed up. However it is all to easy to have a few hours of fun with the Raspberry Pi and then not get round to making a backup, I want something that is automated so that I don’t have to think about it.
The key goals for this backup strategy are:
1) Unattended backup
2) Warnings sent for backup failure [ToDo]
3) Rotating backups
4) Backup to my Synology DiskStation
5) Simple to add additional Raspberry Pi’s to the backup

References

None of this is particularly new, I have pulled together ideas that I’ve found in a number of other sources, all of these were helpful

Solution Overview

I have a Synology DiskStation with Raid disks that I backup all of my machines to, this post backs up to this server, the same basic approach should work going to any Linux server with small modifications.
cron is used on the server to invoke a script to perform the backup, the script is parameterised with the ip address of the Raspberry Pi to backup.
rsync is used to perform the actual backup.
ssh is used to securely connect to the Raspberry Pi.

Backing Up

Step 1 – root SSH access

We need the Synology DiskStation to have root access via SSH to the Raspberry Pi. Open up two SSH sessions, one to the DiskStation (as root) and one to the Pi (as your normal login e.g. pi).
1) In the Raspberry Pi Session first enable root login by setting a root password

sudo passwd root

Enter a password as prompted
Now we need to ensure that there is a directory to hold ssh keys.

su root

mkdir ~/.ssh

exit

2) In DiskStation session
First check to see if you already have a pair of SSH keys by running

ls ~/.ssh

 
If you don’t see a file called id_rsa.pub there you need to generate a pair of keys using this command

ssh-keygen -t rsa -C root@<Your Synology server’s name>

– When prompted for the file in which to save the key, accept the default (hit <Enter>)
– When prompted for a passphrase hit <Enter> (no passphrase)

Now push the public key to the Raspberry Pi (this is why we need the Pi to briefly allow password logins on the root account, because until the public key exists on the destination server, you will be prompted for a password when you run this command):

cat ~/.ssh/id_rsa.pub | ssh root@<your Pi’s IP address> ‘cat >> .ssh/authorized_keys’

Enter the password you created in Step 1 when prompted

Confirm that SSH key logins are now accepted by the Raspberry Pi by running this command (still from the Synology session, don’t toggle back to the Pi session yet🙂

ssh root@<Your Pi’s IP Address>

Now you can close the Synology session’s terminal window
 
3) In the Raspberry Pi Session remove password based root access. 

passwd -d root

Be very careful to do this on the Raspberry Pi – you could cause all sorts of problems doing this from another one of your hosts.
Now close down this ssh session as well
 

Step 2 Creating the backup script files

Using a web browser log in to the DiskStation as admin. Create a top level folder for holding all files related to Raspberry Pi backups (rpi_backup), use the Control Panel->Shared Folder
Then using the File Station create a directory under rpi_backup called scripts, and another called logs.
NOTE: I think the easiest way to create these scripts is to use the Text Editor from the Main Menu on the DiskStation, alternately use ssh to connect to the DiskStation and then use vi to create the files.
Create a file called rpi_backup/scripts/backup_pi.sh with the following content.

#!/bin/ash
#This script uses rsync to backup a named Raspberry Pi at a given IP address
#Three rotating backups are kept. If rsync fails then the preceding backups are retained.
if [ “$#” -ne 2 ] ; then
echo “Usage: 2 arguments required: $0 SERVERNAME IP” >&2
exit 1
fi
# Set up string variables
SERVER=$1
ADDRESS=$2
NOW=$(date +”%Y-%m-%d”)
RPI_BACKUP=”/volume1/rpi_backup”
LOGFILE=”$RPI_BACKUP/logs/$SERVER-$NOW.log”
SERVERDIR=”$RPI_BACKUP/$SERVER”
BASENAME=”$SERVERDIR/$SERVER”
# Paths to common commands used
MV=/bin/mv;
RM=/bin/rm;
MKDIR=/bin/mkdir;
PING=/bin/ping;
RSYNC=/usr/syno/bin/rsync
#Function to check for command failure and exit if there has been one. This is done
# so that when invoked from cron the error is reported
check_exit_code() {
exit_code=$?
if [ “$exit_code” -ne “0” ] ; then
echo “$1”
echo “exit with exitcode $exit_code”
exit 1
fi
}
#Ping the RPI a few times to ensure the interface is up (I’ve not seen this fail)
$PING $ADDRESS -c 3 >> $LOGFILE
# Ensure we have a top level backup directory for this server
if ! [ -d $SERVERDIR ] ; then
$MKDIR $SERVERDIR ;
fi ;
# Backups are made to BASENAME.0, this is then moved if the backup was successfull.
# So we start by clearing out anything from a failed backup
if [ -d $BASENAME.0 ] ; then
$RM -rf $BASENAME.0 ;
fi;
# RSYNC via SSH from the RPI as an incremental against the previous backup.
$RSYNC -av
–delete
–exclude-from=$RPI_BACKUP/scripts/rsync-exclude.txt
–link-dest $BASENAME.1
-e “ssh -p 22” root@$ADDRESS:/
$BASENAME.0 >> $LOGFILE 2>&1
# If RSYNC failed in any way, don’t trust the backup, exit the script
check_exit_code “RSYNC Failed”
#Rotate the existing backups
if [ -d $BASENAME.3 ] ; then
$RM -rf $BASENAME.3 ;
fi;
if [ -d $BASENAME.2 ] ; then
$MV $BASENAME.2 $BASENAME.3 ;
fi;
if [ -d $BASENAME.1 ] ; then
$MV $BASENAME.1 $BASENAME.2 ;
fi;
if [ -d $BASENAME.0 ] ; then
$MV $BASENAME.0 $BASENAME.1 ;
fi;

Create a second file called rpi_backup/scripts/rsync-exclude.txt with this content

/proc/*
/sys/*
/dev/*
/boot/*
/tmp/*
/run/*
/mnt/*

At this stage I like to manually run the script to ensure that it is working as I like. To do this connect to the DiskStation as root via ssh, cd to /volume1/rpi_backup/scripts. To backup a Raspberry Pi that I want to identify as myRPI at address 192.168.0.34. I repeat this until I am happy with the behaviour, including checking for reporting when the RPI is offline.
/volume1/rpi_backup/scripts/backup_rpi.sh myRPI 192.168.0.34

Step 3 Automating the backup

On the DiskStation desktop open Control Panel->Task Scheduler
Create a User Defined Script
Give the task a name and enter the command to run your script with the full path to the script, this example is for my jenkins server at address 192.168.0.34
Set the schedule, in my case I want this task to run at 3am every morning
Save the job by clicking OK
You can now test run the job by selecting it and clicking Run.

Step 4 Restoring from backup

The backup directories are shared from the DiskStation, mounting the volume gives access to the files, for now I have only done this from my mac and used it to restore individual files.
At this stage I have not investigated a full system restore, I rely on having a base img for each RPi taken after any major reconfiguration. I can then restore files from these backups.

Step 5 Backing up a second RPI

We need the Synology DiskStation to have root access via SSH to the Raspberry Pi. Open up two SSH sessions, one to the DiskStation (as root) and one to the Pi (as your normal login e.g. pi).
1) In the Raspberry Pi Session first enable root login by setting a root password

sudo passwd root

Enter a password as prompted
Now we need to ensure that there is a directory to hold ssh keys.

su root

mkdir ~/.ssh

exit

2) In DiskStation session

Push the public key to the Raspberry Pi (this is why we need the Pi to briefly allow password logins on the root account, because until the public key exists on the destination server, you will be prompted for a password when you run this command):

cat ~/.ssh/id_rsa.pub | ssh root@<your Pi’s IP address> ‘cat >> .ssh/authorized_keys’

Enter the password you created in Step 1 when prompted

Confirm that SSH key logins are now accepted by the Raspberry Pi by running this command (still from the Synology session, don’t toggle back to the Pi session yet🙂

ssh root@<Your Pi’s IP Address>

Now you can close the Synology session’s terminal window
 
3) In the Raspberry Pi Session remove password based root access. 

passwd -d root

Be very careful to do this on the Raspberry Pi – you could cause all sorts of problems doing this from another one of your hosts.
Now close down this ssh session as well.

4) Finally repeat step 3 Automating the Backup for the new host.

ToDo

This process has given me a fully automated backup of my Raspery Pi systems. There are a number of improvements that I would like to make as and when time allows.
  1. There is currently no notification sent if the backup fails. For now I inspect the logs, and the backup does at least preserve the last three good backups. It is possible to use the synology notification system, see http://www.beatificabytes.be/wordpress/send-custom-email-notifications-from-scripts-running-on-a-synology/ I may get around to this, I’m hoping that sinology may improve the system though…
  2. I want to investigate if I can perform a full system restore on to a blank card. For now I rely on taking occasional card images, and then this automated system gives me backup of all files.
  3. The timestamp on the individual backup top level directory is incorrect, it gets updated for each backup each time a backup occurs (mv is incorrectly setting the date). I did have a brief look at this, there are a number of obstacles to overcome. mv doesn’t preserve the timestamp on move, I cannot use touch with a specified timestamp because the version available on the DiskStation doesn’t support the feature. I could solve the problem with python, but this isn’t installed as standard. I think I could solve the issue using php, but I haven’t put the time in yet – more important to have a working backup.


Using PiFace Control and Display with CODESYS

This post is intended for CODESYS beginners, it aims to give a step by step guide to creating a CODESYS project for the Raspberry Pi with the PiFace Control and Display add on board. (I am actually using PiFace Control and Display 2, but it appears to be compatible).

Start by creating a new standard CODESYS project.

Select the CODESYS Control for Raspberry Pi as the Device and ST as the programming language
The PiFace Control and Display module is interfaced with using SPI, so we need to add two devices to the device tree, first an SPI Master and then the PiFace Control and Display device. To do this right click on SPI in the device tree and select Add Device
Choose the SPI Master
Click Add Device, then without closing the dialog select SPI_master in the device tree, and then in the dialog select PiFace Control&Display
Click Add Device and close the dialog.
IMPORTANT: PiFace Control and Display operates on SPI port 1, and so the SPI_master device needs to be reconfigured to use this port. To set the port open the SPI_master device in the device tree and change the Value of SPI port as shown to ‘/dev/spidev0.1’.
At this point we have a CODESYS project with all of the drivers installed to operate this display and to read the buttons. Adding the IO device has added a function block called PiFace_Control_Display of type PiFaceCaD. Unfortunately it can be very hard to work out how to use this function block with the version of the library containing this block no documentation is installed and commenting of the function block is hidden. We can find some information by switching to the Predefined Professional Feature Set (Tools->Options->Features->Predefined feature sets…->Professional). Now when the Library Manager is opened in the project additional libraries are visible, in particular we are interested in Raspberry SPI PiFace CaD.

PiFaceCaD

In the Raspberry SPI PiFace CaD library we can see the definition of the PiFaceCaD function block type. The function block has just a single VAR OUTPUT, bySwitches.
The rest of the features of the function block require the use of the Object Oriented features added to IEC61131-3 third edition. The documentation below is extracted directly from the Raspberry SPI PiFace CaD library (With a few corrections)

METHOD Clear

This method is used to clear the display
return value: none 

METHOD DefineCustomBitmap

This method is used to define a custom bitmap, up to 8 custom bitmaps can be used simultaneously return value: none 

Name
Type
Comment
byLocation
BYTE (0..7)
storage positions of the bitmap (0..7)
abyBitmap
ARRAY [0..7] OF BYTE
bitmap definition: each byte (0 (top)..7 (bottom)) represents on line; each bit (0 (right)..4 (left)) of a byte represents one pixel in the line

METHOD Home

This method is used to home the cursor to the upper left corner
return value: none 

METHOD MoveLeft

This method shifts the content of the display about one char to the left
return value: none 

METHOD MoveRight

This method shifts the content of the display about one char to the right
return value: none 

METHOD SetCursor

This method sets the cursor to a specified position
return value: none 
Name
Type
Comment
usiColumn
USINT
column to place the cursor (0..15)
usiRow
USINT
row to place the cursor (0,1)

METHOD SetText

This method sets the content of the display (unspecified characters are left unchanged)
return value: none 
Name
Type
Comment
sLine1
STRING
first line
sLine2
STRING
second line

METHOD Write

This method writes text at the current position
return value: none 
Name
Type
Comment
sText
STRING
string to write

METHOD WriteCustomBitmap

This method writes the specified custom bitmap at the current position
return value: none 
Name
Type
Comment
byLocation
BYTE (0..7)
storage positions of the bitmap (0..7)

PROPERTY Backlight: BOOL (SET)

Sets the backlight on or off 

PROPERTY Blink: BOOL (SET)

Displays or hides the blinking rectangle 

PROPERTY Cursor: BOOL (SET)

Displays or hides the cursor 

PROPERTY Display: BOOL (SET)

Switches the display on or off 

SPI

The PiFaceCad function block Extends the SPI function block, and so we need to understand a little about this function block too. This documentation is lifted from the Raspberry Pi Peripherals library.
This function block is the base class for SPI devices controlled via the SPI device /dev/spidev0.0. It is meant to be extended by other function blocks that overload the body and the following methods/properties and replace it with their specific implementation, always including a call of the base implementation with super^.<MethodName>() :
body (general handling, start-up)
AfterReadInputs (reading input data)
BeforeWriteOutputs (writing output data)
Initialize [optional] (used to read parameters from the configuration)
Operational [optional] (used to signal the status of the device)
The body of this FB is called by the methods AfterReadInputs and BeforeWriteOutputs, where _xAfterReadInputs indicates the caller. Use _iState to control your statemachine. A value of 10 by default indicates that the device is operational. Do not forget to call the base implementation with super^(), where the diagnosis indicators are set according to the Operational property.
 

Hello World

So now we know something about the methods on the PiFaceCaD Function Block we should be able to write a Hello World program.
PROGRAM PLC_PRG
VAR
xUpdate: BOOL := TRUE;
END_VAR
 
IF PiFace_Control_Display.Operational AND xUpdate THEN
PiFace_Control_Display.Clear();
PiFace_Control_Display.SetText(sLine1 := ‘Hello World’, sline2 := ”);
xUpdate := FALSE;
END_IF

Go online and run the application, you should see this

Reading Switches

All of the switches on the PiFace Control and Display board are output as bits within a single byte on the PiFaceCaD function block. The bits are numbered as shown
The sample code below demonstrates reading the switches
PROGRAM PLC_PRG
VAR
xUpdate: BOOL := TRUE;
byLastSwitches : BYTE;
bySwitches : BYTE;
END_VAR
 
bySwitches := PiFace_Control_Display.bySwitches;
IF bySwitches <> byLastSwitches THEN
xUpdate := TRUE;
END_IF
IF PiFace_Control_Display.Operational AND xUpdate THEN
PiFace_Control_Display.Clear();
PiFace_Control_Display.Backlight := TRUE;
PiFace_Control_Display.SetText(sLine1 := ‘Hello World’, sline2 := BYTE_TO_STRING(bySwitches));
xUpdate := FALSE;
byLastSwitches := bySwitches;
END_IF

 

Configuring a Jenkins Slave to build VS2013 projects

Introduction

I have previously installed Jenkins, SVN and Trac on a single Raspberry Pi 2, with the intention of having a home Continuous Integration server (CI). I now want to get a visual studio 2013 solution built by Jenkins.

As a first project I have decided to get googletest (gtest) to build. As a precursor I have downloaded version 1.7.0 and added it to my local SVN repository, I then copied the msvc directory to msvc2013, open the solution in VS2013, allowed the onetime upgrade to happen, and then committed the new directory. If I build locally gtest builds with a couple of warnings (which is good because we can then check that jenkins sees the warnings).

I have a clean windows 8.1 PC (virtual machine actually) with Visual Studio 2013 Community Edition installed, and the latest version of Java installed (Version 8 update 51).

As a starting point I am following the Step by Step guide to setup master and slave in the Jenkins documentation.

Configuring the Jenkins Master

In a browser on the intended Jenkins slave, open up the Jenkins server main page (In my case http://xxx.xxx.xxx.xxx:8080, where xxx.xxx.xxx.xxx is the IP address of my RPi). Select Manage Jenkins->Manage Nodes and then select New Node.
Enter a name for Jenkins to reference the slave as and select Dumb Slave, click OK. You are then shown the Configure page for the slave, these are the initial settings I choose, the Label is important, I use it later when setting up the build to identify this as a suitable slave to build on.

Save and then click on the newly added node and then click the Launch button.

I had to edit the Java security settings in the control panel on the PC to make http://192.168.0.34:8080/ a trusted site, the Jenkins slave then launched successfully
For now I want to launch the slave manually, so the configuration of master and slave is done.

Adding the required plugins to Jenkins

I browsed to Jenkins->Manage Jenkins->Manage Plugins. Before adding new plugins I decided to update all installed plugins to their latest version.
I then selected the Available tab and added the following plugins MSBuild, Log Parser, Warnings, Static Analysis Collector.
I browsed to Jenkins->Manage Jenkins->Configure System, scrolled down to MSBuild and added the following configuration.

Note: the location of MSBuild is specific to each version of Visual Studio, This plugin only offers one global path setting for each MSBuild  installation, so every build slave that you create a particular Visual Studio Installation on must have the same install path for MSBuild. I don’t think this is any great restriction.

Configuring the Build

In a browser go to Jenkins and select New Item, enter an item name (The name of your build, I use GoogleTestVS2013). You are then faced with the project configuration page, the exact content of this page depends on which plugins you have installed. The key sections are
Restrict the build to only run on slaves with vs2013 installed.
Link to the source code to checkout
Click Add build Step and select Build a Visual Studio project or solution using MSBuild
Click Add post-build action and select Scan for compiler warnings
For me that was sufficient, Jenkins can now checkout and build my visual studio project, after the build warnings are shown.

 

Integrating trac and Jenkins

In this post I cover how I have integrated Trac and Jenkins using HudsonTracPlugin and Jenkins Trac Plugin. I am running both Trac and Jenkins on a Raspberry Pi 2.

Trac Plugin

The Trac Plugin is a plugin for Jenkins that creates links from Jenkins projects to Trac instances. 
As an example, if you committed a change with the following log message: 

The Trac plugin decorates Jenkins “Changes” HTML to create links to your Trac wiki, tickets, changesets, and source browser.
Reverted changeset:123 to close ticket #456.
your Jenkins job changes page would make changeset:123 and #456 hyperlinks to the appropriate Trac changeset and ticket pages, respectively.
In the Jenkins change details, there would be a link to the Trac pages for the:

 

  • changeset committed,
  • files changed, and
  • diff of the changes for each changed file.

Installation involved browsing to Jenkins->Manage Jenkins->Manage Plugins->Available, selecting Available Plugins and then checking the Edgewall Trac Plugin.
The plugin is then configured as part of a build configuration


As simple as that, references to changesets and ticket numbers are now shown as hyperlinks and there is a link from the build page back to trac.

HudsonTracPlugin

The HudsonTracPlugin is a Trac plugin that includes Jenkins build results into the Trac timeline and (optionally) provides a navbar menu to link to the Jenkins instance.

As a newbie I found the documentation for installing this plugin to be somewhat limited. It was actually remarkably easy.

The first step is to install the plugin which is written in python using easy_install, so in a terminal session to the RPi

sudo easy_install https://trac-hacks.org/svn/hudsontracplugin/0.10/

This gave the following output
Downloading https://trac-hacks.org/svn/hudsontracplugin/0.10/
Doing subversion checkout from https://trac-hacks.org/svn/hudsontracplugin/0.10/ to /tmp/easy_install-xAXEIt/0.10
Processing 0.10
Running setup.py -q bdist_egg –dist-dir /tmp/easy_install-xAXEIt/0.10/egg-dist-tmp-vkGSex
unrecognized .svn/entries format; skipping .
unrecognized .svn/entries format in 
zip_safe flag not set; analyzing archive contents…
Adding HudsonTrac 0.5-r0 to easy-install.pth file

 

Installed /usr/local/lib/python2.7/dist-packages/HudsonTrac-0.5_r0-py2.7.egg
Processing dependencies for HudsonTrac==0.5-r0

Finished processing dependencies for HudsonTrac==0.5-r0

I then chose to reboot my RPi, I suspect I could have just restarted apache.

Using a browser I then went to the Trac Admin->Plugins page, HudsonTrac 0.5-r0 was now listed, I enabled it and Applied Changes as shown.




Finally I logged back in to the RPi and edited trac.ini

sudo vi /var/trac/projects/prod/conf/trac.ini

I added the following to the end of the file

[hudson]
alternate_success_icon = true
api_token =
display_build_descriptions = false
display_building = true
display_culprit = false
display_in_new_tab = false
display_modules = false
job_url = http://192.168.0.34:8080/
list_changesets = true
main_page = http://192.168.0.34:8080/
password =
timeline_opt_label = Builds
username  =

 
I restarted Apache and it worked 🙂 Builds are shown in the timeline, they act as links to the builds on Jenkins. There is also a builds tab added to the trac navbar.