This is the first post in a series on getting down into the bits of a Raspberry Pi Linux installation. It assumes familiarity with the Linux build process, gcc, make, apt-get, ssh, etc.
Lately I have been thinking about a project that would require a beefy embedded system, one with embedded Linux, fast, and lots of storage. It turns out the RaspberryPi has all the requirements for this project, and I have one laying around, so I figured I would pull it out and get a full development toolchain started to see what the little Pi could do. This project might require a Linux driver module, so for that I need to compile the kernel and modules too. All steps were done on an Xubuntu 12.10 32-bit machine with the Ubuntu GCC/binutils/make packages installed.
The first step was getting an image running. I tried a few and the Arch Linux image is prefect for an embedded project, it doesn’t contain all the X crap by default, it boots in ~10 seconds (thanks to systemd) and the stock image only takes up about 450Mb on a flash drive, leaving lots of space. Here is the image (I used the version from Nov 2013), here is how to make an SD card.
The next step was to get a cross compiler toolchain build. I have seen a lot of posts that say “do an apt-get install gcc-arm-linux-xxxxx on Debian”, that’s all well and good if like relying on Debian, I would like full control over my toolchain, and I don’t want to have to export tons of bash variables for tool locations. Fortunately, there is an awesome application called crosstool-ng that makes downloading and building a custom compiler and tools a breeze. I followed this post successfully and put the output directory of the cross compiler binaries within my home directory, this way the ARM compiler isn’t system wide and I can move it where I want it. I did have to install some packages “sudo apt-get install gperf texinfo gawk libtool automake libncurses5-dev”. The test application compiled without issue and a quick SSH got me “Hello world” on the Pi command line.
Rebuilding the kernel and modules seemed a little daunting, but actually it’s pretty easy once you do it. These two references (PDF and elinux) were good for understanding the process. The kernel for the Raspberry Pi is build from a central git repo, so you just need to clone the repo and you have the whole kernel source all patched and ready to go.
The Arch Linux build has a handy feature enabled, it outputs the kernel config for the running kernel in the /proc directory, which means if you use this config as the base for your config, all the settings match the current kernel, which you know works. Copy the file /proc/config.gz from your Pi, uncompress it to ‘.config’ in the root of your kernel source and it will be read by menuconfig, can’t get easier than that!
Now, because I compiled the toolchain into a local home directory I need to pass the path to it for each call to make. This isn’t that bad because I plan on making scripts that build the kernel and modules whenever I need them. Here is an example of how to run menuconfig and the final make:
make ARCH=arm CROSS_COMPILE=/home/s1axter/raspi/toolchain/arm-unknown-linux-gnueabi/bin/arm-unknown-linux-gnueabi- menuconfig
make ARCH=arm CROSS_COMPILE=/home/s1axter/raspi/toolchain/arm-unknown-linux-gnueabi/bin/arm-unknown-linux-gnueabi-
The kernel make builds both the kernel and the modules for that version of the kernel. You have to copy over both the new kernel and the kernel modules since you can’t use the old modules that exist on the Pi. Again, rather than export a bash variable like the elinux source says I pass the module folder path in the make command.
make modules_install ARCH=arm CROSS_COMPILE=/home/s1axter/raspi/toolchain/arm-unknown-linux-gnueabi/bin/arm-unknown-linux-gnueabi- INSTALL_MOD_PATH=/home/s1axter/raspi/kernel/modules
After these build steps use sftp or some other means to get the modules and firmware directories in the ‘modules/lib/’ folder into the ‘/lib’ folder on the Pi. The kernel new image is ‘arch/arm/boot/Image’ from the kernel source folder and needs to replace /boot/kernel.img on the Pi (Make a backup, just incase). I used scp/sftp, so I logged into the Pi and did a ‘sync‘ command to make sure everything was written to the SD card and then ‘reboot’. I might have been lucky but the Pi came back up and my kernel went from 3.10.18 to 3.10.25!