Crosscompiling modules for Raspberry 3

Compiling a module, and using it on Raspberry 3 without installing a new kernel can be a bit difficult, This description is based on the method described by Martin Kramer, and worked for us - it probably also works for Raspberry 2.

The computer used for the cross-compiling was running Debian (Jessie) and the Raspberry Pi 3 was running Raspbian kernel  All commands are written in bold font - change the YourHomeDir to the name of your home directory.

Kernel compilation

First, the kernel has to be compiled. There is no need to actually use this newly compiled kernel, you can continue to use the kernel that is already installed in your Raspberry. The kernel will be compiled here to get information that is to be used when building modules. You only have to compile the kernel once, after that you can compile the modules any number of times. You will need the version control program git, no if not installed, install it (easiest with synaptic).

  • Copy the cross-compiling tools from github to the Debian-computer, and set CCPREFIX to point to the correct tools:

        ~ $ git clone https://github.com/raspberrypi/tools
        ~ $ export CCPREFIX=/home/YourHomeDir/tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-
  • Copy Raspbian source from github to the same computer, and set KERNEL_SRC to point to the source:

        ~ $ git clone https://github.com/raspberrypi/linux
        ~ $ export KERNEL_SRC=/home/YourHomeDir/linux
  • On the Raspberry Pi, execute these commands (ref: https://www.raspberrypi.org/forums/viewtopic.php?f=66&t=57401,  comments by Zeta):

        ~ $ FIRMWARE_HASH=$(zgrep "* firmware as of" /usr/share/doc/raspberrypi-bootloader/changelog.Debian.gz  | head -1 | awk '{ print $5 }')
        ~ $ echo $FIRMWARE_HASH
        ~ $ KERNEL_HASH=$(wget https://raw.github.com/raspberrypi/firmware/$FIRMWARE_HASH/extra/git_hash -O -)
        ~ $  echo $KERNEL_HASH

    This should give a couple of hexadecimal git hashes, e.g. 03f35fe498e5516091e4fd66d1700e8d0b0f4915. The first hash indicates firmware version, the second one which version of the kernel is in use on the Raspberry Pi.

    Still on the Raspberry, execute the commands:

        ~ $  su
        ~ $ modprobe configs

    This installs a module that makes it possible to copy files from Rasbian to another computer, Secure Copy. This will be used later (from the Debian computer) to copy files from Raspbian.
  • Back on the Debian-computer, select the correct kernel version by giving these commands:

        ~ $ cd linux
        ~/linux $ git checkout INSERT_KERNEL_HASH_HERE

    This will choose the correct source branch (version) of the kernel.
  • Now the cross compilation work can begin: Execute

        ~/linux $ make mrproper

    which cleans up the source directory: earlier generated files and configurations are deleted.

    Copy a new kernel configuration file from the Raspberry Pi - this configuration file will control the compilation of the kernel:

        ~/linux $ scp pi@INSERT_THE_IP_NAME_OF_YOUR_RASPBERRY_HERE:/proc/config.gz ./
        ~/linux $ zcat config.gz > .config

    The last command uncompresses the config file.
  • Compile the kernel:

        ~/linux $ make ARCH=arm CROSS_COMPILE=${CCPREFIX} oldconfig
        ~/linux $ make ARCH=arm CROSS_COMPILE=${CCPREFIX}

    These steps can take a long time (hours...).

    If there were no errors, a new kernel image is available in /home/pernilla/YourHomeDir/linux/arch/arm/boot, but, as noted earlier, you do not need the kernel itself. To check that the correct kernel was compiled, execute the commands

        ~/linux $ cd ..
        ~ $  wget https://raw.githubusercontent.com/raspberrypi/firmware/INSERT_FIRMWARE_HASH_HERE/extra/Module7.symvers

    This command fetches the original symbol table, Module7.symvers, from github. The firmware hash is the output from the 'echo $FIRMWARE_HASH' command that was executed on Raspbian earlier. If you are doing this for a Raspberry 1, substitute Module for Module7.

    Compare the symbol table that was fetched from github with the one generated by the compilation - they should be identical:

        ~ $  diff -s Module7.symvers  linux/Module.symvers
        Files Module7.symvers.txt and linux/Module.symvers are identical

    Now module compilation can begin.

Now module compilation can begin.
  • Set variables to point at the source and the tools, and execute make:

        ~/linux $ export SRC=/home/YourHomeDir/linux/drivers/spi
        ~/linux $ export PREFIX=/home/YourHomeDir/tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-
        ~/linux $ make ARCH=arm CROSS_COMPILE=${PREFIX} -C /home/YourHomeDir/linux M=${SRC} modules
  • Move compiled module(s) to the Raspberry:

        ~/linux $ cd drivers/spi
        ~/linux $ /drivers/spi $ sftp pi@INSERT_THE_IP_NAME_OF_YOUR_RASPBERRY_HERE
        ftp> put *.ko

    Then, login to the Raspberry: move the original modules to safety and copy the new ones to the module directory

        ~ $ sudo mkdir /lib/modules/4.4.38-v7+/kernel/drivers/spi/Originals
        ~ $ sudo mv /lib/modules/4.4.38-v7+/kernel/drivers/spi/*.ko /lib/modules/4.4.38-v7+/kernel/drivers/spi/Originals
        ~ $ sudo cp *.ko /lib/modules/4.4.38-v7+/kernel/drivers/spi
        ~ $ sudo rmmod spi_bcm2835
        ~ $ sudo modprobe  spi_bcm2835

    The new version of the module is now loaded into the kernel and can be tested (check with lsmod command).

If you notice errors, please let us know info [at] tietonoita [dot] fi