kmod: Hello World
Moving on we build a kernel module that prints hello world when loaded. Simple enough but it is integrated into buildroot so we can build it along with the kernel and rootfs.
1. Skeleton Directory structure
A new package is added to the external tree we created earlier. The folder structure is as below. Again just create empty files for now.
br2-ext-stm32f469/
├─ package/
│ ├─ kmod_hello/
│ ├─ Config.in
│ ├─ kmod-hello.mk
│ ├─ Makefile
│ └─ hello.c
2. External tree boilerplate
This time its a Kernel module and depends on the kernel being built. So we add a dependency in the Config.in file.
package/kmod_hello/Config.in
config BR2_PACKAGE_KMOD_HELLO
bool "hello kernel module"
depends on BR2_LINUX_KERNEL # only make sense if we build a kernel
help
Simple out-of-tree hello-world kernel module.
package/kmod_hello/kmod-hello.mk
Kernel modules depend on ARCH and CROSS_COMPILE variables to build. We also need to tell it where the kernel source is. Buildroot provides a variable LINUX_DIR for that. ARCH is an ARM type and CROSS_COMPILE is the toolchain prefix.
################################################################################
#
# kmod-hello
#
################################################################################
KMOD_HELLO_VERSION = 1.0
KMOD_HELLO_SITE = $(BR2_EXTERNAL_SS_STM32F469_EXT_PATH)/package/kmod_hello
KMOD_HELLO_SITE_METHOD = local
KMOD_HELLO_LICENSE = GPL-2.0
KMOD_HELLO_DEPENDENCIES = linux
# Build the module against the kernel Buildroot is building
define KMOD_HELLO_BUILD_CMDS
$(MAKE) -C $(LINUX_DIR) M=$(@D) \
ARCH=$(KERNEL_ARCH) CROSS_COMPILE="$(TARGET_CROSS)" \
modules
endef
# Install into the target rootfs under /lib/modules/$(uname -r)/
define KMOD_HELLO_INSTALL_TARGET_CMDS
$(MAKE) -C $(LINUX_DIR) M=$(@D) \
INSTALL_MOD_PATH=$(TARGET_DIR) \
modules_install
endef
$(eval $(generic-package))
package/kmod_hello/Makefile
This is going to be kernel module, becomes a .ko file when built.
# Kbuild-style makefile for an out-of-tree module
obj-m += hello.o
package/kmod_hello/hello.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ajay Sharma");
MODULE_DESCRIPTION("Hello-world kernel module");
MODULE_VERSION("1.0");
static int __init hello_init(void)
{
pr_info("kmod-hello: hello from STM32F469!\n");
return 0;
}
static void __exit hello_exit(void)
{
pr_info("kmod-hello: goodbye!\n");
}
module_init(hello_init);
module_exit(hello_exit);
3. Enable and Build the kernel module
The default kernel for STM32F469 does not have kernel module support enabled. So first we need to enable that in the kernel config. Check the loadable module support to enable it.
$ make linux-menuconfig

Fig 1: make linux-menuconfig
Now enable the kernel module we created.
$ make menuconfig

Fig 2: make menuconfig
Esc -> Esc -> Yes to save the config.
4. Kernel Utilities
The kernel module can be loaded using insmod and removed using rmmod commands. These commands are part of the busybox package in buildroot. So we need to enable that too.
$ make busybox-menuconfig

Fig 3: make busybox-menuconfig
Then build the system:
make
After completion the kernel module will be built and installed into the rootfs. It usually stored in the following folder
buildroot/output/images/rootfs/lib/modules/5.15.176/extra/hello.ko
5.15.176 is my kernel version, it may vary. Use your version.
5. Test the kernel module
Copy the rootfs to your SD card using the method we did before: bmaptool and boot the board. Login to the board using serial console.
Now we can load the kernel module using insmod command.

Fig 4: insmod hello
The message from the kernel module can be seen using dmesg command.

Fig 5: dmesg hello
This article was originally published on My Blog.
Next we continue doing something interesting …