Wednesday, July 04, 2012

Building kernel modules on the Raspberry Pi

To enable wireless on my RaPi, I bought a Edimax wireless usb dongle. This is based on the Realtek chipset which unfortunately was not supported out of the box on the 2012-06-18-wheezy-beta image I was running.

I was following the instructions posted here to enable the wireless dongle but soon found that the binary driver posted doesn't match the kernel version(3.1.9+ #144) I was running on my RaPi.  This meant that I had to build the kernel module required to run the wireless USB dongle from sources. The kernel headers for the running kernel are not provided in the Debian repository or the Rapi firmware git repository. Instead, the kernel sources used to build the kernel have to be used to setup the build environment.

Given below are instructions to build the kernel module for the latest development kernel on the Rapi as well as cross compile on a Linux based laptop or desktop. The limited resources on the RaPi means that building the kernel on the RaPi will take a long time. For this reason, I recommend that you cross compile on your desktop and then copy over the results to the RaPi.

Building on the RaPi.

1) Install git. Also make sure gcc and make are available on your Rapi.

# apt-get update
# apt-get install git make gcc

2) Clone the RaPi kernel git repository

# git clone --branch rpi-patches --depth 1 https://github.com/raspberrypi/linux.git rapi-linux

In my case, I cloned the branch on another machine and copied the resulting directory rapi-linux over to the RaPi at the location /root/rapi-linux.

3) Create a symlink to the kernel build directory used by the build process

# cd /lib/modules/3.1.9+/
# ln -s /root/rapi-linux/ build

4) Copy over the config file and prepare the sources

# cd /root/rapi-linux
# make mrproper
# zcat /proc/config.gz > .config
# make oldconfig
# make modules_prepare

You can build your kernel module at this stage but will find that the build complains about Module.symvers being missing. Attempting to load the resulting module fails with the error "Error: could not insert module ./8192cu.ko: Invalid module format" and the following line in dmesg "no symbol version for module_layout".

To complete the build environment, you will have to generate a Module.symvers file by building a kernel. To do this, run the command

# make vmlinux


This will take some time to build.


To build the module on the RaPi, simply change in to the module sources directory and run

# make -C /lib/modules/`uname -r`/build/ M=`pwd`


OR

Cross-compiling on a x86 based environment.

If you have a Linux based system, you could cross compile on your laptop and copy the result to the Rapi.

The following commands work for Fedora. You will need to adjust to get it working for your distribution


1) Install git, gcc, make and  gcc-arm-linux-gnu required to cross compile the kernel


# yum install -y git make gcc  gcc-arm-linux-gnu

2) Clone the RaPi kernel git repository

# git clone --branch rpi-patches --depth 1 https://github.com/raspberrypi/linux.git rapi-linux

3) Copy over the config file from the RaPi and prepare the sources

On the RaPi
zcat /proc/config.gz > /tmp/config


Copy over /tmp/config on the RaPi to your own system. Now copy it over to the git repo you just cloned.


On the Laptop/Desktop
# cd rapi-linux
# cp /tmp/config .config
# make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnu- oldconfig
# make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnu- vmlinux

At this point, your build environment is complete.


To build a module on the linux desktop, change into the module sources and run

make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnu- -C ../rapi-linux/ M=`pwd`

Replace ../rapi-linux/ with the location to your own RaPi kernel sources.