- 1 Foreword
- 2 Required software
- 2.1 Preparing the development environment
- 2.2 Building the Linux kernel
- 2.3 Building Android for the ZedBoard platform
- 2.4 Preparing the SD card
- 2.5 Test drive #2 – does Android boot?
- 3 What to do from now?
The Android system is successfully built for the Xilinx ZC702 platform, but for to build it for the new Digilent-Avnet ZedBoard, some modifications are required in the compilation process.
The following guide is a step by step documentation about the build process of the Zynq edition of Android 2.3 (Gingerbread). This documentation is based on two Xilinx wiki pages:
Building Android has three (plus one zeroth) steps:
- Prepare the development environment.
- Build the Linux kernel
- Build the Android userspace
- Prepare the boot SD card
The tutorial assumes that you have basic Linux knowledge, for example installing packages, launching a terminal session, etc.
With this guide you will successfully build and boot a complete Android system.
The compiled Android still has flaws; the mouse and keyboard input does not work yet, making the compiled system fairly unusable.
For building the Android system, the following toolchain was used:
Operating System: Linux Mint Debian Edition
Xilinx ISE 14.4 and the CodeSourcery Lite ARM cross compiler toolchain (Xilinx edition included with ISE).
The Android compilation needs the Oracle Java Development Kit, version 1.6. More recent versions (for example 1.7) can't be used. Building with OpenJDK is not recommended.
The easiest way to build Android is using the 4.4 version of gcc.
For building Linux and Android the Linux host system is mandatory, but you can use your preferred Linux distribution. Building in a virtual machine is not recommended because of the high hard disk space and memory usage.
Preparing the development environment
For compiling the Android system, you will have to install a complete Linux kernel development toolchain and the git versioning tool. On a Debian (or Ubuntu)-based system, the following packages are needed:
fakeroot build-essential crash kexec-tools makedumpfile kernel-wedge git-core libncurses5 libncurses5-dev libelf-dev asciidoc binutils-dev curl
Also, the Android-build part uses the software named curl to download the required tools from the Internet. The Xilinx edition of the CodeSourcery Lite cross compiler is also required.
This tutorial assumes that you have successfully installed these software, and that the required software tools are in the system path.
You will need files from the ZedBoard Linux Hardware Design for ISE 14.4 image found at http://www.digilentinc.com/Data/Products/ZedBoard/ZedBoard_Linux_Design.zip .
This tutorial uses the android user on a Linux system, this is not mandatory, one can use his own Linux user.
The first step is to create a directory in which the Android build will take place. The tutorial builds Android in the ~/android directory.
Launch a terminal session and create the build directory:
You will use this terminal session for building Linux, and Android. In the following stages, you will populate this directory with the Linux kernel and Android sources.
Building the Linux kernel
Android uses Linux as its kernel. Usually each development board has its own port of the Linux kernel, with the board specific drivers included in the source tree. ZedBoard is not different.
Digilent, one of the distributors of the ZedBoard gives a patched version of the Linux kernel source.
Downloading the kernel sources
The repository of the Digilent version of the Linux kernel is accessible at GitHub: https://github.com/Digilent/linux-digilent
To download the sources, the git versioning tool is used:
This command will clone the git repository found at https://github.com/Digilent/linux-digilent.git to the directory named kernel. This will take a little time depending your net connection speed.
Fixing the device tree
Embedded Linux versions (on systems where the hardware configuration can't be autodetected) use a file called the device tree to store the board configuration: for example the supported hardware, the memory addresses, and the IRQ numbers.
The ZedBoard board configuration device tree is found at arch/arm/boot/dts/digilent-zed.dts. Unfortunately the version cloned from the git repository is not appropriate for the hardware system we are going to use. Since we use the Linux Hardware Design for ISE 14.4 Zynq boot image, we have to use the device tree source file included in the zip file downloaded from http://www.digilentinc.com/Data/Products/ZedBoard/ZedBoard_Linux_Design.zip .
Simply extract the contents of this zip file outside of your Android build directory and copy the file ZedBoard_Linux_Design/linux/devicetree.dts to arch/arm/boot/dts/digilent-zed.dts, thus overwriting the old device tree source with this version.
After the successful checkout and preparation you can proceed to the kernel configuration.
Before compiling the Linux kernel, you have to configure it. Configuration is the way to determine the future behaviour of the kernel, the included drivers, and the target platform.
Since we build the Linux kernel for an ARM CPU (the Zynq PS) but on an x86 architecture, cross compiling is needed.
For building the kernel, the CodeSourcery ARM toolchain is used, which has the prefix arm-xilinx-linux-gnueabi- in the name of each tool (for example arm-xilinx-linux-gnueabi-gcc is the C compiler).
We have to tell the Linux build system that we are build for an ARM CPU, and we are going to build with the arm-xilinx-linux-gnueabi- toolchain.
The build system uses to environment variables for this: ARCH for setting the CPU architecture (arm in our case) and CROSS_COMPILE to set the tool chain command prefix (arm-xilinx-linux-gnueabi- in our case).
To ease the work, we are going to create a script which sets the necessary environment variables before the compile.
Create a file named dev.sh (development.sh shortened, but you can call it any name), with the contents:
#!/bin/bash export CCOMPILER=arm-xilinx-linux-gnueabi-gcc export ARCH=arm export CROSS_COMPILE=arm-xilinx-linux-gnueabi- export PATH=$PATH:/opt/CodeSourcery/Sourcery_CodeBench_Lite_for_Xilinx_GNU_Linux/bin/
NOTICE: My CodeSourcery CodeBench Lite for Xilinx toolchain was installed at the directory /opt/CodeSourcery/Sourcery_CodeBench_Lite_for_Xilinx_GNU_Linux/bin/ so I've put this directory in the system path. If you have the toolchain in an other directory, you will have to change this line. The „export CCOMPILER=” line will be used for the Android build in the future.
Give the dev.sh script execute permissions then import it in the shell:
Now everything is ready for the kernel configuration. Every time you want to compile the Linux kernel or the Android in a new terminal session you shall import dev.sh.
From now on, we are going to work in the Linux kernel directory so change the directory to kernel:
The Linux kernel is huge. It has many options which you can enable or disable. To configure the kernel for a new board can be a tedious work. Fortunately the ZedBoard has a default kernel configuration on which our configuration will be based.
To use this default configuration, type:
in your shell.
The Linux build system uses make as its build management tool. This tutorial does not present the possibilities of make, if you are interested, you can read about it for example at http://mrbook.org/tutorials/make/.
Now, a basic kernel configuration is ready. For Android, you will need to enable Android-specific features in the kernel configuration. The easiest way to do it is via the menu-driven configuration, so enter:
in the command window.
After a few compilation messages (starting with e.g. HOSTCC) a kernel configuration program shows up:
Navigation is keyboard-driven and is documented in the heading of the dialog box. Navigate to Device Drivers and enable Staging drivers by pressing “Y” on it:
A star (*) mark shows up in the checkbox: the feature is enabled.
Press ENTER on it and navigate in the Android menuitem and enable all features:
We enabled all of the needed features, we can exit from the kernel configuration tool by continously pressing ESC. When the tool asks whether we want to save the configuration we answer yes:
And thus we finish the kernel configuration.
Now you can build the kernel by typing:
The kernel now compiles, if the build has an error, checking out the sources (with git) again usually solves it. Because the Digilent repository is under active development, there can be times when the kernel build is broken.
You can find the compiled kernel image at arch/arm/boot/zImage, you will need it later when you prepare the SD card for Android.
Test drive #1 – does the compiled kernel boot?
To test that the compiled zImage works, you can try to boot it on ZedBoard.
To achieve it, you have to extract the ZedBoard Linux image on a VFAT formatted SD card (for example the original SD card included with ZedBoard).
This basic Linux hardware design image can be downloaded from the Digilent ZedBoard web page: http://www.digilentinc.com/Data/Products/ZedBoard/ZedBoard_Linux_Design.zip . Notice that we've already used this file when we fixed the device tree.
Download it and copy the contents of the directory ZedBoard_Linux_Design/sd_image on your SD card, so the root directory of the SD card has the following files:
To try your new kernel, copy your newly built zImage (found at arch/arm/boot/zImage in the kernel source directory) to the SD card, instead of the ZedBoard Linux hardware design zImage file, so the SD card has the following files:
|BOOT.BIN||From ZedBoard Linux Design|
|devicetree.dtb||From ZedBoard Linux Design|
|ramdisk8m.image.gz||From ZedBoard Linux Design|
|zImage||The version built by yourself|
After the SD card is ready, you can try to boot your new kernel. If you have an HDMI monitor connected, you can see the Linux logo (“Tux”) showing up. The console output is on the UART, you will have to connect it to your PC with an USB cable and have to use a terminal emulator to access it. You can use minicom, but you can also use your favorite terminal emulator.
If everything is in order, the zynq> prompt shows up in the software:
You can safely ignore the error message starting with “insmod:”.
To test whether your Zynq kernel is correctly configured, type:
zcat /proc/config.gz | grep ANDROID
in the terminal emulator connected to Zynq. This command searches for the string “ANDROID” in the configuration of the kernel booted on the Zynq PS. If you have the correct version, the following should show up:
This means that the Android-specific parts are successfully included in your new kernel.
A possible pitfall can be that the Zynq Linux kernel does not seem to boot from large SD card partitions (e.g. a 16 Gbyte FAT partition) altough a development PC can mount that partition.
Building Android for the ZedBoard platform
Now that we have a working kernel, we can build the Zynq Android sources.
Downloading the Android source code
Android uses git (like the Linux kernel) for version management. But, because Android has many subprojects, a software named repo is used to download all of the necessary sources. Before you can download Android, you have to install repo.
Installing repo is easy, simply download repo to your Android development directory (as you remember, this tutorial uses ~/android):
You will have to add execute permissions to the downloaded program:
Now change directory to the Android development directory and initialize the repository:
After the initialization you can download the sources by typing:
This will download the Zynq port of the Android source tree. Depending on your network connection speed it can take half a day. The downloaded Android source code takes about 8.5 Gbytes of hard disk space.
To compile Android, the gcc version 4.4 is used. The recent (>4.4) gcc versions introduce more strict c++ code checking, which makes some of the subprojects uncompileable. Fixing the source code is usually straightforward, but can be avoided with using gcc-4.4. If you compile on a 64 bit machine, make sure that the multilib versions (gcc-4.4-multilib and g++-4.4-multilib packages on Debian) are installed.
To check your gcc version, simply type:
If the reported gcc version is lesser than 4.6, your build probably will be successful.
Other necessary packages for the build are (notice: most packages are probably already installed for the Linux kernel build):
git gnupg flex bison gperf build-essential zip curl libc6-dev libncurses5-dev:i386 x11proto-core-dev libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-glx:i386 libgl1-mesa-dev g++-multilib mingw32 tofrodos python-markdown libxml2-utils xsltproc zlib1g-dev:i386
Before you build Android, remember to import dev.sh to your shell to set the necessary environment variables.
The Android build system requires other environment variables, this can be added to the shell by running:
The final step before the build is to select the default Zynq Android configuration by
This command selects the default configuration and generates the Makefile used for the build.
With the command make you can start the build:
Compiling Android usually takes a couple of hours. If the build fails, it usually means you have missing packages on your system. Searching the web with the error message usually gives an answer.
Preparing the SD card
The third part of the build process is to prepare the SD card to make Android bootable. The built Android uses the Linux kernel built in the first part of the document.
Generating the Android root filesystem
For building the Android root image (root.img) we use the make tool. Create a file called Makefile.zynq in your Android development directory and put the following into it:
OUT_DIR:=out/target/product/generic ROOT_IMG:=root.img ROOTFS:=rootfs ROOT_DIRS=lib/modules tmp media .PHONY: dummy $(ROOT_IMG): dummy rm -rf $@ sudo rm -rf $(ROOTFS) cp -r $(OUT_DIR)/root $(ROOTFS) cp -r $(OUT_DIR)/system $(ROOTFS) cd $(ROOTFS) && mkdir -p $(ROOT_DIRS) sudo chown -R root:root $(ROOTFS) sudo genext2fs -d $(ROOTFS) -b $$((80*1024)) -m 0 -N $$((64*1024)) $(ROOT_IMG) sudo chown $(shell id -u):$(shell id -g) $(ROOT_IMG) # Phony target forces the rootfs image file to be rebuilt on each make dummy:
Makefile.zynq is the “recipe” how the root.img filesystem image is built.
Notice: because some of the files in the image have to be owned by the root user, to generate it you have to be superuser. The Makefile.zynq uses the sudo command which runs the given command with root privileges. On Debian (Ubuntu) based system it means that the user with which you build the image has to be in the sudo group.
To generate the root image file simply enter:
The resulting root.img file should have a size of cca. 80 Mbytes.
It is possible that sudo asks for your password especially if you are using a new user.
Now you will have to put the generated root.img image file in the root directory of the SD card used to boot ZedBoard.
Modifying the Linux ramdisk
To make the Android boot automatic, we have to modify the ramdisk8m.image.gz extracted from the ZedBoard Linux Hardware Design. The modification automatically mounts the SD card during the Zynq Linux boot and starts Android.
To modify the contents of the ramdisk, first you have to decompress and mount it. Assuming you have the ramdisk8m.image.gz at ~/android and want to mount it to ~/android/ramdisk:
Notice: in most of the Linux distributions you have to mount the image file as superuser, you will have to use sudo.
The mounted ramdisk has the file etc/init.d/rcS. Add the following to the end of the file:
echo "Mounting SD card to /mnt/sd" mkdir -p /mnt/sd mount /dev/mmcblk0p1 /mnt/sd echo "++ Starting startup.sh script on SD card" if [ -f /mnt/sd/startup.sh ]; then . /mnt/sd/startup.sh fi
Hint: you have to make the modifications as root user, since the owner of the file is root.
This code first mounts the SD card to the directory /mnt/sd at the end of the boot process and – if it exists – calls the startup.sh shell script located in the root directory of the SD card.
Save the file, unmount the ramdisk image and recompress it:
Copy the resulting ramdisk8m.image.gz to the root directory of the SD card.
You are almost ready to boot Android. The last thing to do is to create the startup.sh file in the root directory of the SD card, and put the following into it:
echo "++ Preparing for Android" mkdir /mnt/root mount -o loop /mnt/sd/root.img /mnt/root/ mount -t proc proc /mnt/root/proc mount -t sysfs sys /mnt/root/sys mount -t tmpfs tmp /mnt/root/data mkdir -p /mnt/root/tmp/sd mount /mnt/sd /mnt/root/tmp/sd echo "++ Starting Android" chroot /mnt/root /init
The contents of the SD card should be the following:
|BOOT.BIN||From ZedBoard Linux Design|
|devicetree.dtb||From ZedBoard Linux Design|
|ramdisk8m.image.gz||Modified version of ZedBoard Linux Design|
|root.img||The Android you built|
|startup.sh||The startup script|
|zImage||The built Linux kernel|
You are ready to boot Android.
Test drive #2 – does Android boot?
Put the prepared SD card into your ZedBoard and turn it on. The Android boot messages are logged on the UART:
Mounting SD card to /mnt/sd ++ Starting startup.sh script on SD card ++ Preparing for Android [ 2.670000] EXT4-fs (loop0): couldn't mount as ext3 due to feature incompatis [ 2.730000] EXT4-fs (loop0): mounting ext2 file system using the ext4 subsysm [ 2.740000] EXT4-fs warning (device loop0): ext4_update_dynamic_rev:763: updd [ 2.750000] EXT4-fs (loop0): mounted filesystem without journal. Opts: (null) ++ Starting Android [ 3.690000] init: cannot open '/initlogo.rle' [ 3.750000] EXT4-fs (loop0): re-mounted. Opts: (null) [ 3.760000] init (682): /proc/1/oom_adj is deprecated, please use /proc/1/oo. [ 3.850000] init: cannot find '/system/etc/install-recovery.sh', disabling sh: can't access tty; job control turned off # [ 4.300000] warning: `rild' uses 32-bit capabilities (legacy support in us) [ 27.990000] binder: release 1134:1134 transaction 725 in, still active [ 27.990000] binder: send failed reply for transaction 725 to 1218:1218 [ 27.990000] alarm_release: clear alarm, pending 0 [ 28.010000] binder: send failed reply for transaction 733 to 1258:1258 [ 28.010000] binder: release proc 1134, transaction 728, not freed [ 28.030000] binder: 1225:1225 transaction failed 29189, size 148-0 [ 28.040000] binder: 1218:1218 transaction failed 29189, size 3512-4 [ 28.060000] init: untracked pid 1078 exited [ 28.070000] init: untracked pid 1082 exited
On the HDMI monitor you can see the booted Android system.
What to do from now?
The following are suggestions what can you do to enhance your Android:
- Keyboard and mouse input does not yet work, it should be fixed.
- You can modify the build system to create a standard device description of the ZedBoard.