Home Gumstix kernel dev

Gumstix kernel development

Some tips for working on the Linux kernel with OE tools and Gumstix Overo boards.

 

Reconfiguring the kernel

 

These instructions assume you are using the default gumstix-oe kernel, the 'virtual/kernel', which is declared here

$ cd $OVEROTOP
$ grep linux org.openembedded.dev/conf/machine/overo.conf
PREFERRED_PROVIDER_virtual/kernel = "linux-omap3"

And the current version and revision as defined here

$ bitbake --show-versions | grep linux-omap3
linux-omap3 0:2.6.36-r97

So the rest of the example will assume linux-omap3-2.6.36 revision 97. This is the kernel that will be built when we use the reference 'virtual/kernel' in bitbake commands. Your kernel is probably different so make the appropriate substitutions.

 

First build the kernel normally with bitbake. If you have built an image, then it's already done. If not run this command

$ bitbake virtual/kernel

This will create a source directory in ${OVEROTOP}/tmp/work/overo-angstrom-linux-gnueabi/. In this case it will be

${OVEROTOP}/tmp/work/overo-angstrom-linux-gnueabi/linux-omap3-2.6.36-r97

 

Now modify the kernel configuration based on the existing configuration. Do this by passing a command argument to bitbake.

$ bitbake -c menuconfig virtual/kernel

This invokes one of the standard kernel configuration tools menuconfig which provides a minimalist GUI based on the ncurses library. Make your changes and save them.

 

Note: If this command does not launch an ncurses window, you are likely missing some tools on your workstation. For Ubuntu users, I have a check-installed.py script you can use to check your system. You can find it here - oe-build-essentials-project. The other times this command can fail is if you do not have privileges to launch a window on the current DISPLAY. (TODO: Add instructions to fix this.)

 

When you are done, the new kernel configuration file can be found here

${OVEROTOP}/tmp/work/overo-angstrom-linux-gnueabi/linux-omap3-2.6.36-r97/git/.config

 

Next you need to rename the .config file to defconfig and put it where the OE kernel recipe will use it.

 

For linux-omap3-2.6.36 kernels the defconfig location is

${OVEROTOP}/org.openembedded.dev/recipes/linux/linux-omap3-2.6.36/defconfig

 

For older linux-omap3 kernels, the defconfig went in an overo sub-directory like

${OVEROTOP}/org.openembedded.dev/recipes/linux/linux-omap3-2.6.34/overo/defconfig

or

${OVEROTOP}/org.openembedded.dev/recipes/linux/linux-omap-psp-2.6.32/overo/defconfig

 

And for the newest linux-omap3-2.6.39 kernel in the [overo-2011.03] branch of the Gumstix OE repository, the defconfig is back in an overo subdirectory, but now under a generic linux-omap3 parent directory.

${OVEROTOP}/org.openembedded.dev/recipes/linux/linux-omap3/overo/defconfig

 

Copy the .config to defconfig as necessary for the kernel you are using.

For this example

$ cp ${OVEROTOP}/tmp/work/overo-angstrom-linux/gnueabi/linux-omap3-2.6.36-r97/git/.config \
${OVEROTOP}/org.openembedded.dev/recipes/linux/linux-omap3-2.6.36/defconfig

Now rebuild the kernel.

$ bitbake -c clean virtual/kernel; bitbake virtual/kernel

 

Then rebuild the rootfs to get the modules installed correctly. Substitute the image you are using.

For example, if you are using the omap3-console-image

$ bitbake omap3-console-image

 

Then deploy your kernel and rootfs to NAND, MMC or an NFS mount point as usual.

 

You can skip the menuconfig step and directly modify the defconfig file since it is plain text. Many kernel options have dependencies. If you are unsure, you may want to stick with menuconfig.

For example, to disable the ADS7846 touchscreen and/or the LGPHILIPS LB035Q02 display drivers to free up the Overo SPI 1 CS lines, you could do this with sed and not even invoke an editor.

sed -i 's:CONFIG_TOUCHSCREEN_ADS7846=m:# CONFIG_TOUCHSCREEN_ADS7846 is not set:g' defconfig
sed -i 's:CONFIG_PANEL_LGPHILIPS_LB035Q02=y:# CONFIG_PANEL_LGPHILIPS_LB035Q02 is not set:g' defconfig

 

There are some additional modifications done to the defconfig file by OE before it becomes the .config the kernel is compiled with.

One example for the Gumstix linux-omap3 kernels is the setup of the OTG USB controller driver to one of three modes, host, peripheral or otg. There is code in the OE recipe files (linux-omap3_2.6.3x.bb) that simplifies changing the USB mode. But this does mean that any manual changes you make to defconfig for the OTG controller may get overwritten.

Some more details about the OTG controller can be found here - USB Networking with Gumstix Overos.

