U-Boot for the iMX233-OLinuXino

Get U-Boot

[chris@thinkpad OLinuXino]$ git clone git://git.denx.de/u-boot.git u-boot.git
Cloning into 'u-boot.git'...
remote: Counting objects: 200191, done.
remote: Compressing objects: 100% (37411/37411), done.
remote: Total 200191 (delta 161097), reused 198842 (delta 159910)
Receiving objects: 100% (200191/200191), 50.43 MiB | 2.17 MiB/s, done.
Resolving deltas: 100% (161097/161097), done.
[chris@thinkpad OLinuXino]$ cd u-boot.git/
[chris@thinkpad u-boot.git]$ git checkout v2013.07 -b tmp
Switched to a new branch 'tmp'
[chris@thinkpad u-boot.git]$

Note

If you have already built another version of U-Boot then you may need to start with a cleanup:

[chris@thinkpad u-boot.git]$ git checkout master
error: Your local changes to the following files would be overwritten by checkout:
        arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c
Please, commit your changes or stash them before you can switch branches.
Aborting
[chris@thinkpad u-boot.git]$ git reset --hard HEAD
HEAD is now at d10f68a Prepare v2013.04
[chris@thinkpad u-boot.git]$ git checkout master
Switched to branch 'master'
[chris@thinkpad u-boot.git]$ git reset --hard HEAD
HEAD is now at 7315cfd NET: Fix system hanging if NET device is not installed
[chris@thinkpad u-boot.git]$ git clean -fd
Removing spl/arch/
Removing spl/board/
Removing spl/common/
Removing spl/drivers/
Removing spl/lib/
Removing spl/spl/
[chris@thinkpad u-boot.git]$ git checkout v2013.04 -b tmp
fatal: A branch named 'tmp' already exists.
[chris@thinkpad u-boot.git]$ git branch -D tmp
Deleted branch tmp (was d10f68a).
[chris@thinkpad u-boot.git]$ git checkout v2013.04 -b tmp
Switched to a new branch 'tmp'
[chris@thinkpad u-boot.git]$ ls *.patch
0001-mx23_olinuxino-uEnv.txt-bootz-n-fixes.patch  0001-mx23-Put-back-RAM-voltage-level-to-its-original-valu.patch
[chris@thinkpad u-boot.git]$ rm *.patch
[chris@thinkpad u-boot.git]$

Now we will need to apply some patches:

[chris@thinkpad u-boot.git]$ wget -c https://raw.github.com/eewiki/u-boot-patches/master/v2013.07/0001-mx23_olinuxino-uEnv.txt-bootz-n-fixes.patch
[chris@thinkpad u-boot.git]$ patch -p1 < 0001-mx23_olinuxino-uEnv.txt-bootz-n-fixes.patch
patching file include/configs/mx23_olinuxino.h
[chris@thinkpad u-boot.git]$

You will find additional patches under: https://github.com/archlinuxarm/PKGBUILDs/tree/master/alarm/uboot-olinuxino and https://github.com/eewiki/u-boot-patches, decide based on the commit message and the changes whether the patches could be useful.

To debug your OLinuXiono via SJTAG you will need to apply the following patch (have a look at the comments below this blog post, thanks Rouming!):

[chris@thinkpad u-boot.git]$ wget http://www.jann.cc/_downloads/serial_jtag_activation_for_u-boot.patch
[chris@thinkpad u-boot.git]$ patch -p1 < serial_jtag_activation_for_u-boot.patch
patching file arch/arm/cpu/arm926ejs/mxs/spl_power_init.c
Hunk #1 succeeded at 923 (offset 28 lines).
patching file arch/arm/include/asm/arch-mxs/regs-digctl.h
[chris@thinkpad u-boot.git]$

Build U-Boot

Build Prerequisites

To build U-Boot you will need a ARM bare metal cross-compiler, I’m using the cross compiler from Launchpad:

[chris@thinkpad local]$ wget https://launchpad.net/gcc-arm-embedded/4.7/4.7-2013-q1-update/+download/gcc-arm-none-eabi-4_7-2013q1-20130313-linux.tar.bz2
[chris@thinkpad local]$ tar -xjf gcc-arm-none-eabi-4_7-2013q1-20130313-linux.tar.bz2
[chris@thinkpad local]$ echo "export PATH=\$PATH:`pwd`/gcc-arm-none-eabi-4_7-2013q1/bin" >> ~/.bashrc
[chris@thinkpad local]$ source ~/.bashrc
[chris@thinkpad local]$ which arm-none-eabi-gcc
~/local/gcc-arm-none-eabi-4_7-2013q1/bin/arm-none-eabi-gcc
[chris@thinkpad local]$

And elftosb to create the bootstream file:

[chris@thinkpad OLinuXino]$ wget http://repository.timesys.com/buildsources/e/elftosb/elftosb-10.12.01/elftosb-10.12.01.tar.gz
[chris@thinkpad OLinuXino]$ tar -xzf elftosb-10.12.01.tar.gz
[chris@thinkpad OLinuXino]$ cd elftosb-10.12.01/
[chris@thinkpad elftosb-10.12.01]$ wget http://repository.timesys.com/buildsources/e/elftosb/elftosb-10.12.01/elftosb-10.12.01-libm.patch
[chris@thinkpad elftosb-10.12.01]$ wget http://repository.timesys.com/buildsources/e/elftosb/elftosb-10.12.01/elftosb-10.12.01-fix-header-path.patch
[chris@thinkpad elftosb-10.12.01]$ patch -p1 < elftosb-10.12.01-libm.patch
patching file makefile.rules
[chris@thinkpad elftosb-10.12.01]$ patch -p1 < elftosb-10.12.01-fix-header-path.patch
patching file common/stdafx.h
[chris@thinkpad elftosb-10.12.01]$ make
[chris@thinkpad elftosb-10.12.01]$ sudo cp bld/linux/elftosb /usr/local/bin
[chris@thinkpad elftosb-10.12.01]$ sudo ln -s /usr/local/bin/elftosb /usr/local/bin/elftosb2
[chris@thinkpad elftosb-10.12.01]$

Compile U-Boot

[chris@thinkpad elftosb-10.12.01]$ cd ..
[chris@thinkpad OLinuXino]$ cd u-boot.git/
[chris@thinkpad u-boot.git]$ make ARCH=arm CROSS_COMPILE=arm-none-eabi- distclean
Generating include/autoconf.mk.dep
Generating include/autoconf.mk
[chris@thinkpad u-boot.git]$ make ARCH=arm CROSS_COMPILE=arm-none-eabi- mx23_olinuxino_config
Configuring for mx23_olinuxino board...
[chris@thinkpad u-boot.git]$ make ARCH=arm CROSS_COMPILE=arm-none-eabi- u-boot.sb
Generating include/autoconf.mk
Generating include/autoconf.mk.dep
arm-none-eabi-gcc -DDO_DEPS_ONLY \
...
make[1]: Leaving directory `/home/chris/local/OLinuXino/u-boot.git/spl'
elftosb -zf imx23 -c /home/chris/local/OLinuXino/u-boot.git/arch/arm/cpu/arm926ejs/mxs/u-boot-imx23.bd \
                -o u-boot.sb
[chris@thinkpad u-boot.git]$

Install the U-Boot bootloader

I’m using my previously generated Arch Linux ARM image and my kernel that are already on the SD card.

First copy the bootloader to the first partition of your SD card:

[chris@thinkpad u-boot.git]$ sudo dd if=u-boot.sb of=/dev/mmcblk0p1 bs=512 seek=4
463+1 records in
463+1 records out
237376 bytes (237 kB) copied, 0.325154 s, 730 kB/s
[chris@thinkpad u-boot.git]$

I’ve uploaded my u-boot.sb here: https://sourceforge.net/projects/janncc/files/olinuxino/u-boot/

If you boot your SD card now, you will see something like this:

[chris@thinkpad ~]$ minicom oli

Welcome to minicom 2.5

OPTIONS: I18n
Compiled on Jan 14 2012, 12:40:23.
Port /dev/ttyUSB0

Press CTRL-A Z for help on special keys

HTLLCLC

U-Boot 2013.07-dirty (Sep 09 2013 - 13:07:07)

CPU:   Freescale i.MX23 rev1.4 at 454 MHz
BOOT:  SSP SD/MMC #0
DRAM:  64 MiB
MMC:   MXS MMC: 0
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   Net Initialization Skipped
No ethernet found.
Hit any key to stop autoboot:  0
mmc0 is current device
SD/MMC found on device 0
** File not found /boot/uEnv.txt **
Checking if uenvcmd is set ...
Running default loadzimage ...
** File not found /boot/zImage **
=>

You don’t have to care about *** Warning - bad CRC, using default environment, since this is not a bug but a desired feature (http://u-boot.10912.n7.nabble.com/U-Boot-Warning-bad-CRC-using-default-environment-td2572.html).

Now we need to create a configuration file for U-Boot and also copy our kernel to the /boot directory.

My SD card has the following partitions:

[chris@thinkpad ~]$ sudo fdisk -l /dev/mmcblk0

Disk /dev/mmcblk0: 3904 MB, 3904897024 bytes, 7626752 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0xdcc08fa1

        Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1            2048       67583       32768   53  OnTrack DM6 Aux3
/dev/mmcblk0p2           67584     3164159     1548288   83  Linux
/dev/mmcblk0p3         3164160     3854335      345088   82  Linux swap / Solaris
[chris@thinkpad ~]$

Mount the root partition:

[chris@thinkpad ~]$ sudo mount /dev/mmcblk0p2 /mnt/olinuxino/
[chris@thinkpad ~]$

Copy the zImage and the device tree blob .dtb file to the /boot directory:

[chris@thinkpad u-boot.git]$ cd ../imx23-olinuxino/kernel/linux-stable/
[chris@thinkpad linux-stable]$ sudo cp arch/arm/boot/zImage /mnt/olinuxino/boot/
[chris@thinkpad linux-stable]$ sudo cp arch/arm/boot/dts/imx23-olinuxino.dtb /mnt/olinuxino/boot/
[chris@thinkpad linux-stable]$

I’ve uploaded both here: https://sourceforge.net/projects/janncc/files/olinuxino/kernel/

Edit the uEnv.txt boot script:

[chris@thinkpad ~]$ sudo vim /mnt/olinuxino/boot/uEnv.txt
[chris@thinkpad ~]$ cat /mnt/olinuxino/boot/uEnv.txt
#These are the default settings for some useful u-boot variables:
#Uncomment to override...

fdt_file=/boot/imx23-olinuxino.dtb
optargs=
mmcroot=/dev/mmcblk0p2 rw
mmcrootfstype=ext4 rootwait fixrtc

[chris@thinkpad ~]$

Umount the SD card:

[chris@thinkpad ~]$ sudo umount /mnt/olinuxino
[chris@thinkpad ~]$

The first boot

[chris@thinkpad ~]$ picocom -b 115200 -d 8 -p n --send-cmd "sz -y" --receive-cmd "rz -y" /dev/ttyUSB0
picocom v1.7

port is        : /dev/ttyUSB0
flowcontrol    : none
baudrate is    : 115200
parity is      : none
databits are   : 8
escape is      : C-a
local echo is  : no
noinit is      : no
noreset is     : no
nolock is      : no
send_cmd is    : sz -y
receive_cmd is : rz -y
imap is        :
omap is        :
emap is        : crcrlf,delbs,

Terminal ready
HTLLCLC

U-Boot 2013.07-dirty (Sep 09 2013 - 13:07:07)

CPU:   Freescale i.MX23 rev1.4 at 454 MHz
BOOT:  SSP SD/MMC #0
DRAM:  64 MiB
MMC:   MXS MMC: 0
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   Net Initialization Skipped
No ethernet found.
Hit any key to stop autoboot:  0
mmc0 is current device
SD/MMC found on device 0
199 bytes read in 101 ms (1000 Bytes/s)
Importing environment from mmc (uEnv.txt)...
Checking if uenvcmd is set ...
Running default loadzimage ...
4221888 bytes read in 1353 ms (3 MiB/s)
9693 bytes read in 99 ms (94.7 KiB/s)
Booting from mmc ...
Kernel image @ 0x42000000 [ 0x000000 - 0x406bc0 ]
## Flattened Device Tree blob at 41000000
  Booting using the fdt blob at 0x41000000
  Loading Device Tree to 43b64000, end 43b695dc ... OK

Starting kernel ...

[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 3.10.11-dirty (chris@thinkpad) (gcc version 4.7.3 20130312 (release) [ARM/embedded-4_7-branch revision 196615] (GNU Tools3
[    0.000000] CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177
[    0.000000] CPU: VIVT data cache, VIVT instruction cache
[    0.000000] Machine: Freescale MXS (Device Tree), model: i.MX23 Olinuxino Low Cost Board
[    0.000000] Memory policy: ECC disabled, Data cache writeback
[    0.000000] Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 16256
[    0.000000] Kernel command line: console=ttyAMA0,115200 root=/dev/mmcblk0p2 rw rootfstype=ext4 rootwait fixrtc video=
[    0.000000] PID hash table entries: 256 (order: -2, 1024 bytes)
[    0.000000] Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
[    0.000000] Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
[    0.000000] Memory: 64MB = 64MB total
...
[  OK  ] Started Login Service.
Arch Linux 3.10.11-dirty (ttyAMA0)

olinuxino login:
[  OK  ] Started OpenNTP Daemon.

Arch Linux 3.10.11-dirty (ttyAMA0)

olinuxino login: root
Password:
Last login: Wed Dec 31 18:00:34 on ttyAMA0
[root@olinuxino ~]# uname -r
3.10.11-dirty
[root@olinuxino ~]# cat /proc/version
Linux version 3.10.11-dirty (chris@thinkpad) (gcc version 4.7.3 20130312 (release) [ARM/embedded-4_7-branch revision 196615] (GNU Tools for ARM Embedd3
[root@olinuxino ~]# reboot # reboot works too :-)

Using a uImage

This is just a test, because it was asked in the comments and it seems to work.

You should be familiar with with building a kernel before reading the steps below.

Instead of running:

[chris@thinkpad linux-stable]$ make ARCH=arm CROSS_COMPILE=arm-none-eabi- zImage modules

you will need to use the following command to build a uImage:

[chris@thinkpad linux-stable]$  make ARCH=arm CROSS_COMPILE=arm-none-eabi- uImage modules
  CHK     include/generated/uapi/linux/version.h
  CHK     include/generated/utsrelease.h
make[1]: `include/generated/mach-types.h' is up to date.
  CALL    scripts/checksyscalls.sh
  CHK     include/generated/compile.h
  CHK     kernel/config_data.h
  Kernel: arch/arm/boot/Image is ready
  Kernel: arch/arm/boot/zImage is ready
  UIMAGE  arch/arm/boot/uImage
"mkimage" command not found - U-Boot images will not be built
make[1]: *** [arch/arm/boot/uImage] Error 1
make: *** [uImage] Error 2
[chris@thinkpad linux-stable]$

O.K. we need to edit our ~/.bashrc and add the u-boot/tools directory to the PATH:

[chris@thinkpad ~]$ vim .bashrc
[chris@thinkpad ~]$ grep -i u-boot .bashrc
export PATH=$PATH:$HOME/local/OLinuXino/u-boot.git/tools/
[chris@thinkpad ~]$

Now we can try to build the uImage again:

[chris@thinkpad linux-stable]$ source ~/.bashrc
[chris@thinkpad linux-stable]$ make ARCH=arm CROSS_COMPILE=arm-none-eabi- uImage
  CHK     include/generated/uapi/linux/version.h
  CHK     include/generated/utsrelease.h
make[1]: `include/generated/mach-types.h' is up to date.
  CALL    scripts/checksyscalls.sh
  CC      scripts/mod/devicetable-offsets.s
  GEN     scripts/mod/devicetable-offsets.h
  HOSTCC  scripts/mod/file2alias.o
  HOSTLD  scripts/mod/modpost
  CHK     include/generated/compile.h
  CHK     kernel/config_data.h
  Kernel: arch/arm/boot/Image is ready
  Kernel: arch/arm/boot/zImage is ready
  UIMAGE  arch/arm/boot/uImage
Image Name:   Linux-3.9.4-dirty
Created:      Tue Jun 25 20:15:47 2013
Image Type:   ARM Linux Kernel Image (uncompressed)
Data Size:    4288184 Bytes = 4187.68 kB = 4.09 MB
Load Address: 40008000
Entry Point:  40008000
  Image arch/arm/boot/uImage is ready
[chris@thinkpad linux-stable]$

Nice, we have a uImage now we have to modify the U-Boot configuration to boot this image and copy it to the SD card. The U-Boot manual describes also other ways to load the image, like using a serial bootloader or a TFTP server but I will just copy it to my SD card.

[chris@thinkpad linux-stable]$ sudo mount /dev/mmcblk0p2 /mnt/olinuxino/
[chris@thinkpad linux-stable]$ sudo cp arch/arm/boot/uImage /mnt/olinuxino/boot/
[chris@thinkpad linux-stable]$ sudo vim /mnt/olinuxino/boot/uEnv.txt
[chris@thinkpad linux-stable]$ cat /mnt/olinuxino/boot/uEnv.txt
#These are the default settings for some useful u-boot variables:
#Uncomment to override...

#fdt_file=/boot/imx23-olinuxino.dtb
#optargs=
#mmcroot=/dev/mmcblk0p2 rw
#mmcrootfstype=ext4 rootwait fixrtc

dtb_file=imx23-olinuxino.dtb

initrd_high=0xffffffff
fdt_high=0xffffffff

mmc_load_image=load mmc 0:2 0x42000000 /boot/uImage
mmc_load_dtb=load mmc 0:2 0x41000000 /boot/${dtb_file}

mmcargs=setenv bootargs noinitrd console=ttyAMA0,115200 root=/dev/mmcblk0p2 init=/usr/lib/systemd/systemd rw rootwait ssp1=mmc

xyz_mmcboot=run mmc_load_image; run mmc_load_dtb; echo Booting from mmc ...
uenvcmd=run xyz_mmcboot; run mmcargs; bootm 0x42000000 - 0x41000000

[chris@thinkpad linux-stable]$ sudo umount /mnt/olinuxino
[chris@thinkpad linux-stable]$

I had to replace bootz with bootm (boot application image from memory), else I would get:

Booting from mmc ...
Bad Linux ARM zImage magic!
=>

Just in case someone googles this error.

And the uenvcmd gets added by the patch 0001-mx23_olinuxino-uEnv.txt-bootz-n-fixes.patch:

#define CONFIG_BOOTCOMMAND \
 - "mmc dev ${mmcdev}; if mmc rescan; then " \
 -   "if run loadbootscript; then " \
 -     "run bootscript; " \
 -   "else " \
 -     "if run loaduimage; then " \
 -       "run mmcboot; " \
 -     "else run netboot; " \
 -     "fi; " \
 -   "fi; " \
 - "else run netboot; fi"
 + "mmc dev ${mmcdev};" \
 + "if mmc rescan; then " \
 +   "echo SD/MMC found on device ${mmcdev};" \
 +   "if run loadbootenv; then " \
 +     "run importbootenv;" \
 +   "fi;" \
 +   "if test -n $uenvcmd; then " \
 +     "echo Running uenvcmd ...;" \
 +     "run uenvcmd;" \
 +   "fi;" \
 +   "if run loadzimage; then " \
 +     "run loadfdt;" \
 +     "run mmcboot;" \
 +   "fi;" \
 + "fi;"

There it gets tested ("if test -n $uenvcmd; then ") whether uenvcmd was set in uEnv.txt. Arch Linux ARM uses a similar patch but without support for booting zImages.

And it boots:

HTLLCLC

U-Boot 2013.04-dirty (Jun 26 2013 - 11:46:21)

CPU:   Freescale i.MX23 rev1.4 at 454 MHz
BOOT:  SSP SD/MMC #0
DRAM:  64 MiB
MMC:   MXS MMC: 0
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   Net Initialization Skipped
No ethernet found.
Hit any key to stop autoboot:  0
mmc0 is current device
SD/MMC found on device 0
658 bytes read in 113 ms (4.9 KiB/s)
Importing environment from mmc (uEnv.txt)...
Running uenvcmd ...
4288248 bytes read in 1397 ms (2.9 MiB/s)
8674 bytes read in 91 ms (92.8 KiB/s)
Booting from mmc ...
## Booting kernel from Legacy Image at 42000000 ...
  Image Name:   Linux-3.9.4-dirty
  Image Type:   ARM Linux Kernel Image (uncompressed)
  Data Size:    4288184 Bytes = 4.1 MiB
  Load Address: 40008000
  Entry Point:  40008000
  Verifying Checksum ... OK
## Flattened Device Tree blob at 41000000
  Booting using the fdt blob at 0x41000000
  Loading Kernel Image ... OK
OK
  Using Device Tree in place at 41000000, end 410051e1

Starting kernel ...

Uncompressing Linux... done, booting the kernel.
[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 3.9.4-dirty (chris@thinkpad) (gcc version 4.7.3 20130312 (release) [ARM/embedded-4_7-branch revision 196615] (GNU Tools f3
[    0.000000] CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177
[    0.000000] CPU: VIVT data cache, VIVT instruction cache
[    0.000000] Machine: Freescale i.MX23 (Device Tree), model: i.MX23 Olinuxino Low Cost Board