O.S. Systems live

News from our smart team...

Yocto with Boundary Device's 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.