grasping the Pi, part 4: traceberry Pi

I wanted to take a break from compiling kernel modules and making hardware work and so decided to compile tRayce, a raytracer that I wrote recently, on the Pi and see how slower it exactly was.

The first problem arose on the compilation stage: it was slow. tRayce has 8 source files and it took the Pi about 5 minutes to compile the first one. That wasn’t terribly inspiring, since I did plan to do some programming on it and didn’t have enough swords or chairs to help me tolerate long compilation times.

Hence I compiled a cross-compilation toolkit with crosstool-ng so that I could create binaries for the Pi on my laptop, which would be tremendously faster.

I used the instructions here, which was quite straightforward with the only effort required from me being waiting two hours for the toolkit to get compiled. I did mess up a bit by forgetting to choose to build the C++ compiler and so had to rebuild everything from scratch. I did mess up twice, actually, as the AUR already has the required packages. Oh well.

I compiled tRayce for the ARM architecture on my laptop, transferred the executable onto the Pi using scp and launched it.

It took about 2 minutes for the scene to render (the same scene took 2.5 seconds on my laptop) and there was another problem: the scene was dim. This probably was due to the compiler messing up some floating-point instructions. I changed all float variables to double in my code (which isn’t supposed to change the performance much) and recompiled it again.

It was better this time: my scene was ready in 30 seconds, however, the scene still wasn’t the same as the reference one I rendered on my laptop: the specular highlights on the spheres were bigger than on the reference. Still some floating-point issues or incorrect compiler flags.

ImageImage
 
(reference render and the render I got from the Pi.)

The next day, I decided to wait through the compilation on the Pi to see if the image was still different. To my surprise, the compilation went much quicker (~30s for the whole project) for no apparent reason. The scene, on the other hand, took about 3 minutes to render, which definitely was too much and probably meant that my system only supported soft ABI (instead of floating-point operations, the system uses integers and doesn’t delegate anything to the FPU, which is quite a waste). However, the scene now was completely the same as the reference.

According to the Raspbian FAQ, I could compile my program so that it could do the floating-point operations on the FPU and pass the function parameters around in FP registers (hard ABI). The bad news were, I couldn’t do that on a soft-ABI system — all libraries on my system must support hard ABI and I did confirm that the Arch ARM build that I was using wasn’t built with hard ABI support.

I could start using Rasbian, but this could lead me down the route where I would have to compile most of the needed packages myself, as the precompiled binaries wouldn’t be supported by my system. I also could theoretically rebuild all libraries and the whole toolchain to create a version that would only be used for tRayce (according to this StackOverflow comment), but there was an easier solution.

Luckily, GCC supports the flag –mfloat-abi=softfp that, according to this page, “allows use of VFP while remaining compatible with soft-float code”. The exact mechanism of compatibility, apparently, is that the resulting program uses the FPU, but all parameters are passed around using integer registers, which does have some overhead. Nevertheless, I compiled tRayce with these flags:

CFLAGS := -g -Wall -march=armv6 -mfpu=vfp -mfloat-abi=softfp -O2

and launched it, which brought the rendering time back down to ~40s and giving the same scene as the reference.

(In unrelated news, I printed out and glued together Punnet, a printable and together-glueable case, which probably should make the Pi hotter (in both senses)).

And this is a full-sized (1280×800) scene with 4x antialiased edges and soft shadows that was rendered on the Pi in 256 seconds (nice number), which is ~12 times slower than on my laptop (strange, since the light version of this scene was rendered ~20 times slower on the Pi).

Advertisements

grasping the Pi, part 3: wireless notworking

Linux is very famous for having problems with certain hardware, including NVIDIA Hybrid SLI (and its successor, the infamous NVIDIA Optimus) -enabled GPUs and various wireless chips. The situation has been improving recently — there are a lot of open- and closed-source wireless drivers available (that still require some weird actions, like downloading things from a computer that doesn’t have the Internet connection to make the Internet connection work), but for some chips the situation is still bleak.

I had a D-Link DWL-G132 USB wireless dongle lying around. Plugging it into the Pi and doing lsusb revealed this:

Bus 001 Device 004: ID 2001:3a03 D-Link Corp. DWL-G132 (no firmware) [Atheros AR5523]

Bad news: there is no firmware for the wireless dongle. Good news: we found the name of the chip that it uses, i.e. Atheros AR5523. I first decided to acquire the firmware, since it seemed like the actual driver was already in the system.

A Google search revealed that there existed a driver called ar5523 (surprise!) and it apparently hadn’t made it yet into the kernel. I downloaded the firmware from its page, copied it into my /usr/lib/firmware and restarted the Pi. Nothing.

I tried using ndiswrapper, which is essentially a way to adapt the Windows driver to work on Linux, but a comment here stated that ndiswrapper only worked on the x86 architecture.

I then resorted to compiling the driver myself using the instructions here (I had some experience with kernel modules — I use the xps_nv module that disables the discrete video card on my Studio XPS so that it doesn’t draw power). However, simply following the instructions didn’t work — the kernel headers were missing. Or that’s what the build system thought. Since a recent update, the /lib folder in Arch Linux got deprecated and was supposed to be symlinked to /usr/lib (or that’s just the way Debian stores the kernel header files). I edited the Makefile again, pointing it to the actual headers and tried to compile the module again. Nope.

I then found some patches in the folder with the source code and applied them. Nothing. I also investigated this and this blog posts where the writer had exactly the same problem and applied the patches that he had there. The compilation errors remained. However, the definition of some functions in the kernel had changed, according to a comment in that post linking to here and the author didn’t replace all occurrences of the functions in the source. Doing that did the trick and I ended up with a .ko file — the kernel module.