Many of the non linux-omap3 recipes specify numerous patches, some that may be modifying the defconfig file. You can check through these patches if you have some unexplained behavior. Note that this won't be a problem if you go through the steps of generating a patch as described in the next  sections and then making sure your patch is the last one applied.

If neither of these explains why your defconfig is not getting used, refer to the run scripts bitbake generates in the kernel working temp directory. For the kernel in this example, it would be this script

${OVEROTOP}/tmp/work/overo-angstrom-linux-gnueabi/linux-omap3-2.6.36-r97/tmp/run.do_configure.xxxx

 

If you want to go back to the default defconfig file, you can use git to restore it.

$ cd $(OVEROTOP)
$ git checkout -- recipes/linux/linux-omap3-2.6.36/defconfig

This clobbers your changes, so you should make a backup first.

 

An alternative would be to create your own OE branch and let git do the backup work for you. Here are some ideas on Gumstix / OE development that might be useful.

 

Patching the board file (board_overo.c)

 

I find kernel development and patch generation are best handled using the procedure in the next section (working on the kernel without bitbake). If the changes are very minor and only impact a single file, such as configuring spidev in the board-overo.c file, an abbreviated procedure like the following can be useful.

 

Follow the same steps as above to get an initial kernel downloaded, patched and configured in the OETMP directory.

As a convenience in writing this, here is a definition for the kernel source directory

KERNEL_SRC = ${OVEROTOP}/tmp/work/overo-angstrom-linux-gnueabi/linux-omap3-2.6.36-r97

 

The board-overo.c file can be found here

${KERNEL_SRC}/git/arch/arm/mach-omap2/board-overo.c

 

First make a copy of it

$ cd ${KERNEL_SRC}/git/arch/arm/mach-omap2
$ cp board-overo.c board-overo.c-orig

Make your changes to board-overo.c and save it.

$ <edit> board-overo.c

Make a patch file of your differences.

$ cd ${KERNEL_SRC}
$ git diff --no-prefix git/arch/arm/mach-omap2/board-overo.c-orig \
git/arch/arm/mach-omap2/board-overo.c > my-board-overo.patch

Important Note: The patch must be generated from the $KERNEL_SRC directory to use with OE. If you generate your patch from another directory like $KERNEL_SRC/git then the patch will fail when bitbake tries to apply it during the build. Also, if you fail to provide the '--no-prefix' argument to the git diff command, you will have to provide additional arguments to bitbake in the recipe below. Easiest just to use '--no-prefix'.

 

Copy the patch to where the OE build system will use it.

$ cp my-board-overo.patch ${OVEROTOP}/org.openembedded.dev/recipes/linux/linux-omap3-2.6.36/

Edit the kernel recipe to use the patch

$ cd ${OVEROTOP}/org.openembedded.dev/recipes/linux
$ <edit> linux-omap3_2.6.36.bb

Add a line like this

@@ -12,6 +12,7 @@ SRCREV = "587b76771e60ab7afd18709a8b9441c2175fc39c"
SRC_URI = "git://www.sakoman.com/git/linux-omap-2.6.git;branch=omap-2.6.36;protocol=git \
file://defconfig \
file://${BOOT_SPLASH} \
+ file://my-board-overo.patch \
"

MUSB_MODE ?= "host"

 

Or in the linux-omap3_2.6.34.bb recipe, it would look like this

@@ -15,6 +15,7 @@ PV = "2.6.34"

SRC_URI = "git://www.sakoman.com/git/linux-omap-2.6.git;branch=omap3-2.6.34;protocol=git \
file://defconfig \
+ file://my-board-overo.patch \
"

SRC_URI_append = " \

 

Then rebuild the kernel and rootfs as above and deploy.

 

Working on the kernel without bitbake

 

You can directly use the cross-build tools OE provides when working on the kernel. At the bottom of this page is a script file with some environment variables to set things up.

How you obtain your kernel source is up to you. What I usually do is use git and directly clone the linux repository that OE would have used.

For example, if you look in the OE recipe for linux-omap3_2.6.36.bb you'll see

...
SRCREV = "587b76771e60ab7afd18709a8b9441c2175fc39c"
SRC_URI = "git://www.sakoman.com/git/linux-omap-2.6.git;branch=omap-2.6.36;protocol=git \
...

To get this repository the command is

$ git clone -n git://www.sakoman.com/git/linux-omap-2.6.git linux-omap

After the clone, you need to checkout the correct branch.

Here is how to list the available branches

$ cd linux-omap
$ git branch -a
remotes/origin/HEAD -> origin/master
remotes/origin/dss2
remotes/origin/exp
remotes/origin/for-tomba
remotes/origin/master
remotes/origin/omap-2.6.36
remotes/origin/omap-2.6.37
remotes/origin/omap-2.6.38
remotes/origin/omap3-2.6.32
remotes/origin/omap3-2.6.33
remotes/origin/omap3-2.6.34
remotes/origin/omap3-2.6.34-mmc3
remotes/origin/omap3-2.6.35
remotes/origin/whoi

