Post

Cross compiling kernel modules

Note for config linux kernel build

Just got to compile a driver for ti-ads1220 running with Orange Pi Zero. I’ve figure out some stuff when digging to kernel modules. Below is how I config cross build for my Pi.

Target system

Orange Pi Zero running Armbian Bionic 20.02.1 with Linux 5.4.20-sunxi

alt target-system

Download kernel source

Download kernel source from kernel.org

The version of kernel source need to be download, must be exact version of the target system. Otherwise, you would be end up with:

alt mod_unload

My target is linux-5.4.20-sunxi so I downloaded linux-5.4.20.tar.gz. Note that the -sunxi suffix could be add later by .config file.

Cross compile toolchain

arm-linux-gnueabihf working well for me. On Debian just run:

1
$ sudo apt install gcc-arm-linux-gnueabihf

and every things works like a charm. Google it for more information or how to install it on other distro.

The kernel build config

The build configuration must be exact the same configuration of our target system. You can get a copy from a running system:

  • /proc/config.gz (the file is zipped)
  • /boot/config
  • /boot/config-*

In my case, I’m using:

1
~$ zcat /proc/config > .config

then use scp to copy .config from Pi to root folder of kernel source has just downloaded.

Linux kernel suffix

TL;DR

My target is linux-5.4.20-sunxi but the source is linux-5.4.20 when I got my first-complete-module-build-without-error output file, I was happy to test it on my Pi. But unfortunately, I got Invalid module format when using insmod to load my module. It took me 2 days to figure out what I’m doing wrong.

Things is the version magic of my module should match every single letter to the target version. For example, in my case, vermagic of my module was:

1
linux-5.4.20 SMP mod_unload ARMv7 thumb2 p2v8

while my Pi is:

1
linux-5.4.20-sunxi SMP mod_unload ARMv7 thumb2 p2v8

You can use modinfo for checking vermagic of module and uname -a for a running target.

Fix it

The .config file you had taken from the running target, change CONFIG_LOCALVERSION="" to CONFIG_LOCALVERSION="-sunxi" before run make and everything should work properly.

Build the kernel

From root folder of kernel source run:

1
2
3
4
# update current .config file
$ make ARCH=arm CROSS_COMPILE=<arm-linux-gnueabihf- oldconfig
# build 
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j4

Once done, kernel directory are ready to build your module.

Build the module

A simple Makefile

obj-m += mymodule.o

KDIR=<your/path/to/kernel/source/root/folder>
CROSS=<toolchain compiler>

all:
	make ARCH=arm CROSS_COMPILE=$(CROSS) -C $(KDIR) M=$(PWD) modules
clean:
	make ARCH=arm CROSS_COMPILE=$(CROSS) -C $(KDIR) M=$(PWD) clean

From your module source code, run:

1
$ make
This post is licensed under CC BY 4.0 by the author.