Search This Blog

Jul 31, 2011

i.MX28 Android porting

1. Overview

Customer wants implement their minus Android R2.1 system on i.MX28 platform, don’t need Android graphics interface. Require keep uboot, Linux kernel and Android Rootfs on Nand flash.

2. Prepare source code and MFG tool

2.1. Get uboot source code

Since official release uboot doesn’t support Nand flash on i.MX28 EVK rev C, We have to get source code from internal git server. Get snapshot of “ENGR00133530 plug-in support mfgtools and sb_loader”, commit number is “2cbb0e33bd31c9a34fcf3313329c005ae4ad44d6”, and then we get uboot-imx-2cbb0e33bd31c9a34fcf3313329c005ae4ad44d6.tar.gz.

2.2. Get Kernel source code

Since Android R8.1 kernel doesn’t support i.MX28 EVK rev C, we choose Android R9.1 kernel for this case. Prepare imx28evk_android_defconfig to generate i.MX28 configuration.

2.3. Get Android Rootfs

Since Customer required Android R2.1, we choose Android R8.1 for them. However, we need to do something to make it works on i.MX28 EVK rev C.

2.4. Get elf2sb tool

We need generate sb file for i.MX28 ROM code recognize. We need prepare below files for generating sb file.
“boot_prep, power_prep, uboot.db and elftosb2”.
Those files can be found in general i.MX28 BSP project, package imx-bootlets-src-10.09.00.

2.5. Get MFT tool

We use MFT tool v1.6.2.019-ga09cdce for this case.

3. Build uboot

  • Extract uboot-imx-2cbb0e33bd31c9a34fcf3313329c005ae4ad44d6.tar.gz to “uboot-imx” directory. 
  • Do some modification in “include/configs/mx28_evk.h”
    /*
      * We save Nand flash boot setting here. In default, uImage in 0x300000, uramdisk.img in 0x600000,
      * Android_recvoery.img in 0x800000, android_root.img in 0x1c00000. And i.MX28 kernel Nand flash driver
      * will divide Nand flash into 2 partitions when Nand flash size smaller than 2GB. First partition is 
      * boot area, Default size is 20MB, it cannot keep android_root.img. We have to burn android_root.img 
      * to secondary partition. So we set in uboot setting “ubi.mtd=1”.
      */
    #define CONFIG_BOOTCOMMAND "run bootcmd_nand" 
    #define CONFIG_EXTRA_ENV_SETTINGS \
     "bootcmd=run bootcmd_nand\0" \
     "nand_read_kernel=nand read ${loadaddr} 0x300000 0x250000\0" \
     "nand_read_rd=nand read ${rd_loadaddr} 0x600000  0x4B000\0" \
     "bootcmd_nand=run bootargs_base bootargs_android bootargs_nand;" \
      "run nand_read_kernel;run nand_read_rd;" \
      "bootm ${loadaddr} ${rd_loadaddr}\0" \
     "bootargs_base=setenv bootargs console=ttyAM0,115200\0" \
     "bootargs_nand=setenv bootargs ${bootargs} ubi.mtd=1\0" \
     "bootargs_android=setenv bootargs ${bootargs} init=/init androidboot.console=ttyAM0\0" \
     "loadaddr=0x40800000\0" \
     "rd_loadaddr=0x40B00000\0" \
    
    /* iMX28 Nand flash share pins with secondary SSP interface, we need set SSP num as only one.*/
    #define CONFIG_SYS_SSP_MMC_NUM 1  
    /* Change environment location to Nand flash*/
    //#define CONFIG_FSL_ENV_IN_MMC
    #define CONFIG_FSL_ENV_IN_NAND  
    
  • Compile uboot
    Copy elf2sb files “boot_prep, power_prep, uboot.db, elftosb2” to “uboot-imx” directory.
    $ cd uboot-imx
    $ make distclean
    $ make mx28_evk_config
    $./efltosb2 –z –c ./uboot.db –o imx_uboot.sb
    
    We get imx_uboot.sb for MFG tool use.

