Yocto Project for iMX6ULL Part 1: Creating a meta layer and adding a custom device tree.
Created by Charles Dias.

Yocto Project for iMX6ULL Part 1: Creating a meta layer and adding a custom device tree.

In the first article of this series, Yocto Project for iMX6ULL Part 0: Concepts, Setting up, and Building, we took a look at the basic Yocto Project concepts and setup the environment, finishing by building a reference image and install on the iMX6ULL module.

In this new one, we'll learn how to create a meta layer that will be used to add our customizations.

We'll begin by creating a meta layer that will be utilized throughout this and subsequent articles to implement our customizations. Following that, we'll explore how to customize the Kernel by adding a custom Device Tree to rectify the resolution issues discussed in the first article.

Visit the project's GitHub repository, and feel free to leave suggestions.

So, let's get started!

Other articles related to the iMX6ULL module

Hardware requirements

I'll use the following hardware configuration:

Creating a custom meta layer

In the Yocto Project (YP), creating a meta layer is the right way to customize a reference Linux image or create a new one. The meta layers are modular components that encapsulate configuration information and instructions for the build system, allowing us to customize and extend the build process without directly altering other core functionality.

Let's begin by creating our meta layer called meta-article. For sure, you can choose another name. However, using the meta-<name> as the initial part is recommended to keep aligned with the community practices.

Could you look at the layers folder to see how many meta layers there are?

Access the project folder, in my case, the Yocto-Project-for-iMX6ULL, and run the Docker image to start the build environment. Always remember to use the latest image version!

$ docker run --rm -it -v ~/.gitconfig:/etc/gitconfig -v $(pwd):/home/imx6ull/oe-core charlesdias/yocto_imx6ull_bsp6:latest        

Note: Ensure you have Git installed and configured on your host machine. Check if the file ~/.gitconfig exists on your host machine. See the link to learn more about Git initial config, https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup.

Remember to source the environment variable when the image starts by the command.

$ . export        

After that, we are inside ~/oe-core/build folder. I suggest to change to ~/oe-core/

$ cd ~/oe-core/        

Creating the meta-article

Note: You can find the meta-article layer files on the GitHub repository.

The bitbake provides a command to help us to create the meta layer. Run the command bitbake-layers create-layer plus the PATH and name of the meta layers you select. I selected the meta-article name.

$ bitbake-layers create-layer layers/meta-article        

Run the tree command to see the folders and files created inside the layers/meta-article.

$ tree layers/meta-article        

This is the expected output regardless of the two previous commands:

The meta-article folder contains configuration files, licensing information, and example recipes. See the description below:

  • conf/layer.conf - this file is essential as it contains the metadata information required by the BitBake tool to process the layer, such as priority level and version compatibility.
  • COPYING.MIT - it contains the MIT license.
  • README - it is a standard file created by the command bitbake-layers create-layer.
  • recipes-example/example/example_0.1.bb - it is a basic recipe example.

After creating a new meta layer, we must add its path to the build/bblayers.conf to enable our layer. Open this file and add the following line ${TOPDIR}/../layers/meta-article \ at the end of the BBLAYERS variable.

Be careful not to change other information.

Run the command bitbake-layers show-layers to see if the meta-article layer appears on the list. See below the expected output result.

Check the path inside the build/bblayers.conf file if the meta-article is not shown.

In the previous console image output, we have some information, such as the meta layer name, the full path, and the priority value.

It's important to know that the priority value is used to inform which layer has precedence if there are recipes with the same name in multiple layers. The recipe file from the layer with a higher priority number takes precedence for these cases. See more information on this link, Prioritizing Your Layer.

See the Understanding and Creating Layers link for more information on creating layers.

Customize the Kernel

In the first article, we saw that the display resolution was not setup correctly. This way, we must add our device tree to inform the Kernel of the proper configuration. Let's do it!

First of all, we have to create a folder structure in our project folder, like the one below:

$ cd layers/meta-article
$ mkdir -p recipes-kernel/linux/linux-toradex        

After that, we'll create a linux-toradex%.bbappend file to inform our custom device tree.

$ touch recipes-kernel/linux/linux-toradex%.bbappend        

Copy the following content to the bbappend file:

FILESEXTRAPATHS:prepend := "${THISDIR}/linux-toradex:"

CUSTOM_DEVICETREE = "my-custom-devicetree-file.dts"

SRC_URI += " \ 
    file://${CUSTOM_DEVICETREE} \
    "

do_configure:append() {
    cp ${WORKDIR}/${CUSTOM_DEVICETREE} ${S}/arch/arm/boot/dts
}        

