Device Tree Overlay

  • DTBO feature requires a specific kernel version or up. Please see the following for the boards.
    • Odroid-XU4: 5.4
    • Odroid-N2/N2+: 4.9.230
    • Odroid-C4: 4.9.230
  • And also need the latest boot.ini, config.ini and including overlays directory structure in BOOT partition.
  • On the Android, /odm/env.ini & /odm/boot.ini are same rule on the linux.
  • The other boards including C2 are not supported and there's no plan to support them for now.

By using this Overlay feature, we can easily set the board to use a peripheral including a shield product.

To use a shield, you should have set your DTB file by using 'fdt' tool on the Ubuntu system. Or, you have to build from the scratch after downloading the Odroid kernel source, just to use a shield.

If a shield uses several protocols that different from each other, then it was too easy to do some mistakes. Those mistakes are very hard to be found so that several people were going to give up using their shields.

But, by the DTB overlay, you can set your board by editing config.ini file. Only one thing needed is setting a DTBO name for the shield.

Now we're providing config.ini file besides the boot.ini file in the BOOT partition.

The config.ini file contains various parameters that can be set by the user to configure the board for their tastes, and it is called by the boot.ini file at the multiple moments it needs.

If there's no config.ini file on the BOOT partition, then the default parameters stored in boot.ini will be used automatically. So you don't have to worry if you have deleted config.ini file or left some typos on that by mistake.

But keep in mind that boot.ini must not be removed. This is the core script file U-boot uses.

In Android, a the env.ini from /odm is same works like config.ini.

Linux

This is the DTBO part of the config.ini file of Odroid-C4. It can be different from yours but the structure is the same.

; Device Tree Overlay
overlay_resize=16384
overlay_profile=
overlays="spi0 i2c0 i2c1 uart0"
 
[overlay_custom]
overlays="i2c0 i2c1"
 
[overlay_hktft32]
overlays="hktft32 ads7846"
 
[overlay_hktft35]
overlays="hktft35 sx865x-i2c1"

Android

The ODROID-Settings provide editing feature the list of device tree overlay on ODROID-N2/C4.

Open Odroid-Settings apps and select the DTB Overlay menu. And you can edit the device tree overlay list by clicking the DTB Overlay List menu.

The content of the list should consist of model names and separators. The separator must be a *' '* space.

And the DTBO Size Resize values are used to resize dtbo address size to apply device tree overlays.

Here is a example from the ODROID-C4.

i2c0 i2c1 spi0 uart0 pcf8563

Overlay profile

You should see overlay_profile and overlays variables of each section. Section is enclosed in square brackets.

All of the sections having prefix overlay_, and the rest of the section name, which is after the prefix, is used as a profile name. The profile name will be located to the overlays_profile.

See the examples below.

  • [overlay_custom]: It can be the overlay profile, and the profile name is custom.
  • [overlay_hktft32]: It can be the overlay profile, and the profile name is hktft32.
  • [hktft32]: It cannot be the overlay profile. The overlay profile name must have the prefix overlay_.

Each profile should have its own overlays variable. And the overlays variable lists the overlay files corresponding to the respective proposal. For sure, it should be related to the name of the covering profile.

