Cross compiling kernels (2014 edition)
Published on July 9, 2014
A while back, we posted some notes about how to cross compile an i.MX6 kernel using the LTIB toolchain. Fast forward to the middle of 2014 and these are a bit dated.
In particular:
- LTIB should be considered a legacy toolkit, since the latest Freescale release is now based on tools from the Yocto Project, and
- Recent Ubuntu releases have nice support for ARM cross-compilation, and
- The 3.10.17 Linux kernel uses the Device Tree framework, and
Cross Compiler
As a result of the first two points, we now recommend these simple steps to install a cross-compiler:
~/$ sudo apt-get install gcc-arm-linux-gnueabihf
~/$ arm-linux-gnueabihf-gcc -v
Using built-in specs.
COLLECT_GCC=arm-linux-gnueabihf-gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc-cross/arm-linux-gnueabihf/4.8/lto-wrapper
Target: arm-linux-gnueabihf
...
gcc version 4.8.2 (Ubuntu/Linaro 4.8.2-16ubuntu4)
Other dependencies
A couple of other tools are also needed for compilation of the kernel when building a U-Boot wrapped kernel:
~/$ sudo apt-get install u-boot-tools lzop
Compilation
This is clearly simpler than installing LTIB and configuring your PATH to point at the toolchain, and is sufficient to replace the arm-none-linux-gnueabi- from LTIB with arm-linux-gnueabihf-, but the process for a 3.0.35 kernel is essentially the same:
~/$ git clone git://github.com/boundarydevices/linux-imx6.git
~/$ cd linux-imx6
~/linux-imx6$ export ARCH=arm
~/linux-imx6$ export CROSS_COMPILE=arm-linux-gnueabihf-
~/linux-imx6$ export
~/linux-imx6$ git checkout boundary-imx_3.10.17_1.0.2_ga
~/linux-imx6$ make nitrogen6x_defconfig
~/linux-imx6$ make uImage modules -j4
As in the previous post, the output will be placed in ~/linux-imx6/arch/arm/boot/uImage.
Module installation
Also unchanged is the module installation process. To get a directory tree suitable for placement into a rootfs (that is, without any symlinks), you can install them into a temporary location as follows.
~/linux-imx6$ make INSTALL_MOD_PATH=~/tmp modules_install
~/linux-imx6$ find ~/tmp/lib/modules -type l -exec rm -f {} ;
~/linux-imx6$ cp -ravf ~/tmp/lib/modules/* /media/myrootfs/lib/modules/
Device Tree
For kernels after 3.0.35, a couple of other wrinkles are added:
- You'll need to set the LOADADDR environment variable to 10008000, and
- You'll need to make the dtbs target and copy the Device Tree Binary files into your boot directory.
The files *.dtb are placed in the arch/arm/boot/dts directory, so the following shows the complete process for kernel 3.10.17:
~/$ git clone git://github.com/boundarydevices/linux-imx6.git
~/$ cd linux-imx6
~/linux-imx6$ export ARCH=arm
~/linux-imx6$ export CROSS_COMPILE=arm-linux-gnueabihf-
~/linux-imx6$ export LOADADDR=10008000
~/linux-imx6$ git checkout boundary-imx_3.10.17_1.0.2_ga
~/linux-imx6$ make nitrogen6x_defconfig
~/linux-imx6$ make uImage modules dtbs -j4
~/linux-imx6$ cp -fv arch/arm/boot/uImage /media/myboot/
~/linux-imx6$ cp -fv arch/arm/boot/dts/*.dtb /media/myboot/
~/linux-imx6$ make INSTALL_MOD_PATH=~/tmp modules_install
~/linux-imx6$ find ~/tmp/lib/modules -type l -exec rm -f {} ;
~/linux-imx6$ cp -ravf ~/tmp/lib/modules/* /media/myrootfs/lib/modules/
Note that depending on your O/S distribution, the uImage and *.dtb files may go in the root of a partition (Yocto, Buildroot, Timesys, OpenWRT), or into the /boot directory (Debian, Ubuntu). The key is to match the boot script.
Notes if switching versions
If you're switching from the 3.0.35 to 3.10.17 kernel versions within the same tree, you'll need to delete include/linux/version.h from your tree, or you'll get mysterious error messages about missing mach/hardware.h while compiling gc_hal_kernel_device.c.