Compiling Kernel Modules for Raspberry Pi
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
root@raspberrypi:/# uname -r
3.2.27+
root@raspberrypi:/# 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
andtar 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
: executemake mrproper
to ensure you have a clean kernel source tree. -
Pull
/proc/config.gz
from your running Raspberry Pi and extract it intoKERNEL_SRC
on your Ubuntu machine.scp pi@rpiaddress:/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:
root@raspberrypi:/# 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
:
root@raspberrypi:/# 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
Comments
JoeDeb
Brian, thank you very much for writing this!
Actually -with my limited knowledge in linux- i have been struggling for almost 6 days to compile a stk1160 Module for my new Raspberry Pi.
Following your explanation (simple copy and paste ;)) i was successful!!! I used a VM with Ubuntu 12.04 for cross-compiling.
I hope you don’t mind that i tell you about a few things i stubled across:
1) Its not “tar xzf tools.tar.gz” but “tar xzf master.tar.gz”
2) “In KEREL_SRC”: should be: “In KERNEL_SRC”
3) 2 things in this line:
scp pi@rpiaddress:/proc/config.gz ./; zcat config.gz > .config; mv .config $KEREL_SRC
did not work…
sudo scp pi@rpiaddress:/proc/config.gz ./; zcat config.gz > .config; mv .config $KERNEL_SRC
..did.
Thanks again
Joerg
Brian Chavez
Thanks, updated with your edits/suggestions.
-cowboy
Heri
Brian, this is actually a concise explanation as to how to compile a kernel for the RPi, kudos.
However, the most recent O/S contains a WiFi driver module which is not suitable for the EDIMAX-EW7811 (requires Realtek rtl8192cu driver). Since compiling is not my forte, I wonder if you could expand your explanation to cover this issue in order to add or compile this driver to the Kernel.
I think that this would help quite few of us who struggle with the same predicament.
Brain_ReCall
Great guide, thanks!
For those using a 64-bit install of Ubuntu, you have to have the ia32-libs package otherwise you get some very strange errors about missing files. For a fresh install of Ubuntu, its best to just do: “sudo apt-get install build-essential ia32-libs”
Martin
Great guide, I was also stuck trying to compile a module on the rpi itself, but your guide works like a charm and cross compiling is better anyway for performance reasons.
Heri
Hi Brian,
I ran into a problem trying to follow your section 2. above.
The driver (directory) supplied by Realtek for the Edimax WiFi device contains a bunch of subdirectories and files such as:Makefile, include, clean,etc.
1. Would the driver directory be the equivalent of your example ~/pwm ?
2. Should the driver directory be part of the KERNEL_SRC directory?
The issue is somwhat confusing since the KERNEL_SRC and the WIFi driver directory contain a Makefile albeit dissimilar in contents.
Your help very much appreciated.
BTW-Compiling the Kernel, as per your instructions of para.1, went without problems.
rpi
Great guide. Martin, thanks a lot. I ran into the same issue on 64-bit ubuntu. your suggestion works fine. thanks
Stacey
Thank you so much.
PeterK
small typo remove .
zcat config.gz > .config
should be
zcat config.gz > config
PeterK
Sorry, pls forget previous post. No typo!
Krishna
The instructions worked with 3.6.11 source as well when I replaced 3.2.27 with 3.6.y in the instructions given above. Thanks a ton for your guide!
Sorin
works perfectly, thank you;)
fabrizio
I did all the steps, but didn’t work. I’ve noticed that my modinfo says 3.6.11 preempt mod_unload modversions ARMv5, instead of v6.
I used ubuntu 12.04
Saurabh
Hi, I have compiled a kernel successfully using cross tool chain.
I am using Ubuntu installed in VM and Raspbian V3.6.11 running in Raspberry pi board.
I have written a simple code for device driver and compiled it using make file.
I got following errors
make ARCH=arm CROSS_COMPILE= -C /home/saurabh/rpiRaspi M= modules
make[1]: Entering directory
/home/saurabh/rpiRaspi'<br /> CHK include/linux/version.h<br /> CHK include/generated/utsrelease.h<br />make[2]:
include/generated/mach-types.h’ is up to date.CC kernel/bounds.s
cc1: error: unrecognized command line option ‘-mlittle-endian’
cc1: error: unrecognized command line option ‘-mno-thumb-interwork’
kernel/bounds.c:1:0: error: unknown ABI (aapcs-linux) for -mabi= switch
kernel/bounds.c:1:0: error: bad value (armv5t) for -march= switch
kernel/bounds.c:1:0: error: bad value (strongarm) for -mtune= switch
make[2]: ** [kernel/bounds.s] Error 1
make[1]: ** [prepare0] Error 2
make[1]: Leaving directory `/home/saurabh/rpiRaspi’
make: *** [all] Error 2
Please provide suggestion to solve it!!
praneeth
I am using 64bit ubuntu 12.4 to cross compile rpi (3.6.11) kernel modules. I followed the above steps and compiled the kernel crc successfully. But, I am seeing errors when I compile kernel modules. Here is the errors I am seeing.
make ARCH=arm CROSS_COMPILE= -C /home/rppendya/rpi/linux-rpi-3.6.y M=/home/rppendya/workspace/ds1307 modules
make[1]: Entering directory
/home/rppendya/rpi/linux-rpi-3.6.y'<br /> CC [M] /home/rppendya/workspace/ds1307/ds1307.o<br />cc1: error: unrecognized command line option ‘-mlittle-endian’<br />cc1: error: unrecognized command line option ‘-mno-thumb-interwork’<br />/home/rppendya/workspace/ds1307/ds1307.c:1:0: error: unknown ABI (aapcs-linux) for -mabi= switch<br />/home/rppendya/workspace/ds1307/ds1307.c:1:0: error: bad value (armv5t) for -march= switch<br />/home/rppendya/workspace/ds1307/ds1307.c:1:0: error: bad value (strongarm) for -mtune= switch<br />make[2]: *** [/home/rppendya/workspace/ds1307/ds1307.o] Error 1<br />make[1]: *** [_module_/home/rppendya/workspace/ds1307] Error 2<br />make[1]: Leaving directory
/home/rppendya/rpi/linux-rpi-3.6.y’make: *** [all] Error 2
Any help and advise would be appreciated
Andre Carvalhosa
Excellent tutorial! I was having problems compiling a module on the rpi itself …
Thanks!
Simon
For Saurabh, paraneeth, and others who find this page later and are looking for a solution to that problem,
The problem is you are invoking the standard, x86 gcc and asking it to compile for arm. Naturally, standard x86 gcc has no idea how to do this, so is throwing a bunch of errors back at you.
If you’re coping Brian’s Makefile, be sure you have your CCPREFIX set to point to your cross-toolkit, as Brian did in step 1. export CCPREFIX=
/home/cowboy/rpi/tools-master/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi- (Your toolkit will probably be somewhere different! You should have downloaded it as part of the tools tarball)
TIK
hi Brian and everyone:
thank you for this writing!!
I have some problem in the kernel building. After Build the kernel:
“make ARCH=arm CROSS_COMPILE=${CCPREFIX}”
(firmament@NKG:/media/sf_F_DRIVE/TI_D/RaspberryPi/srcTree/linux-rpi-3.12.y$ sudo make ARCH=arm CROSS_COMPILE=/home/firmament/rpi/tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-
)
This error happened
———————————
mkdir -p include/generated
scripts/kconfig/conf –silentoldconfig Kconfig
** Error during update of the configuration.
make[2]: ** [silentoldconfig] Error 1
make[1]: ** [silentoldconfig] Error 2
make: ** No rule to make target
include/config/auto.conf’, needed by
include/config/kernel.release’.————————————
could you give me some suggestions or tell me which part I need to check first
Thank you very much
TIK
Hi Brian& everyone:
first time I tried to compile kernel was failed at
“make ARCH=arm CROSS_COMPILE=${CCPREFIX}”
with error:
scripts/kconfig/conf –silentoldconfig Kconfig
** Error during update of the configuration.
make[2]: ** [silentoldconfig] Error 1
make[1]: ** [silentoldconfig] Error 2
The reason was related to the permission in my Ubuntu. After I moved the source tree to my home folder, this problem had been solved.
But after about an hour compiling, another error happened. Could you give me some suggestions? Thanks
make[1]:
include/generated/mach-types.h' is up to date.<br /> CALL scripts/checksyscalls.sh<br /> CHK include/generated/compile.h<br /> CHK kernel/config_data.h<br />make[2]: *** No rule to make target
net/bridge/br_fdb.o’, needed by `net/bridge/bridge.o’. Stop.make[1]: ** [net/bridge] Error 2
make: *** [net] Error 2
Ray
Thanks!
FYI To get the latest 3.12.32+ source I did.
mkdir ~ray/meinberg
cd ~ray/meinberg
wget https://github.com/raspberrypi/tools/archive/master.zip
unzip master.zip
git clone https://github.com/raspberrypi/linux.git
export CCPREFIX=/home/ray/meinberg/tools-master/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-
export KERNEL_SRC=/home/ray/meinberg/linux
cd linux/
make mrproper
etc.
One hiccup for me. NEWBIE ALERT. When copying the Makefile example above, make sure that the character before ‘make’ is a TAB and not multiple spaces. Arrgh. Otherwise you get the error: “make: Nothing to be done for `all’.” Took me ages to find that.
marvic
cp pi@raspberrypi:/proc/config.gz ./
ssh: connect to host raspberrypi port 22: Connection timed out
How to solve this.
Thank you
Ganesh
Hello,
When I try to set up an environment it gives following error
bash: export: `/home/ganesh/RPICComp/tools-master/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-‘: not a valid identifier
I have stored my tool master folder in home/ganesh/RPICComp/
and Kernel virsion is 3.18.y
I am using following command for setting up the Environment
export CCPREFIX= /home/ganesh/RPICComp/tools-master/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-
Kindly Guide Me
Thank You
don
Have you any idea where to find the kernel version 3.10.25+ ??
John
where do I find kernel version 3.18.14+
John
This doesn’t work at least not for building an rpi module for the edimax ew-7811uac ac600. i got a bunch of warnings/errors when i ran the ARCH=arm CROSS_COMPILE=${CCPREFIX} oldconfig step. i have no clue how to configure the kernel so i accepted the defaults so i got a bunch of errors instead when i tried to build the kernel. but i was able to build the kernel (error free) merely by copying the proc/config.gz from my rpi and overwriting the .config in linux-rpi-3.18.y directory and skipping the above mentioned step.
I’m doing this on linux mint 17.1 (more or less ubuntu) which may or may-not (i suspect not) make a difference.
I put everything as indicated in my home directory
ls -1 ~/EDIMAX-COMPILE/RPI
linux-rpi-3.18.y
rtl8812au-master
tools-master
I created a directory outside the RPI directory and created the makefile as follows:
obj-m += 8812au.o
all:
make ARCH=arm CROSS_COMPILE=${CCPREFIX} -C /home/maihoa/EDIMAX-COMPILE/RPI/linux-rpi-3.18.y M=$(PWD) modules
clean:
make -C /home/maihoa/EDIMAX-COMPILE/RPI/linux-rpi-3.18.y M=$(PWD) clean
and made sure i had the TAB before make
The evn vars appear to be correct
echo $CCPREFIX
/home/maihoa/EDIMAX-COMPILE/RPI/tools-master/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-
maihoa@Dell-LinuxMint ~/EDIMAX-COMPILE/RPI-8812au-module $ echo $KERNEL_SRC
/home/maihoa/EDIMAX-COMPILE/RPI/linux-rpi-3.18.y
My rpi kernel is: uname -a
Linux raspberrypi 3.18.14+ #794 PREEMPT Sun Jun 7 12:02:04 BST 2015 armv6l GNU/Linux
what i don’t understand in the Makefile script is how does it know that i want to build a module for rtl8812au-master. I can’t get it to work.
What am i doing wrong?
Thanks
John
Sai
Thanks for this blog, it works, now i can able to compile module files on my PC and tested on rspi board.
thankyou.
Leave a comment
Your email address will not be published. Required fields are marked *