Search by Tags

Building External Kernel Modules With Torizon

 

Article updated at 15 Mar 2021
Subscribe for this article updates

Select the version of your OS from the tabs below. If you don't know the version you are using, run the command cat /etc/os-release or cat /etc/issue on the board.



Remember that you can always refer to the Torizon Documentation, there you can find a lot of relevant articles that might help you in the application development.

Torizon 5.2.0

Introduction

It is often necessary to build an external kernel module (a.k.a. an out-of-tree module) when this module doesn't exist in the standard Linux tree.

Some examples where this is necessary:

  • When adding support to some device/peripheral you're using.
  • When including some proprietary code.

In both cases, the process is the same. You'll need to compile the kernel module's source code against the kernel source to make it compatible.

The typical way to do this in embedded Linux would be to add your kernel module via the Yocto Project/OpenEmbedded build system. However, this requires quite a bit of knowledge, and as we deliver TorizonCore as a binary distribution, we try to simplify this process greatly in a way that you don't need to fallback to a Yocto build.

In a summary, these are the steps to build and deploy external kernel modules on TorizonCore using TorizonCore Builder Tool:

  1. Install TorizonCore Builder Tool and unpack a base TorizonCore Easy Installer image following the installing instructions.
  2. Copy your kernel module source code into a single directory within the TorizonCore Builder Tool working directory.
  3. Use the build_module command, targeting your source directory.
  4. Use the union command to merge them onto the base image.
  5. Use the deploy command to deploy the changes onto the device or create a new Easy Installer image.
  6. Use the modprobe command to load your newly built kernel module.

In this article, we will show an example of how to build and load your out-of-tree kernel modules in TorizonCore with a simple example.

This article complies to the Typographic Conventions for Torizon Documentation.

Prerequisites

Installing TorizonCore Builder

To use TorizonCore Builder, you need to create an alias. Follow the installation instructions on the TorizonCore Builder article. Make sure to:

  • Unpack the TorizonCore image, as explained in the article.
  • Use an empty working directory and navigate to it. This directory is shared (bind-mounted) with the TorizonCore Builder container, and it stores temporary files and the final image.

Hello World Kernel Module Example

Begin by organizing your kernel module source code into a single directory; let's call this your source_dir. At a minimum, your source code should have at least one source C file and one Makefile.

Preparing the Module's Source Files

As an example, see the following source file:

hello.c
#include <linux/module.h>
 
int init_module(void)
{
    printk("Hello World!\n");
    return 0;
}
 
void cleanup_module(void)
{
     printk("Goodbye Cruel World!\n");
}
 
MODULE_LICENSE("GPL");

Preparing the Module's Makefile

Take extra notice of the Makefile. In particular, notice the environment variable $(KERNEL_SRC). The TorizonCore Builder tool uses this variable, so include this in your Makefile as shown below. Alternatively, you can also use $(KDIR) instead. You do not need to define both these variables, but including at least one is mandatory.

Makefile
obj-m := hello.o
 
SRC := $(shell pwd)
 
all:
        $(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules
 
clean:
        $(MAKE) -C $(KERNEL_SRC) M=$(SRC) clean

Building the Out-of-Tree Module

Now that you have the files in your source_dir organized, you need to copy/move the source_dir to the working directory you have set up your TorizonCore Builder Tool. Remember to unpack a Torizon Toradex Easy Installer image into TorizonCore Builder before proceeding, as shown on the tool's installation instructions.

With everything in place, you can begin using TorizonCore Builder to build the kernel module.

For this, you'll be using the kernel build_module sub-command. After some time, if the compilation was successful, you'll see output similar to the following:

$ torizoncore-builder kernel build_module source_dir
make: Entering directory '/workdir/module_source'
make -C /storage/linux M=/workdir/module_source modules
make[1]: Entering directory '/storage/linux'
  CC [M]  /workdir/module_source/hello.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC [M]  /workdir/module_source/hello.mod.o
  LD [M]  /workdir/module_source/hello.ko
make[1]: Leaving directory '/storage/linux'
make: Leaving directory '/workdir/module_source'
Kernel module(s) successfully built and ready to deploy.
All kernel module(s) have been built and prepared.

Deploying the module

Now that the kernel module has been built, you can use the union and deploy commands to deploy the changes either to your device or a custom TorizonCore image.

After you've deployed the changes to your device, the kernel module will be located in the following location on the device:

# ls /usr/lib/modules/<kernel_ver>/extra/
hello.ko

From here, you should be able to use the modprobe command to load your kernel module. As a note, by default, the kernel module will not load on boot. You can change this behavior by adding the --autoload flag to the build_module command. Also, if you're building from two or more different sets of source code, you can run build_module multiple times targeting each source directory separately. Each kernel module will be added in succession.