In this post we are going to build and deploy Android Kitkat for the Wandboard Quad. The instructions are mostly identical for the Wandboard Dual, although you will need a different u-boot bootloader configuration, and a different dtb file. With the current Android 4.4.4 build we are able to use ethernet, wifi in client and AP mode, as well as ALSA sound. Bluetooth and hardware accelerated graphics is not yet accomplished.
- Host Build System: Ubuntu 13.10 (64 Bit)
It is important to use a 64 Bit version, otherwise, it is not possible to build Android. - Hardware: Wandboard Quad revision B1
- Kernel version: 3.16 rc5
We will use the latest kernel provided by Robert Nelson - Bootloader: u-boot bootloader by Denx
We will also download and patch as per instructions provided by Robert Nelson. - Android version: 4.4.4_r1 AOSP
- An USB to serial converter for communicating with the Wandboard
Unless your computer has a serial port of course. - A microSD card
We recommend at least class 10, it really makes a big difference. A size of 2GB should be enough.
For this tutorial, we will have 3 main source code repositories, namely Android, u-boot and Linux kernel sources. It is assumed that we download the Android source code, and place the u-boot and Kernel sources in their respective sub-folders “u-boot” and “armv7-multiplatform” inside the Android source‘s root. While the exact location does not matter, we will use /opt/android as an example here. Since we are going to use a cross-compiler from Android for building the bootloader, it makes sense to first download all the source code repositories before starting with this tutorial.
# Download Android source /opt/android mkdir /opt/android cd /opt/android repo init -u https://android.googlesource.com/platform/manifest -b android-4.4.4_r1 repo sync # Download u-boot source into /opt/android/u-boot cd /opt/android git clone git://git.denx.de/u-boot.git # Download Linux kernel sources into /opt/android/armv7-multiplatform cd /opt/android git clone https://github.com/RobertCNelson/armv7-multiplatform.git
u-boot bootloader
We will start by downloading, building and deploying the u-boot bootloader to a microSD card. Not to take anything away, this step is identical to the Wandboard u-boot instructions provided by Robert Nelson, thanks a lot for sharing! For completeness, I will add all instructions here as well.
cd /opt/android git clone git://git.denx.de/u-boot.git cd u-boot/ git checkout v2014.07 -b tmp # Patching wget -c https://raw.githubusercontent.com/eewiki/u-boot-patches/master/v2014.07/0001-wandboard-uEnv.txt-bootz-n-fixes.patch patch -p1 < 0001-wandboard-uEnv.txt-bootz-n-fixes.patch # start build export ARCH=arm export CROSS_COMPILE=../prebuilts/gcc/linux-x86/arm/arm-eabi-4.7/bin/arm-eabi- make distclean make wandboard_quad_config make -j8
If everything works fine, you should get a binary called u-boot.imx. This is our bootloader which must be placed on the SD card. Different chipsets have different mechanisms for obtaining the bootloader. For instance, on the Beaglebone a file called MLO and another u-boot binary is to be placed on the first FAT partition. The reason for this is that the location and name (‘MLO’) is unalterably burnt into the chip. For the Wandboard with its i.MX6 chipset, the process is slightly different. The u-boot.imx bootloader file needs to be placed at an offset of exactly 1024 bytes into the SD card’s storage, and is itself around 300KB in size. Therefore, it is important that we leave some space before the beginning of the first partition. Let’s just do that: insert an SD card into your host computer, and use the partitioning program of your choice. A nice and easy tool is “gparted” for instance.
On our SD card, we want to create 3 partitions:
- File system: ext4
Size: 512MiB
Label: RFS
Free space preceding: 10MiB - File system: ext4
size: 512MiB
Label: CACHE - File system: ext4
size: (rest of disk space)
Label: DATA
You could of course use less space preceding before the first partition, this is just to be super safe. Here is a screenshot of what it should look like, when you are using gparted.
Notice the unallocated region before the first partition. Also, note the device name in the upper right corner (“/dev/sde” in this case). When you are done with partitioning, we will copy the bootloader onto the SD card with the Linux “dd” command. Be very careful that you do not accidentally write to your computer’s hard disk instead. You should already know the SD card’s device name from the partitioning tool used earlier. Before continuing however, it is still a good idea to run “lsblk”, which will again list all the attached disk drives. Only execute the “dd” command, if you are certain that this is your SD card.
$ lsblk ... -sdb5 8:21 0 11.7G 0 part sdc 8:32 0 465.8G 0 disk -sdc1 8:33 0 100M 0 part -sdc2 8:34 0 465.7G 0 part sde 8:64 1 7.4G 0 disk -sde1 8:65 1 512M 0 part -sde2 8:66 1 512M 0 part -sde3 8:67 1 6.4G 0 part # In this case, we would replace sdX with sde $ sudo dd if=u-boot.imx of=/dev/sdX bs=512 seek=2 $ sync
You can now try if the bootloader is recognized correctly. For this you will need to connect the Wandboard’s serial port with your computer, and use a serial terminal program such as “minicom”. The serial port settings should be
- Bps/Par/Bits: 115200 8N1
- Hardware Flow Control: No
- Software Flow Control: No
- Serial Device: probably /dev/ttyUSB0 or /dev/ttyACM0
Insert the SD card into the Wandboard and power up the board. Of course, since we do not have a Linux kernel installed yet, nothing good will come of this ๐ Nevertheless, some output similar to the following should be visible:
U-Boot 2014.07-dirty (Jul 23 2014 - 13:23:55) CPU: Freescale i.MX6Q rev1.2 at 792 MHz Reset cause: POR Board: Wandboard I2C: ready DRAM: 2 GiB MMC: FSL_SDHC: 0, FSL_SDHC: 1 ...
Linux kernel
The next thing we need is a Linux kernel binary. Once more, check out Robert Nelson’s instructions.
cd /opt/android git clone https://github.com/RobertCNelson/armv7-multiplatform.git cd armv7-multiplatform git checkout origin/v3.16.x -b tmp ./build_kernel.sh
The last step will download the Linux source code together with minimal patches. It will also download a recent cross-compiler. If you want to save bandwidth, you could also edit the system.sh file and adjust the CC variable, and in that case, your own cross compiler would be used instead. Furthermore, the configuration process is started, and after some time, you should be greeted with a menuconfig screen. Since we are aiming to run Android later on, navigate to the Android section and include the Android log driver (which is used for logcat) statically in the kernel. The Android section is found under Device Drivers – Staging drivers – Android. Navigate to “Android log driver” and hit “Y” or toggle spacebar until an asterisk is visible at the beginning of the line.
For sound support, choose:
- Device Drivers
- <*> Sound Card Support
- <*> Advanced Linux Sound Architecture
- <*> ALSA for SoC audio support
- SoC Audio for Freescale CPUs ->
- <*> Soc Audio for Freescale i.IMX CPUs and <*> SoC Audio support for i.MX boards with sgtl5000
Furthermore, you may want to enable UVC support for USB cameras and alike
- Device Drivers
- <*> Multimedia support
- <*> Media USB Adapters
- <*> USB Video Class (UVC)
Also make sure that you have input event support for USB mices. The corresponding configuration should be enabled under
- Device Drivers
- Input device support – – ->
- <*> Event interface
Then hit ESC repeatedly and choose to save the current configuration.
After finishing the configuration, the compile process also starts automatically and if everything works well, you will end up with a compressed kernel image in
/opt/android/armv7-multiplatform/KERNEL/arch/arm/boot/zImage
There is also a device tree blob/binary found in
/opt/android/armv7-multiplatform/KERNEL/arch/arm/boot/dts/imx6q-wandboard.dtb
(or imx6dl-wandboard.dtb for Wandboard Dual)
Deploying Linux kernel and uEnv.txt
Our u-boot bootloader already has a lot of built-in environment variables. Have a look at u-boot/include/configs/wandboard.h for more information. The basic startup sequence is as follows:
- Each partition of the SD card will be searched for an environment file under /boot/uEnv.txt
- If an uEnv.txt file is found, its contents are imported to the current u-boot environment. (This also allows for overriding certain variables)
- If the uEnv.txt file contains a variable named “uname_r”, the function “uname_boot” is called.
- Within uname_boot, a compressed kernel binary is assumed to be under /boot/vmlinuz-{uname_r}
- The name of a device tree binary may be specified with the variable “dtb”. The file itself will then be searched in /boot/dtbs/{uname_r}/{dtb} and /boot/{dtb} amongst other locations.
- At the end of uname_boot, “run mmcargs” is called.
To edit the kernel command line for instance, you could modify the file u-boot/include/configs/wandboard.h by setting “cmdline=…” and recompile u-boot. However, that is of course an impractical approach, especially for development purposes. To include a custom cmdline parameter, it is much easier to create an uEnv.txt file and put it on the first partition of our SD card under /boot/uEnv.txt. Within the uEnv.txt we are free to set our own parameters. As described above, mmcargs will be executed ultimately.
The default value of mmcargs as defined in u-boot/include/configs/wandboard.h is…
mmcargs=setenv bootargs console=${console} ${optargs} root=${mmcroot} rootfstype=${mmcrootfstype} ${cmdline}
… and including your own parameters is done by setting “optargs” and “cmdline” in the uEnv.txt file. It would also be possible of course, to completely override “mmcargs” or even “uname_boot”.
An example uEnv.txt file would be:
uname_r=3.16 dtb=imx6q-wandboard.dtb optargs=androidboot.console=ttymxc0 androidboot.hardware=wandboard-quad cmdline=init=/init
Either create your own, or download this example uEnv.txt file, and copy it to the SD card. Notice, that the variable uname_r is set to 3.16. Therefore, our kernel binary should be named vmlinuz-3.16 as described above.
sudo mkdir /media/user/RFS/boot sudo cp Downloads/serverbox_wandboard_uEnv.txt /media/user/RFS/boot/uEnv.txt sudo cp /opt/android/armv7-multiplatform/KERNEL/arch/arm/boot/zImage /media/user/RFS/boot/vmlinuz-3.16 sudo cp /opt/android/armv7-multiplatform/KERNEL/arch/arm/boot/dts/imx6q-wandboard.dtb /media/user/RFS/boot sync
Again, try to boot the Wandboard with the current SD card. It should find the uEnv.txt as well as the compressed kernel and dtb file. After a few seconds, you will get a kernel panic “not syncing: No working init found”, which was to be expected. After all, there is no init binary on our SD card, yet…
Building Android
This is where it gets exciting ๐ Download the Android source code with the repo tool. In this tutorial, we are using the release branch “android-4.4.4_r1”.
mkdir /opt/android/ cd /opt/android/ repo init -u https://android.googlesource.com/platform/manifest -b android-4.4.4_r1 repo sync
Downloading will probably take a few hours, unless you already have a local Android mirror! Have a look at the official instructions for setting up your very own Android mirror, in case you are interested.
We started development by modifying the generic “mini_armv7a_neon” product under device/generic/armv7-a-neon. You can download our armv7-a-neon folder from here. Just copy its contents over your fresh install, this way, you can use git to see all the changes and also revert back if needed.
cd ~/Downloads # download wget http://android.serverbox.ch/wp-content/uploads/2014/07/serverbox_wandboard_android.tar # extract tar -xf serverbox_wandboard_android.tar # copy over original folder cp -r armv7-a-neon/* /opt/android/device/generic/armv7-a-neon # check cd /opt/android/device/generic/armv7-a-neon git status # git status should show # 4 modified and # 3 untracked files
A few more changes are needed if you also want to be able to create a wireless access point (AP mode). There are two functions “wifi_get_fw_path” and “wifi_change_fw_path” from hardware/libhardware_legacy/wifi/wifi.c which need modifications. Just add a return statement right at the beginning of each, like so:
cd hardware/libhardware_legacy vim wifi/wifi.c
const char *wifi_get_fw_path(int fw_type) { return "dummy"; .. } int wifi_change_fw_path(const char *fwpath) { return 0; .. }
On some devices, there are different wifi module firmwares for “normal” STA mode, access point (AP), and peer-to-peer (P2P) mode. And those firmwares are dynamically loaded, depending on which mode is active. However, on the Wandboard only one firmware is used for all modes (although we did not test P2P specifically). Therefore, the above functions can be stubbed as described. Note that the firmware in armv7-a-neon/root_overlay is an APSTA variant with version 4.220.48, which was originally downloaded from this Wandboard forum post.
The external/wpa_supplicant_8 project contains the source code for both wpa_supplicant and hostapd version 2.1-devel. For AP mode to work properly, we need to replace hostapd with the newer 2.2 version directly from http://w1.fi.
rm -rf /opt/android/external/wpa_supplicant_8/hostapd cd ~/Downloads wget http://w1.fi/releases/hostapd-2.2.tar.gz tar -xzf hostapd-2.2.tar.gz cd hostapd-2.2 mv hostapd /opt/android/external/wpa_supplicant_8/ mv src /opt/android/external/wpa_supplicant_8/hostapd/
Furthermore, if you also want to activate AP mode via the Android UI, comment out the “updateBluetoothState” function call in the Settings application:
cd packages/apps/Settings vim src/com/android/settings/TetherSettings.java
private void updateState(String[] available, String[] tethered, String[] errored) { updateUsbState(available, tethered, errored); // Quick hack to fix NullPointerException //updateBluetoothState(available, tethered, errored); }
The above fix is needed because we do not have proper Bluetooth support yet, and when the “Portable hostspot” tab is opened via the Settings application, the above function call would result in a Java NullPointerException.
Finally, we can start the Android build process!
cd /opt/android/ . build/envsetup.sh choosecombo 1 mini_armv7a_neon 3 make -j8
Depending on your host computer, this may take up to a few hours. The last output you will get if everything succeeded should be something like this:
... Install system fs image: out/target/product/armv7-a-neon/system.img
The wpa_supplicant executable from external/wpa_supplicant_8/wpa_supplicant/Android.mk will not build by default. But we can build it manually by issuing…
mmm -j8 external/wpa_supplicant_8
Also, for testing ALSA sound, build the external tinyalsa project.
mmm -j8 external/tinyalsa
Deploying Android on an SD-card
This is a very important and often times underrated step. If Android fails to boot up, it is almost always a problem of an incorrect deployment. Android needs very specific permissions and ownership for its files. For instance, the init process will fail – for security reasons – if there are any “*.rc” scripts in the root directory with incorrect file permissions. Also, other files need their user and group id’s set to shell (2000), system (1000), wifi (1010) and so on. These custom Android user and group id values are defined in system/core/include/private/android_filesystem_config.h if you are interested.
Prepare an SD-card with 3 partitions and bootloader integrated before the first partition begins, as described above in the u-boot bootloader section. The first partition will be our root file system, which is where we put both the Android root and system directory. The second partition is used as cache, and the last partition as data, both of which will be left empty.
As mentioned, it isn’t enough to simply copy the contents of the out directory to our SD card partition. We also need to modify the file permission and ownerships first, after which we could create an archive to extract to the SD-card. This could be done by hand, but luckily there are already tools available for this task, namely mktarball.sh and fs_get_stats.
Have a look at the script “export-android-sd.sh” in the updated device/generic/armv7-a-neon folder. Change the first four variables if needed, especially ANDROID_ROOT, and then execute the script. If this is the first time you run export-android-sd.sh, it will create the mentioned host tool “fs_get_stats”. The output should look something like this:
cd /opt/android/device/generic/armv7-a-neon ./export-android-sd.sh ... ... host C: fs_get_stats <= build/tools/fs_get_stats/fs_get_stats.c host Executable: fs_get_stats (out/host/linux-x86/obj/EXECUTABLES/fs_get_stats_intermediates/fs_get_stats) Install: out/host/linux-x86/bin/fs_get_stats make: Leaving directory `/opt/android/4.4.4_r1'
Now re-run the export-android-sd.sh script, which will take some time, especially for extracting the system folder.
./export-android-sd.sh # IMPORTANT: wait for sync to complete before removing the SD-card # alternatively, you could also use umount for safe unmounting sync
Insert the SD-card into the Wandboard and you should be golden ๐
Some useful commands for host and target
On the host:
# on the Wandboard serial terminal, issue 'su', followed by 'netcfg' # to determine the IP address of the ethernet interface adb connect 192.168.1.XXX # by default, the root partition is mounted as read-only adb shell mount -o rw,remount / # for instance adb push out/target/product/armv7-a-neon/symbols/system/bin/wpa_supplicant /system/bin/
On the target:
# test ALSA sound capturing and playback # make sure to connect to the correct mic and lineout sockets cd /data/local/tmp tinycap test.wav tinyplay test.wav # restore default wpa_supplicant.conf and start wpa_supplicant service cp /system/etc/wifi/wpa_supplicant.conf /data/misc/wifi/wpa_supplicant.conf chmod 660 /data/misc/wifi/wpa_supplicant.conf chown system.wifi /data/misc/wifi/wpa_supplicant.conf start wpa_supplicant # Enable AP mode and dnsmasq DHCP server # Need to create a hostapd.conf file in /data/misc/wifi/hostapd.conf # One will be created if you use the Android UI to enable AP mode. # An example hostapd.conf with SSID=WandboardAP and PW=wandboard # is also available in armv7-a-neon/root_overlay/hostapd.conf ndc interface setcfg wlan0 192.168.43.1 24 up dnsmasq --no-resolv --no-poll --pid-file --dhcp-range=192.168.43.30,192.168.43.99,1h ndc softap startap # to stop AP mode ndc softap stopap # Scan for Wifi wpa_cli -p /data/misc/wifi/sockets/ -iwlan0 > status > scan > scan_results
Also, here is a compiled busybox binary for Android. Install and use with the following commands
host$ adb connect 192.168.1.XXX host$ adb shell mount -o rw,remount / host$ adb push busybox /system/bin host$ adb shell target$ busybox vi test.txt
very well done guys ๐
Neither too short nor too long and many valuable hints!
Hello,
Do you know if hardware accel video is enabled ? Can I play 720/1080p videos ?
Hi Leonardo
Hardware acceleration is not enabled. Still, it might be possible to play videos, I doubt it will play 1080p smoothly though..
Also, we will probably try to include hardware acceleration in the near future, since this is something we are also interested in.
If we find the time and succeed, we will of course update this post.
By the way, the official Wandboard Android 4.3 from the Wandbord download section should have hardware acceleration enabled, so if you don’t mind using Android 4.3, I would definitely try this.
Best regards
andreas
after the linux kernel config (after the menuconfig screens) i get:
fixdep: error opening config file: /opt/android/armv7-multiplatform: No such file or directory
make[1]: *** [kernel/bounds.s] Fehler 2
make: *** [prepare0] Fehler 2
I guess the config is not written to right place? Can anybody tell me what is the place to write the config to? When in menuconfig I click the default filename is just “.config” and I didn’t change that. Just I need to state that I’m on Ubuntu 14 LTS version…
Hi Thomas
Did you start the kernel building and configuring process with “./build_kernel.sh” inside “/opt/android/armv7-multiplatform”? This will create a subfolder “/opt/android/armv7-multiplatform/KERNEL”. And the kernel config will be in “/opt/android/armv7-multiplatform/KERNEL/.config”
Is it possible that you renamed the “armv7-multiplatform folder”? In the meantime, we switched to Ubuntu 14.04 LTS as well, so I don’t think this should be a problem.
If it helps, I am on commit “303c023a854f7adacc2dccb034f050aee31204ac” inside the armv7-multiplatform project. So maybe try:
$ cd /opt/android/armv7-multiplatform
$ git checkout 303c023a854f7adacc2dccb034f050aee31204ac
If you already have the KERNEL directory, and just want to rebuild the kernel, you can do so by
$ export ARCH=arm
$ export CROSS_COMPILE=../../prebuilts/gcc/linux-x86/arm/arm-eabi-4.7/bin/arm-eabi-
$ make menuconfig
$ make -j16
Best Regards
andreas
you guys rock – awesome help. “i glaub i muass a schoggi i d’schwiiiez schicka ๐
maybe OT… however I got everything compiling and now the whole thing boots! That really makes lots of fun now.
One open problem is now that no usb device is recognized nor is lsusb command working. I found that there is a “libusb” folder in ./external folder when I tried to do the same from your other post to get libusb compiled (which was for the beagleboard) … I’m bit lost … any hint what has to be done to get usb working? Actually I just want to get the USB connected touch of an old ELO touchscreen working… or as a soft start a normal USB mouse device.
Thanks ๐
USB mouse support should be working out of the box, that is, you should get an on-screen mouse pointer. If not, check in the kernel menuconfig, that you have Device Drivers -> Input device support > Event interface built statically (*) into the kernel.
Also check with the dmesg command after you connected the mouse.
Best Regards
andreas
yap! that was it… activated that and it supports the USB HID
Excellent, thanks! I updated the instructions accordingly..
cheers
andreas
Hi would you please tell me how can I add ov5640 camera driver to the Android srouce code for wandboard
Hi Omid
I dont think there is yet a driver for this particular camera in any 3.16 kernel. However, you could try to use another kernel version from here:
https://github.com/wandboard-org/linux
Best Regards
andreas
marvelous article.
any idea for this? after 10 min. the screen attached to the wandboard turns off and cannot be reactiavated. The message (dmesg) when screen goes out is:
[ 605.963498] imx-ipuv3 2400000.ipu: DC stop timeout
after 50 ms
=> this is from the linux kernel as it seems… but no idea to make screen on again on a click/touch/move event. Any idea??
Hi Johnny
Thanks for the appreciation ๐
I think the “screen saver”can be disabled by adding the following option to the kernel boot parameters:
consoleblank=0
Edit the file /boot/uEnv.txt and append it to either cmdline or optargs. By the way, it is also a good idea to add the “rootwait” argument. We made some tests with the mainline kernel and it would always crash without “rootwait”.
Please report back if consoleblank=0 fixes the issue, so that I can update the instructions.
Best Regards
andreas
yap that works perfectly!
I put rootwait now too but had no crashes before.
do you experts know how to make the display-timeout of android working on the HDMI output? Or how to programmatically turn on/off the HDMI from this android setup?
Hi Johnny
At the moment, we only have an HDMI monitor attached, which does not blank at all even without the consoleblank=0 argument. So we can not really test a timeout feature or similar. But most monitor-features are within /sys/class/graphics/fb0.
For instance, to blank the monitor, use:
cd /sys/class/graphics/fb0
# blank
echo 1 > blank
# un-blank (may need to move mouse pointer afterwards)
echo 0 > blank
There is also a folder ‘power’ with entries like autosuspend_delay_ms, which is probably what you are looking for.
cheers
andreas
Hej hej,
really nice article! However, I’ve got a problem. I’ve managed to download all the sources and successfully build the patched u-boot and the configured linux kernel by Robert Nelson (only that I used version 3.17 and “make ARCH=arm CROSS_COMPILE={CC} wandboard_dl_defconfig” (after setting up the CROSS_COMPILE environment variable) as stated in the linked eewiki.net article.
I’m just stuck at building Android. “git status” still works as described, but then I’ve typed in “make -j4” in the source root directory. It would start building, but after a few minutes it cancels with some make error: http://pastebin.com/0qUyuPeG
Do you have any idea why? Is it because of the newer kernel and should I try again with 3.16?
Kind regards,
Henrik
Hi Henrik
No that is not a problem with the kernel. When downloading and building Android from the official sources (AOSP), the kernel is not built or touched in any way, only the Android system is built.
From your pastebin I can see errors such as “Can’t exec /home/hm/WandBoard/android-4.4.4/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/arm-linux-gnueabihf-“. This points to a cross-compiler, but when building Android AOSP, it should use its own cross-compiler located at android-4.4.4/prebuilts/gcc/linux-x86/arm/…
So I am guessing something is not properly initialized. Maybe you already figured it out in the meantime, but I would just open a new terminal, then go to the Android source and initialize by including build/envsetup.sh. In your example this would be:
cd /home/hm/WandBoard/android-4.4.4
. build/envsetup.sh
choosecombo 1 mini_armv7a_neon 3
make -j8
Best Regards
Andreas
Thank you for looking into my problem, Andreas!
Unfortunately, I still can’t compile. I executed the commands as you told me (I’ve just used “make -j4” because I have a quadcore processor), but the building process still fails. ๐ Here is my output after the second build attempt: http://pastebin.com/bCw0kp7c Any more ideas?
Thanks for your support!
Hi.
Did you get the hardware acceleration enabled ?
I’m trying to find a way to include the Vivante GPU driver on this setup.
Anyone can recommend any working driver version or tutorial that is known to be compatible with this method?
Hi ApriOri
Just to make sure… The Vivante GPU driver with hardware acceleration works if you use the official wandboard kernel and Android image. It does not work with a (close to) mainline kernel and Android AOSP like we are using here. The best shot to get hardware acceleration working is probably the “Etnaviv” open-source driver project, but we have not tried this yet.
Best Regards
Andreas