Let's decompose the previous file.

  • FILESEXTRAPATHS:prepend := "${THISDIR}/linux-toradex:" tells the BitBake to look in the linux-toradex directory (located in the same directory as this .bbappend file) for any extra files it might need.
  • CUSTOM_DEVICETREE = "my-custom-devicetree-file.dts" defines a variable named CUSTOM_DEVICETREE and sets its value to the string "my-custom-devicetree-file.dts". Easy peasy!
  • SRC_URI is a standard variable in Yocto recipes that specifies the source locations (e.g., URLs) from where the recipe should fetch its source files.
  • file://${CUSTOM_DEVICETREE} specify a local file as a source (hence the file:// prefix) and uses the previously defined CUSTOM_DEVICETREE variable to denote its name.
  • do_configure:append() defines a function that will be appended to the existing do_configure task. In Yocto, tasks like do_configure, do_compile, and do_install are part of the build process. By appending to a task, you can customize or extend its behavior.
  • cp ${WORKDIR}/${CUSTOM_DEVICETREE} ${S}/arch/arm/boot/dts copy the DTS file to arch/arm/boot/dts directory, which is a standard location for device tree files in the Linux kernel source tree.

Now, it is time to create our device tree.

Create the my-custom-devicetree-file.dts device tree file inside the recipes-kernel/linux/linux-toradex folder.

$ touch recipes-kernel/linux/linux-toradex/my-custom-devicetree-file.dts        

And copy the following content to it:

/dts-v1/;

#include "imx6ull-colibri-nonwifi.dtsi"
#include "imx6ull-colibri-aster.dtsi"

/ {
    model = "Toradex Colibri iMX6ULL 512MB - LinkedIn articles";
    compatible = "toradex,colibri-imx6ull-aster",
            "toradex,colibri-imx6ull",
            "fsl,imx6ull";
};

&ad7879_ts {
    status = "okay";
};
 
&i2c2 {
    status = "okay";
};

// Enable the parallel RGB interface on the Colibri iMX6ULL.

&backlight {
    status = "okay";
};

&lcdif {
    status = "okay";
};

&panel_dpi {
    data-mapping = "bgr666";
    status = "okay";
};

&pwm4 {
    status = "okay";
};

// Panel with a resolution of 800x480 pixel.
&panel_dpi {
    compatible = "panel-dpi";
    status = "okay";
 
    width-mm = <154>;
    height-mm = <86>;
 
    panel-timing {
        clock-frequency = <33230769>;
        hactive = <800>;
        vactive = <480>;
        hsync-len = <128>;
        hfront-porch = <40>;
        hback-porch = <88>;
        vsync-len = <1>;
        vfront-porch = <10>;
        vback-porch = <33>;
        pixelclk-active = <1>;
    };
};        

To briefly explain the previously mentioned file:

  • The #include ... command functions similarly to its use in the C/C++ programming languages. Here, we're incorporating two other device tree files.
  • / { ... } denotes the root node of the device tree. Within this node, we find the model and compatible properties. These describe the device model and allow the Linux kernel to identify and adjust to various hardware versions.
  • Outside the root node, we activate the parallel RGB interface on the Colibri iMX6ULL by setting some status properties as "okay".
  • &panel_dpi { ... }; modifies some settings offered by the panel_dpi node. These configurations are vital to control the display properly.

After creating our custom device tree, we must undertake additional steps.

Create the file meta-article/conf/machine/colibri-imx6ull-extra.conf.

$ mkdir conf/machine/
$ touch conf/machine/colibri-imx6ull-extra.conf        

Then, set the KERNEL_DEVICETREE:append variable, which defines which device trees are built and included in the final image. Insert the following content below. Don't forget to include a space character when appending the .dtb file, or strange errors will occur.

KERNEL_DEVICETREE:append = " my-custom-devicetree-file.dtb"        

Note that in the colibri-imx6ull-extra.conf file, the extension is .dtb instead of .dts, as seen in the linux-toradex%.bbappend file.

The conf/machine/colibri-imx6ull-extra.conf must be referenced in another configuration file. This can be achieved by adding the following line at the end of conf/layer.conf:

include conf/machine/colibri-imx6ull-extra.conf        

Lastly, instruct U-Boot to load my-custom-devicetree-file.dtb instead of the default. For this, establish the following directory structure within layers/meta-article:

$ mkdir -p recipes-bsp/u-boot        

Then, generate the u-boot-toradex_%.bbappend file within:

$ touch recipes-bsp/u-boot/u-boot-toradex_%.bbappend        

And populate it with:

