Compiling a Kernel on the Raspberry PI

The reason I had to do this was because I needed video4linux to get a webcam working for a forcoming series of posts connecting a telescope to the pi. Although the connection to the telescope wasn’t a problem, the customized webcam I have needed it.

Here I compile the kernel on a more powerful linux box to save time then transfer the kernel over to the PI.

Also this article is mainly my personal notes on compiling a new kernel rather than a tutorial on how to do it. Writing it here makes sense to keep things together & maybe it’s useful for anyone else.

These instructions are based on the RPI Kernel Compilation available at elinux.org.

Terminology

Here were going to cross compile the kernel on one machine for installation on another. Cross compiling is when we compile on a machine of a different architecture to the target machine.

  • tabitha – Intel based linux box which will be performing the compilation
  • lindesfarne – Raspberry PI which is obviously running on the arm architecture

You’ll also notice that when copying files between the two I’m simply using the cp command. This is because I have setup an NFS share between the two. You’ll need to read the previous article on setting up NFS on how this is setup.

Install the cross compiler

You need the gcc cross compiler for arm, make, git and ncurses:

peter@tabitha:~$ sudo apt-get install gcc-arm-linux-gnueabi make git-core ncurses-dev

Get the sources

Here we’ll download the sources for the kernel & whilst were at it the latest firmware:

First create a directory to install everything, for example:

peter@tabitha:~$ mkdir raspberrypi

Now I used:

peter@tabitha:~$ mkdir -p /srv/public/kernel

as I needed a public location to copy everything to the PI. This is an NFS share which is why I wrote the previous article on setting up NFS.

Next to get the sources. These are fairly large so it will take a while:

peter@tabitha:~$ cd /srv/public/kernel 
peter@tabitha:/srv/public/kernel$ git clone https://github.com/raspberrypi/firmware
peter@tabitha:/srv/public/kernel $ git clone https://github.com/raspberrypi/linux.git
peter@tabitha:/srv/public/kernel $ cd linux

Configure the kernel

Here I copied the config from the running kernel on a pi as a baseline:

pi@lindesfarne:~$ sudo zcat /proc/config.gz > .config
pi@lindesfarne:~$ cp .config /srv/public/kernel/linux

Next configure the new kernel with the old config:

peter@tabitha:/srv/public/kernel/linux$ make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- oldconfig

Now the optional bit, run menuconfig to edit the new configuration. I needed to do this to add v4l:

peter@tabitha:/srv/public/kernel/linux$ make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- menuconfig

Build the kernel

peter@tabitha:/srv/public/kernel/linux$ make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- -k

Now go to the pub. Seriously, depending on how powerful your machine is this can take quite some time. If you were building this natively on a pi then it could take all night, on other machines a lot less but it’s still long enough to have a pint!

Update the firmware

You may or may not need to do this but I did on the first time as the firmware has been updated since the original Debian image was created:

First I backed up the existing firmware incase I needed to restore to it:

pi@lindesfarne:~$ mkdir -p /srv/public/raspberry/orig-firmware/
pi@lindesfarne:~$ sudo su -
root@lindesfarne:~# cp arm128_start.elf arm192_start.elf arm224_start.elf bootcode.bin loader.bin start.elf /srv/public/raspberry/orig-firmware/

Now copy the new firmware onto the pi:

pi@lindesfarne:~$ sudo su -
root@lindesfarne:~# cd /srv/public/kernel/firmware/boot
root@lindesfarne:~# cp arm128_start.elf arm192_start.elf arm224_start.elf bootcode.bin loader.bin start.elf /boot

Install the new kernel

pi@lindesfarne:~$ sudo cp /srv/public/kernel/linux/arch/arm/boot/Image /boot/kernel.img

Install the new kernel modules

Now here’s why I used nfs, on the pi we need to run make to install our new modules.

pi@lindesfarne:~$ cd /srv/public/kernel/linux
pi@lindesfarne:/srv/public/kernel/linux$ sudo make modules_install

Thats it. Reboot and you should have your new kernel.

Notes

I get a black screen when I reboot

If you get just a black screen and only the red power led lighting up then you probably missed out the step updating the firmware. The older firmware required a special kernel image whilst the newer one only needed the image as built by the build.

If you get this you’ll need to mount the SD card directly to your linux box and install the firmware directly to the boot partition on the card.

How to see what kernel is running

The easiest way is with uname. Here’s the output on a PI with the original Debian image installed:

pi@kell:~$ uname -a
Linux kell 3.1.9+ #90 Wed Apr 18 18:23:05 BST 2012 armv6l GNU/Linux

Here’s the output with the new kernel:

pi@lindesfarne:~$ uname -a
Linux lindesfarne 3.1.9+ #1 Sat Jul 7 21:18:19 BST 2012 armv6l GNU/Linux

You’ll notice the kernel versions are the same (3.1.9) but the build time is different.

Author: petermount1

Prolific Open Source developer who also works in the online gaming industry during the day. Develops in Java, Go, Python & any other language as necessary. Still develops on retro machines like BBC Micro & Amiga A1200

5 thoughts on “Compiling a Kernel on the Raspberry PI”

    1. It’s been a while so I can’t remember where the setting was exactly but I do remember going through all the modules & when I found the v4l section I just enabled all of them (as modules).

      Doing that ensured they were build so when the time came to test I could just run mod probe to load it.

  1. Hi petermount,

    Thanks for your great post. I have few questions

    1) You are not using the hf version of compiler (arm-bcm2708hardfp-linux-gnueabi, gcc-linaro-arm-linux-gnueabihf-raspbian) from raspberrypi/tools. Any reasons and is the process similar ?

    sudo apt-get install gcc-arm-linux-gnueabi make git-core ncurses-dev

    2) Also if we use gcc-arm-linux-gnueabi it does not use hard float ?

    2) Also what is the reason for

    peter@tabitha:/srv/public/kernel/linux$ make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- oldconfig

    Is the oldconfig the original config from raspberry pi just renamed to oldconfig ?

    Thanks,
    Mohsin

    1. Sorry for the late reply.

      1: I used the standard compiler rather than the hf one simply because at the time I didn’t know the other existed – I only had the standard examples on cross compiling to go by.

      I don’t see any reason for the process to be different other than pointing it to the hf compiler.

      2: I don’t know if gcc-arm-linux-gnueabi uses hf or not – see below.

      3: oldconfig is the config from the pi. I did that as I wanted the exact same config.

      Now at the time I wrote this article I was using the original distribution rather than raspian and that distro didn’t have certain modules, specifically the v4l ones needed to handle a webcam. So I took the exact config from the pi, then added the additional modules I wanted adding to that file. This then meant that when the kernel sources were updated the builds got the required modules rather than the ones defined by the sources.

      Now some updates:
      Since I wrote this article:

      1. The Raspian distribution does have these extra modules and more -especially IPv6 which all but one of my pi’s are running with, so in most cases the required modules are now already on the PI
      2. At the time I ran this on a Jenkins instance on Amazon EC2. Now I have better connectivity at home I’m running this in-house & have a jobs which keep the sources in sync. But I’ve not had time to recreate the kernel build. If I get time I’ll get it running with hard float enabled.

      You might also want to take a look at RPi_Kernel_Compilation over on elinux.org as it has a section on cross compiling from Linux & OSX. There they talk about using gnueabi but also using the pre-built bmc2708 compiler from the RPI tools section on GitHub. That one looks like it uses Hard Float.

      I hope that helps

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: