Compiling BeagleBone Kernel and Making a Kernel Module.

In my process of learning Linux and the BeagleBone, I have needed to compile the CircuitCo standard released kernel and to make kernel modules. This post will give a brief overview of how I have accomplished this and hopefully help out others that seem to be struggling in the same area.

First I would like to thank several long time friends and past co-workers for their help and patience in helping me get over some of the hurdles I have encountered. Thanks goes to Matt Porter (http://engineersofthecorn.blogspot.com) and Mark Greer of Animal Creek Technologies (mgreer@animalcreek.com) for their continued friendship and assistance in git and Linux.

Note: All of this blog entry was performed as root. If you are not root then there is a good chance you will have to proceed the commands with “sudo” to not get errors.

Step #1 – Getting a Linux Development Environment

If you have a Linux system set up already, skip to step #2.

Instead of going through what is needed in a Linux development environment, I’ll just point you to what I was pointed to when I first started. The link below is a virtual machine based on the VMware architecture that has everything you need to get started except the cross environment tools.

http://www.trendsigma.net/vmware/lubuntu1110t.zip

This image can be used on Windows (by VMware Player – http://www.trendsigma.net/vmware/vmwareplayer.html ) or on a MAC (by Parallels – http://www.parallels.com ). If you want to see details on this,  see http://www.trendsigma.net/vmware/lubuntu1110t.html.

Step #2 – Getting Cross Development Tools

Once you get the Linux up and going, login as root (note: on kernel above acct and password are:  “root” and “password”) and get a terminal window up. In the terminal window issue the following command:

# apt-get install build-essential gcc-arm-linux-gnueabi git lzop u-boot-tools

This command will download and install:

Step #3 – Find Out What Kernel Branch is Used on a CircuitCo Release

In this section we will determine what makes up the current CircuitCo kernel .To do this, we will need to load up the kernel and boot it. The BeagleBone CircuitCo standard releases are located here: http://circuitco.com/support/index.php?title=BeagleBone. At the time of this writing, the latest version (Revision A6 Image) is located here. All of the examples are based on this Linux 3.2.18 based A6 image.

Follow the instructions on how to make an SD card and boot it on your BeagleBone. From a terminal window do the following command…

# opkg list_installed | grep kernel-image-3.2.18
kernel-image-3.2.18 - 3.2.18-r12j+gitr720e07b4c1f687b61b147b31c698cb6816d72f01

We are interested in the long string after the kernel image. This is the branch that the kernel was made from. Copy it down or copy/paste it somewhere for reference in the next step.

Step #4 – Git the Linux Kernel

Note:  There is a lot of commands below that are for the git revision control system. I am not going to get into detail on what these commands do or how git works. If you need help or background, see this page for a list of the Top 10 Git Tutorials for Beginners.

In this step you will get (or clone) the Linux kernel repository used by CircuitCo and set up the branch that makes up the current kernel from CircuitCo.

The BeagleBone Linux kernel that is used is located in Koen Kooi’s Linux github repository. In your Linux development system start a terminal widow and execute the commands below. Be warned, the first command will take a while to complete depending on your network connection and system performance. Also, the output from the commands are omitted due to the length of the output.

# git clone git://github.com/koenkooi/linux.git
# cd linux
# git checkout remotes/origin/linux-ti33x-psp-3.2.18-r12j+gitr720e07b4c1f687b61b147b31c698cb6816d72f01 -b beaglebone-a6

The first command will clone the repository on your system. This will make a snapshot of what has been checked in at this moment. This includes code that has been changed since the release we are trying to duplicate (A6) was produced.

The next two commands (cd and git checkout), set up a branch that contains the version of the source that was used to produce the A6 kernel. This is where the long string that was found in the previous step is used.

Check to make sure you are on the proper branch by doing the following and see that the asterisk “*” is located on the branch we made above (beaglebone-a6).
# git branch
 * beaglebone-a6
   master
#

And finally we need to get the firmware that the BeagleBone kernel needs. The kernel will need this binary PM firmware blob to build.

# wget -O firmware/am335x-pm-firmware.bin http://arago-project.org/git/projects/?p=am33x-cm3.git;a=blob_plain;f=bin/am335x-pm-firmware.bin;hb=HEAD

Step #5 – Build The Kernel…

And now that we have the proper tools, the kernel source and firmware blob we can start it building. In these steps we will make a directory to put the kernel we are building, copy the configuration file that was used and finally start the build.

# mkdir a6
# cp defconfig a6/.config
# make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- O=./a6 uImage modules

Note: Again I did not put in the output from the commands. The make command will take a fair amount of time depending on your system performance and output pages and pages.  Also note, the directory name ( “a6″ ) can be changed to anything you want it to be. But you will have to change the Makefile in the later kernel module build steps.

When the make command is completed, you have duplicated the CircuitCo A6 kernel and kernel modules. Now this has made all of the necessary directories, source and headers that are needed to easily build a kernel module. And if you wanted to, you could even replace the kernel and modules on the BeagleBone SD card and reboot the kernel. I’ll make another post later on how to do that as well as how to change the kernel configuration away form the default.

Step #6 – Making a New Kernel Module

In this section I will finally make a kernel module and get it on the BeagleBone. First steps will be to make a directory for building the kernel module, putting in some source (I have example source) and compiling the module.

The kernel module that I am going to build is my version of the “hello world” kernel module. It is a version of the hello_world.c program made into a kernel module and is a fairly common first kernel module. Do a little googling and you will see several versions of it on the internet. In my version (like others), a kernel message will be made when the module is added and when it is removed.

hello.c source here… ( kernel module )
#include <linux/module.h>       /* Needed by all modules */
#include <linux/kernel.h>       /* Needed for KERN_INFO */
#include <linux/init.h>         /* Needed for the macros */

static int __init hello_start(void)
{
    printk(KERN_INFO "Loading hello.ko module...\n");
    printk(KERN_INFO "Hello world\n");
    return 0;
}

static void __exit hello_end(void)
{
    printk(KERN_INFO "Goodbye: hello.ko exiting...\n");
}

module_init(hello_start);
module_exit(hello_end);

MODULE_DESCRIPTION("Example kernel module based on many sources on the internet.");
MODULE_AUTHOR("Ken Keller <kkeller@cabinprograms.com>");
MODULE_LICENSE("GPL");
Makefile source here… ( kernel module Makefile )
obj-m = hello.o
KDIR := /root/linux/a6
all:
    make -C $(KDIR) M=$(shell pwd) modules
clean:
    make -C $(KDIR) M=$(shell pwd) clean

Note: In the Makefile above, you will need to change the KDIR to point to the directory path where you compiled the kernel.

Here are the simple commands to make the kernel module. When these are done, you will have a hello.ko file that can be put in the kernel on the BeagleBone.

# cd
# mkdir kernel_mod
# cd kernel_mod
<get hello.c and Makefile source above and put the files in here>
# make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-

At this point, you need to copy the hello.ko kernel module over to the BeagleBone. I personally use the “scp” command to move files around. There are many different ways to do this so choose your favorite way. (I see need for another blog post on this subject…)

Once the kernel module is moved over, login to the BeagleBone and “cd” to where you moved the module. Below are the commands to install the module (insmod), check to see if the module was installed (lsmod) and remove (rmmod) the module into the kernel.

# insmod hello.ko
# lsmod
Module                  Size  Used by
hello                    738  0 
ip_tables               7829  0 
x_tables               14368  1 ip_tables
spidev                  3920  0 
g_mass_storage         24002  0 
rfcomm                 24289  0 
ircomm_tty             14015  0 
ircomm                  8515  1 ircomm_tty
irda                   85575  2 ircomm_tty,ircomm
hidp                   10079  0 
bluetooth             109011  4 rfcomm,hidp
rfkill                 14663  2 bluetooth
ipv6                  208881  16 
# dmesg | tail
[ 8307.639412] gpio_request: gpio-38 (sysfs) status -16
[ 8307.639424] export_store: status -16
[ 8307.639534] gpio_request: gpio-73 (sysfs) status -16
[ 8307.639546] export_store: status -16
[ 8307.639647] gpio_request: gpio-70 (sysfs) status -16
[ 8307.639659] export_store: status -16
[ 8307.639756] gpio_request: gpio-71 (sysfs) status -16
[ 8307.639767] export_store: status -16
[13479.961098] Loading hello.ko module...
[13479.961112] Hello world
# rmmod hello
# dmesg | tail
[ 8307.639424] export_store: status -16
[ 8307.639534] gpio_request: gpio-73 (sysfs) status -16
[ 8307.639546] export_store: status -16
[ 8307.639647] gpio_request: gpio-70 (sysfs) status -16
[ 8307.639659] export_store: status -16
[ 8307.639756] gpio_request: gpio-71 (sysfs) status -16
[ 8307.639767] export_store: status -16
[13479.961098] Loading hello.ko module...
[13479.961112] Hello world
[13511.073550] Goodbye: hello.ko exiting
#

Final comment…  This is a really long set of instructions and not much was said about what can go wrong. Believe me, there is a lot that go wrong. Good luck and hope it helps!

Note: All of this blog entry was performed as root. If you are not root then there is a good chance you will have to proceed the commands with “sudo” to not get errors.