CI20 Dev Zone

Revision as of 10:38, 13 December 2017 by Crlarsen (talk | contribs) (Change outline indentation.)
Jump to: navigation, search

Everybody is welcome, and encouraged, to contribute back to the CI20 community, no matter how big or small their contribution is.

Contributions can come as small as a bug report, to some distro or Linux kernel work, to placing a whole new OS or distro on the board.

There are a number of ways to contribute, and a number of channels to help you along.

Source Code

The Linux kernel and U-Boot sources for the CI20 are publically available on github.

Linux Kernel

The CI20 kernel source code is available on github.

There are presently two versions of the kernel

  • the ci20-v3.0.8 kernel branch as shipped by default in the Debian NAND image derived directly from the Ingenic kernel source code releases.
  • the latest kernel branch (ci20-v3.18 as of 02-03-2014) tracking mainline which is a nearly complete work in progress of upstreamable quality code to be soon pushed towards See details about this branch here CI20_upstream

Patches for the CI20 kernel and U-Boot should be submitted to the CI20 development mailing list.

Once the CI20 code is accepted into upstream repositories and mainline then patches should go via the appropriate upstream mailing lists and maintainers as suggested by ./scripts/


The CI20 U-Boot source is available on github

The ci20-v2013.10 branch of U-BOOT is the one shipped in the factory NAND image.

Bug reports

Bug reports for the CI20 are being taken via the github issue tracker linked to the CI20 kernel git repositories.

For linux kernel

For U-Boot

Mailing lists and Forum

The CI20 has user & development mailing lists/forums via google groups

List name Description Forum link Subscribe via web Subscribe via email Feed
mips-creator-ci20 For general discussion & support Forum Subscribe Subscribe via email Atom
mips-creator-ci20-dev For submission & review of patches Forum Subscribe Subscribe via email Atom


CI20 also has an IRC channel #ci20 on

NAND Flashing SD card

The NAND Flashing SD image creates an SD card that boots via MMC and writes the NAND of the CI20.

This can be used to restore the NAND on your CI20 to the factory default state, or upgrade the NAND image to a newer factory image file.

Note: Any changes you have made to your NAND (installed programs etc) will be irrecoverably lost during the NAND flash process.

Note: Whilst the NAND flashing process is occurring, it is possible to connect to the serial port and see progress output.


1. Open a terminal

2. To determine the device name of the SD card, run lsblk which will list all block devices. Then insert the SD card, wait a few seconds, and run lsblk again. A new device plus any partitions should have appeared compared to the original list, the SD card will be the new top level device. Be sure that you have the right device name!

3. Unmount all partitions on the SD card. If the device name were sdx, this would be done with:

umount /dev/sdx*

4. Write the image file with the following (replacing sdx with the correct device name):

dd if=debian7_2015_02_02.img of=/dev/sdx bs=8M

5. When it completes (note that dd will give no progress indication), run:


6. Remove the SD card.

7. Put SD card in CI20.

8. Check the boot_sel switch is on the MMC boot mode.

9. Boot and wait (~10 minutes) for the LED to go from red to blue (NAND writing) and then red!

10. The NAND has been flashed to factory default state. Power off the board. Remove the SD card. change the boot_sel switch to NAND boot mode. And boot the board.

Mac OS X

