ARM Cross Compiler

To compile the mainline Linux kernel for the Raspberry Pi, you must first have an ARM cross compiler installed. I use gcc-4.7.3-arm-linux-gnueabi that comes with Ubuntu 14.04. To install the compiler run:

sudo apt-get install gcc-arm-linux-gnueabi

Compiling the Raspberry Pi mainline Kernel

# wget
# tar -xJf linux-3.15.tar.xz
# cd linux-3.15

Make and run the configuration menu:

# make ARCH=arm bcm2835_defconfig
# make ARCH=arm menuconfig

Customise your kernel. I enable the following:

Networking support -> Networking Options -> TCP/IP networking -> IP: kernel level autoconfiguration
Networking support -> Networking Options -> TCP/IP networking -> IP: DHCP support
File Systems -> Network File Systems -> Root file system on NFS

Once you have finished configuring your kernel, save the config. Then build it:

# make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- zImage dtbs -j4

Now build the modules and install them to a suitable path:

# make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- modules
# make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- INSTALL_MOD_PATH=/home/export/rootfs modules_install


To support your newer Linux Mainline Kernel with Device Tree Support, you will need to boot from U-Boot.

Please see Compiling U-Boot with Device Tree Support for the Raspberry Pi

TFTP Server

Rather than flashing your newly created kernel to find out it doesn't work or it is not quite configured correctly, a better way to load the kernel into RAM and boot it from there. U-Boot allows kernel images to be loaded via TFTP.

To speed up development, I create an 'export' directory. A TFTP server is then configured to use this directory as the TFTP root.

From the export directory, add symbolic links to the kernel images. This way, you can recompile the kernel and the new image is instantly available without having to move it.

# ln -s /path to linux/arch/arm/boot/zImage zImage
# ln -s /path to linux/arch/arm/boot/dts/bcm2835-rpi-b.dtb bcm2835-rpi-b.dtb

U-Boot tftpboot

To test your kernel, bring up a U-Boot serial console. First we will need to configure the IP addresses. The ipaddr variable contains the IP address for the Raspberry Pi, while the serverip variable is the address of the TFTP server containing the kernel image.

usb start
setenv ipaddr
setenv serverip

Next load the kernel image and Device Tree BLOB into memory:

tftpboot 0x02000000 bcm2835-rpi-b.dtb
tftpboot 0x01000000 zImage

You will also require a root filesystem to do any serious testing. One option is to use the filesystem already in place as I have done below. However, it is unlikely to have your new kernel modules installed.

setenv bootargs console=ttyAMA0 console=tty1 root=/dev/mmcblk0p2 rootwait

The preferred option is to export a root NFS filesystem with your newly installed kernel modules installed. This has the added advantage as you can compile userland binaries on your development box, install them to the NFS export and have instant access to them on your target system.

setenv bootargs console=ttyAMA0 console=tty1 root=/dev/nfs rw nfsroot= ip=

Finally, you can boot the kernel from the memory:

bootz 0x01000000 - 0x02000000

Hopefully you should yield results similar to the following:

Kernel image @ 0x1000000 [ 0x000000 - 0x347bf0 ]
## Flattened Device Tree blob at 02000000
   Booting using the fdt blob at 0x2000000
   Loading Device Tree to 07b49000, end 07b4cf02 ... OK

Starting kernel ...

Uncompressing Linux... done, booting the kernel.
[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Initializing cgroup subsys cpuset
[    0.000000] Initializing cgroup subsys cpu
[    0.000000] Initializing cgroup subsys cpuacct
[    0.000000] Linux version 3.15.0 (cpeacock@ubuntu) (gcc version 4.7.3 (Ubuntu/Linaro 4.7.3-12ubuntu1) ) #5 Thu Jun 12 23:45:26 PDT 2014
[    0.000000] CPU: ARMv6-compatible processor [410fb767] revision 7 (ARMv7), cr=00c5387d
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
[    0.000000] Machine model: Raspberry Pi Model B