do_configure:append() {
    # Remove existing fdtfile, if there is one
    sed -i '/"fdtfile=.*\\0" \\/d' ${S}/include/configs/colibri-imx6ull.h

    # Add new fdtfile, "my-custom-devicetree-file.dtb" should be replaced with your device tree binary file
    sed -i 's/\("fdt_board=.*\\0" \\\)/\0\n      "fdtfile=my-custom-devicetree-file.dtb\\0" \\/' ${S}/include/configs/colibri-imx6ull.h
}        

This bbappend file instructs U-Boot to utilize my-custom-devicetree-file.dtb instead of imx6ull-colibri${variant}-${fdt_board}.dtb.

Ultimately, your directory structure should mirror:

imx6ull@c66e08badebe:~/oe-core/layers/meta-article$ tree
.
├── conf
│?? ├── layer.conf
│?? └── machine
│??     └── colibri-imx6ull-extra.conf
├── COPYING.MIT
├── README
├── recipes-bsp
│?? └── u-boot
│??     └── u-boot-toradex_%.bbappend
├── recipes-example
│?? └── example
│??     └── example_0.1.bb
└── recipes-kernel
    └── linux
        ├── linux-toradex
        │?? └── my-custom-devicetree-file.dts
        └── linux-toradex%.bbappend

9 directories, 8 files        

Now, start your first build custom image by launching the bitbake command.

$ bitbake -k tdx-reference-multimedia-image        

This build should be quicker than your initial one. A new image will be ready after a couple of minutes, maybe one hour.

Adjusting the image installer

There's one final adjustment to ensure everything works smoothly!

Unzip the customized image Colibri-iMX6ULL_Reference-Multimedia-Image-upstream-Tezi_6.4.0-<build-date>.tar onto a USB memory stick. Note that the date the image was built is included in the file name.

Inspect the contents of the image's folder. Can you locate the custom my-custom-devicetree-file.dtb file?

Next, cautiously open the image.json file within the image's folder on the USB memory stick and change the content from:

                        "rawfiles": [
                            {
                                "filename": "imx6ull-colibri-eval-v3.dtb",
                                "product_ids": "0036"
                            },
                            {
                                "filename": "imx6ull-colibri-wifi-eval-v3.dtb",
                                "product_ids": "0040"
                            },
                            {
                                "filename": "imx6ull-colibri-eval-v3.dtb",
                                "product_ids": "0044"
                            },
                            {
                                "filename": "imx6ull-colibri-wifi-eval-v3.dtb",
                                "product_ids": "0045"
                            }
                        ]        

to

                        "rawfiles": [
                            {
                                "filename": "my-custom-devicetree-file.dtb",
                                "product_ids": "0036"
                            },
                            {
                                "filename": "my-custom-devicetree-file.dtb",
                                "product_ids": "0040"
                            },
                            {
                                "filename": "my-custom-devicetree-file.dtb",
                                "product_ids": "0044"
                            },
                            {
                                "filename": "my-custom-devicetree-file.dtb",
                                "product_ids": "0045"
                            }
                        ]        

Ensure you don't modify or delete other parts of the information. Once done, save and close the file.

This modification will apply our custom device tree to every iMX6ULL module model. We'll see a better way to modify this in an upcoming article.

Testing the custom image

Insert the USB memory stick into the Aster board and install the new image.

Note: Refer to Install the Linux image on iMX6ULL in the first article of this series for detailed instructions.

After installing the image, reboot the board and wait for its initialization.

How does the display appear? Is the resolution as expected? Hopefully, it is!

Next, establish an SSH connection to the board. The username is root, and no password is required.

Upon accessing, execute the command dmesg | grep -i model.

# dmesg | grep -i model
[    0.000000] OF: fdt: Machine model: Toradex Colibri iMX6ULL 512MB - LinkedIn articles        

Do you recognize the message corresponding to our device tree's model property?

Lastly, run the following command inside the board to initiate the touch calibration process. As the calibration begins, tap on the indicated points on the screen.

# weston-touch-calibrator /sys/devices/platform/soc/2100000.bus/21a4000.i2c/i2c-1/1-002c/input/input0/event0        

Conclusion

Things start to get more interesting, don't you think?

In our upcoming article, we'll explore further customizations. Stay tuned for more insights!

See you there!

Links:

Farooq Ahmad

Embedded Software Entwickler | Master in Electrical Engineering

1 年

Keep the good work. Appreciated

Mustafa Destegul

Embedded Systems Engineer | Digital Design Engineer

1 年

Thanks.

Nistor Flaviu

Automotive Expert Multi-processors architectures

1 年

Nice explanations. Thanks for the article

要查看或添加评论,请登录

Charles Dias, M.Sc.的更多文章

社区洞察

其他会员也浏览了