4. Build Kernel

As we talked, we choose Android R9.1 kernel in this case. But we don’t have android configuration for i.MX28, we need add configuration file for i.MX28.
  • Modification in “kernel-imx/arch/arm/mach-mx28/device.c”
    .MX28 Nand flash first partition defaults size setting is 20MB, since we will burn android_root.img to 0x1c00000 in Nand flash, that is to say, we need set secondary partition offset 28MB.
    static struct gpmi_nfc_platform_data  gpmi_nfc_platform_data = {
     .nfc_version             = 1,
     .boot_rom_version        = 1,
     .clock_name              = "gpmi",
     .platform_init           = gpmi_nfc_platform_init,
     .platform_exit           = gpmi_nfc_platform_exit,
     .min_prop_delay_in_ns    = 5,
     .max_prop_delay_in_ns    = 9,
     .max_chip_count          = 2,
     .boot_area_size_in_bytes = 28 * SZ_1M,  
     .partition_source_types  = gpmi_nfc_partition_source_types,
     .partitions              = 0,
     .partition_count         = 0,
    };
    
  • Modification in “kernel-imx/arch/arm/mach-mx28/mx28evk_pins.c”
    i.MX28 Nand flash pins share with secondary SSP interface, Android R9.1 kernel imx28 default setting is SSP1, we need change it to support Nand flash GPMI.
    int enable_gpmi = { 1 };
    void __init mx28evk_pins_init(void)
    {
     mx28evk_init_pin_group(mx28evk_fixed_pins, ARRAY_SIZE(mx28evk_fixed_pins));
    /* if (enable_ssp1) {
      pr_info("Initializing SSP1 pins\n");
      mx28evk_init_pin_group(mx28evk_ssp1_pins, ARRAY_SIZE(mx28evk_ssp1_pins));
     } else */
            if (enable_gpmi) {
      pr_info("Initializing GPMI pins\n");
      mx28evk_init_pin_group(mx28evk_gpmi_pins, ARRAY_SIZE(mx28evk_gpmi_pins));
     }
    #if defined(CONFIG_FEC) || defined(CONFIG_FEC_MODULE)\
     || defined(CONFIG_FEC_L2SWITCH)
      mx28evk_init_pin_group(mx28evk_eth_pins,
          ARRAY_SIZE(mx28evk_eth_pins));
    #endif
    }
    
  • Add new android configuration file for i.MX28