And this creates a local branch 2.6.36 that tracks the remote 2.6.36

$ git checkout -b omap-2.6.36 origin/omap-2.6.36

In the case of the linux-omap3_2.6.36.bb recipe, a particular commit is referenced

SRCREV = "587b76771e60ab7afd18709a8b9441c2175fc39c"

This is not a git tutorial, but to get a quick idea of how far back the 587b767 commit is you could run this

$ git log --oneline
1ebf6b3 omap: Fix mtd subpage read alignment
587b767 video: omap: vram: remove from normal memory
27c8d82 ARM: allow, but warn, when issuing ioremap() on RAM
d023172 OMAP: Overo: Add support for spidev
...

So only the 1ebf6b3 commit separates the two.

If you wanted to start from the exact place the linux-omap3_2.6.36.bb recipe will use, you could check out that commit directly. I am choosing a name for the branch that makes sense.

$ git checkout -b omap3-2.6.36r97 587b767
Switched to a new branch 'omap3-2.6.36r97'

$ git branch
omap-2.6.36
* omap3-2.6.36r97

$ git log --oneline
587b767 video: omap: vram: remove from normal memory
27c8d82 ARM: allow, but warn, when issuing ioremap() on RAM
d023172 OMAP: Overo: Add support for spidev
...

This is all standard git stuff and there is more then one way to go about it. If your overo-oe repository is up to date, the SRCREV will usually be the latest commit. The Gumstix maintainers do a good job keeping things current.

 

Next I usually copy the overo kernel config file from the OE repository

$ cp ${OVEROTOP}/org.openembedded.dev/recipes/linux/linux-omap3-2.6.36/defconfig .config

For older kernels, it's in the overo sub-directory.

$ cp ${OVEROTOP}/org.openembedded.dev/recipes/linux/linux-omap3-2.6.34/overo/defconfig .config

 

At this point you will have to manually apply any patches in the OE recipe if you want to start with the same kernel bitbake gives you. The Gumstix maintainer usually applies these patches directly to the repository, so for Overos there is nothing to be done. For Beagleboard repositories, you will likely have to do some work. The utility 'patch' and the OE kernel source/git/patches directory are your friends here.

 

Then, after sourcing the environment file at the bottom of the page, you can run normal kernel build commands like

make oldconfig (or make menuconfig)
make include/linux/version.h
make uImage
make modules

 

Because you are now working in a proper git repository, generating patches is much simpler. A git diff command with some formatting arguments is all it takes.

For example, if I were working on the musb driver and had changed several of the musb driver files, I might do this

$ git diff --src-prefix=git/ --dst-prefix=git/ > musb-gadget.patch

That musb-gadget.patch can now be added to OE the same way the board-overo.c patch was in the previous section.

Note that diff-ing the entire repository like that could include changes from many files in one patch. You may want to be more selective when you generate your patches, breaking the solution down into smaller independent changes. This is generic git workflow stuff and there are plenty of git tutorials on the web to help you.

 

Working on driver modules

 

If you are building a module outside the kernel source tree you can use the header files and tools OE generated when it built a kernel. Source the environment file at the bottom of this page and your module Makefile can look like this

 

ifneq ($(KERNELRELEASE),)
obj-m := <your-module-name>.o
else
PWD := $(shell pwd)

default:
ifeq ($(strip $(KERNELDIR)),)
$(error "KERNELDIR is undefined!")
else
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
endif

 

This environment and general procedure also works for building U-Boot outside the OE directories and without bitbake.

 

Here is the environment. Save it as a file like 'kernel-dev.txt' and then run the command

$ source kernel-dev.txt

--- kernel-dev.txt contents ---

MACHINE=overo

# export an alternative OETMP before sourcing this file if you
# don't want the default
if [[ -z "${OETMP}" ]]; then
OETMP=${OVEROTOP}/tmp
fi

SYSROOTSDIR=${OETMP}/sysroots
STAGEDIR=${SYSROOTSDIR}/`uname -m`-linux/usr

export KERNELDIR=${SYSROOTSDIR}/${MACHINE}-angstrom-linux-gnueabi/kernel

PATH=${PATH}:${STAGEDIR}/bin:${STAGEDIR}/armv7a/bin

unset CFLAGS CPPFLAGS CXXFLAGS LDFLAGS MACHINE

export ARCH="arm"
export CROSS_COMPILE="arm-angstrom-linux-gnueabi-"
export CC="arm-angstrom-linux-gnueabi-gcc"
export LD="arm-angstrom-linux-gnueabi-ld"
export STRIP="arm-angstrom-linux-gnueabi-strip"