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.
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.
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.