Friday, 15 November 2013

Building a Cubieboard Kernel: Part 1

To date it seems that all of the pre-compiled kernels and toolchains online for the Cubieboard are using stock parameters which tend to be tuned for the Cortex-A9 or built using an older version of GCC which does not fully support the Cortex-A7 CPU!

For these reasons, and also because I would like to make a more 'Lean and Mean' kernel with less pointless drivers to waste memory, I have endeavoured to build my own. This post will describe the general process of building a kernel for the Cubieboard. I will note a few initial changes I made to the kernel config but there needs to be some testing before I can conclude whether my changes (and more to come, I'm sure) are worth it or not. I plan on making a 'Part 2' to confirm performance changes and my final kernel config.

Let's Get Started!

The first step is to ensure you have a working cross-compiler toolchain installed. If you do not, see my post here on setting up the latest Linaro toolchain. This post describes how to modify this toolchain to be more optimised for the Cortex-A7.

Besides the toolchain setup, above, please make sure you have u-boot-tools installed:

sudo apt-get install u-boot-tools

This package contains the mkimage command that is required to make the final image. You then need to get the source code. Kernel sources tend to be huge so I opted to get only the latest revision of code and no history. I think this at least halved the download size!

git clone --depth 1 --branch sunxi-3.4

This was about a 400 MB download. Once it completes, there is a handy command to load an initial working config for the Cubieboard:

make ARCH=arm CROSS_COMPILE=${CC201310A7} sun7i_defconfig

Some Config Changes

If you would like to view or modify this default configuration then you can get to the normal menuconfig with:

make ARCH=arm CROSS_COMPILE=${CC201310A7} menuconfig

This will bring up the classic Linux kernel menuconfig. Here you can browse through, see some info on the various items with the help command, and change things! Be sure to save the config when you are done: there is a save option near the bottom of the main menu. Save the config as .config for it to be used by the make command.

As I mentioned earlier I chose to modify a few things in this initial run. I plan on comparing the performance between the kernels supplied by the community, a kernel that is a stock configuration but compiled for the Cortex-A7 with GCC 4.8 and also a kernel with my modifications to the config.

Initially, I chose to only turn of forced preemption, which should allow higher throughput by telling the kernel to not jump through tasks too quickly. The default was set to a real-time system which is great for desktop, but not great for processing tasks. Here's how you find the setting:

Kernel Features -> Preemption Model -> No Forced Preemption

Another issue I discovered was that by default, the ethernet drivers are not compiled into the kernel - they are build as a module. This means that to use the module we have to manually tell Linux to load it. I don't want this behaviour, so I specified to build the ethernet drivers into the kernel.

Note that to get ethernet to work after you first boot, later on in the process, you will probably have to tell the system to bring up the interface and add some stuff to the config files so that this happens on boot:

ifconfig eth0 up
echo auto eth0 >> /etc/network/interfaces
echo iface eth0 inet dhcp >> /etc/network/interfaces

The Build

Once you are happy with your changes you can build the kernel. Modify the -j3 to -j(number of CPU's + 1) to suite your build system for a faster build.

make ARCH=arm CROSS_COMPILE=${CC201310A7} uImage modules -j3

and then

make ARCH=arm CROSS_COMPILE=${CC201310A7} INSTALL_MOD_PATH=output modules_install

This will take a while... Once it's done you only need to copy the kernel uImage and modules onto your SD card! The commands below will do this for you. Note that I have mounted the boot partition of my SD card to /media/boot and the rootfs to /media/rootfs. If the uImage file is missing then the compile above failed at some point.

sudo cp -v arch/arm/boot/uImage /media/boot/
sudo rm -r /media/rootfs/lib/*
sudo cp -rv output/* /media/rootfs/lib/

Unmount the SD card, put it in your Cubieboard and hope for the best! ;)

No comments:

Post a Comment