January 2013 Blog Posts
Compiling Kernel Modules for Raspberry Pi

image I tried loading rpi-pwm on my Raspberry Pi, but ran into some issues. After some tinkering I was able to compile rpi-pwm.c on the Raspberry Pi, but I kept running into Invalid Format issues anytime I tried to insmod rpi-pwm.ko which had the following dmesg:

rpi_pwm: disagrees about version of symbol module_layout

I guess this generally means I need to compile my module in the same way the kernel is compiled on the Raspberry Pi. Otherwise, the kernel will reject the module.

I've found that cross-compiling works best. This means, building your kernel and modules on a different platform rather than on the Raspberry Pi hardware directly. I did NOT have any luck compiling my kernel module directly on Raspberry Pi hardware.

In detail, first you'll want to cross-compile the Raspberry Pi Linux kernel so it builds Module.symvars and other intermediates. You won't actually use the kernel that is being cross-compiled, just the intermediates to compile your module. Next, you'll cross-compile your module using those intermediates. Once your module is cross-compiled, copy the .ko module to your running Raspberry Pi and you should be able to load it along with the stock kernel. The following is a quick how-to cross-compile the Raspberry Pi Kernel modules on Ubuntu 12.04:

First, know what version of RPi you're running:

uname -r and uname -a

[email protected]:/# uname -r
3.2.27+
[email protected]:/# uname -a
Linux raspberrypi 3.2.27+ #250 PREEMPT Thu Oct 18 19:03:02 BST 2012 armv6l GNU/Linux

I've downloaded everything into a directory called ~/rpi on my Ubuntu machine.

1. Compile the Kernel

For 3.2.27+:

(instructions generally flow from: http://elinux.org/RPi_Kernel_Compilation)

  • Install Ubuntu
  • Get the rpi-3.2.27.tar.gz tarball
  • Get the tools tarball
  • tar xzf rpi-3.2.27.tar.gz and tar xzf master.tar.gz (tools)
  • Set the environment variable CCPREFIX:
    export CCPREFIX=
    /home/cowboy/rpi/tools-master/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-
  • Set the environment variable KERNEL_SRC:
    export KERNEL_SRC=/home/cowboy/rpi/linux-rpi-3.2.27
  • In KERNEL_SRC: execute "make mrproper" to ensure you have a clean kernel source tree.
  • Pull /proc/config.gz from your running Raspberry Pi and extract it into KERNEL_SRC on your Ubuntu machine.

    scp [email protected]:/proc/config.gz ./ (transfers it to Ubuntu)
    zcat config.gz > .config (uncompresses .config)
    mv .config $KERNEL_SRC (moves the uncompressed .config to KERNEL_SRC) 

  • On Ubuntu: Prime kernel with the old config:
    make ARCH=arm CROSS_COMPILE=${CCPREFIX} oldconfig
  • On Ubuntu: Build the kernel:
    make ARCH=arm CROSS_COMPILE=${CCPREFIX}

This will produce a fresh Module.symvers and since you're using the cross-compile tools, the intermediates the tools generate should be binaurally compatible with Raspberry Pi.

2. Compile your kernel module

Next, make a separate directory outside of KERNEL_SRC (or example: ~/pwm) and write a quick Makefile for your kernel module:

obj-m += rpi-pwm.o

all:
    make ARCH=arm CROSS_COMPILE=${CCPREFIX} -C /home/cowboy/rpi/linux-rpi-3.2.27 M=$(PWD) modules

clean:
    make -C /home/cowboy/rpi/linux-rpi-3.2.27 M=$(PWD) clean

(learn more about compiling Linux kernel modules here)

When you're ready to compile your module, go ahead and execute "make" and you should be gold. Copy your rpi-pwm.ko to your RPI then use modinfo rpi-pwm.ko to review the module information:

[email protected]:/# modinfo rpi-pwm.ko
filename:       /home/pi/temp/rpi-pwm.ko
alias:          platform:bcm2708_pwm
author:         Sean Cross <[email protected]> for Adafruit Industries <www.adafruit.com>
license:        GPL
srcversion:     44D62553C321E91B0CB1996
depends:       
vermagic:       3.2.27 preempt mod_unload modversions ARMv6

Last but not least, you should be able to insmod rpi-pwm.ko without any problems. My dmesg:

[email protected]:/# dmesg | tail -5
[18852.504621] rpi_pwm: disagrees about version of symbol module_layout
[19043.461377] rpi_pwm: disagrees about version of symbol module_layout
[21401.160720] rpi_pwm: disagrees about version of symbol module_layout
[22026.927225] rpi_pwm: disagrees about version of symbol module_layout
[26733.475758] Adafruit Industries' Raspberry Pi PWM driver v1.0

If you want your module to auto start:

  • Copy your .ko module to /lib/modules/3.2.27+
  • Edit /etc/modules and append your module to the end of the list.
    Mine looks like:

    # /etc/modules: kernel modules to load at boot time.
    #
    # This file contains the names of kernel modules that should be loaded
    # at boot time, one per line. Lines beginning with "#" are ignored.
    # Parameters can be specified after the module name.

    snd-bcm2835
    spi-bcm2708
    i2c-bcm2708
    i2c-dev
    rpi-pwm

  • Next, run: depmod -a
  • Next, run: modprobe <yourmodulename>

Then reboot and your module should auto start on boot.

Hope that helps!
Brian Chavez