Froyo on Nitrogen-E

Published on August 28, 2010

Archived Notice

This article has been archived and may contain broken links, photos and out-of-date information. If you have any questions, please Contact Us.

Froyo for i.MX51 has arrived! We've been waiting for the Froyo release from Freescale to enable our efforts in Android integration, and the wait is now over. Freescale's imx-android-r9 release is based on Froyo and has some nice new features. In this article, I'll walk through the steps I used to acquire, compile and deploy Froyo for our Nitrogen-E board. To begin with, everything starts with the 400+MB package imx-android-r9.tar.gz. The steps I'll walk through below are largely based on the file doc/i_MX_Android_R9_User_Guide.html contained within, tailored to show where we differ from the Freescale Babbage platform. The Freescale notes explain how to get the Froyo baseline release:

    $ mkdir ~/myandroid
    $ cd ~/myandroid
    $ wget https://android.git.kernel.org/repo
    $ chmod a+x ./repo
    $ ./repo init -u git://android.git.kernel.org/platform/manifest.git -b froyo
    $ cp /opt/imx-android-r9/code/r9/default.xml .repo/manifests/default.xml
    $ ./repo sync
They also explain how to retrieve the Freescale kernel and U-Boot patches from their respective repositories:
    $ cd ~/myandroid
    $ git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-2.6.31.y.git kernel_imx
    $ cd ~/myandroid/bootable/bootloader
    $ git clone git://git.denx.de/u-boot.git uboot-imx
