Bootloader and kernel
We shall now look at how we can build the two main components of the operating system, the bootloader and the kernel.
The source code we need (290 MB for the current version) is available from the Elektor website. The simplest approach is to download the files using a browser: on a Linux machine the files will normally end up in the directory.
When the download is complete, switch to the directory and find the file called ‘-11.zip . Move the file into your home directory using the command
mv ~/Downloads/120026-11.zip ~/
To unpack the file, switch back to your home directory using cd and enter the command
Building the bootloader
The bootloader is a program which is copied from the SD card to the internal SRAM of the LPC3131 on system reset. The following sequence of commands shows how we can compile the bootloader for ourselves and copy it to the SD card, to allow us to boot from the card. Before starting we need to install a couple of packages on the Ubuntu system:
sudo apt-get install patch libncurses5-dev
Now switch to the source code directory
unpack the tar file that contains the bootloader
tar xvzf bootloader.tar.gz
then switch to the new directory
cd bootloader and unpack the source code proper:
tar xvzf apex-1.6.8.tar.gz
Now comes an important step if we want to be able to distribute any changes we make to the bootloader. We create a so-called copy of the source code and make changes only on that copy. Later it will be easy to create and publish a that represents the changes we have made.
mv apex-1.6.8 work_1.6.8 cd work_1.6.8
In the source code tree we need to apply a couple of patches that are required to make the bootloader work with the Elektor Linux board.
patch-p1 < ../apex-1.6.8_lpc313x.patch
patch-p1 < ../gnublin-apex-1.6.8.patch
The build process for the bootloader is controlled by what is called a file . We have to copy the master version of this file into our directory, with the new name ‘.config . Note that here the full stop before the word is very important: it marks the file as to the operating system.
cp ../gnublin-apex-1.6.8.config .config
At this point, if you installed the toolchain manually and did not arrange for the environment variables to be set in your .bashrc file, you will need to set them by running the script . ~/set.sh .
The build process can now be initiated:
Normally at this point we would need to copy the bootloader firmware into flash memory on the microcontroller using a suitable programmer. Here, however, we can copy the firmware to the SD card using ordinary Linux commands.
With the SD card once again in the PC s card reader, run the
to see the messages output by the kernel running on the PC. As you can see, the SD card has been recognised as ‘/dev/sdh and contains two partitions, called ‘/dev/sdh1 and ‘/dev/sdh2 . For safety it is best to unmount these partitions, as we will be copying the bootloader across by accessing the blocks on the SD card directly rather than via a file system:
sudo umount /dev/sdh1 sudo umount /dev/sdh2
The following command (where the will need to be modified to reflect the results from the dmesg command above) will copy the file .bin to the SD card in such a way that the LPC3131 can find it when booting:
sudo dd if=src/arch-arm/rom/apex.bin of=/dev/sdh2 bs=512
The command copies the bootloader code to the beginning of the second partition of ‘/dev/sdh using a block size of 512 bytes. The Linux operating system does not guarantee exactly when the new blocks of data are actually written to the NAND storage on the SD card. The command
is therefore needed to force the operating system to ensure that all pending blocks are written out and that the new bootloader code is safely stored on the SD card. We can now try to boot the Linux board from the SD card.
Building the kernel
Building the kernel is a similar process to building the bootloader. First we switch to the home directory using the command cd, and then into the source code directory.
We unpack the kernel source code
tar xvzf linux-2.6.33-lpc313x-gnublin-032012.tar.gz
switch to the kernel source directory
and start the build process that will result in a bootable kernel.
We also need to compile the loadable kernel modules. The is simply done using the command:
With everything built we need to copy the kernel and the modules to the SD card. In our case the kernel happens to be there already, but it is worth practising the process for replacing the kernel. We need to copy the file /arm/boot/zImage in the kernel source tree directly to the first partition on the SD card: the procedure is much the same as for the bootloader above, with the appropriate changes. Don t forget to unmount the partition!
A look at the possibilities
Now we are in the happy position of being able to rebuild the bootloader and kernel at will, we can look at the possibilities for making modifications to them, in particular to the kernel. Of course, we only have space here to look at this in general terms. You can take a first look at the Linux kernel configuration by typing
from the directory .6.33-lpc3131x . If, for example, you want to use a particular USB device with the Linux board, you have to enable to corresponding driver here.
You can navigate around the blue window using the arrow keys. The key opens and closes the menu. With a bit of hunting around you will be able to find drivers for various devices you recognise. In the next article in this series we will go into this subject in more detail.
Restoring the boot image
Since we are now beginning to get down to the nitty-gritty of how the Elektor Linux board works, it is a good idea to make an exact copy of the SD card for backup purposes.
Put the card in the PC s card reader and then check, using dmesg, what device name the operating system has chosen for it.
Again, for safety, unmount the partitions:
umount /dev/sdletter1 umount /dev/sdletter2
(where you should insert the appropriate character for , for example giving ‘/dev/sdb1 and ‘/dev/sdb2 or ‘/dev/sdh1 and ‘/ dev/sdh2 ).
You can now take an exact copy of the card s contents:
sudo dd if=/dev/sdletter of=Image_SD_card_backup_ copy.img
This will take some time. You should now find a file in your current directory whose size is exactly equal to the capacity of the SD card:
You now need to put another SD card, exactly the same size as the original, in the PC s card reader. Again, find out the device name using dmesg. The following command will copy the card image you have just created onto the new card:
sudo dd if=Image_SD_card_backup_copy.img of=/dev/ sdletter
This will take even longer than reading the original card. Assuming the command is successful you can now issue the sync command to ensure all blocks are actually written out to the card, and then try the new card in the Elektor Linux board. There is no need to umount the card as the file system on the card was never mounted in the first place: we wrote blocks directly to the card.
The above process is fairly straightforward, but unfortunately it does not work if the sizes of the two cards are not identical. Also, we sometimes want to create a new card with different partitions or with a different file system from those of the original card. These cases are handled by a graphical installer, which we shall look at briefly in the next article in this series.
What the future holds
In this installment we have made good progress on the route to understanding our embedded GNU/Linux system. We have a development environment in place, we can now build our own bootloader and kernel, and we have compiled and run a small program. In the next article we will take a quick look at the structure of the source code for Linux so that we can be in a position to write our own driver for a particular piece of hardware. We will also see how easy it is to write programs using scripting languages.