1. Open a terminal (/Applications/Utilities/

2. Plug the SD card into your Macintosh. List the block devices on your system by running:

diskutil list

3. Using diskutil's output, Identify the device name for the SD card by finding the entry which matches your SD card's partition name and size. The device name is of the form /dev/diskX, where X is some number. Make sure you've got the right one before continuing!

4. Unmount the mounted partitions on the SD card:

diskutil unmountDisk /dev/diskX

5. Write the new image to the SD card (it might take a while to finish):

sudo dd if=debian6-20130815.img of=/dev/diskX bs=8m

6. When it completes (note that dd will give no progress indication), run:


7. Remove the SD card.

8. Put SD card in CI20.

9. Check the boot_sel switch is on the MMC boot mode.

10. Boot and wait (~10 minutes) for the LED to go from red to blue (NANDwriting) and then red!

11. The NAND has been flashed to factory default state. Power off the board. Remove the SD card. change the boot_sel switch to NAND boot mode. And boot the board.


1. Download and run Win32DiskImager:

2. Insert the SD card, and select the image file and the drive letter for the SD card in Win32DiskImager. Win32DiskImager may not be able to see built-in SD card slots, so if it doesn't show up, use a USB adapter instead.

4. Click Write and wait for it to complete.

5. Close the imager and then remove the SD card.

6. Put SD card in CI20.

7. Check the boot_sel switch is on the MMC boot mode.

8. Boot and wait (~10 minutes) for the LED to go from red to blue (NAND writing) and then red!

9. The NAND has been flashed to factory default state. Power off the board. Remove the SD card. change the boot_sel switch to NAND boot mode. And boot the board.


For cross-compiling code on your desktop, to build the Kernel or U-Boot from sources you will need a MIPS toolchain and u-boot-tools for mkimage

For the toolchain, you can use the one from Imagination or Mentor (for u-boot, use the mentor one)

Default Debian stretch compiler

  $ sudo apt-get install crossbuild-essential-mipsel

Imagination Technologies Codescape MIPS SDK

Look for the ones labelled MTI GNU Linux. These are for mips32r2 on the jz4780.

Mentor Sourcery CodeBench Lite 2013.11-36

For compiling u-boot, please use this. u-boot first stage spl has a size limitation.
And this toolchain manages to generate a binary that is just within the limit.

The Getting Started guide on the link above explains the install process

Little Endian switch

Note: By default, the toolchain compiles programs for big endian configuration. The JZ4780 on the CI20 is little endian. When compiling programs, do pass -EL so the binary is little endian.

mips-linux-gnu-gcc -EL helloworld.c -o helloworldapp

or directly

mipsel-linux-gnu-gcc helloworld.c -o helloworldapp

Building uboot from sources

For u-boot-tools and mkimage run,

sudo apt-get install u-boot-tools

Clone the U-Boot repositories from github. For U-Boot,

To build U-Boot:

git checkout ci20-v2013.10
make ARCH=mips CROSS_COMPILE=mips-linux-gnu- ci20_mmc
make ARCH=mips CROSS_COMPILE=mips-linux-gnu-

Note, the CROSS_COMPILE for the toolchain path must be set in your environment. This could be mipsel when using Debian default cross compiler:

make ARCH=mips CROSS_COMPILE=mipsel-linux-gnu- ci20_mmc
make ARCH=mips CROSS_COMPILE=mipsel-linux-gnu-

This will generate 2 files, spl/u-boot-spl.bin and u-boot.img. We will use them in the next sections.

Building Linux Kernel from sources

For the Linux kernel, there are 2 branches that you can use:

  • ci20-v3.0.8: Default 3.0.8 kernel. All hardware supported.
  • ci20-v3.xx: the latest kernel branch (3.18) tracking mainline which is a nearly complete work in progress of upstreamable quality code to be soon pushed towards For details on driver support, check the github branch readme page and the wiki.

Note: various other branches might have wip-updates.

Clone the repository from github. To build the kernel for 3.0.8 (change branch name accordingly):

git checkout ci20-v3.0.8
make ARCH=mips ci20_defconfig
make ARCH=mips CROSS_COMPILE=mips-linux-gnu- uImage

Adjust CROSS_COMPILE with the toolchain path if it isn't in your $PATH. You can also set it in your environment.

This will give you a uImage for the kernel (arch/mips/boot/uImage for 3.15 onwards, arch/mips/boot/compressed/uImage for 3.0.8).

Building Linux Kernel Modules from sources

You'll also need to compile kernel modules that match your newly compiled kernel. From within your kernel source directoy, run:

 make ARCH=mips CROSS_COMPILE=mips-linux-gnu- modules
 make ARCH=mips INSTALL_MOD_PATH=mods modules_install

Keep the generated directory handy as you'll need to copy it into your rootfs.

Building GPU Kernel Module from sources

The GPU driver relies on an out of tree kernel module. The kernel module has to be recompiled when you recompile the kernel. For more details and instructions visit CI20-SGX kernel module

Building Android Image from sources

The latest Android SD image was built with the tag ci20-ng-7.1.2_r17.m1.xml on github.

To download the new tag from github and build the system image:

mkdir OREO && cd OREO
repo init -u git:// -b dev-mips-nougat-mr2 -m mips-oreo-8.0.0_r4.m1.xml
repo sync
export TOP=`pwd`
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64

When building there are several different architecture variants which can be chosen.

To build for various emulators:

Build the mips32r5 system image

export TARGET_ARCH_VARIANT=mips32r5
source build/ && lunch aosp_mips-eng

Build the mips32r6 system image

export TARGET_ARCH_VARIANT=mips32r6
source build/ && lunch aosp_mips-eng

Build the mips64r6 system image

export TARGET_ARCH_VARIANT=mips64r6
source build/ && lunch aosp_mips64-eng

Build the mips32[r2][dsp|dspr2]-fp system image

# mips32r1 support
export TARGET_ARCH_VARIANT=mips32-fp
source build/ && lunch aosp_mips-eng
# mips32r2 support
export TARGET_ARCH_VARIANT=mips32r2-fp
source build/ && lunch aosp_mips-eng
# mips32r2 + dspr1 support
export TARGET_ARCH_VARIANT=mips32r2dsp-fp
source build/ && lunch aosp_mips-eng
# mips32r2 + dspr2 support
export TARGET_ARCH_VARIANT=mips32r2dspr2-fp
source build/ && lunch aosp_mips-eng

After choosing which emulator variant you use to use run make, and when make has completed successfully, launch the emulator:

make -j<N>
emulator -show-kernel -gpu on

Build for CI-20

source build/
lunch aosp_ci20-userdebug

Building the system images for boot from sdcard (ext4)

export WITH_EXT4=true
make -j<N>

To install the Android image onto an SD card:

# Now insert the sdcard into a card reader and identify how was it registered using lsblk command.
cd device/imgtec/ci20/sdcardinstaller
# Where X is replaced with the correct letter for the SD device on your Linux build system.
# unmount any partition which got automounted:
sudo umount /dev/sdX*
sudo dd if=/dev/zero of=/dev/sdX bs=512 count=1
# Now burn the images onto sdcard
device/imgtec/ci20/sdcardinstaller/mksdcard /dev/sdX

Booting the board from sdcard

  • Set the JP3 jumper into 2-3 position on the CI20 board
  • Insert the sdcard into the slot and power up the board

The first boot takes a little bit longer, but if everything goes well, you should see the Android homescreen.

Building the system images for boot from NAND

make -j<N>
# Now insert the sdcard into a card reader and identify how was it registered using lsblk command.
# unmount any partition which got automounted:
sudo umount /dev/sdX
# Now burn the images onto sdcard
CROSS_COMPILE=mips64el-linux-android- device/imgtec/ci20/sdcardinstaller/mksdcard /dev/sdX

Booting the board from NAND

  • Set the JP3 jumper into 2-3 position on the CI20 board
  • Insert the sdcard into the slot and power up the board
  • The indicator led should turn blue and stay blue during the NAND flashing process
  • After flashing process is finished, indicator led will go back to red
  • Set the JP3 jumber into 1-2 position on the CI20 board
  • Reboot the board.

The first boot takes a little bit longer, but if everything goes well, you should see the Android homescreen.

Making a bootable SD card from sources

To make a bootable SD card, first partition your card with an MBR such that the first partition starts at an offset of no less than 270KB. This is illustrated in the following steps (Note: it is assumed that you're running these commands as root):

Ensure you know which device your SD card is, run the following command to find it:


Note: The following example considers the SD card writer to be loaded on /dev/sdx

This command will partition your SD card (You must be certain you know which device your SD card is).

sudo sfdisk /dev/sdx -uM -L << EOF

Pay attention that some version of sfdisk have deprecated the option -u, in which case you need to run instead:

sudo sfdisk /dev/sdx -L << EOF

Then create an ext4 partition using

sudo mkfs.ext4 /dev/sdx1

Pay attention that with newer mkfs.ext4 you may want to specify:

sudo mkfs.ext4 -O^64bit /dev/sdx1

Then delete the old U-Boot environment variables in the SD card, install U-Boot SPL and the full U-Boot image to the card like:

dd if=/dev/zero of=/dev/sdx bs=1K seek=526 count=32
dd if=spl/u-boot-spl.bin of=/dev/sdx obs=512 seek=1
dd if=u-boot.img of=/dev/sdx obs=1K seek=14

Mount the partition using

mount /dev/sdx1 /mnt

Then copy your kernel image and kernel modules to the ext4-formatted partition.

cp /path_to_uImage /mnt/boot/vmlinux.img
cp -r /path_to_modules/* /mnt/

Unmount the SD card

umount /mnt

At this point, the board will boot with U-BOOT and the kernel, but it will panic without a filesystem - you still need a rootfs.

You can use any existing tarball for a rootfs and extract it in the ext4 partition of the SD card, or you can use buildroot.

The following script implements these steps.

make flash card
Note on previous U-BOOT environment saved on SD card

If you follow the steps above again on an SD card on which you had already installed U-BOOT previously, you might note that the environment variables from your previous installation are already there.

The environment data for SD cards is 32KiB in size & starts 526KiB into the card (which leaves 512KiB for u-boot.img).

If you want to clear your environment when writing your card then just run dd an extra time something like this:

dd if=/dev/zero of=/dev/sdx bs=1K seek=526 count=32

Or if you want to reset to the default environment from the U-Boot shell you can run the following at the U-Boot prompt:

 env default -a
 env save

Using Buildroot

Buildroot is a small rootfs which can be easily loaded to the ram and runs from there. Note, if the filesystem is built as a ramdisk, no configuration is saved if rebooted.

We can use buildroot to build a ramdisk.

git clone git:// buildroot
cd buildroot
make qemu_mipsel_malta_defconfig
make menuconfig

The malta_defconfig is a good basic start and boots on the ci20.

Enable the following options in buildroot

Toolchain -->
    Toolchain type -->
        External toolchain
        (download or select path of your preinstalled toolchain)
Filesystem images -->
    cpio the root filesystem
 Kernel -->
    <Disable the Linux kernel option. We built our own>

Exit and Save the configuration.


Once the build has finished, you should have an


file. Lets ignore it for now

To build the kernel with the Ramdisk, in the kernel sources directory, after the previous kernel compile instructions have been carried out.

make ARCH=mips CROSS_COMPILE=mips-linux-gnu- menuconfig
General setup -->
    Initial RAM filesystem and RAM disk (initramfs/initrd) support -->
        (/path_to_buildroot/arch/mips/boot/rootfs.cpio) Initramfs source files(s)
    Support initial ramdisks compressed using gzip
    Built-in initramfs compression mode -->

Save and Exit.

make ARCH=mips CROSS_COMPILE=mips-linux-gnu- uImage

This will generate a uImage with the ramfs. The file should be larger than the usual 3-4mb kernel as it has a ramdisk built in.

Copy the uImage file to the SD card in the /boot/vmlinux.img

Boot the board and enjoy :)

Loading the Linux Kernel over ethernet via TFTP

First, set up a TFTP server by using the following link:

Copy the kernel image to the root of the TFTP server and then boot the board with serial console.

Stop the auto boot during U-Boot and then run:

dhcp 0x88000000 <server IP>:uImage
bootm 0x88000000

You can set the bootcmd environment variable and save it to the SD card so that you will not need to type these commands each boot. For example:

setenv bootcmd dhcp 0x88000000 <server IP>:uImage\; bootm 0x88000000

This will configure automatic booting over TFTP.

Note: the backslash before the semicolon is important.

How to make your own rootfs

Articles describing how to generate your own rootfs can be found in the CI20 Rootfs Guides Category.

Guidelines on booting via NFS filesystem

Set up a rootfs in your NFS export directory. Here is a short version of how to do that

Do not set up the rootfs in a subdirectory. Add the following in /etc/export


Modify the IP depending on your network configuration

Restart the service

service nfs-kernel-server restart

You can use the rootfs tarball generated using How_to_make_a_buildroot_rootfs_for_MIPS_CI20.

Make sure permissions of your /export directory are 777.

Extract the tarball into /export using

tar -xapf rootfs.tar -C /export

In order to get NFS support in the kernel, recompile the 3.0.8 kernel with the following options enabled.


If using 3.16, enable the following as well as they are not enabled by default in the 3.16 config.


These compile DHCP support and external memory controller support (via which the ethernet chip is connected) into the kernel so the kernel can assign an IP to eth0 during boot.

Boot the new kernel with the following bootargs

bootargs=console=ttyS4,115200 mem=256M@0x0 mem=768M@0x30000000 root=/dev/nfs nfsroot=192.168.XX.XX:/export ip=dhcp devtmpfs.mount=1 rw

Configure ttyS4/0 depending on your setup.

Configure your IP settings depending on your host system.

Note: ip=dhcp can be replaced with an ip=192.168.YY.YY depending on your setup. A static IP can be assigned if DHCP is unavailable.

If you have TFTP setup for transferring a kernel image, you can do the following:

Boot the Ci20 and stop it via serial during U-BOOT.

dhcp 0x88000000 192.168.XX.XX:uImage;
setenv bootargs console=ttyS4,115200 mem=256M@0x0 mem=768M@0x30000000 root=/dev/nfs nfsroot= ip=dhcp devtmpfs.mount=1 rw
bootm 0x88000000;

Your board should boot into whichever rootfs you assigned.

Note: NFS can be difficult to initially setup. If the kernel fails to mount NFS, it could be missing NFS support or a bad export on the server side.

You can check your export to see if it is ok using

mount -t nfs localhost:/export tempdir

You can also use the init=/bin/sh option in the bootargs if something is suspect during init.

Fastboot usage (when you already have fastboot capable U-boot installed on the system):

Fastboot functionality does not behave similarly on UBIFS and EXT4 set-ups. Important differences are related to cache.img, system.img and userdata.img flashing.

UBIFS cache.img and userdata.img may be cleared simply by running command "fastboot erase <partition>", while this is not functional for EXT4. Under EXT4 system set-up generated cache.img and userdata.img have to be flashed instead of being erased, with the command "fastboot flash <partition>". Even though the approach is different, the final result is the same.

And the difference regarding the system.img comes from the fact that UBIFS system image is not in the UBIFS format right after the build. It is being converted when running scripts sdcardinstaller/mksdcard and sdcardinstaller/ Although it can be converted directly by using script sdcardinstaller/convert_extfs_to_ubifs. The result of this is the inability of using command "fastboot flashall", since it internally uses command "fastboot flash system", which would refer to system.img which is in EXT4 format. Instead of this command "fastboot $device_id_option flash system ${OUT}/system.ubifs.img" has to be used.

To bring the device in fastboot mode, run the following command once the Android enables adb connection:

   $ adb reboot-bootloader

For flashing images on UBIFS system set-up, use the following commands:

   $ fastboot erase cache
   $ fastboot erase userdata
   $ fastboot flash boot
   $ fastboot flash recovery
   $ fastboot flash system ${OUT}/system.ubifs.img
   $ fastboot reboot

For flashing images on EXT4/F2FS system set-up, use the following commands:

   $ fastboot flash cache
   $ fastboot flash userdata
   $ fastboot flashall

Since the above procedure is error prone, a script has been written to simplify things

When you have only one device connected to the PC using OTG cable, just run: device/imgtec/ci20/sdcardinstaller/fastboot-flash-all

If you have multiple boards connected to the PC, you need to specify which board should be flashed using its serial ID. device/imgtec/ci20/sdcardinstaller/fastboot-flash-all <CI20_ADB_SERIAL_ID>

Once the script finishes the flashing process, it will try to boot android as a last step.