Overview
NXP has recently updated their MCIMX8M-EVK Yocto BSP to the Linux L5.15.52 kernel. We have found that some of NXP's Yocto Linux related documentation is confusing, so we have developed this article about how we perform basic development steps with the Yocto Project, Linux kernel, and user space in the context of our i.MX8 EVK.
The steps shown below can be followed to create a working EVK system from source using an Ubuntu host as the Yocto build machine (and package server).
The Yocto Project itself has fantastic documentation, and there is a lot of it! If you're new to Yocto Project, then start with the Quick Build Guide. And don't overlook What I Wish I'd Known.
Listed below are some of the data points that we need to establish to move forward when building a Yocto image from source for our EVK:
- The NXP i.MX 8MQuad is powered by a quad core 1.5 GHz ARM CORTEX-A53 with an auxiliary ARM M4
- We are working with the NXP L5.15.52-2.1.0 release. This was developed using the Yocto Project Kirkstone (4.0) branch / release.
- Kirkstone 4.0 was released May 2022 and is considered a Long Term Support release, which will be supported at least through April 2024.
- We utilize the Wayland graphics back end. XWayland is also supported (Wayland with X11 support) by the BSP.
- Our Yocto Machine: imx8mqevk
- Our Yocto distro: "fsl-imx-wayland"
- There is an EVKB and EVK. We are using the EVKB, and this has an upgrade to the WIFI over the EVK and a later revision of the i.MX8 SoC.
Initial Steps
As recommended by NXP, we're using the repo tool, which is a Python script developed by Google to pull all the necessary Git repositories at the correct commits based on NXP's GA release manifest. Refer to NXP's "i.MX Repo Manifest" README for additional details.
Below we install NXP's Yocto Project release in our /build/imx8/ folder:
$ mkdir -p /build/imx8; cd /build/imx8 $ repo init -u https://github.com/nxp-imx/imx-manifest -b imx-linux-kirkstone -m imx-5.15.52-2.1.0.xml Downloading Repo source from https://gerrit.googlesource.com/git-repo ... repo has been initialized in /build/imx8 $ ls -a . .. .repo $ repo sync ... repo sync has finished successfully. $ ls imx-setup-release.sh README README-IMXBSP setup-environment sources $ ls sources/ base meta-clang meta-freescale-3rdparty meta-imx meta-openembedded meta-timesys poky meta-browser meta-freescale meta-freescale-distro meta-nxp-demo-experience meta-qt6 meta-virtualization
Create our Yocto Project build environment under the folder bld-wayland:
$ DISTRO=fsl-imx-wayland MACHINE=imx8mqevk source imx-setup-release.sh -b bld-wayland ... You can now run 'bitbake' Common targets are: core-image-minimal meta-toolchain meta-toolchain-sdk adt-installer meta-ide-support Your build environment has been configured with: MACHINE=imx8mqevk SDKMACHINE=i686 DISTRO=fsl-imx-wayland EULA= BSPDIR= BUILD_DIR=. meta-freescale directory found $ pwd /build/imx8/bld-wayland $ tree . └── conf ├── bblayers.conf ├── bblayers.conf.org ├── local.conf ├── local.conf.org ├── local.conf.sample └── templateconf.cfg
Using another shell, let's take a look at the meta-sdk folder:
$ cd /build/imx8/sources/meta-imx/meta-sdk/recipes-fsl/images $ ls *.bb fsl-image-gui.bb fsl-image-validation-imx.bb imx-image-core.bb imx-image-multimedia.bb
And it may be instructive to realize that the Git repositories under sources are not on a branch and may have been modified during the previous setup:
$ git branch * (no branch) $ git log commit a0303c88a5abf96cbe3e4dccd339a323aad726fa (HEAD, tag: rel_imx_5.15.52_2.1.0, m/imx-linux-kirkstone) Author: Jun Zhu Date: Sat Oct 8 00:44:07 2022 -0700 u-boot-imx: Update to commit 16e841 Signed-off-by: Jun Zhu
The bitbake command below will build an sdcard image in the deploy folder that we can use to boot our NXP EVK. Return to our original build shell:
$ bitbake imx-image-multimedia ... Build Configuration: BB_VERSION = "2.0.0" BUILD_SYS = "x86_64-linux" NATIVELSBSTRING = "ubuntu-18.04" TARGET_SYS = "aarch64-poky-linux" MACHINE = "imx8mqevk" DISTRO = "fsl-imx-wayland" DISTRO_VERSION = "5.15-kirkstone" TUNE_FEATURES = "aarch64 armv8a crc crypto" TARGET_FPU = "" meta meta-poky = "HEAD:602922d492351ee747d2ff00f8ed5aab284a706b" meta-oe meta-multimedia meta-python = "HEAD:8f2dc1023482863e2630d1b94052c41ce748b38f" meta-freescale = "HEAD:06e1cf4099caa53da33c10e1884064f73dc184dd" meta-freescale-3rdparty = "HEAD:6d8213fc5ec192c33f963b8095d1f01af1574eea" meta-freescale-distro = "HEAD:fc15f5003043da23212596be7366ae2547c308ad" meta-bsp meta-sdk meta-ml meta-v2x = "HEAD:a0303c88a5abf96cbe3e4dccd339a323aad726fa" meta-nxp-demo-experience = "HEAD:c3bd9b4789d87fc259d1fb2c2ffa27b39f1310b5" meta-chromium = "HEAD:e232c2e21b96dc092d9af8bea4b3a528e7a46dd6" meta-clang = "HEAD:d669d873edf68dc7440bb07096737203bb7ec505" meta-gnome meta-networking meta-filesystems = "HEAD:8f2dc1023482863e2630d1b94052c41ce748b38f" meta-qt6 = "HEAD:41ddf0b33167ea28df0ce5b56583976c20e7f187" meta-virtualization = "HEAD:cca772a457a75b2661371932ff79c392da3118db" ... WARNING: vim-native-9.0.0063-r0 do_fetch: Failed to fetch URL git://github.com/vim/vim.git;branch=master;protocol=https, attempting MIRRORS if available WARNING: opencv-4.6.0.imx-r0 do_fetch: Failed to fetch URL git://github.com/opencv/opencv_3rdparty.git;branch=ippicv/master_20191018;destsuffix=ipp;name=ipp;protocol=https, attempting MIRRORS if available WARNING: nlohmann-json-3.10.5-r0 do_fetch: Failed to fetch URL git://github.com/nlohmann/json.git;nobranch=1;protocol=https, attempting MIRRORS if available WARNING: apt-2.4.5-r0 do_fetch: Failed to fetch URL http://ftp.debian.org/debian/pool/main/a/apt/apt_2.4.5.tar.xz, attempting MIRRORS if available WARNING: sigma-dut-git-r0 do_populate_lic: QA Issue: sigma-dut: No generic license file exists for: BSD in any provider [license-exists] WARNING: sudo-1.9.5p2-r0 do_populate_lic: QA Issue: sudo: No generic license file exists for: BSD in any provider [license-exists] WARNING: wireless-tools-1_30.pre9-r0 do_populate_lic: QA Issue: wireless-tools: No generic license file exists for: BSD in any provider [license-exists] WARNING: opencv-4.6.0.imx-r0 do_fetch: Failed to fetch URL git://github.com/opencv/opencv_3rdparty.git;branch=ippicv/master_20191018;destsuffix=ipp;name=ipp;protocol=https, attempting MIRRORS if available WARNING: tesseract-lang-4.1.0-r0 do_fetch: Failed to fetch URL git://github.com/tesseract-ocr/tessdata.git;branch=main;protocol=https, attempting MIRRORS if available WARNING: imx-image-multimedia-1.0-r0 do_rootfs: QA Issue: The license listed BSD was not in the licenses collected for recipe sigma-dut [license-file-missing] WARNING: imx-image-multimedia-1.0-r0 do_rootfs: QA Issue: The license listed BSD was not in the licenses collected for recipe sudo [license-file-missing] WARNING: imx-image-multimedia-1.0-r0 do_rootfs: QA Issue: The license listed BSD was not in the licenses collected for recipe sudo [license-file-missing] WARNING: imx-image-multimedia-1.0-r0 do_rootfs: QA Issue: The license listed BSD was not in the licenses collected for recipe sudo [license-file-missing] WARNING: imx-image-multimedia-1.0-r0 do_rootfs: QA Issue: The license listed BSD was not in the licenses collected for recipe wireless-tools [license-file-missing] ...
When we want to come back to the build system, we can do the following:
$ cd /build/imx8 $ source sources/poky/oe-init-build-env bld-wayland/ ### Shell environment set up for builds. ### You can now run 'bitbake <target>' Common targets are: core-image-minimal core-image-sato meta-toolchain meta-ide-support You can also run generated qemu images with a command like 'runqemu qemux86' Other commonly useful commands are: - 'devtool' and 'recipetool' handle common recipe tasks - 'bitbake-layers' handles common layer tasks - 'oe-pkgdata-util' handles common target package tasks $ bitbake imx-image-multimedia
Burning our *.wic image on an SD Card
Let's first take a look at the image file system types we have configured:
$ bitbake imx-image-multimedia -e | grep ^IMAGE_FSTYPES IMAGE_FSTYPES="wic.bmap wic.zst tar.zst" IMAGE_FSTYPES_DEBUGFS="tar.gz"
We decompress the *wic.zst file before writing our SD Card. We run the following in our Ubuntu shell on our build machine:
$ cd /build/imx8/bld-wayland/tmp/deploy/images/imx8mqevk/ $ ls *.zst imx-image-multimedia-imx8mqevk-20221102210426.rootfs.tar.zst imx-image-multimedia-imx8mqevk.tar.zst imx-image-multimedia-imx8mqevk-20221102210426.rootfs.wic.zst imx-image-multimedia-imx8mqevk.wic.zst $ unzstd imx-image-multimedia-imx8mqevk.wic.zst Warning : imx-image-multimedia-imx8mqevk.wic.zst is a symbolic link, ignoring imx-image-multimedia-imx8mqevk.wic.zst: 4552681472 bytes $ file imx-image-multimedia-imx8mqevk.wic imx-image-multimedia-imx8mqevk.wic: DOS/MBR boot sector; partition 1 : ID=0xc, active, start-CHS (0x80,0,1), end-CHS (0x3ff,3,32), startsector 16384, 170392 sectors; partition 2 : ID=0x83, start-CHS (0x3ff,3,32), end-CHS (0x3ff,3,32), startsector 196608, 8695348 sectors
Note that the resulting *.wic image is ~4.3GB, but we expect this to grow significantly once we add a other packages.
Our next step is to program our SD Card, which is inserted but not mounted in our Ubuntu host:
$ sudo fdisk /dev/mmcblk0 Welcome to fdisk (util-linux 2.31.1). Changes will remain in memory only, until you decide to write them. Be careful before using the write command. Command (m for help): p Disk /dev/mmcblk0: 29.7 GiB, 31914983424 bytes, 62333952 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 Disklabel type: dos Disk identifier: 0xa0a5537f
Let's use dd to write our wic file to our SD Card.
$ sudo dd if=imx-image-multimedia-imx8mqevk.wic of=/dev/mmcblk0 bs=1M status=progress 2952790016 bytes (3.0 GB, 2.8 GiB) copied, 1 s, 3.0 GB/s 4341+1 records in 4341+1 records out 4552681472 bytes (4.6 GB, 4.2 GiB) copied, 334.837 s, 13.6 MB/s
Let's take a look at what we just did. As you can see below, this process created two partitions (as expected).
$ sudo fdisk -l /dev/mmcblk0 Disk /dev/mmcblk0: 14.9 GiB, 15931539456 bytes, 31116288 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 Disklabel type: dos Disk identifier: 0xd4337d42 Device Boot Start End Sectors Size Id Type /dev/mmcblk0p1 * 16384 186775 170392 83.2M c W95 FAT32 (LBA) /dev/mmcblk0p2 196608 8891955 8695348 4.1G 83 Linux
Note that we can also insert our programmed SD Card back into our Ubuntu host later and make changes to the partitions and their contents.
Notes on Directories and Source
imx-image-multimedia.bb can be found in sources/meta-imx/meta-sdk/recipes-fsl/images
As you may have noticed, there are several NXP layers under sources. Here's one way to determine where a recipe is located:
$ cd /build/imx8/sources/ $ find . -name 'linux-imx*bb' ./meta-freescale/recipes-kernel/linux/linux-imx-mfgtool_5.15.bb ./meta-freescale/recipes-kernel/linux/linux-imx-headers_5.15.bb ./meta-freescale/recipes-kernel/linux/linux-imx_5.15.bb ./meta-imx/meta-bsp/recipes-kernel/linux/linux-imx-mfgtool_5.15.bb ./meta-imx/meta-bsp/recipes-kernel/linux/linux-imx-headers_5.15.bb ./meta-imx/meta-bsp/recipes-kernel/linux/linux-imx_5.15.bb
We can see above that the linux-imx_5.15 recipe is located in both the meta-imx/meta-bsp and meta-freescale layers. The former defines the newer 5.15.52 kernel. This makes sense since NXP tells us that the purpose of this layer is to introduce new features into the Yocto Project build that might not have been availble for the Yocto Kirkstone release.
View the manifest:
$ cd /build/imx8/bld-wayland/tmp/deploy/images/imx8mqevk $ more imx-image-multimedia-imx8mqevk.manifest | more acl armv8a 2.3.1-r0 adwaita-icon-theme-symbolic all 41.0-r0 alsa-conf armv8a-mx8m 1.2.6.1-r0 alsa-plugins-pulseaudio-conf armv8a 1.2.6-r0 alsa-state imx8mqevk 0.2.0-r5 alsa-states imx8mqevk 0.2.0-r5 alsa-tools armv8a 1.2.5-r0 alsa-topology-conf all 1.2.5.1-r0 alsa-ucm-conf all 1.2.6.3-r0 ... $ grep make imx-image-multimedia-imx8mqevk.manifest automake armv8a 1.16.5-r0 cmake armv8a 3.22.3-r0 make armv8a 4.3-r0 makedevs armv8a 1.0.1-r0
It can be confusing trying to determine where the source is hosted that is used to build our image. One way of determining this is shown below:
$ cd /build/imx8/bld-wayland/tmp/work/ $ ls all-poky-linux armv8a-mx8m-poky-linux armv8a-poky-linux imx8mqevk-poky-linux x86_64-linux $ grep url imx8mqevk-poky-linux/linux-imx/5.15.52+gitAUTOINC+36363d8623-r0/git/.git/config url = https://github.com/nxp-imx/linux-imx.git $ grep url imx8mqevk-poky-linux/u-boot-imx/2022.04-r0/git/.git/config url = https://github.com/nxp-imx/uboot-imx.git
Note that the source is now hosted on github.com instead of codeaurora.org.
Remote login via SSH
We find that our EVK Linux image supports Ethernet connectivity without requiring customization.
After boot up of our EVK and determination of our EVK's IP address, we add the IP address for the EVK board to /etc/hosts and login remotely:
ssh root@evk The authenticity of host 'evk (192.168.7.230)' can't be established. RSA key fingerprint is SHA256:ZOx862o0VxZf4NOaqEHROt9pU+mb4cN3t0VyvkIxffg. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'evk,<ip address>' (RSA) to the list of known hosts. # uname -a Linux imx8mqevk 5.15.32-lts-next+gfa6c3168595c #1 SMP PREEMPT Tue Jun 7 02:34:46 UTC 2022 aarch64 aarch64 aarch64 GNU/Linux # cat /proc/cpuinfo processor : 0 BogoMIPS : 16.66 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid CPU implementer : 0x41 CPU architecture: 8 CPU variant : 0x0 CPU part : 0xd03 CPU revision : 4 processor : 1 .. processor : 2 ... processor : 3 ...
DNF and package management
We add DNF package management support to our EVK target and build machine following Yocto documentation and our article "Use DNF Package Manager on a Yocto Linux Development System"
When we're done, our conf/local.conf file looks like below:
MACHINE ??= 'imx8mqevk' DISTRO ?= 'fsl-imx-wayland' PACKAGE_CLASSES ?= 'package_rpm' EXTRA_IMAGE_FEATURES ?= "debug-tweaks" USER_CLASSES ?= "buildstats" PATCHRESOLVE = "noop" BB_DISKMON_DIRS ??= "\ STOPTASKS,${TMPDIR},1G,100K \ STOPTASKS,${DL_DIR},1G,100K \ STOPTASKS,${SSTATE_DIR},1G,100K \ STOPTASKS,/tmp,100M,100K \ HALT,${TMPDIR},100M,1K \ HALT,${DL_DIR},100M,1K \ HALT,${SSTATE_DIR},100M,1K \ HALT,/tmp,10M,1K" PACKAGECONFIG:append:pn-qemu-system-native = " sdl" CONF_VERSION = "2" DL_DIR ?= "${BSPDIR}/downloads/" ACCEPT_FSL_EULA = "1" EXTRA_IMAGE_FEATURES += "package-management"
After rebuilding, don't forget to run "bitbake package-index" on the build machine. Next, on our EVK, we run:
# dnf makecache timer: config: 11 ms DNF version: 4.2.2 Command: dnf makecache Installroot: / Releasever: zeus cachedir: /var/cache/dnf Base command: makecache Extra commands: ['makecache'] Repository 'oe-packages' is missing name in configuration, using id. Making cache files for all metadata files. oe-packages: has expired and will be refreshed. repo: downloading from remote: oe-packages ... oe-packages: using metadata from Sun Jun 20 14:08:43 2021. Last metadata expiration check: 0:00:04 ago on Sun Jun 20 14:53:21 2021. No module defaults found timer: sack setup: 3798 ms Metadata cache created. Cleaning up.
Let's also take a look at the updated manifest after updating the package-index:
$ bitbake package-index $ cd /build/imx8/bld-wayland/tmp/deploy/images/imx8mqevk/ grep autoconf grep autoconf imx-image-multimedia-imx8mqevk.manifest autoconf aarch64 2.69 $ grep cmake imx-image-multimedia-imx8mqevk.manifest
As you can see above, cmake isn't included in the SDK, so let's add it by using dnf as described above:
build server:
$ bitbake cmake $ bitbake package-index
imx shell:
# dnf makecache # dnf install cmake ... Installed: cmake-3.15.3-r0.aarch64 Complete! Cleaning up. # cmake --version cmake version 3.15.3 CMake suite maintained and supported by Kitware (kitware.com/cmake).
Obviously, creating customizations to an SD Card partition that will be later overwritten might not be what we want. We may want to move our rootfs off of the SD Card (i.e., use an NFS mount)
In Part 2 of this article we'll discuss topics like building the Linux Kernel outside of Yocto using a Yocto generated SDK and booting our EVK via TFTP and NFS.
References and Resources
- OpenEmbedded Layer Index
- Yocto Project Compatible Layers
- Yocto Project Source Repositories
Acronyms and Terms
- SRC: i.MX8 System Reset Controller