Here we add new configuration file in “kernel-imx/arch/arm/configs/imx28evk_android_defconfig”.
We just copy imx28evk_defconfig as template, add some definition which Android need. Below is roughly setting, some of them may not need, you may try to remove it base on your situation.
CONFIG_ASHMEM=y
CONFIG_WAKELOCK=y
CONFIG_WAKELOCK_STAT=y
CONFIG_USER_WAKELOCK=y
CONFIG_EARLYSUSPEND=y
CONFIG_FB_EARLYSUSPEND=y
CONFIG_APM_EMULATION=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_DEVMEM=y
#
# Android
#
CONFIG_ANDROID_PMEM=y
CONFIG_PMEM_SIZE=24
CONFIG_LOW_MEMORY_KILLER=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_ANDROID_LOGGER=y
CONFIG_ANDROID_RAM_CONSOLE=y
CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE=y
CONFIG_ANDROID_TIMED_OUTPUT=y
CONFIG_ANDROID_TIMED_GPIO=y
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
  • Build uImage
    $ cd kernel-imx
    $ make imx28evk_android_defconfig
    $ make uImage –j4
    
    We get uImage in “kernel/arch/arm/boot/”

    5. Build Android rootfs

    As customer’s requirement, they need Android R2.1, so we choose Android R8.1 for them. Android R8.1 doesn’t contains i.MX28 setting, for quickly reason, we choose i.MX51_3stack setting for customer.
  • Modification in “vendor/fsl/imx51_3stack/BoardConfig.mk”
    flash we use is Samsung MLC, page size 2048 bytes, 128 pages per block, block size 256KB.
    TARGET_MKUBIFS_ARGS := -m 2048 -e 258048 -c 1200 -x none
    TARGET_MKUBIFS_ARGS_RECOVERY := -m 2048 -e 258048 -c 100 -x none
    TARGET_UBIRAW_ARGS := -m 2048 -p 256KiB $(PRODUCT_OUT)/ubinize.ini
    TARGET_UBIRAW_RECO_ARGS := -m 2048 -p 256KiB $(PRODUCT_OUT)/ubinize_reco.ini
    
    Parameter setting:
        -m  one page size
        -p  one block size
        -e   one block size – two pages size. (256K- 2Kx2 =252K= 258048 Bytes)
        -c   block counts
    
  • Modification in “vendor/fsl/imx51_3stack/init.rc”
    Remove all unnecessary part, only keep minus setting which guarantee enter Android console.
    # below setting was removed for i.MX28 support
    -    export BACKLIGHT_PATH /sys/class/backlight/mxc_mc13892_bl.0/brightness
    -    export MAX_BACKLIGHT_PATH "/sys/class/backlight/mxc_mc13892_bl.0/max_brightness"
    -    export LIGHTSENSOR_PATH /sys/class/i2c-adapter/i2c-3/3-0044
    -    export VPU_SHM_PATH /sqlite_stmt_journals
    -    export VPU_FW_PATH /system/etc/vpu/vpu_fw
    -    export GST_PLUGIN_PATH /system/lib/gst_plugins
    -    chmod 0777 /dev/mxc_vpu
    -    chmod 0777 /dev/mxc_iim
    -    symlink /dev/mxc_iim /dev/mxc_mem
    -    exec /sbin/ts_calibrator
    -# Define fsl avi/aac/asf/rm/flv format support
    -   setprop ro.FSL_AVI_PARSER 0
    -   setprop ro.FSL_AAC_PARSER 0
    -   setprop ro.FSL_ASF_PARSER 0
    -   setprop ro.FSL_RMVB_PARSER 0
    -   setprop ro.FSL_FLV_PARSER 0
    -   setprop ro.FSL_MKV_PARSER 0
    -
    -# Define fsl display init mode
    -   setprop ro.FSL_LANDSCAPE_MODE 0
    -
    -# Define 3D acceleration property
    - setprop debug.sf.software_backend 1
    - setprop debug.sf.enable_hgl 1
    -
    -# Define fsl xec mode
    -    setprop xec.dls.enabled 1
    -    setprop xec.aa.enabled 1
    -    setprop xec.dls.rate 0
    -    setprop xec.aa.rate 100
    -
    -# Define fsl dvfs property
    -    setprop ro.dvfs.enabled 1
    -
    -# Define UI to TVOUT,change this setting to 1 and uncomment below write commands
    -    setprop ro.UI_TVOUT_DISPLAY 0
    -    #write /sys/class/graphics/fb0/blank 1
    -    #write /sys/class/graphics/fb1/blank 1
    -    #write /sys/class/graphics/fb2/blank 1
    -    #write /sys/class/graphics/fb0/fsl_disp_property 1-layer-fb
    -    #write /sys/class/graphics/fb1/mode U:720x480i-60
    -    #write /sys/class/graphics/fb1/blank 0
    -
    -# Prepare for wifi
    -#
    -    setprop wifi.interface wlan0
    -#    mkdir /data/misc/wifi 0770 system system
    -    mkdir /data/misc/wifi/sockets 0770 wifi wifi
    -    mkdir /data/misc/dhcp 0770 dhcp dhcp
    -    chown dhcp dhcp /data/misc/dhcp
    -
    -# Prepare for bluetooth
    -    chmod 666 /sys/class/rfkill/rfkill0/state
    -    chown bluetooth bluetooth /sys/class/rfkill/rfkill0/state
    -    write /sys/class/rfkill/rfkill0/state 0
    -
    -service servicemanager /system/bin/servicemanager
    -    user system
    -    critical
    -    onrestart restart zygote
    -    onrestart restart media
    -service vold /system/bin/vold
    -    socket vold stream 0660 root mount
    -service nexus /system/bin/nexus
    -    socket nexus stream 0660 root system
    -    disabled
    -#service ril-daemon /system/bin/rild -l /system/lib/libreference-ril.so -- -d /dev/ttymxc2 -u /dev/ttyUSB0
    -service ril-daemon /system/bin/rild -l /system/lib/libreference-ril.so -- -d /dev/ttyUSB3 -u /dev/ttyUSB0
    -    socket rild stream 660 root radio
    -    socket rild-debug stream 660 radio system
    -    user root
    -    group radio cache inet misc
    -
    -service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    -    socket zygote stream 666
    -    onrestart write /sys/android_power/request_state wake
    -    onrestart write /sys/power/state on
    -service media /system/bin/mediaserver
    -    user media
    -    group system audio camera graphics inet net_bt net_bt_admin
    -service bootanim /system/bin/bootanimation
    -    user graphics
    -    group graphics
    -    disabled
    -    oneshot
    -service dbus /system/bin/dbus-daemon --system --nofork
    -    socket dbus stream 660 bluetooth bluetooth
    -    user bluetooth
    -    group bluetooth net_bt_admin
    -service bluetoothd /system/bin/bluetoothd -n
    -    socket bluetooth stream 660 bluetooth bluetooth
    -    socket dbus_bluetooth stream 660 bluetooth bluetooth
    -    group bluetooth net_bt_admin misc
    -    disabled
    -
    -service hciattach /system/bin/logwrapper /system/bin/sh /system/etc/bluez/mxc_bt.sh
    -    user bluetooth
    -    group bluetooth net_bt_admin
    -    disabled
    -    oneshot
    -service hfag /system/bin/sdptool add --channel=10 HFAG
    -    user bluetooth
    -    group bluetooth net_bt_admin
    -    disabled
    -    oneshot
    -service hsag /system/bin/sdptool add --channel=11 HSAG
    -    user bluetooth
    -    group bluetooth net_bt_admin
    -    disabled
    -    oneshot
    -service installd /system/bin/installd
    -    socket installd stream 600 system system
    -service racoon /system/bin/racoon
    -    socket racoon stream 600 system system
    -    group net_admin keystore
    -    disabled
    -    oneshot
    -service mtpd /system/bin/mtpd
    -    socket mtpd stream 600 system system
    -    user vpn
    -    group vpn net_admin net_raw
    -    disabled
    -    oneshot
    -service keystore /system/bin/keystore /data/misc/keystore
    -    user keystore
    -    group keystore
    -    socket keystore stream 666
    -service wpa_supplicant /system/bin/logwrapper /system/bin/wpa_supplicant \
    -    -Dwext -iwlan0 -c/data/misc/wifi/wpa_supplicant.conf
    -    user root
    -    group wifi inet system
    -    socket wpa_wlan0 dgram 660 system system
    -    oneshot
    -
    -service pppd_gprs /etc/init.gprs-pppd
    -    user root
    -    group radio cache inet misc
    -    disabled
    -    oneshot
    -service glgpsd /system/bin/glgps -c /etc/glconfig.xml normal
    -    user root
    -    group system
    -    disabled
    -#install z430 GPU kernel module
    -service gpu_z430 /etc/init.GPU_z430.sh
    -    user root
    -    group system
    -    oneshot
    
    
    ## Below setting was modified or added
    -# Prepare for RIL
    -    setprop gsm.ril.delay 15
    +    write /sys/bus/platform/drivers/fsl-ehci/fsl-ehci.1/power/wakeup enabled
    -service dhcpcd /system/bin/logwrapper /system/bin/dhcpcd -d -B wlan0
    +service dumpstate /system/bin/dumpstate -s
    +    socket dumpstate stream 0660 shell log
    -    chmod 0660 /sys/class/backlight/mxc_mc13892_bl.0/brightness
    +    chmod 0660 /sys/class/backlight/pwm-backlight/brightness
    -    chown system system /sys/class/backlight/mxc_mc13892_bl.0/brightness
    +    chown system system /sys/class/backlight/pwm-backlight/brightness
    # Set timeout value for rmnet stats.
         write /sys/devices/virtual/net/rmnet0/timeout_suspend 5000000
     +    setprop dalvik.vm.checkjni false
    +
    
  • Build rootfs
    $ make PRODUCT-imx51_3stack-eng
    
    After building done, we get “android_root.img, android_recovery.img, ramdisk.img” in directory “out/target/product/imx51_3stack”
  • Generate uramdisk.img
    $ cd out/target/product/imx51_3stack
    $ mkimage –A arm –O linux –T ramdisk –C none –a 0x40308000 –n “Android Root Filesystem” –d ramdisk.img uramdisk.img
    

    6. Download image into i.MX28 Nand flash.

  • Prepare image into MFT tool directory
    Copy “imx-uboot.sb, uImage, uramdisk.img, android_recovery.img and android_root.img” to MFG tool directory “Profiles\MX28 Linux Update\OS Firmware\files”
  • Modification in “Profiles\MX28 Linux Update\OS Firmware\ucl.xml”
