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.MX6D i.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
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
$ 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
, Getting source code
repo init -u https://github.com/Freescale/fsl-community-bsp-platform -b dylan
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
$ MACHINE=nitrogen6x source ./setup-environment build
One of the environment variables used by bitbake is
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
, Image build
$ 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
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
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
$ dd if=tmp/deploy/images/fsl-image-gui-nitrogen6x.sdcard of=/dev/<SD device> bs=4M
<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 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: FSLSDHC: 0, FSLSDHC: 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: enablewaitmode=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. NRIRQS:624 MXC GPIO hardware schedclock: 32 bits at 3000kHz, resolution 333ns, wraps every 1431655ms armmaxfreq=2 MXCEarly serial console at MMIO 0x21e8000 (options ‘115200’) bootconsole [ttymxc1] enabled Console: colour dummy device 80x30 Calibrating delay loop… 1581.05 BogoMIPS (lpj=7905280) pidmax: 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: apmd 3.2.1 interfacing with apm driver 1.13 and APM BIOS 1.2 ipuinitsyncpanel: disp=1, pixelclk=74250000 74250000 creating NFS state directory: done starting 8 nfsd kernel threads: ipuinitsyncpanel: disp=1, pixelclk=74250000 74250000 pwmconfig: pwm freq = 32786, clkselect=2 clockrate=22000000 pwmconfig: pwm freq = 20000, clkselect=2 clockrate=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. ipuinitsyncpanel: disp=1, pixelclk=74250000 74250000 pwmconfig: pwm freq = 32786, clkselect=2 clockrate=22000000 pwmconfig: pwm freq = 20000, clkselect=2 clockrate=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:
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.