Oracle Blog

speakjava

Monday Jan 21, 2013

Building an SD Card Image For a Raspberry Pi Hands On Lab
Last year we ran a very successful hands on lab for developers at Devoxx in Antwerp. The concept
was to have 40 people in a room, give them all a Raspberry Pi, cables and a
pre-configured SD card and get them to build cool JavaFX
apps. One of the things I had to do was organise all the
equipment and make a suitable image for the SD card. As this was
before Oracle had announced the early access of JDK8 for
the Raspberry Pi with hard float support we used the soft float of Java
SE embedded version 7 for ARMv6 and a non-production build of
JavaFX. As we're repeating this lab at JFokus
in a couple of weeks I thought it might be useful to write up how I
built the SD image as there may well be people who want to run
something similar.

Hardware Setup

To simplify matters from a hardware perspective (and to make the lab
economically viable) we decided not to provide attendees with monitors,
keyboards and mice. All interaction with the Pi would need to be
via the network connection. To eliminate the need for two power
outlets per attendee we also decided to use USB Y power cables that can
draw power from two USB ports on the attendee's laptop. Since USB
ports are rated at 500mA two would give us more than the minimum 700mA
required for the Pi (as a side note I've found that you can happily
boot a Pi from one USB port on a MacBook Pro - although that is without
any USB peripherals attached to the Pi).

With no monitor or USB keyboard/mouse all interaction would be via the
network connection. Again, to simplify the infrastructure we
provided all attendees with an ethernet cross-over cable. One end
is connected to the ethernet port on the attendee's laptop, the other
to the ethernet port on the Raspberry Pi.

The hardware setup is shown in the diagram below:

Software Setup

For this part I'll describe the setup necessary for the Rasbian distro
so we can use the new JDK8
EA build. One issue with this is that the JavaFX libraries
included no longer supprt rendering via X11. Since the
ARM port of JavaFX is aimed at embedded devices like parking meters and
point-of-sale devices we don't expect these to use an X based desktop
underneath. Now that rendering is only supported directly to the
framebuffer (which gives us significantly better performance)
projecting the JavaFX applications back to the attendees laptop via VNC
will no longer work. Although there is a package calld fbvnc this will not
work as the rendering on the Pi does not use areas of memory that are
accessible this way.

Here is a step-by-step guide:

Install the Rasbian
distro on an SD card. I use 4Gb SanDisk class 4 cards which
provide enough space, work with the Pi and are cheap. When you
need to replicate a significant number of cards, smaller is
quicker. To install the distro either use DiskImager
(on Windows) or a simple dd command
on Linux or Mac (detailed
instructions can be found on the Raspberry Pi web site).

Put this in a Pi and boot. I do this with a monitor and USB
keyboard connected to make life simpler. When the Pi has finished
booting you will be presented with a screen as shown:

Move down to expand_rootfs and select this by pressing
RETURN. This will expand the filesystem to fill the available
space on the SD card.

Select overclock and accept the notice about potentially
reducing the lifetime of your Pi. Remember: live fast, die
young. Seriously, though, given the cost of the Pi and the fact
that the manufacturers will honour the warranty for anything up to a
1GHz
clockrate and I think this is pretty safe. I go for the medium
setting of 900MHz. This has not given me any issues, although you
may want to go higher or lower as preferred.

Select SSH. I think this is enabled by default, but just to
make sure select it.

Lastly on this screen select update. This will update any
packages necessary in the Linux distribution. Obviously for this
you will need your Pi connected to a network where it can find the
internet settings via DHCP, etc.

Tab to 'Finish', hit RETURN and you will be dropped into a shell.

Being an old school UNIX hacker I really don't like sudo, so the
first thing I do is sudo bash
and then set a password for root so I can su
whenever I need to.

There is a user account, pi, that is created by default.
For our labs I create a separate account for attendees to login
as. Use something like useradd
-u 1024 -d /home/lab -m -s /bin/bash lab. Remember to set
the user's password: passwd
lab.

Since we want things to be as simple as possible we setup a DHCP
server on the Pi. Before we do that we need the Pi to use a
static IP address. Edit the /etc/network/interfaces
file and
change

In these settings I've used a class
Aprivate
network which is the same
as the one I use in my office. This makes things easy, as I can
also configure the gateway so that the Pi can access the internet which
will be required for the next stages. If you are using a class C
private network (like 192.168.0.X) you will need to change this
accordingly.