The overlay files are located in the BOOT partition. You can see the overlay files in the following paths.

  • Odroid-XU4: ./overlays/*.dtbo
  • Odroid-N2: ./amlogic/overlays/odroidn2/*.dtbo
  • Odroid-C4: ./amlogic/overlays/odroidc4/*.dtbo

In C4, we're providing some useful overlays in advance. The prepared DTBO files can be changed later.

root@odroid:~# ll /media/boot/amlogic/overlays/odroidc4
total 34
drwx------ 2 root root 2048 Jun  4 01:25 ./
drwx------ 3 root root 2048 Jun  4 01:25 ../
-rwx------ 1 root root  830 Jun  4 01:25 ads7846.dtbo*
-rwx------ 1 root root  545 Jun  4 01:25 can0.dtbo*
-rwx------ 1 root root 1587 Jun  4 01:25 hifishield.dtbo*
-rwx------ 1 root root 1726 Jun  4 01:25 hifishield2.dtbo*
-rwx------ 1 root root 1238 Jun  4 01:25 hktft32.dtbo*
-rwx------ 1 root root 1877 Jun  4 01:25 hktft35.dtbo*
-rwx------ 1 root root  223 Jun  4 01:25 i2c0.dtbo*
-rwx------ 1 root root  223 Jun  4 01:25 i2c1.dtbo*
-rwx------ 1 root root  417 Jun  4 01:25 onewire.dtbo*
-rwx------ 1 root root  469 Jun  4 01:25 pcf8563.dtbo*
-rwx------ 1 root root  516 Jun  4 01:25 spi0.dtbo*
-rwx------ 1 root root  768 Jun  4 01:25 sx865x-i2c1.dtbo*
-rwx------ 1 root root  225 Jun  4 01:25 uart0.dtbo*
-rwx------ 1 root root  225 Jun  4 01:25 uart1.dtbo*
-rwx------ 1 root root  225 Jun  4 01:25 uart2.dtbo*

Usage

So, let's see the [overlay_hktft32] section. In this case, this section's profile name is hktft32. This contains its own overlays variable, which lists hktft32 LCD DTBO file and ads7846 touchscreen DTBO file. We can see the hktft32.dtbo, ads7846.dtbo files under the ./amlogic/overlays/odroidc4 directory on the BOOT partition.

If you want to use this profile, you can put the profile name into the overlay_profile variable.

; Device Tree Overlay
overlay_resize=16384
overlay_profile=hktft32
overlays="spi0 i2c0 i2c1 uart0"
 
[overlay_custom]
overlays="i2c0 i2c1"
 
[overlay_hktft32]
overlays="hktft32 ads7846"
 
[overlay_hktft35]
overlays="hktft35 sx865x-i2c1"

Check the overlay_profile variable.

Then the U-Boot loads the DTBO files named in overlays variable. In this case, it will load only hktft32.dtbo and ads7846.dtbo.

If you left the overlay_profile variable empty, as the default states, then the U-Boot references the overlays variable the right after the overlay_profile variable. This means that any other overlays variable in a section won't be referenced. In this case, U-Boot will load the 4 DTBO files, spi0.dtbo, i2c0.dtbo, i2c1.dtbo, uart0.dtbo. This 4 components are on the 40 pin header on the board. So, by default, SPI, UART, and two I2C buses are turned on without any edits.

Of course, you can make a section as you want. The only thing you have to do is putting overlays variable and assigning some .dtbo files to that. The files named on that must exist under the overlays directory on the BOOT partition.

The basics

Here's the sample source code of the .dts file that is to be compiled to .dtbo file.

/dts-v1/;
/plugin/;

/ {
	fragment@0 {
		// i2c2 aliased with i2c0.
		// This activates i2c2 but it will be named as i2c0 on the userspace.
		target = <&i2c2>;

		__overlay__ {
			status = "okay";
		};
	};
};

This DTBO enables i2c2 node of the main DTB. If there's no i2c2 node in the DTB file, this overlay will not be loaded.

You can see some prefixes on the top of the file.

/dts-v1/;
/plugin/;

These two lines describe that this file is a kind of plugin of a device tree blob. Required to be used as a DT overlay.

/ {
	fragment@0 {
		// i2c2 aliased with i2c0.
		// This activates i2c2 but it will be named as i2c0 on the userspace.
		target = <&i2c2>;

		__overlay__ {
			status = "okay";
		};
	};
};

This part is the main content of this overlay file.

You can see the fragment part. The fragment is a code block that contains some nodes or properties. It is able to locate multiple fragment on the one DT overlay file. An example of this will be mentioned again later.

A fragment must have one target property to determine where these new nodes and their properties to be located. In this sample, i2c2 node is the target node. This means that the flattened device tree must have an i2c2 node.

The below of target property, there's a __overlay__ block. All of the fragment also has to have one __overlay__ block. You can write your code, which are some nodes and some properties, into this block.

In short terms, if a DTBO loaded successfully, the contents of the __overlay__ block will overwrite the target node on the flattened device tree.

Multiple fragments

You can locate multiple fragments into a one DTS file that is to be compiled to .dtbo file. See the following code.

/dts-v1/;
/plugin/;

/ {
	fragment@0 {
		// i2c2 aliased with i2c0.
		// This activates i2c2 but it will be named as i2c0 on the userspace.
		target = <&i2c2>;

		__overlay__ {
			status = "okay";
		};
	};

	fragment@1 {
		// i2c3 aliased with i2c1.
		// This activates i2c2 but it will be named as i2c1 on the userspace.
		target = <&i2c3>;

		__overlay__ {
			status = "okay";
		};
	};
};

There're two fragments. Each fragment is having a number, 0 and 1. These numbers are the order to be executed. In this case, fragment@0 will be loaded first then the fragment@1 will be loaded.

Target to an absent node

In many cases, there's no corresponding node to overwrite if you write your own DTS for your sensors. In this case, you can use target-path. Please see the following code.

/dts-v1/;
/plugin/;

/ {
	fragment@0 {
		target-path = "/";

		__overlay__ {
			foo: foo {
                            status = "okay";
                            compatible = "foo, bar";
                            
                            integer-property = <10>;
                        }
		};
	};
};

This example code has target-path property instead of target property to determine where it'd be located.

The proper value to the target-path property is the absolute path starting from the root of the flattened device tree. In this case, the foo node will be located under the very root place of the target flattened device tree.

  • You should use Linux to use the dtc tool. Ubuntu 20.04 LTS is used in this guide.
  • If you need any header file dependencies, such as using GPIO defines for a specific AP family, the whole kernel source will be needed.
    • Clone the Linux kernel source and use make dtbs command within that source tree in this case.

In order to make a .dtbo file, there's no needed to download whole kernel source codes because we have the dtc (Device Tree Compiler) tool.

After preparing the DTS file, finally, you can compile that to .dtbo file and get to be ready to use it on your board.

Install dtc tool via package manager.

sudo apt install device-tree-compiler

See this example first before understanding the options.

dtc -I dts -O dtb -o my-sensors.dtbo my-sensors.dts

This command is using 3 options.

  • -I: Input file format
  • -O: Output file format
  • -o: Output filename

So this command means,

  • Its input file format is dts, and the output file format is dtb. And the output file name is my-sensors.dtbo.
    • Compile my-sensors.dts to my-sensors.dtbo with the specified options.

After finishing the compiling, you can use your .dtbo file with the config.ini described on the top of this document.

Put the new .dtbo file to the proper directory on BOOT partition. Please see the guide including directory paths of each Odroid board and its usage at the overlay profile section.

    • Raspberry Pi's DTBO document is one of the excellent guides to study how Device Tree works. But, R.Pi has a special bootloader file and kernel ingredients so that they can deal with DTBO very fluently, such as dynamic loading of the DTBOs or DTBO parameters. We're planning to support them but afraid to say that it might not be achieved.