Froyo on Nitrogen-E
Published on August 28, 2010
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 syncThey 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-imxThen 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_r9If 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:
- out/target/product/imx51_bbg/system/* goes into the /media/SYSTEM partition
- out/target/product/imx51_bbg/system/recovery/root goes into /media/RECOVERY
- U-Boot, the Linux kernel, and the initial RAM disk go into the /media/BOOT partition
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.