One of the nice things about the Raspberry Pi is that it runs Linux and you can do a lot of development right on the board. The converse of that is you can do a lot of development on a Linux desktop and then move things over to the Pi once you get the biggest bugs out. However, sometimes you really need to run code on the actual platform.
There is, however, an in-between solution that has the added benefit of upping your skills: emulate a Pi on your desktop. If you use Linux or Windows on your desktop, you can use QEMU to execute Raspberry Pi software virtually. This might be useful if you don’t have a Pi (or, at least, don’t have it with you). Or you just want to leverage your large computer to simplify development. Of course we would be delighted to see you build the Pi equivalent of the Tamagotchi Singularity but that’s a bit beyond the scope of this article.
Since I use Linux, I’m going to focus on that. If you insist on using Windows, you can find a ready-to-go project on Sourceforge. For the most part, you should find the process similar. The method I’ll talk about works on Kubuntu, but should also work on most other Debian-based systems, including Ubuntu.
Step 1. Tools
Your PC probably has some sort of Intel processor in it. The Pi has an ARM chip. QEMU is the emulator that lets you run–among other things–ARM executables on the PC. You need a static copy and the binfmt-support package. This combination will let Linux recognize alien executables and run them transparently. Here’s how you install what you need:
apt-get install qemu qemu-user-static binfmt-support
Step 2. Raspberry Pi Image
Make a working directory and download a Pi image in zip format. You can then unzip it, to create an IMG file. Here are the steps:
wget https://downloads.raspberrypi.org/raspbian/images/raspbian-2015-11-24/2015-11-21-raspbian-jessie.zip unzip 2015-11-21-raspbian-jessie.zip
Step 3. Get Data
We need a few numbers from the img file and yours may be different than mine, depending on what you downloaded. The command you want to run is:
fdisk -lu 2015-11-21-raspbian-jessie.img
Here’s the output, with the important parts in bold:
Disk 2015-11-21-raspbian-jessie.img: 3.7 GiB, 3934257152 bytes, 7684096 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0xea0e7380 Device Boot Start End Sectors Size Id Type 2015-11-21-raspbian-jessie.img1 8192 131071 122880 60M c W95 FAT32 (LBA) 2015-11-21-raspbian-jessie.img2 131072 7684095 7553024 3.6G 83 Linux
The first partition is the boot partition and the second is the filesystem.
Step 4: Increase Hard Drive Size
The base filesystem isn’t very large, so let’s make it bigger:
dd if=/dev/zero bs=1M count=2048 >>2015-11-21-raspbian-jessie.img
This will add 2 GB to the image. However, the filesystem won’t know about it yet. First, we need to mount the image as though it were a set of disks:
losetup -f --show 2015-11-21-raspbian-jessie.img losetup -f --show -o $((131072*512)) 2015-11-21-raspbian-jessie.img
The numbers (131072 and 512) must match the ones highlighted in step 3. The 512 probably won’t change, but the start of the filesystem can and does change.
Unless you already had loopback devices, this should give you a /dev/loop0 that corresponds to the whole “disk” and /dev/loop1 that is the filesystem (the part we want to expand). Recreate the partition table to know about the extra space (the mkpart command will need some numbers you can read from the output and those numbers are marked in bold):
$ sudo parted /dev/loop0 GNU Parted 3.2 Using /dev/loop0 Welcome to GNU Parted! Type 'help' to view a list of commands. (parted) print Model: Loopback device (loopback) Disk /dev/loop0: 6082MB Sector size (logical/physical): 512B/512B Partition Table: msdos Disk Flags: Number Start End Size Type File system Flags 1 4194kB 67.1MB 62.9MB primary fat16 lba 2 67.1MB 3934MB 3867MB primary ext4 (parted) print (parted) rm 2 (parted) mkpart primary 67.1 6082 (parted) quit $ e2fsk -f /dev/loop1 $ resize2fs /deve/loop1 $ losetup -d /dev/loop
Step 5: Mount Filesystem
Make a directory to use as a mount point. I usually just make a directory called mnt in the current directory. You’ll need to be root to mount and use the offsets found in step 3 (8192 and 131072, in this case):
mkdir mnt sudo mount 2015-11-21-raspian-jessie.img -o loop,offset=$((131072*512)),rw mnt sudo mount 2015-11-21-raspbian-jessie.img -o loop,offset=$((8192*512)),rw mnt/boot sudo mount --bind /dev mnt/dev sudo mount --bind /sys mnt/sys sudo mount --bind /proc mnt/proc sudo mount --bind /dev/pts mnt/dev/pts
Step 6: Modify ld.so.preload and Copy Executable
As root, you need to edit mnt/etc/ld.so.preload with your favorite editor (which is, of course, emacs). You could, if you wanted to, use vi or some other editor of your choice. Just make sure you are root. Just put a hash mark (#) in front of the line you’ll find there. Failure to do this will cause illegal instruction errors to pop up later.
In addition, you need the qemu-arm-static executable available to the new fake Raspberry Pi:
sudo cp /usr/bin/qemu-arm-static mnt/usr/bin
Step 7: Chroot!
The chroot command will cause the Pi’s filesystem to look like the root directory (in one shell window). Then you can change user to pi (or any other user you want to configure):
cd mnt sudo chroot . bin/bash su pi
How do you know it is working? Try a uname -a command. You should see an armv7l processor type. You can run executables just like on the Pi. If you want to use X, set DISPLAY=:0 to use your main screen. For example:
Or you can set the display for all programs:
Optional: Flash It
Now you are ready to go. After some development, you might want to save your work. All you need to do is to exit the chroot (type exit) and change /etc/ld.so/preload back (remove the # character you added). Then you should unmount everything that you mounted. The image file will remain and will contain all your changes. You can flash it, and you can reload it by repeating the chroot and mount instructions.
There are lots of ways to do cross development on the PC for the Raspberry Pi. This is one of them. However, it also points out the power of using QEMU to run alien executables. That’s a trick you could use for lots of different development boards and platforms. There are QEMU emulators for several CPU types ranging from Microblaze to other ARM variants to PowerPC, to an S390. A quick glance at the /usr/bin directory for qemu-*-static will give you a list.
Sure, it is easy enough to get a Pi and use that. But this is yet another tool to do cross development when you need it.