MFT tool default ucl.xml doesn’t support download android image to Nand flash, we need add it.
In section “
Add below code.
"push" body="mknod class/mtd,mtd0,/dev/mtd0"/>
"push" body="mknod class/mtd,mtd1,/dev/mtd1"/>
"push" body="mknod class/misc,ubi_ctrl,/dev/ubi_ctrl"/>
"push" body="mknod block,mtdblock0,/dev/mtdblock0,block"/>
"push" body="mknod block,mtdblock1,/dev/mtdblock1,block"/>
"push" body="$ flash_eraseall /dev/mtd0">Erasing rootfs partition0
"push" body="$ flash_eraseall /dev/mtd1">Erasing rootfs partition1
"push" body="send" file="files/imx_uboot.sb">Sending uboot
"push" body="$ kobs-ng init $FILE">Flashing firmware

"push" body="send" file="files/uImage">Sending uImage
"push" body="$ nandwrite -p /dev/mtd0 -s 0x300000 $FILE">Programming Android uImage

"push" body="send" file="files/uramdisk.img">Sending uramdisk.img
"push" body="$ nandwrite -p /dev/mtd0 -s 0x600000 $FILE">Programming Android uramdisk

"push" body="pipe nandwrite -p /dev/mtd1 -s 0x800000" file="files/android_root.img">Programming Android Root Partition
"push" body="frf">Finishing Rootfs partition

"push" body="$ echo Update Complete!">Done
For image file android_root.img, it is too large, we need use “pipe” to download into Nand flash, and as we talked before, we store it in secondary partition.
  • Download image to Nand flash
    Connect i.MX28 EVK rev C board to Windows via USB cable by pressing “RECOVERY” key, and rund MFT tool, MFT will recognize HID device and ready. Click “Start” button at right bottom of MFT window, Image will be downloaded into i.MX28 Nand flash.

7. Run Android.

Disconnect from PC, set i.MX28 EVK rev C board boot mode as Nand boot, reset, we can see uboot start up, and then load uImage and uramdisk.img, and then Android rootfs beed loaded. Now we enter Android world.

2 comments:

Bina Software Solutions said...

hi
can android run on imx28 evk from sd card?
thanks
liran

Unknown said...

Hi Liran,
Sure it definitely possible to run from SD card.
Thanks.
Mark