The complete patchfile is available on the Pastebin.

I then copied the .ko file into /usr/lib/modules/(my kernel version)/kernel and did

sudo depmod -a

sudo modprobe ar5523

ifconfig -a then showed that a mysterious wlan0 interface appeared on the system. Doing sudo ifconfig wlan0 up then made the light on the dongle flash. Hooray!

Well, not really. Searching for networks (iwlist wlan0 scan) didn’t show anything useful. My next quest apparently had to be postponed.

grasping the Pi, part 2: an SD card full of awesome

I don’t really know much about minimalistic window managers: I use GNOME 3 (which is a story of its own), but have tinkered with xmonad (a window manager written in Haskell), so I decided to install in onto the Pi and set up a VNC server to be able to actually see what was going on from my laptop.

xmonad, however, wasn’t in the Arch ARM repository and I didn’t have any idea of how long compiling it would take. I therefore took the path of least resistance and installed openbox, a famous window manager (sudo pacman -S openbox obmenu obconf + a bunch of X libraries).

Setting up the VNC server was quite straightforward: I used the guide from the Arch wiki to install TightVNC (package name tightvnc).

I also copied a small script from here that would start and stop the VNC server with just one command (I didn’t register it as a service — Arch Linux uses init, a different way of managing services and starting the system, so the script sits in my home directory).

I then started the VNC server and connected to it from my laptop by installing tightvnc on it as well and typing

gvncviewer 192.168.1.161:1

(the IP address obviously is not constant) which gave me a completely empty screen with a cursor (standard X “desktop”).

I obviously forgot to start openbox, which could be easily fixed by adjusting the ~/.vnc/xstartup file:

#!/bin/sh

export XKL_XMODMAP_DISABLE=1
exec ck-launch-session openbox-session

which didn’t work since I forgot to install ConsoleKit. After I did, OpenBox launched normally (except for some strange graphical glitches).

I also decided to try out a more awesome window manager (couldn’t resist making that joke) called awesome by doing

sudo pacman -S awesome

and changing the line in xstart to say exec awesome.

Image

(more awesome + some moire artifacts)

I didn’t play around more with awesome though (I did think of setting it up on my laptop eventually), since I never planned to connect my Pi to a screen and make it into a traditional computer with a desktop environment and VNCing to it over the network seems like a waste of bandwidth. I moved on to a different goal — setting up the wireless.

grasping the pi, part 1: setting up

So to probably help their Computer Science students get some programming practice before the start of term, University of Cambridge provided each one of them with a Raspberry Pi computer. I guess there is no need to introduce the Pi (there has been a lot of buzz about it on the Internet lately), so I will directly move on to sharing my experiences with this strange machine.

The Pi doesn’t exactly have a CD drive or a way to change where it boots from, so the OS cannot be installed onto it in the traditional sense of words. The only storage it has is an SD card and the Downloads section of the Pi website (http://www.raspberrypi.org/downloads) has images that are preloaded with the bootloaders and Linux distributions built specifically for the Pi.

I first downloaded the recommended Raspbian Wheezy image that apparently has a lot of useful software already preinstalled. Since I use Arch Linux on my laptop, I easily flashed the image onto the SD card using dd, plugged the card, an Ethernet cable and my mobile phone charger (which is basically a Micro USB 2 cable) into the Pi and waited for some time, hoping to remotely log onto it to start playing around (I felt too lazy to go find an RCA cable to actually see what was happening on the screen).

Not much happened though — the Link light that presumably represented the fact that the Pi had detected the network didn’t flash on, so I did have to dig around and connect it to the TV, which revealed that the Pi didn’t get anywhere useful because of a strange kernel panic due to it not being able to mount the root partition on the card.

I reflashed the card, which didn’t help. I then noticed that the flashed image didn’t use the whole amount of space on the card (it contained two partitions totaling 2GB, whereas the card was 4GB big) and the root partition couldn’t be mounted even on my laptop, so I used GParted to extend it to the full size of the card. That didn’t help either — during the initial boot stages, the Pi failed to preload some libraries and hung in a loop, forever trying to fix that problem.

After reflashing the card again and failing, I decided to install the Arch Linux image available from the same page, which somehow worked flawlessly. Despite that Arch is a fairly minimal system, its wiki (wiki.archlinux.org) is excellent and provides a lot of guidance to making that system less minimal, so it wasn’t too much of a loss. Raspbian, however, seems to have some sort of optimisations for the floating-point code, which makes multimedia packages work much faster, so I am still yet to find out whether it can be done in Arch as well.

I now was prepared to go headless and continue to set up my system via ssh from my laptop. I did some minor things, such as:

  • Adding a new, non-root user
  • Running pacman -Syu to upgrade the system (which also upgraded the firmware to the latest version)
  • Setting up sudo (allows to run a command with root privileges)
  • Installing yaourt (build packages in the Arch User Repository from source), links (a text-based browser), vim (editor), tmux (terminal multiplexer) and some programming-related things like base-devel (a package that contains the GNU Compiler Collection, make, ld etc) and a Python interpreter.

At this stage, I had a box that I could connect to Ethernet, remotely log onto it (if I could find the IP), and do some minor browsing and programming, which wasn’t particularly exciting. I wanted some sort of a graphical interface and a way for it to use a wireless dongle that I had lying around to avoid tripping hazards from the Ethernet cable stretched across the room.