At this point I reboot the machine
with the monitor and keyboard
disconnected and switch to doing everything over SSH.

Login over the network using SSH (use either the lab account or
the pre-installed pi one) and su to
root.

Install the DHCP server package, apt-get install
isc-dhcp-server

Configure DHCP by editing the /etc/dhcp/dhcpd.conf
file.
Under the comment line

# This is a very
basic subnet declaration.
Add

subnet
10.0.0.0 netmask 255.255.255.0 {
range 10.0.0.164 10.0.0.170;}

This will provide an IP address in the range from 164 to 170. Having
seven
available
addresses is a bit of overkill, but gives us some flexibility (change
your IP addresses as necessary). In
addition you must comment out these
two lines at the start of
the file:

This was one of the things that changed between the soft float Wheezy
distro and the hard float Raspbian distro. It took me ages to
figure out why
the DHCP server would not work properly on Raspbian. When I used
the soft float distro all I needed to do was add the subnet and range
definition. On Raspbian the DHCP server refused to serve IP
addresses even though the log messages seemed to indicate that it was
fine. After I did a diff on the dhcp.conf
files from both I
noticed the two lines that had been uncommented. I commented them
out again and everything worked fine.
For our lab the attendees wrote the code on their laptops using
the NetBeans IDE and then
transferred the project across to the Pi to
run. To make life as easy as possible the Pi is configured to
support multiple ways of getting files onto it: FTP, NFS and Samba.

Install the FTP server package, apt-get install
proftpd-basic. Although it would seem logical to want to
run this from inetd,
choose the standalone option as this actually works better and gets
started, quite happily, at boot time.

Configure the FTP server by editing the /etc/proftpd/proftpd.conf
file. This is not strictly necessary, but if you want to be able
to use anonymous ftp then uncomment the sizeable section that
starts with the comment,

At this point you would think, like I did, that rebooting the machine
would give you a functioning NFS server. In fact on the soft
float Wheezy distro this is exactly what happened. As with DHCP
there is some weirdness in terms of changes that were made between the
soft float Wheezy distro and the Raspbian one. With Raspbian if
you use the showmount
-e command, either locally or remotely you get the somewhat
cryptic error message, clnt_create: RPC:
Port mapper failure - RPC: Unable to receive.

I'm sure with hindsight I should have been able to solve this quicker,
but having had it working fine on Wheezy I just couldn't figure out why
the same thing didn't work on Raspbian. Evantually after much
Googling and head scratching I determined that it was down to the RPC
bind daemon not being started at boot time. Some kind and
thoughtful person decided that RPC didn't need to run at boot
time. Rather than leaving the package out so that when it's
needed it gets installed and correctly configured they just moved the
links from /etc/rc2.d
and /etc/rc3.d
from being S (for start) to K (for kill), so it doesn't start.

Make the RPC bind daemon start at boot time by running update-rc.d rpcbind
enable (as root)

If you want the attendees to be able to project the desktop of the Pi
to their laptops then you will need VNC.

Install the VNC server, apt-get install
tightvncserver

As the lab user, set a password for the VNC server with tightvncpasswd.
When doing this you can set different passwords for a fully interactive
session and a view only one.

Run tightvncserver
:1 to generate all the necessary configuration
files. You will now be able to access the Raspberry Pi desktop
remotely using a VNC client (I use [the bizarrely named] Chicken
of the VNC on the Mac, RealVNC
on Windows and xtightvncviewer on Linux).

In order for the VNC server to start up whenever the system boots
a script is required in the /etc/init.d
directory. I call it tightvncviewer,
for which the code is:

Make sure that this script has execute permission. To create the
necessary links into the /etc/rc*.d
directories run update-rc.d
tightvncserver defaults. Note that this provides the
desktop of the 'lab' user. If you want to support a different
user change the name. More users can be supported by creating
additional servers running on screens other than :1.

To avoid having to provide printed instructions for the lab or
distribute files on a CD or memory stick I also configure Apache on the
Pi so that once the Pi is connected to the attendee's laptop they can
simply open a web page and have whatever instructions and software
available from there.

Install Apache, apt-get install
apache2

Create your HTML content and put it in /var/www

Finally install the Java runtime. I put it in /opt and set
the PATH
environment variable in the user's .bashrc file.

About

A blog covering aspects of Java SE, JavaFX and embedded Java that I find fun and interesting and want to share with other developers. As part of the Developer Outreach team at Oracle I write a lot of demo code and I use this blog to highlight useful tips and techniques I learn along the way.