Note: This project was written in August of 2023 using Yocto Project version 4.2"Mickledore" and Linux kernel 6.1 but should continue to be applicable to newer releases
Table of contents- 1 Describe what i.MX Embedded Linux is and why it is important
- 2 Provide a list of acronyms
- 3 Understanding Yocto Project versions and codenames
- 4 Host system requirements
- 5 Specify where to find documentation and how to use it
- 6 Start on our project
- 7 Prepare our Docker container
- 8 Initialize the build
- 9 Build i.MX Embedded Linux
- 10 Burn a SD card with the image we just built
- 11 To return to this project later
i.MX Embedded Linux is the NXP Linux SDK (Software Development Kit) that supports the features of i.MX processors and enables use of i.MX EVK (Evaluation Kits).
There are 4 Linux projects for the i.MX
Note: This project will build #1
- 1) i.MX Embedded Linux - The main project and most popular
- 2) Desktop - Adds Ubuntu experience to #1
- 3) Harpoon - Adds Jailhouse supervisor and RTOS/Bare-metal support to #1
- 4) Real-Time Edge - i.MX Embedded Linux with a real-time kernel, real-time networking stacks, Harpoon.
i.MX Embedded Linux provides
- Bootloaders based on Das U-Boot
- The NXP Linux Kernel
- Standard Linux distibution userspace applications
- Deployment mechanisms
- Trusted Platform-A
History
The history of i.MX Embedded Linux starts around 2014 when Freescale adopted Yocto Project as the preferred method to build a Linux SDK for i.MX 6 processors. Soon thereafter, NXP purchased Freescale. The i.MX Embedded Linux process continued, continually improving in quality, and incorporating all new i.MX processors as they are released. The process has been in place for over 9 years now and is one of the reasons why i.MX processors are so popular.
CodeAurora to GitHub
For most of the history of i.MX Embedded Linux, the source code repositories were stored on CodeAurora.org which was controlled by Qualcomm. With Qualcomm sunsetting CodeAurora in the spring of 2023, NXP migrated all the projects to GitHub in the Fall of 2022.
2 Provide a list of acronymsAPT Advanced Packaging Tool
BSP Board Support Package
EVK Evaluation Kit
i.MX innovative Multimedia eXperience
LF Linux Factory
LTS Long Term Support
SDK Software Development Kit
WIC OEIC = OpenEmbedded Image Creator
In order to match up the Yocto Project version number to the codename, please refer to the official Yocto Project release activity page under their wiki.
At the time this article was published, these were the latest Yocto Project versions and codenames
4.4 Scarthgap
4.3 Nanbield
4.2 Mickledore
4.1 Langdale
4.0 Kirkstone
Yocto Project is very specific about supported Linux distributions and the distro version number. If you run Yocto Project tools in an environment that is not in the list of supported distros, you may experience problems.
Refer to the Yocto Project reference manual for system requirements, section 1.3 "Supported Linux Distributions"
As of August 2023, these are the supported distributions and versions
Ubuntu 18.04 (LTS)
Ubuntu 20.04 (LTS)
Ubuntu 22.04 (LTS)
Fedora 36
Fedora 37
AlmaLinux 8.7
AlmaLinux 9.1
Debian GNU/Linux 11.x (Bullseye)
OpenSUSE Leap 15.3
OpenSUSE Leap 15.4
A) The NXP IMXLINUX web page "Embedded Linux for i.MX Applications Processors"
The IMXLINUX web page at NXP should be your first destination to find documentation. At the time this article was written, this web page was located in the following hierarchy: Home / Software / Embedded Software / iMX Software / Embedded Linux for iMX Applications Processors
A new documentation package is released approximately every three months. It is essential that you check this website often to make sure you are using the latest documentation. At the time that this article was written, the latest release is Linux 6.1.22_2.0.0
which was released in June of 2023
List of documentation provided as of when this article was published
- i.MX Linux Release Notes
- i.MX Linux User’s Guide
- i.MX Linux Reference Manual
- i.MX Porting Guide
- i.MX Yocto Project User’s Guide
- i.MX VPU API Reference Manual
- i.MX Graphics User’s Guide
- i.MX Machine Learning User's Guide
- Harpoon User's Guide
- i.MX 8M Plus Camera and Display Guide
- i.MX Digital Cockpit HW Partitioning Enablement for i.MX 8QuadMax
- i.MX DSP User's Guide
- uPower User Guide
- NXP Wi-Fi Driver Features and Release Notes
- NXP Demo Experience User Guide
B) The GitHub project imx-manifest
The nxp-imx/imx-manifest GitHub project is the starting point for building i.MX Embedded Linux.
Find the most recent branch
It is essential to make sure that you are looking at the latest branch of this project. Linux branches are named with the format of imx-linux-<Yocto_Codename>
. At the time this article was written, the Yocto Project version is 4.2 which corresponds to codename "Mickledore", so the latest branch is imx-linux-mickledore
. Tags and releases have no meaning in this project.
Note: i.MX Embedded Android also uses this project to store manifest files, the Android-specific branches are named imx-android-<VersionNumber>
Files
There are 4 files in imx-manifest
project that are useful
The manifest file for building i.MX Embedded Linux is named imx-<VersionNumbers>.xml
and does not include any additional text such as desktop
or harpoon
. For branch imx-linux-mickledore
, we care about manifest file imx-6.1.22-2.0.0.xml
Repo Manifest Format
Google has a good article that describes the repo manifest format.
The manifest file describes remote sources and projects for downloading recipes needed to build iMX Embedded Linux with Yocto Project.
iMX Embedded Linux Manifest
Look inside the imx-6.1.22-2.0.0.xml
manifest file and you will see the following remote sources and projects specified. These are the highest level sources which will in turn call additional sources.
- yocto/meta-arm
- yocto/meta-security
- yocto/poky
- oe/meta-openembedded
- kraj/meta-clang
- community/fsl-community-bsp-base
- community/meta-freescale
- community/meta-freescale-3rdparty
- community/meta-freescale-distro
- ossystems/meta-browser
- yocto: qt/meta-qt6
- timesys/meta-timesys
- nxp-imx/meta-imx
- imx-support/meta-nxp-demo-experience
Gather documentation
There are two sources of documentation to follow when building i.MX Embedded Linux. It is recommended to keep these documents open while you work through this project.
- 1 i.MX Yocto Project User’s Guide, sections 3 through 6
- 2 meta-nxp-desktop/README.md
Decide on your target hardware, i.MX Embedded Linux release number, and Yocto Project version codename
For this project, I am targeting the NXP MCIMX93-EVKCM
Evaluation Kit which uses the NXP i.MX93 processor. I will use the latest NXP i.MX Embedded Linux release which at the time I wrote this article is 6.1.22-2.0.0
, and this version dictates the Yocto Project version as Mickledore
. You should decide on your targets now.
Create the project directory and move into it
Your directory structure will likely be different from mine
[flint@ZBook] $ DIR=/work/imx93/mickledore && \
mkdir -pv ${DIR} && cd ${DIR}
7 Prepare our Docker containerWe will use Docker to provide a containerized build environment. If you do not have Docker installed, please follow the instructions provided in this project
We will use a Dockerfile to automate building our Docker image. The Dockerfile name is yocto-mickledore-ubuntu-20
and can be found attached to this project. This file is a text script that instructs Docker how to build an image.
Although the Dockerfile has the word mickledore
in it, there is a very high probability that this Dockerfile will continue to be useful for subsequent Yocto Project releases.
Save the Dockerfile to your download directory ${HOME}/Downloads
Edit the Dockerfile
The Dockerfile has my name and email address embedded in it. This will work for you but I highly recommend editing the file and replacing my info with your own.
Build the Docker image
The command we are going to issue will
- use a Dockerfile called
<DockerFile>
- to build a Docker image named
<ImageName>
- Note: Don't forget the dot "." at the end of the command.
- Note: Don't forget to change the Dockerfile location to where you installed it.
EXAMPLE $ docker build --no-cache \
--file <DockerFile> \
--tag <ImageName> .
I will configure the command as follows, given both the Dockerfile and the resulting image the same name
<DockerFile> = yocto-mickledore-ubuntu-20
<ImageName> = yocto-mickledore-ubuntu-20
Issue this command to build the Docker image
Note: The text does not copy properly, I recommend you type this out in your terminal
[flint@ZBook] $ docker build --no-cache \
--file "${HOME}/Downloads/yocto-mickledore-ubuntu-20" \
--tag yocto-mickledore-ubuntu-20 .
The process of building the yocto-mickledore-ubuntu-20
Docker image will take at least a few minutes.
Deploy our Docker image to a container while mounting the working directory
Note: The difference between a Docker image and a Docker container is when a Docker image is deployed (run), the specific instance is called a Docker container. We can use the Docker image we just built and deploy it to as many Docker containers we want.
The command we are going to issue will
- use Docker image
<ImageName>
- to create a Docker container called
<ContainerName>
- that will have a computer host name of
<HostName>
and will link the filesystems of
- the Docker container home directory
<ContainerHome>
- to our host computer directory
<HostDirectory>
EXAMPLE $ docker run -dit -P \
--hostname <HostName> \
--name <ContainerName> \
-v <HostDirectory>:<ContainerHome> \
<ImageName>
I have configured my command as follows
<ImageName> = yocto-mickedore-ubuntu-20
<ContainerName> = imx93evk-mickledore
<HostName> = Docker
<ContainerHome> = /home/build
<HostDirectory> = /work/imx93/mickledore
Issue this command to deploy the Docker image to a container
[flint@ZBook] $ docker run -dit -P \
--hostname Docker \
--name imx93evk-mickledore \
-v /work/imx93/mickledore:/home/build \
yocto-mickedore-ubuntu-20
Attach (Log In) to the new container
[flint@ZBook] $ docker attach imx93evk-mickledore
Install dotfiles (optional)
I prefer my Docker containers to operate similarly to my host computer's Linux Bash shell, so I install my personal dotfiles to give me that environment. This is purely optional for you. My dotfiles are attached to this project in a zip archive for you to review.
When I install my dotfiles into a Docker container, I use the following command
[build@Docker] $ curl https://gitlab.com/fweller/flint-configuration/-/raw/master/Tools/dockerfiles/dotfiles/dockerfile-install-dotfiles.sh?ref_type=heads | bash && source .bashrc
At this point our Docker container is ready for use
8 Initialize the buildNXP uses Repo to create an environment for building LLDP. Google Repo is "the multiple Git repository tool". The Dockerfile already installed Repo for us and placed it in location /usr/local/bin/repo
Install Repo (for reference only)
Note: This is for reference, the way you would install Repo as per NXP documentation. Only follow this if you did not use the supplied Dockerfile is as per the NXP instructions
EXAMPLE $ mkdir ~/bin && \
curl http://commondatastorage.googleapis.com/git-repo-downloads/repo > ~/bin/repo && \
chmod a+x ~/bin/repo && \
PATH=${PATH}:~/bin
Initialize Repo
The command we are going to issue will
- use URL
<URL>
to retrieve a manifest repository - using manifest file
<ManifestFile>
within the repository - and the specific manifest-branch
<Branch>
EXAMPLE $ repo init \
-u <URL> \
-b <Branch> \
-m <ManifestFile>
The specifics for our build are as follows. You should expect to update these values based on newer branches and manifest files.
<URL> https://github.com/nxp-imx/imx-manifest
<ManifestFile> imx-6.1.22-2.0.0.xml
<Branch> imx-linux-mickledore
This is the command that I issued. You should now build your own command and issue it.
[build@Docker] $ repo init \
-u https://github.com/nxp-imx/imx-manifest \
-b imx-linux-mickledore \
-m imx-6.1.22-2.0.0.xml
Download the NXP Yocto layers
Instructing Repo to sync is basically telling it to download files
[build@Docker] $ repo sync
When Repo is done initializing (downloading) everything, you should see 4 files and one directory
imx-setup-release.sh -> sources/meta-imx/tools/imx-setup-release.sh
README -> sources/base/README
README-IMXBSP -> sources/meta-imx/README
setup-environment -> sources/base/setup-environment
sources/
Setup the build folder
The instruction we are going to run will set up the environment with 3 specific settings
<Machine>
Target evaluation kit machine name<Backend>
The graphics backend type<BuildName>
A name you give to the build
EXAMPLE $ MACHINE=<Machine> DISTRO=fsl-imx-<Backend> source imx-setup-release.sh -b <BuildName>
Selecting the machine name
Machine names will correspond to one EVK usually, but sometimes more than one when the differences are unimportant to the BSP. Machine names will obviously apply to a specific processor, but may also be categorized by the type of RAM and the processor package size.
There are two sources that you can use to identify a machine name
- IMXLXYOCTOUG "i.MX Yocto Project User's Guide" section 5.1 "Build Configurations"
- GitHub meta-bsp/conf/machine
Some machine names that have been released in recent years
imx8mp-lpddr4-evk
Supports both the 8MPLUSLPD4-EVK and 8MPLUSLPD4-PEVK. Both use LPDDR4imx8mm-lpddr4-evk
For the 8MMINILPD4-EVK which uses LPDDR4imx8mn-lpddr4-evk
For the 8MNANOLPD4-EVK which uses LPDDR4imx8mn-ddr4-evk
For the 8MNANOD4-EVK which uses DDR4imx8mnddr3levk
For the 8MNANOD3L-EVK which uses DDR3Limx8ulp-lpddr4-evk
The standard MCIMX8ULP-EVK using the 15mm x 15mm 8ULP package;uses LPDDR4imx8ulp-9x9-lpddr4-evk
A special variant of the 8ULP-EVK built for the 9mm x 9mm 8ULP package; uses LPDDR4imx93evk
This is the standard MCIMX93-EVKCM Evaluation Kit built for the 11mm x 11mm iMX93 package, using LPDDR4imx93-11x11-lpddr4x-evk
A special variant of the iMX93-EVK built for the 11mm x 11mm package, using LPDDR4Ximx93-9x9-lpddr4-qsb
A special variant of the iMX93-EVK built for the 9mm x 9mm package, using LPDDR4imx93-14x14-lpddr4x-evk
A special variant of the iMX93-EVK built for the 14mm x 14mm package, using LPDDR4X
Selecting the distro graphics backend
There are three graphics backend options. One of these must be selected. If you do not intend to use graphics, you should select one of these and then remove the graphics recipes later.
fsl-imx-wayland Pure Wayland graphics without X11
fsl-imx-xwayland Wayland graphics with X11 (xwayland)
fsl-imx-fb Frame Buffer graphics - no X11 or Wayland
Note: You should select fsl-imx-xwayland
unless you have a very specific reason to use fsl-imx-wayland
or you are using a few select i.MX6 processors that require frame buffer graphics.
Selecting a BuildName
This is just a name that you want to use for your build. The NXP documentation recommends using bld-<Backend>
Finalize your settings
The settings that I will use for the standard MCIMX93-EVKCM
Evaluation Kit are
<Machine> imx93evk
<Backend> fsl-imx-xwayland
<BuildName> bld-xwayland
Issue the command in your Docker shell
[build@Docker] $ MACHINE=imx93evk DISTRO=fsl-imx-xwayland source imx-setup-release.sh -b bld-xwayland
You will be asked to confirm overwriting 'conf/bblayers.conf~
' Just type in Y + <Return>
for each one.
Next you will be asked to scroll through a license agreement with <Space>
and then accept it: Y + <Return>
When finished, your working directory will change. Mine is now /home/build/bld-xwayland
The Bitbake configurations that can be run are specified in IMXLXYOCTOUG Table 1 "i.MX Yocto Project images"
Although there are 7 possible configurations to build, I have recommendations to make.
These are the 3 configurations that I recommend.
imx-image-core - This is a minimal image that NXP uses for daily testing
imx-image-multimedia - Builds an image with a GUI but no Qt content
imx-image-full - Builds a GUI with Qt content and machine learning features
These are the 4 configurations that you should only select if you know exactly what they are for
core-image-minimal - The smallest image that can only boot the device
core-image-base - Console only with full hardware support
core-image-sato - Supports the Sato mobile environment
fsl-image-machine-test - A freescale community core image with console only
I prefer to instruct Bitbake to download all of the required files before I instruct it to begin the build. This way I can catch download issues in a few minutes instead of waiting hours for the build process to fail.
Fetch (download)all the packages
[build@Docker] $ bitbake imx-image-full --runall fetch
Bitbake will issue some warnings while is parses recipes. After all the recipes are parsed, Bitbake will begin fetching packages. For my particular build, this requires 786 tasks which takes at least 15 minutes to complete.
Now that Bitbake has completed fetching all the packages, it is time to kick off the build process. Just issue the same command as before but without the "--runall fetch
"
Build all the packages
[build@Docker] $ bitbake imx-image-full
For my project, there are 10396 tasks to complete. The entire build process will take at least a few hours.
Build Completion
All the output files that we care about have been placed into the deployed machine image folder that will be in a location with this configuration
<BuildName>/tmp/deploy/images/<Machine>
For the example I have been using, where <Machine> = imx93evk
, the exact folder location is:
- Within the Docker image:
/home/build/bld-xwayland/tmp/deploy/images/imx93evk
- On the host computer:
/work/imx93/mickledore/bld-xwayland/tmp/deploy/images/imx93evk
Change directory to the image deploy folder and list the Wic files
[build@Docker] $ cd /home/build/bld-xwayland/tmp/deploy/images/imx93evk
[build@Docker] $ ls -l *wic*
There are 4 results
imx-image-full-imx93evk-20230809224935.rootfs.wic.bmap
imx-image-full-imx93evk-20230809224935.rootfs.wic.zst
imx-image-full-imx93evk.wic.bmap -> imx-image-full-imx93evk-20230809224935.rootfs.wic.bmap
imx-image-full-imx93evk.wic.zst -> imx-image-full-imx93evk-20230809224935.rootfs.wic.zst
The important filename is imx-image-full-imx93evk.wic.zst
which is a symbolic link to the actual file that includes a date and time stamp in the name. For my project this is called imx-image-full-imx93evk-20230809224935.rootfs.wic.zst
The significant thing about the Wic file is that this can be burned to a SD card, which can in turn be inserted into the i.MX evaluation kit. While this is very useful for initial testing of the evaluation kit, we eventually want to program the flash on the kit or on our custom board.
Yocto Project has some documentation on how to use Wic files
10 Burn a SD card with the image we just builtThe first Bitbake command created a compressed wic file which is the only file we need to program a SD card
On the host computer we need to change directory to the deployed machine image directory
<BuildName>/tmp/deploy/images/<Machine>
For the example in this training, this is the directory: /work/imx93/mickledore/bld-xwayland/tmp/deploy/images/imx93evk
Change to the deployed machine image folder
[flint@ZBook] $ cd /work/imx93/mickledore/bld-xwayland/tmp/deploy/images/imx93evk
Decompress the zst file
In previous releases of i.MX Embedded Linux, bzip2 was the preferred compression for the Wic file. The recipe changed to make use of Zst which is a vastly superior compression method. Beware that zstd does not operate on symbolic links so be sure to feed it the proper file name.
[flint@ZBook] $ zstd -d imx-image-full-imx93evk-20230809224935.rootfs.wic.zst
The decompressed file will have the same name but without the .zst
at the end
There are many tools to burn a Wic image to a SD card. Balena Etcher is one such popular tool. My preferred method is to use the dd "disk duplicator" tool. But beware, dd is also known as "disk destroyer" if you end up writing to an unintended device.
Burn the Wic image to an SD card
In the example below
<ImageName>
is the filename for the.wic
file<Device>
is the disk device name such as/dev/sda
NOTE: Be certain that you know the exact /dev/sdx for the sd card or else you risk overwriting an important filesystem
EXAMPLE: $ sudo dd if=<ImageName> of=<Device> bs=4k conv=fsync status=progress && sync
For my setup, the command will be
[flint@ZBook] $ sudo dd if=imx-image-full-imx93evk-20230809224935.rootfs.wic of=/dev/sdb bs=4k conv=fsync status=progress && sync
11 To return to this project laterThe following are the steps needed to restart a stopped container and attach to it
List all Dockercontainers,including stopped containers
[flint@ZBook] $ docker container ls -a
I can see the Docker container that I named imx93evk-mickledore
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
435ce7f2da6f yocto-mickedore-ubuntu-20 "/bin/bash" 29 hours ago Exited (130) 13 seconds ago imx93evk-mickledore
Restart the Docker container
[flint@ZBook] $ docker restart imx93evk-mickledore
List all Docker containers that are presently running
[flint@ZBook] $ docker container ls
I can see that my container is running
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
435ce7f2da6f yocto-mickedore-ubuntu-20 "/bin/bash" 29 hours ago Up 6 seconds imx93evk-mickledore
Attach to the Docker container
[flint@ZBook] $ docker attach imx93evk-mickledore
I am immediately presented with a prompt from my container
[build@Docker] $
In order to make sure that the terminal we are running has the right configuration for kicking off another build, we must source the setup-environment
file. This is usually unnecessary when returning to a Docker container, but just in case, here is the command.
Set up the environment
[build@Docker] $ source setup-environment bld-xwayland
Now we can continue with performing another build
The End
Comments
Please log in or sign up to comment.