Getting started with DTS#

If you want to create a SimpleSwitch™ application to deploy and use a Device Tree, please follow this guide to get you easily started.

Example Project#

Here is a very small project, with a single DTS, overlay-lvds0-screen-example.dts:

// SPDX-FileCopyrightText: (C) 2024 Avnet Embedded GmbH
// SPDX-License-Identifier: GPL-2.0-only

// This is a example based on IMX8MPlus SMARC module device tree overlay
// for an LVDS0 screen. Value from lvds0_panel and panel-timing node must
// be adapted.

/dts-v1/;
/plugin/;

/ {
	fragment@4000 {
		target-path = "/";
		__overlay__ {
			lvds0_panel {
				pinctrl-names = "default";
				pinctrl-0 = <&pinctrl_lcd0_panel>;
				compatible = "panel-lvds";
				backlight = <&lcd0_backlight>;
				enable-gpios =  <&gpio1 0 0>;

				label = "Example Screen";
				width-mm = <0>;
				height-mm = <0>;
				data-mapping = "";

				 panel-timing {
					clock-frequency = <0>;
					hactive = <0>;
					vactive = <0>;
					hback-porch = <0>;
					hfront-porch = <0>;
					vback-porch = <0>;
					vfront-porch = <0>;
					hsync-len = <0>;
					vsync-len = <0>;
					hsync-active = <0>;
					vsync-active = <0>;
					de-active = <0>;
					pixelclk-active = <0>;
				};

				port {
					panel_lvds_in: endpoint {
						remote-endpoint = <&lvds_out>;
					};
				};
			};
		};
	};

	fragment@4001 {
		target = <&lcdif2>;
		__overlay__ {
			status = "okay";
		};
	};

	fragment@4002 {
		target = <&ldb>;
		__overlay__ {
			status = "okay";

			lvds-channel@0 {
				#address-cells = <1>;
				#size-cells = <0>;
				status = "okay";

				port@1 {
					reg = <1>;

					lvds_out: endpoint {
						remote-endpoint = <&panel_lvds_in>;
					};
				};
			};
		};
	};

	fragment@4003 {
		target = <&ldb_phy>;
		__overlay__ {
			status = "okay";
		};
	};

	fragment@4004 {
		target = <&pwm1>;
		__overlay__ {
			status = "okay";
		};
	};

	fragment@4005 {
		target = <&lcd0_backlight>;
		__overlay__ {
			status = "okay";
		};
	};

	fragment@4006 {
		target = <&gpu_3d>;
		__overlay__ {
			status = "okay";
		};
	};

	fragment@4007 {
		target = <&gpu_2d>;
		__overlay__ {
			status = "okay";
		};
	};

	fragment@4008 {
		target = <&ml_vipsi>;
		__overlay__ {
			status = "okay";
		};
	};

	fragment@4009 {
		target = <&mix_gpu_ml>;
		__overlay__ {
			status = "okay";
		};
	};
};

And a Makefile:

# SPDX-FileCopyrightText: (C) 2024 Avnet Embedded GmbH
# SPDX-License-Identifier: LicenseRef-Avnet-OSS-1.0
DTS = overlay-lvds0-screen-example.dts
DTB = $(DTS:.dts=.dtb)

DTBDIR ?= usr/share/dtb

all: $(DTB)

%.dtb: %.dts
	dtc -I dts -O dtb -o $@ $<

clean:
	rm -f $(DTB)

install: $(DTB)
	install -m 0755 -d "$(PREFIX)/$(DTBDIR)/"
	install -m 0755 $(DTB) "$(PREFIX)/$(DTBDIR)/"

.PHONY: clean install

Build the project using a Makefile#

With a makefile aware of cross-compilation, building the binary is as simple as sourcing the SDK and running make, e.g.

$ . /opt/sc/0.1.0/sm2s-imx8plus/environment-setup-cortexa53-crypto-simplecoredistro-linux
$ make
dtc -I dts -O dtb -o overlay-screen-example.dtb overlay-screen-example.dts
overlay-screen-example.dts:72.19-84.6: Warning (unit_address_vs_reg): /fragment@4002/__overlay__/lvds-channel@0: node has a unit name, but no reg or ranges property

If the makefile has an install target using the PREFIX variable as installation path, it can be used directly with the --makefile-dir option of the Generate a SimpleSwitch™ package script

  $ simpleswitch-generate-package --name simpleswitch-example --template dts \
  --makefile-dir . --startup-command "while true; do sleep 1800; done" \
  --install-command "dtb-configure install /usr/share/dtb/overlay-lvds0-screen-example.dtb" \
  --uninstall-command "dtb-configure remove /usr/share/dtb/overlay-lvds0-screen-example.dtb" \
  --no-autostart

The goal with that command is to generate a SimpleSwitch™ application which will deploy the device tree blob in the boot partition and set the environment to use it. It is done thanks to the dtb-configure script which is called to deploy the dtb at the installation, and to remove the dtb at the uninstallation.

The startup command should do nothing and is not really important, as the SimpleSwitch™ application should never run thanks to the --no-autostart parameter.

If your makefile lack of a compatible install target, see below.

Build the project using an external tool#

You can also build with any external tool and create a package by copying the content of a directory. All you need is this directory to reproduce the structure desired in the package

$ find deploy_dir -printf "%y %p\n"
d deploy_dir
d deploy_dir/usr
d deploy_dir/usr/share
d deploy_dir/usr/share/dtb
f deploy_dir/usr/share/dtb/overlay-lvds0-screen-example.dtb

You can then use the --copy-dir option of the simpleswitch-generate-package the Generate a SimpleSwitch™ package

  $ simpleswitch-generate-package --name simpleswitch-example --template dts \
  --copy-dir deploy_dir --startup-command "while true; do sleep 1800; done" \
  --install-command "dtb-configure install /usr/share/dtb/overlay-lvds0-screen-example.dtb" \
  --uninstall-command "dtb-configure remove /usr/share/dtb/overlay-lvds0-screen-example.dtb" \
  --no-autostart

Deploy to the target#

Now it is time to deploy the generated SimpleSwitch™ container to the device. The SimpleSwitch™ application should never run as it is only the install/uninstall command which are useful. So for the deployment you can refer to the following page but DO NOT USE the --start parameter Deploy a SimpleSwitch™ package

Further reading#