Pages

Thursday, May 29, 2014

Cross compiling for the Raspberry PI

Developing C/C++ applications for the raspberry pi can be done on the PI itself, you will need to get gcc package and related tools. However, compiling applications on the PI is slow and some applications might not even compile at all due to the slow processor. It is for this reason that most applications are compiled on a different machine with a much more capable processor than on the pi itself. 

Before I discuss about testing the device drivers on my previous post, I'd like to show my setup on how the device drivers are compiled and linked in my Fedora 19 box, targetting applications for the raspberry pi.

On my Fedora box (Fedora 19, 64 bit), I first downloaded a cross compiler from the following link:


Download and unzip it to the directory of your choice, once that is done. In the arm-bcm2708 directory, you would find the different compiler packages that can target the raspberry pi. Depending on your distribution,  you may want to copy one of these to your tools dir. In my case since I have a 64 bit Fedora, I choose gcc-linaro-arm-linux-gnueabihf-raspbian-x64 and copied it to /opt/cross/raspberrypi. I then created a gcc soft link to point to this directory. I'd like to keep my cross compilers, kernel source and application sources in one directory, so this is the reason why I keep everything in /opt/cross/raspberry


Next we need to modify build variables, I usually invoke a shell command to set my environment variables for doing raspberry targets. So in my home directory, I create this shell script:


The setraspberryenv.sh simply sets the environment variables, mostly build variables to point to the correct compiler (in this case the arm-linux-gnueabihf-gcc, etc.). You can create an alias in your .bashrc file to invoke this shell script, in my case I added an entry in my .bashrc:

alias pidev=". ~/bin/setraspberry.sh"

Once that is done and the environment variables set, we can now go ahead and download the Raspbian Linux kernel.


[vco@localhost raspberry]$ git clone git://github.com/raspberrypi/linux.git

Once that's done, we can now modify and build our kernel (Note that in my previous post, we need to modify some files in the kernel /opt/cross/raspberry/linux/arch/arm/mach-bcm2708/bcm2708.c file.).

After making the changes above, we also need to get the current configuration of our raspberry pi and use this configuration to build our kernel. You must first login to your raspberry pi via console and invoke this command:


pi@raspberrypi ~ $ zcat /proc/config.gz > .config

Then copy the .config file to the root of your downloaded kernel source

[vco@localhost raspberry]$ cd linux
[vco@localhost linux]$ scp pi@192.168.0.115:/home/pi/.config .

Now we can start building the kernel


[vco@localhost linux]$ pidev
[vco@localhost linux]$ make ARCH=arm CROSS_COMPILE=${CCPREFIX}

During compilation, you maybe prompted for some kernel build options which you either have to turn on or off. In my case, I just accepted the default for all options. At this point, you can go ahead make coffee or whatever, kernel compilation can take time. When finished, we also need to compile the modules after the kernel compilation.


[vco@localhost linux]$ make ARCH=arm CROSS_COMPILE=${CCPREFIX} modules

After successful compilation of the kernel and the loadable modules, you can grab the copy of it from:



The zImage file is what you need, it contains the compressed image of the kernel.

Next we will transfer our image to the Raspberry Pi's SD card and replace the current kernel image that is running. To do this, I took out the SD card from the raspberry pi and plugged it into my Fedora development machine. There are two partitions on this SD card, one Fat16 partition, which is used by the boot loader for loading the kernel image and other firmware files. And another linux partition which contains the root file system of the raspberry pi.

To access these partitions form my Fedora box, I mounted them on my Fedora machine like this:


[root@localhost linux]# mount /dev/sdb1 -t vfat /media/raspiboot
[root@localhost linux]# mount /dev/sdb2 /media/raspiroot

The two commands above mounts the two partions on the sd card to /media/raspiroot and /media/raspiboot (you need to become root of course to do this).

During the boot process of the raspberry pi, the main ARM microprocessor is currently disabled, instead the GPU is the one that takes over during this boot process. Before activating the ARM processor, it does some initialization sequence, reads the SD card for the kernel - kernel.img, load the kernel at 0x8000 memory address, and finally releasing the hold on the reset switch to let the kernel run at the loaded memory address.

To replace the kernel, we only need to copy the genrated zImage file and ovewrite the kernel.img on the FAT16 partition of the SD card.


[root@localhost linux]# cd arch/arm/boot
[root@localhost linux]# cp zImage /media/raspiboot/kernel.img

If you wish to backup the old kernel, you can copy it to a different file before copy overwrite command above.

Before we can boot to our new kernel, we also need to copy the modules and transfer it to the root filesystem of the raspberry pi.


[root@localhost linux]# make ARCH=arm CROSS_COMPILE=${CCPREFIX} INSTALL_MOD_PATH=/media/raspiroot modules_install
The avobe command installs the kernel modules in /media/raspiroot which we have mounted earlier. 

Once done, unmount /media/raspiboot and /media/raspiroot and plug the card to the raspberry pi and reboot. We can go ahead and boot the new kernel and proceed to compiling the device drivers in my previous blog.

No comments: