News from our smart team...

Yocto with Nitrogen6X: 5 steps only!

Apr 15, 2013

Boundary Devices Nitrogen6X board align-middle

In this text we will describe in detail how to use the Yocto project to build a system for the Boundary Device’s Nitrogen6X platform.

The Nitrogen6X platform is a development system based on Freescale’s i.MX6 processor (ARM-Cortex A-9). It provides many interesting features and connection options packed into the same board which includes a Quad-Core ARM® Cortex A9 processor at 1GHz and 1GBytes of 64-bit wide DDR3 at 532MHz.

The Yocto Project is an open source collaboration project that provides templates, tools and methods to help you create custom Linux-based systems for embedded products regardless of the hardware architecture. It was founded in 2010 as a collaboration among many hardware manufacturers, open-source operating systems vendors, and electronics companies to bring some order to the chaos of embedded Linux development. It is hosted by the Linux Foundation as an open source project providing a vendor neutral collaboration environment, and encouraging community contributions in line with the best practices of the open source development model.

The Yocto build system is a powerful framework for cross-compilation which provides tools and data to drive the build process: from source code to the generation of images to be run on the target platform. The huge recipe set is up to date and it is maintained by the members of Yocto community and vendors which provide commercial support for it.

O.S. Systems provides support for the Freescale’s community driven BSP. We’re contributing to this open-source project to help to bring rock-solid tools and software components to embedded customers using Freescale processors. The Freescale Community BSP supports, currently, 19 boards of different SoC types (i.MX23, i.MX28, i.MX31, i.MX35, i.MX51, i.MX53, i.MX6S, i.MX6SL, i.MX6Di.MX6DL and i.MX6Q) which includes the Nitrogen6X among the supported boards with its full set of features, including WIFI and Bluetooth support and accelerated GPU and VPU.

The whole process of going from source code to a final image to be run on the target platform involves a lot of steps. For example: fetching source code from the original locations, resolving dependencies among packages, extracting source archives, cross-compiling source code, deploying binaries, generating system packages etc. Each of those tasks has its own complications, which are nicely handled by Yocto.

So, enough of theory. Let’s practice! :-)

Step 1: Get the code

To start building software, we need some development tools. The Yocto project provides a handy list that we can use. You can see it at their documentation, click here.

Once all the required tools have been installed, we can proceed to install repo, a neat tool initially developed to help the development of Android. repo is a standalone Python script and it allows us to manage multiple git repositories.

Here are the steps to locally install it on our home directory:

Installing repo
1
2
3
$ mkdir $HOME/bin
$ curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > $HOME/bin/repo
$ chmod a+x $HOME/bin/repo

Now that we have repo installed, we can use it to initialize our work directory to build software with Yocto. Here are the commands to do that:

Getting source code
1
2
3
4
5
PATH=${PATH}:$HOME/bin
mkdir fsl-community-bsp
cd fsl-community-bsp
repo init -u https://github.com/Freescale/fsl-community-bsp-platform -b dylan
repo sync

The above commands download the “platform” repository, which contains a XML file that links all the repositories that will be managed by repo.

Once this has complete, we will have the following directory structure in the fsl-community-bsp directory:

  • README: contains some information about Freescale’s Community Yocto BSP (Board Support Packages).

  • setup-environment: is a shell script that performs some basic sanity checks and configures the environment to run bitbake, the tool that actually drives the build process by consuming recipes.

  • sources: directory with Yocto’s source code.

Step 2: Setup the build system

At this point we have everything we need to start the build process. So we can just run:

Environment setup
1
$ MACHINE=nitrogen6x source ./setup-environment build

One of the environment variables used by bitbake is MACHINE, which indicates the target machine we will be building for, so we set it to nitrogen6x. This instructs the build system about the machine we want to build for.

Note that we have “sourced” setup-environment instead of creating a new subshell for it. This part is important because setup-environment sets variables that must be available in the current environment, so that bitbake can use them. The first argument to setup-environment is the build directory. Bitbake will use that directory to store all the temporary files generated during the build process (source files, object files, binary packages etc).

Step 3: Build an image

Yocto provides some standard images by default, which are very useful for daily and development use. The most commonly used are:

  • core-image-minimal: A very small image usually used for kernel and bootloader development, board bring-up and basic testing of hardware

  • core-image-base: Console image providing support for most hardware of the board, not including a graphical interface. Among the supported features are audio, Bluetooth and WIFI

  • core-image-x11: Similar to core-image-base but providing a terminal emulator on a graphical environment. This allows easily testing the X11 system without a full desktop environment

  • core-image-sato: Desktop environment for more generic use and test

The Freescale Community BSP provides two additional images for demonstration and testing purposes, which are:

  • fsl-image-test: Includes core-image-base and Freescale unit-tests, Freescale hardware accelerated gstreamer plugins, Freescale hardware accelerated graphic libraries, and a complete set of test utilities

  • fsl-image-gui: Includes core-image-sato and Freescale unit-tests, Freescale hardware accelerated gstreamer plugins, Freescale hardware accelerated graphic libraries, and a complete set of test utilities

To start a build, we should call bitbake, as:

Image build
1
$ bitbake fsl-image-gui

If you look at the content of the fsl-community-bsp again, after running bitbake, you will notice that a new directory was created: downloads. That’s the directory where the downloaded source code archives are stored, so that they can be reused if you run bitbake again.

The build process is intensive in terms of CPU and disk usage. Its first run will probably take a couple of hours on a modern multicore machine. Next runs will be faster, since bitbake creates a cache of packages that it builds.

Step 4: Install the built image

After bitbake is finished, we will have our cross-compiled system files in build/tmp/deploy/images. Basically, we have files for the boot loader, system kernel, kernel modules and “rootfs” (the target system’s root filesystem).

For example, after building the fsl-image-gui image, the following files (some are actually symbolic links) in build/tmp/deploy/images are generated:

  • u-boot.imx: Boot loader

  • fsl-image-gui-nitrogen6x.sdcard: Partitions and filesystem

  • uImage-nitrogen6x.bin: Kernel

  • modules--3.0.35-r36.12-nitrogen6x-20xxxxxxxxxxxx.tgz: Kernel modules

All you need to get your system image running is fsl-image-gui-nitrogen6x.sdcard. You can just write it the an SD card using dd from the build directory, for example:

Writing image to the SD card
1
$ dd if=tmp/deploy/images/fsl-image-gui-nitrogen6x.sdcard of=/dev/<SD device> bs=4M

The <SD device> is something like sdb, sdc etc (check the dmesg output to see how Linux named the device for your SD card).

Step 5: Boot

Once you write the system image to the SD card, it is just a matter of connecting it to the board’s SD slot and turn the board on. You’ll get the system we built from scratch running on your Nitrogen6X board.

You should see a boot log on the serial console like:

Boot log
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
U-Boot 2013.01-00058-g5957f6d (Feb 12 2013 - 10:39:04)

CPU:   Freescale i.MX6Q rev1.2 at 792 MHz
Reset cause: POR
Board: Nitrogen6X
DRAM:  2 GiB
WARNING: Caches not enabled
MMC:   FSL_SDHC: 0, FSL_SDHC: 1
SF: Detected SST25VF016B with page size 4 KiB, total 2 MiB
*** Warning - bad CRC, using default environment

auto-detected panel HDMI
enable_hdmi: setup HDMI monitor
Display: HDMI (1024x768)
In:    serial
Out:   serial
Err:   serial
Net:   using phy at 6
FEC [PRIME]
Warning: FEC using MAC address from net device

Hit any key to stop autoboot:  1  0
AHCI 0001.0300 32 slots 1 ports 3 Gbps 0x1 impl SATA mode
flags: ncq stag pm led clo only pmp pio slum part
No port device detected!
** Bad device size - sata 0 **
** Bad device size - sata 0 **

SATA device 1: unknown device
** Bad device sata 1 **
** Bad device sata 1 **
mmc0 is current device
reading /6x_bootscript
1523 bytes read in 13 ms (114.3 KiB/s)
## Executing script at 10008000
Setting bus to 2
Valid chip addresses:
------ no Freescale display
Valid chip addresses:
------ no 1024x600 display
Valid chip addresses:
------ no 800x480 display
reading uImage
3887908 bytes read in 193 ms (19.2 MiB/s)
## Booting kernel from Legacy Image at 10800000 ...
   Image Name:   Linux-3.0.35-1.1.0+g2dc5560
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    3887844 Bytes = 3.7 MiB
   Load Address: 10008000
   Entry Point:  10008000
   Verifying Checksum ... OK
   Loading Kernel Image ... OK
OK

Starting kernel ...

Uncompressing Linux... done, booting the kernel.
Linux version 3.0.35-1.1.0+g2dc5560 (otavio@monster) (gcc version 4.7.2 (GCC) ) #1 SMP PREEMPT Sun Apr 14 23:46:05 BRT 2013
CPU: ARMv7 Processor [412fc09a] revision 10 (ARMv7), cr=10c53c7d
CPU: VIPT nonaliasing data cache, VIPT aliasing instruction cache
Machine: Freescale i.MX 6Quad Sabre-Lite Board
Memory policy: ECC disabled, Data cache writealloc
CPU identified as i.MX6Q, silicon rev 1.2
PERCPU: Embedded 7 pages/cpu @8c810000 s5440 r8192 d15040 u32768
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 487424
Kernel command line: enable_wait_mode=off video=mxcfb0:dev=hdmi,1280x720M@60,if=RGB24 video=mxcfb1:off video=mxcfb2:off fbmem=28M console=ttymxc1,115200 vmalloc=400M root=/dev/mmcblk0p2 rootwait consoleblank=0
PID hash table entries: 4096 (order: 2, 16384 bytes)
Dentry cache hash table entries: 262144 (order: 8, 1048576 bytes)
Inode-cache hash table entries: 131072 (order: 7, 524288 bytes)
Memory: 640MB 1280MB = 1920MB total
Memory: 1940112k/1940112k available, 157040k reserved, 638976K highmem
Virtual kernel memory layout:
    vector  : 0xffff0000 - 0xffff1000   (   4 kB)
    fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
    DMA     : 0xf4600000 - 0xffe00000   ( 184 MB)
    vmalloc : 0xd9800000 - 0xf2000000   ( 392 MB)
    lowmem  : 0x80000000 - 0xd9000000   (1424 MB)
    pkmap   : 0x7fe00000 - 0x80000000   (   2 MB)
    modules : 0x7f000000 - 0x7fe00000   (  14 MB)
      .init : 0x80008000 - 0x8003a000   ( 200 kB)
      .text : 0x8003a000 - 0x806fe7b4   (6930 kB)
      .data : 0x80700000 - 0x8075a2c0   ( 361 kB)
       .bss : 0x8075a2e4 - 0x807a6584   ( 305 kB)
SLUB: Genslabs=13, HWalign=32, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
Preemptible hierarchical RCU implementation.
NR_IRQS:624
MXC GPIO hardware
sched_clock: 32 bits at 3000kHz, resolution 333ns, wraps every 1431655ms
arm_max_freq=2
MXC_Early serial console at MMIO 0x21e8000 (options '115200')
bootconsole [ttymxc1] enabled
Console: colour dummy device 80x30
Calibrating delay loop... 1581.05 BogoMIPS (lpj=7905280)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
hw perfevents: enabled with ARMv7 Cortex-A9 PMU driver, 7 counters available
CPU1: Booted secondary processor
CPU2: Booted secondary processor
CPU3: Booted secondary processor
Brought up 4 CPUs
SMP: Total of 4 processors activated (6324.22 BogoMIPS).
devtmpfs: initialized
...
...
INIT: Entering runlevel: 5
Starting Xserver
Starting system message bus: dbus.
Starting Connection Manager
Starting Dropbear SSH server: dropbear.
Starting advanced power management daemon: apmd.
apmd[1873]: apmd 3.2.1 interfacing with apm driver 1.13 and APM BIOS 1.2
ipu_init_sync_panel: disp=1, pixel_clk=74250000 74250000
creating NFS state directory: done
starting 8 nfsd kernel threads: ipu_init_sync_panel: disp=1, pixel_clk=74250000 74250000
pwm_config: pwm freq = 32786, clk_select=2 clock_rate=22000000
pwm_config: pwm freq = 20000, clk_select=2 clock_rate=22000000
rpc.nfsd: Unable to access /proc/fs/nfsd errno 2 (No such file or directory).
Please try, as root, 'mount -t nfsd nfsd /proc/fs/nfsd' and then restart rpc.nfsd to correct the problem
done
starting mountd: done
starting statd: done
Starting syslogd/klogd: done
 * Starting Avahi mDNS/DNS-SD Daemon: avahi-daemon
   ...done.
Starting Telephony daemon
Starting Linux NFC daemon
imx-audio: setting default mixer settings.
amixer: Unable to find simple control 'Playback',0

Starting OProfileUI server
Running local boot scripts (/etc/rc.local).
Stopping Bootlog daemon: bootlogd.
ipu_init_sync_panel: disp=1, pixel_clk=74250000 74250000
pwm_config: pwm freq = 32786, clk_select=2 clock_rate=22000000
pwm_config: pwm freq = 20000, clk_select=2 clock_rate=22000000

Poky 8.0 (Yocto Project 1.3 Reference Distro) 1.3+snapshot-20130415 nitrogen6x ttymxc1

nitrogen6x login:

If you have an HDMI display connected to the board, you will get:

Boundary Devices Nitrogen6X running fsl-image-gui using HDMI align-middle

This gives you a working system, completely built from scratch :-)

As demonstrated by this small tutorial, Yocto is very easy to use and it is able to reduce the complexities of building a full operating system from scratch. O.S. Systems has been working to make the Freescale’s community driven BSP easier to use, a good base for products and a pleasant environment for contributors. O.S. Systems has been working with Freescale and “community” boards, and can help you to achieve the same for your products. It can design a specific BSP with personalized applications for your own needs. If you want more information, please contact us.