Then they explain how to patch Android, U-Boot, and Linux with the Freescale updates using a provided patch script.
$ cd ~/myandroid
$ . /opt/imx-android-r9/code/r9/and_patch.sh
$ help                  # You should see "c_patch" function
$ c_patch /opt/imx-android-r9/code/r9 imx_r9
If everything goes smoothly, you should see a message like this: ************************************************************** Success: Now you can build android code for FSL i.MX platform ************************************************************** Even though we have separate repositories for our Linux kernel and U-Boot, I allowed c_patch to perform its updates. Alternatively, you could skip the clones of the kernel and U-Boot trees by removing the first two lines of /opt/imx-android-r9/code/r9/baseversion: 1 CHANGE 3d35d87d5482de23cd5dc4d7721b1086107cae50 bootable/bootloader/uboot-imx platform/bootable/bootloader/uboot-imx 2 NEW 74fca6a42863ffacaf7ba6f1936a9f228950f657 kernel_imx kernel/imx I believe that each line of this file tells c_patch to add, update, or keep a particular directory within the tree parented at the current working directory. So, now we have a working tree, allowing us to compile U-Boot, Linux, and Android. We'll take a little detour first, because we'll want to use the Boundary versions of kernel and U-Boot. I created a new branch in our kernel tree named imx-android-r9. I checked it out and compiled it like so: user@host:~/myandroid$ rm -rf kernel_imx user@host:~/myandroid$ git clone -b imx-android-r9 https://boundarydevices.com/git-repos/linux-bd.git kernel_imx user@host:~/myandroid$ cd kernel_imx user@host:~/myandroid/kernel_imx$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- nitrogen_android_defconfig user@host:~/myandroid/kernel_imx$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- uImage modules In the U-Boot case, I just checked out and built the current head, boundary20100817: user@host:~/myandroid/bootable/bootloader$ rm -rf uboot-imx user@host:~/myandroid/bootable/bootloader$ git clone -b boundary20100817 https://boundarydevices.com/git-repos/u-boot-nitrogen.git uboot-imx user@host:~/myandroid/bootable/bootloader$ cd uboot-imx user@host:~/myandroid/bootable/bootloader/uboot-imx$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- nitrogen_config user@host:~/myandroid/bootable/bootloader/uboot-imx$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- all At this point, we can build Froyo as described in the Freescale manual. We're basing our Nitrogen-E platform on the Freescale Babbage, so the command line is this: user@host:~/myandroid$ make PRODUCT-imx51_bbg-eng 2>&1 | tee build_imx51_bbg_android.log And, as mentioned in the Freescale docs, the output is placed in ~/myandroid/out/target/: user@host:~/myandroid$ ls -l out/target/product/imx51_bbg/ total 313748 -rw-r--r-- 1 ericn ericn 16 2010-08-24 16:40 android-info.txt -rw-r--r-- 1 ericn ericn 8866 2010-08-27 15:59 clean_steps.mk drwxr-xr-x 3 ericn ericn 4096 2010-08-17 12:47 data -rw-r--r-- 1 ericn ericn 24942 2010-08-27 16:02 installed-files.txt drwxr-xr-x 13 ericn ericn 4096 2010-08-24 16:40 obj -rw-r--r-- 1 ericn ericn 189 2010-08-27 15:59 previous_build_config.mk -rw-r--r-- 1 ericn ericn 212576 2010-08-27 16:02 ramdisk.img drwxr-xr-x 3 ericn ericn 4096 2010-08-24 16:40 recovery -rw-r--r-- 1 ericn ericn 4710400 2010-08-27 16:02 recovery.img drwxr-xr-x 8 ericn ericn 4096 2010-08-27 14:35 root drwxr-xr-x 4 ericn ericn 4096 2010-08-17 12:47 symbols drwxr-xr-x 11 ericn ericn 4096 2010-08-27 16:03 system -rw-r--r-- 1 ericn ericn 106344448 2010-08-27 16:02 system.img -rw-r--r-- 1 ericn ericn 209715200 2010-08-24 16:40 userdata.img The .img files are ext3 filesystem images with one exception: ramdisk.img is a gzipped cpio archive, which makes it easier to create a RAM disk suitable for use with U-Boot. When creating a bootable SD card, I'll use the directories instead. I'll also assume that you have a completely blank SD card to start with. The first step will be to partition the card. I'll use roughly the same partitioning scheme that the Freescale docs outline, with a VFAT partition labelled BOOT, followed by four ext3 partitions labelled SYSTEM, DATA, CACHE, and RECOVERY respectively. Then I'll add an second VFAT partition to house MEDIA to keep it away from our boot partition. Note that these instructions are for a 4GB card. You'll want to rework things for other sizes. I'll also install our first-level boot loader at offset 1k: user@host:~$ sudo dd bs=512 seek=2 if=sdmmc of=/dev/mmcblk0 user@host:~$ echo -e "nnpn1nn+100Mnnnpn2nn+200Mnnnen3nn+1Gnnnpnn+300Mnnnn+100Mnnnn+100Mnnnn+100Mntn1nbntn2n83ntn4n83ntn5n83ntn6n83ntn7nbnwn" | sudo fdisk /dev/mmcblk0 user@host:~$ sudo fdisk -l /dev/mmcblk0 Disk /dev/mmcblk0: 3999 MB, 3999268864 bytes 4 heads, 16 sectors/track, 122048 cylinders Units = cylinders of 64 * 512 = 32768 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0x986e3cfa Device Boot Start End Blocks Id System /dev/mmcblk0p1 1 3201 102424 b W95 FAT32 /dev/mmcblk0p2 3202 9602 204832 83 Linux /dev/mmcblk0p3 9603 42371 1048608 5 Extended /dev/mmcblk0p4 42372 51972 307232 83 Linux /dev/mmcblk0p5 9603 12803 102424 83 Linux /dev/mmcblk0p6 12804 16004 102424 83 Linux /dev/mmcblk0p7 16005 19205 102424 b W95 FAT32 user@host:~$ sudo mkdosfs /dev/mmcblk0p1 -n BOOT user@host:~$ sudo mkfs.ext3 /dev/mmcblk0p2 -L SYSTEM user@host:~$ sudo mkfs.ext3 /dev/mmcblk0p4 -L RECOVERY user@host:~$ sudo mkfs.ext3 /dev/mmcblk0p5 -L DATA user@host:~$ sudo mkfs.ext3 /dev/mmcblk0p6 -L CACHE user@host:~$ sudo mkdosfs /dev/mmcblk0p7 -n MEDIA user@host:~$ sync Removing and re-inserting the SD card, you can see the resulting volumes more clearly: user@host:~$ df -h | grep media | sort /dev/mmcblk0p1 100M 0 100M 0% /media/BOOT /dev/mmcblk0p2 194M 5.6M 179M 4% /media/SYSTEM /dev/mmcblk0p4 291M 11M 266M 4% /media/RECOVERY /dev/mmcblk0p5 97M 5.6M 87M 7% /media/DATA /dev/mmcblk0p6 97M 5.6M 87M 7% /media/CACHE /dev/mmcblk0p7 2.8G 4.0K 2.8G 1% /media/MEDIA Since we've already copied the first-level loader sdmmc, there are three partitions that we need to create:
  1. out/target/product/imx51_bbg/system/* goes into the /media/SYSTEM partition
  2. out/target/product/imx51_bbg/system/recovery/root goes into /media/RECOVERY
  3. U-Boot, the Linux kernel, and the initial RAM disk go into the /media/BOOT partition
The first two can be done directly: user@host:~$ sudo cp -arvf ~/myandroid/out/target/product/imx51_bbg/system/* /media/SYSTEM/ user@host:~$ sudo cp -arvf ~/myandroid/out/target/product/imx51_bbg/recovery/root/* /media/RECOVERY The first two components of the BOOT partition are also just copies: user@host:~$ cp -vf ~/myandroid/kernel_imx/arch/arm/boot/uImage /media/BOOT user@host:~$ cp -vf ~/myandroid/bootable/bootloader/uboot-imx/u-boot.bin /media/BOOT The third requires that we wrap the ramdisk with a U-Boot header: user@host:~$ mkimage -A arm -O linux -T ramdisk -n "Initial Ram Disk" -d ~/myandroid/out/target/product/imx51_bbg/ramdisk.img /media/BOOT/initrd.u-boot Alright, that's all the copying to be done. We have a couple of other steps to take before running Android, but first we need to boot this card: user@host:~$ sync && sudo umount /media/* Inserting this into a Nitrogen, you should be able to boot to the SD card. Interrupt the boot and set up the display and boot arguments as shown below for a 7" CMO panel: U-Boot > set bootargs console=ttymxc0,115200 video=mxcdi1fb:raw:24000000,800,480,1,2,2,0,18,24,90,2,4,4,1,0,565 di1_primary init=/init no_console_suspend U-Boot > set bootcmd 'fatload mmc 0 92000000 uImage && fatload mmc 0 92400000 initrd.u-boot && bootm 92000000 92400000' The 'no_console_suspend' clause tells Android to keep the serial console alive. Since we haven't configured any buttons yet, this is very useful. That's it for now. You should be able to boot the Froyo version of Android using just these steps. If you've installed the Android SDK and have a USB connection to the Nitrogen, you should be able to see the device using adb: user@host:~$ sudo ~/android-sdk-linux_86/tools/adb start-server user@host:~$ ~/android-sdk-linux_86/tools/adb devices List of devices attached 0123456789ABCDEF device user@host:~$ ~/android-sdk-linux_86/tools/adb shell # # ps USER PID PPID VSIZE RSS WCHAN PC NAME root 1 0 312 220 c00b42b4 0000cf5c S /init root 2 0 0 0 c0060168 00000000 S kthreadd root 3 2 0 0 c005114c 00000000 S ksoftirqd/0 root 4 2 0 0 c005cc20 00000000 S events/0 root 5 2 0 0 c005cc20 00000000 S khelper root 8 2 0 0 c0066020 00000000 S async/mgr root 11 2 0 0 c005cc20 00000000 S suspend root 177 2 0 0 c005cc20 00000000 S kblockd/0 root 187 2 0 0 c005cc20 00000000 S mxc_spi.0 root 192 2 0 0 c005cc20 00000000 S ksuspend_usbd root 197 2 0 0 c01ca05c 00000000 S khubd root 209 2 0 0 c005cc20 00000000 S kmmcd root 216 2 0 0 c0225c40 00000000 S pmic-event-thre root 299 2 0 0 c0083b20 00000000 S pdflush root 300 2 0 0 c0083b20 00000000 S pdflush root 301 2 0 0 c0088468 00000000 S kswapd0 root 348 2 0 0 c005cc20 00000000 S aio/0 root 357 2 0 0 c005cc20 00000000 S nfsiod root 361 2 0 0 c005cc20 00000000 S crypto/0 root 961 2 0 0 c0197ee0 00000000 S kapmd root 1058 2 0 0 c005cc20 00000000 S kstriped root 1062 2 0 0 c005cc20 00000000 S kconservative/0 root 1096 2 0 0 c005cc20 00000000 S usbhid_resumer root 1099 2 0 0 c005cc20 00000000 S binder root 1118 2 0 0 c0239570 00000000 S mmcqd root 1144 2 0 0 c005cc20 00000000 S rpciod/0 root 1154 2 0 0 c01e9dc0 00000000 S usb_mass_storag root 1159 2 0 0 c0226934 00000000 S mxc_ts root 1990 2 0 0 c010d624 00000000 S kjournald root 1998 2 0 0 c010d624 00000000 S kjournald root 1999 2 0 0 c010d624 00000000 S kjournald root 2001 1 712 300 c0185ea0 afd0d8fc S /system/bin/sh system 2002 1 780 292 c0250370 afd0db9c S /system/bin/servicemanager root 2003 1 3712 568 ffffffff afd0e20c S /system/bin/vold root 2004 1 3700 548 ffffffff afd0e20c S /system/bin/netd root 2005 1 640 252 c0280bec afd0e52c S /system/bin/debuggerd root 2006 1 120948 26936 c00b42b4 afd0dcc4 S zygote media 2007 1 41776 4796 ffffffff afd0db9c S /system/bin/mediaserver bluetooth 2008 1 1236 712 c00b42b4 afd0e9dc S /system/bin/dbus-daemon root 2009 1 780 316 c02dc474 afd0d8fc S /system/bin/installd log 2010 1 640 288 c0185ea0 afd0d8fc S /system/bin/logwrapper root 2011 1 3380 184 ffffffff 0000f474 S /sbin/adbd dhcp 2015 2010 820 400 c00b42b4 afd0e9dc S /system/bin/dhcpcd system 2061 2006 268488 35968 ffffffff afd0db9c S system_server root 2073 2 0 0 c005cc20 00000000 S z1xx_workq app_33 2167 2006 166972 21676 ffffffff afd0eb58 S com.android.inputmethod.latin radio 2173 2006 187884 23688 ffffffff afd0eb58 S com.android.phone app_16 2182 2006 213292 25104 ffffffff afd0eb58 S com.android.launcher system 2201 2006 182528 20184 ffffffff afd0eb58 S com.android.settings app_7 2254 2006 191112 26672 ffffffff afd0eb58 S android.process.acore app_0 2277 2006 162876 19808 ffffffff afd0eb58 S com.android.providers.calendar app_1 2298 2006 176300 20556 ffffffff afd0eb58 S android.process.media app_6 2326 2006 183544 20764 ffffffff afd0eb58 S com.android.mms app_12 2349 2006 179228 21312 ffffffff afd0eb58 S com.android.email app_19 2374 2006 161860 19936 ffffffff afd0eb58 S com.android.deskclock app_20 2386 2006 161936 19756 ffffffff afd0eb58 S com.android.bluetooth app_8 2394 2006 162864 19664 ffffffff afd0eb58 S com.android.quicksearchbox app_17 2405 2006 160084 18816 ffffffff afd0eb58 S com.android.protips app_28 2412 2006 162396 19196 ffffffff afd0eb58 S com.android.music app_2 2421 2006 163700 20384 ffffffff afd0eb58 S com.cooliris.media root 2431 2011 712 320 c004ed0c afd0e80c S /system/bin/sh root 2433 2431 860 340 00000000 afd0d8fc R ps # In my next post, I'll cover some of the quirks (especially touch-screen) and discuss how to actually tailor things for the Nitrogen and explain how we're keeping track of changes.