Having a cross compilation environment on the host PC can bring great convenience to the development of kernel modules. In the process, there are a lot of things that require attention. The process I followed is documented here for future reference.
The building of out-of-tree modules depends on many files (configs, kernel Makefile, headers, /scripts directory etc.) from the kernel. They can be obtained by downloading and building a kernel or installing the headers directly. The first approach is introduced here. Note that a full kernel build is not necessary, since the kernel image itself is not required.
To make the setup capable of cross compilation, the kernel source code, configuration and compiler need to match those of the target device.
Beaglebone Black, PC running on Linux system (Ubuntu ver 20.04)
Serial to USB cable, USB type A to mini B cable
On the board, find out the version of the kernel image and the compiler used to build it with:
cat /proc/version
My kernel version was linux 5.10.168-ti-r71 and compiler version was gcc 10.2.1 (Debian).
The closest compiler I could get was arm-linux-gnueabihf-gcc 10.5.0 (Ubuntu), which can be installed by:
sudo apt-get update
sudo apt-get install gcc-10-arm-linux-gnueabihf
Check if it is the default cross compiler:
which arm-linux-gnueabihf-gcc
arm-linux-gnueabihf-gcc --version
If it is not, find its location by running:
ls -al /usr/bin | grep gcc
Configure it as the default cross compiler with update-alternatives, which can handle the coexistence of multiple different versions of the same package:
sudo update-alternatives --install /usr/bin/arm-linux-gnueabihf-gcc arm-linux-gnueabihf-gcc /usr/bin/arm-linux-gnueabihf-gcc-10 60
On the host, create a directory for the kernel source. Since this kernel source is not intended for the host, it is suggested to put it under /home/user:
mkdir /path/to/kernel
Initialize the directory with:
git init
Download the kernel source with:
git clone https://github.com/beagleboard/linux.git
Switch to the required version:
git checkout $version-of-your-kernel$
Check under the /arch/arm/config directory of the kernel source, there should be a bb.org_defconfig file. Copy it to the main directory to act as the .config file with:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bb.org_defconfig
Check the default configuration with:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
I did not make any modification to it.
Run the following to prepare the source for module compilation:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules_prepare
It only took a few seconds on my host, which was much faster than building a whole kernel.
Write a simple module in hello_module.c:
#include <linux/module.h>
#include <linux/init.h>
static int __init hello_module_init(void) {
printk("Hello!\n");
return 0;
}
static void __exit hello_module_exit(void) {
printk("Byebye!\n");
}
module_init(hello_module_init);
module_exit(hello_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Testing kernel source for cross compilation");
Compose a Makefile:
KERN_DIR := /path/to/kernel/linux
PWD := $(shell pwd)
obj-m := hello_module.o
ARCH=arm
CROSS_COMPILE=arm-linux-gnueabihf-
all:
make $(ARCH) $(CROSS_COMPILE) -C $(KERN_DIR) M=$(PWD) modules
clean:
make $(ARCH) $(CROSS_COMPILE) -C $(KERN_DIR) M=$(PWD) clean
Run make to compile the module:
make
The result should contain a hello_module.ko file. Move it the NFS shared directory. Setting up NFS is introduced in https://gist.github.com/Zixuan-Qiao/20fa82699fb0e01119b79eeaee56d3a3. On your board, load the module with:
sudo insmod hello_module.ko
Run the following to varify if it is loaded successfully:
lsmod | grep hello
Check the printk message with:
sudo dmesg
Unload it with:
sudo rmmod hello_module
- https://www.modbus.pl/bbb/cross-compile-kernel-for-beaglebone-black/
- https://stackoverflow.com/questions/70707519/how-can-i-prepare-a-linux-source-tree-so-an-external-module-can-be-compiled-agai
- http://charette.no-ip.com:81/programming/2011-12-24_GCCv47/
- https://askubuntu.com/questions/1152383/how-to-switch-the-version-of-arm-linux-gnueabihf-gcc
- https://stackoverflow.com/questions/25572395/cross-compiling-a-kernel-module-arm
- https://unix.stackexchange.com/questions/202910/how-to-check-a-kernel-version-which-was-used-when-building-package
- https://packages.debian.org/bullseye/gcc-10-arm-linux-gnueabihf
- https://askubuntu.com/questions/1412122/how-to-install-debian-package-in-ubuntu
- https://lwn.net/Articles/81398/
- https://unix.stackexchange.com/questions/213947/some-questions-regarding-linux-kernel-external-module-build-process
- https://www.kernel.org/doc/Documentation/kbuild/modules.txt
- http://derekmolloy.ie/writing-a-linux-kernel-module-part-1-introduction/