How to get started writing a kernel module

You have to remove the dependecy on mt7621 target, and hidden property so you can select it in menuconfig so it actually compiles.

The kernel module I linked to was just as an example. It has a very simple Makefile, only one source file so I figured since you already wrote kernel modules for Ubuntu it shouldn't be to hard to modify to you actual needs.

As others have stated: building the .ko file and transferring to your device during development is faster (easier) than patching your source into the kernel and having to recompile the whole kernel. If you want you should be able to actually compile directly on the RPi3 but I'm not sure if the time to set that up plus likely longer waiting times to compile would actually benefit you. (see: building openwrt on openwrt )

1 Like

Thanks for your time.
I have no problem with cross-compiling, in fact, I've set up the build system on a powerful machine. The Makefile I used to use to compile modules in ubuntu seemed to me easier and easy to understand. But in this case the module you linked, I'm really struggling to figure out where I should make the change in the Makefile to work with this .c file.

#include <linux/init.h> 
#include <linux/kernel.h>
#include <linux/module.h> 

static int __init hello_init(void)
{
    printk(KERN_INFO "Hello, world\n");
    return 0;
}

static void __exit hello_exit(void)
{
    printk(KERN_INFO "Goodbye, world\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");

I made this commented Helloworld Makefile when I first started building. Not geared to kmods, but might give some insight into buildroot Makefile Structure.

Summary
include $(TOPDIR)/rules.mk

# Name, version and release number
# The name and version of your package are used to define the variable to point to the build directory of your package: $(PKG_BUILD_DIR)
PKG_NAME:=helloworld
PKG_VERSION:=1.0
PKG_RELEASE:=1

# Source settings (i.e. where to find the source code)
# This is a custom variable, used below
SOURCE_DIR:=/home/user/helloworld

include $(INCLUDE_DIR)/package.mk

# Package definition; instructs on how and where our package will appear in the overall configuration menu ('make menuconfig')
define Package/helloworld
        SECTION:=source
        CATEGORY:=Myprograms
        TITLE:=Hello, World!
endef

# Package description; a more verbose description on what our package does
define Package/helloworld/description
        A simple "Hello, world!" -application.
endef

# Package preparation instructions; create the build directory and copy the source code.
# The last command is necessary to ensure our preparation instructions remain compatible with the patching system.
define Build/Prepare
        mkdir -p $(PKG_BUILD_DIR)
        cp $(SOURCE_DIR)/* $(PKG_BUILD_DIR)
        $(Build/Patch)
endef

# Package build instructions; invoke the target-specific compiler to first compile the source file, and then to link the file into the final executable
define Build/Compile
        $(TARGET_CC) $(TARGET_CFLAGS) -o $(PKG_BUILD_DIR)/helloworld.o -c $(PKG_BUILD_DIR)/helloworld.c
        $(TARGET_CC) $(TARGET_LDFLAGS) -o $(PKG_BUILD_DIR)/$1 $(PKG_BUILD_DIR)/helloworld.o
endef

# Package install instructions; create a directory inside the package to hold our executable, and then copy the executable we built previously into the folder
define Package/helloworld/install
        $(INSTALL_DIR) $(1)/usr/bin
        $(INSTALL_BIN) $(PKG_BUILD_DIR)/helloworld $(1)/usr/bin
endef

# This command is always the last, it uses the definitions and variables we give above in order to get the job done
$(eval $(call BuildPackage,helloworld))

Your Makefile is quite similar to what I got in this guide: https://openwrt.org/docs/guide-developer/helloworld/chapter3.
Unfortunately, I've followed this guide, and though I've got no error the .ipk file is not generated in the expected directory.

Create a folder: since you are making a kernel module, put in in ~/openwrt/package/kernel and lets call it "hello-world"
Inside that folder create a sub-folder called "src"
Inside the "hello-world" folder create a almost minimal Makefile like:

#
# Copyright (C) 2006-2009 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#

include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk

PKG_NAME:=hello-world
PKG_RELEASE:=0.1

include $(INCLUDE_DIR)/package.mk

define KernelPackage/hello-world
  SECTION:=kernel
  CATEGORY:=Kernel modules
  SUBMENU:=Other modules
  TITLE:=Hello World Kernel Module
  FILES:=$(PKG_BUILD_DIR)/hello-world.ko
endef

define Build/Compile
	$(MAKE) -C "$(LINUX_DIR)" \
		$(KERNEL_MAKE_FLAGS) \
		M="$(PKG_BUILD_DIR)" \
		EXTRA_CFLAGS="$(BUILDFLAGS)" \
		modules
endef

$(eval $(call KernelPackage,hello-world))

In your "src" sub-folder you should have a file with the source code from your post above. Lets call that: "hello-world.c"

Now add another Makefile INSIDE the src folder:

obj-m += hello-world.o

Again: those are simple files, add more fancy stuff as you get more comfortable (or need extra).

from ~/openwrt and as normal user:

make package/hello-world/compile V=s

V=s is optional but I would recommend to see any errors.
Change the source and I recommend:

make package/hello-world/{clean,compile} V=s

you will end up the an kmod-hello-world_(kernel version)(version)(target).ipk in ~/openwrt/bin/target/(whatever your target)/packages

in ~/openwrt/build_dir/(target)/(linux)/hello-world you end up the everything the original "src" folder plus anything that was needed to build the .ko file and the .ipkg stuff.

Edit:
DON'T forget to do a "make menuconfig" and select your module (either as * or M, but I would use M for clarity). Inside "kernel modules/Other modules" as defined in the "top" Makefile.

3 Likes

Do I need to select it in menuconfig before running make package/hello-world/compile V=s?

Thanks a lot. I've successfully created the .ipk files and .ko.
I've loaded the .ko and installed the .ipk. When the module is loaded I see the log messages in the system log as written in the source code. But what are the similar outcomes for the installed package? Can a package be used just like its corresponding module? What is the relation between them?

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.