11.7. Device Tree Build System and Custom Overlays

Important

This developer note is applicable to J722S devices with SDP 8.0.0. The device tree build system allows you to customize hardware initialization by enabling or disabling peripherals using device tree overlays.

11.7.1. Introduction

The QNX BSP includes support for building custom startup files that use device tree (DTS) and device tree overlays (DTSO) to configure which peripherals are initialized. This feature allows you to:

  • Build with the default hardware configuration (all devices enabled)

  • Build with specific peripherals disabled via overlays

  • Build with specific peripherals enabled via overlays

  • Customize the QNX hardware initialization (hw_init.c) based on your device tree configuration

This guide explains how to use the build system to generate a custom startup file with your chosen device tree configuration. It assumes that the device tree source files already exist in your repository.

11.7.2. Device Tree Files Location

For J722S devices, device tree files are located in ${PSDK_QNX_PATH}/qnx/utils/dt/dts/j722s/:

Base Device Tree Files:

  • Minimal DTS: j722s-hw-init.dts — Contains only the nodes required by QNX hardware initialization. This is the default base DTS used when building with device tree overlays.

  • Full Preprocessed DTS: k3-j722s-qnx-preprocessed.dts — The complete device tree with all includes expanded. This file is provided for reference and debugging purposes.

Overlay Files:

Device tree overlays are located in ${PSDK_QNX_PATH}/qnx/utils/dt/dts/j722s/overlay/. Overlay files follow a naming convention:

  • Enable overlays: enable_<device>.dtso — Enables the specified device (sets status = "okay")

  • Disable overlays: disable_<device>.dtso — Disables the specified device (sets status = "disabled")

For example:

  • enable_dss0.dtso and disable_dss0.dtso — Control the DSS0 display subsystem

  • enable_gpu.dtso and disable_gpu.dtso — Control the GPU

  • enable_main_i2c0.dtso and disable_main_i2c0.dtso — Control I2C0 controller

There are approximately 28 enable/disable overlay pairs available for J722S devices, covering common peripherals such as display, GPU, USB, SD card, Ethernet, and serial interfaces.

11.7.2.1. Available Devices

The following devices can be controlled via overlays for J722S:

  • Display: dss0, dss1

  • Compute: gpu

  • USB: usb0, usb1, usbss0, usbss1

  • Storage: sdhci0, sdhci1, ospi0

  • Serial: Main I2C (main_i2c0, main_i2c1, main_i2c2)

  • Networking: Ethernet (cpsw3g, cpsw3g_mdio)

  • High-Speed: Serdes (serdes0, serdes_wiz0)

  • Pin Control: Various peripheral pin configurations

  • Clocks and PHY: Device clock and PHY configurations

11.7.3. Building Without Device Tree (Default Mode)

By default, the BSP builds without device tree infrastructure. In this mode:

  • All devices are enabled (legacy behavior)

  • No device tree headers are generated

  • Device tree overlays are not applied

  • The build is backward compatible with existing configurations

To build without device tree:

cd ${PSDK_QNX_PATH}
make all SOC=j722s

Alternatively, to build only the BSP:

make bsp SOC=j722s

This generates a startup file with all peripherals initialized in hardware.

11.7.4. Building With Base Device Tree (No Overlays)

To build with the minimal device tree configuration without any overlay modifications, use the sentinel value base:

cd ${PSDK_QNX_PATH}
make all SOC=j722s DTS_OVERLAY=base

Alternatively, to build only the BSP:

make bsp SOC=j722s DTS_OVERLAY=base

This builds using the minimal device tree (j722s-hw-init.dts) without any overlay modifications. The special value base enables the device tree infrastructure and defines the USE_DT preprocessor macro, but uses the base DTS directly without applying any overlays.

11.7.5. Building With Device Tree and Overlays

To customize the hardware configuration using overlays, specify the overlay files via the DTS_OVERLAY variable:

Single overlay:

cd ${PSDK_QNX_PATH}
make all SOC=j722s DTS_OVERLAY=disable_dss0.dtso

Multiple overlays (comma-separated):

cd ${PSDK_QNX_PATH}
make all SOC=j722s DTS_OVERLAY=disable_dss0.dtso,disable_gpu.dtso

The overlays are applied in order to the base device tree. The resulting combined device tree is used to generate the hardware initialization header, which is then compiled into the startup file. Specifying DTS_OVERLAY with overlay files automatically enables device tree infrastructure and defines the USE_DT preprocessor macro.

11.7.6. Overlay File Selection

When selecting which overlays to apply, keep the following in mind:

  • Enable overlays set a device’s status to "okay" (initialized and functional)

  • Disable overlays set a device’s status to "disabled" (not initialized)

  • Use enable overlays to re-enable devices that should be functional

  • Use disable overlays to exclude devices that your system does not require

For example, if you have a minimal system that only requires Ethernet and serial communication, you might build with:

make all SOC=j722s DTS_OVERLAY=disable_dss0.dtso,disable_gpu.dtso,disable_usb0.dtso,disable_usb1.dtso

This disables the display subsystem, GPU, and USB controllers, reducing power consumption and boot time.

11.7.7. Overlay Constraints and Validation

Important Constraint: You cannot mix an enable overlay and a disable overlay for the same device in a single build. For example, the following command is invalid:

# INVALID - do not mix enable and disable for same device:
make all SOC=j722s DTS_OVERLAY=enable_dss0.dtso,disable_dss0.dtso

11.7.7.1. Validating Overlays Before Building

Before building, you can validate your overlay list to ensure there are no conflicting enable/disable pairs. Use the validation script:

# Validate a single overlay:
utils/dt/scripts/validate_overlay_conflicts.sh "disable_dss0.dtso"

# Validate multiple overlays:
utils/dt/scripts/validate_overlay_conflicts.sh "disable_dss0.dtso disable_gpu.dtso"

# Using the same format as DTS_OVERLAY (space-separated):
utils/dt/scripts/validate_overlay_conflicts.sh "disable_dss0.dtso disable_gpu.dtso enable_main_i2c0.dtso"

Successful validation (exit code 0):

$ utils/dt/scripts/validate_overlay_conflicts.sh "disable_dss0.dtso enable_main_i2c0.dtso"
# Script exits silently with code 0
$ echo $?
0

Validation failure with conflicting overlays (exit code 1):

$ utils/dt/scripts/validate_overlay_conflicts.sh "enable_dss0.dtso disable_dss0.dtso"
ERROR: Conflicting overlays for node 'dss0':
  - enable_dss0.dtso
  - disable_dss0.dtso

ERROR: Found 1 conflicting overlay pair(s).
Remove either the enable_ or disable_ overlay for each conflicting node.
$ echo $?
1

If validation fails, revise your overlay list to remove the conflicting pairs and try again.

11.7.8. Make Clean Between Builds

Important

When switching between different build modes (legacy → DT, DT → legacy, or changing overlays), you MUST run make clean to delete previously generated device tree headers. Otherwise, the old devicetree_generated.h will be used and your new overlay settings will not take effect.

Example: Switching from overlay mode to legacy mode:

# Build 1: With overlays
make all SOC=j722s DTS_OVERLAY=disable_dss0.dtso,disable_gpu.dtso

# Clean before switching modes
make clean

# Build 2: Back to legacy mode (no DT)
make all SOC=j722s

Example: Switching from legacy to base DT mode:

# Build 1: Legacy mode (no DT)
make all SOC=j722s

# Clean before enabling DT
make clean

# Build 2: With base DT only
make all SOC=j722s DTS_OVERLAY=base

11.7.9. Build Examples

Example 1: Disable Display and GPU

Disable the display subsystem and GPU to reduce power consumption:

cd ${PSDK_QNX_PATH}
utils/dt/scripts/validate_overlay_conflicts.sh "disable_dss0.dtso disable_dss1.dtso disable_gpu.dtso"
make all SOC=j722s DTS_OVERLAY=disable_dss0.dtso,disable_dss1.dtso,disable_gpu.dtso

Example 2: Enable Minimal Interfaces

Build with only essential interfaces (Ethernet and UART):

cd ${PSDK_QNX_PATH}
# Build defaults to enabling basic interfaces; disable others as needed
utils/dt/scripts/validate_overlay_conflicts.sh "disable_dss0.dtso disable_gpu.dtso disable_usb0.dtso disable_usb1.dtso"
make all SOC=j722s DTS_OVERLAY=disable_dss0.dtso,disable_gpu.dtso,disable_usb0.dtso,disable_usb1.dtso

Example 3: Enable Additional Interfaces

If the default build doesn’t enable certain required interfaces, use enable overlays:

cd ${PSDK_QNX_PATH}
utils/dt/scripts/validate_overlay_conflicts.sh "enable_main_i2c2.dtso enable_sdhci1.dtso"
make all SOC=j722s DTS_OVERLAY=enable_main_i2c2.dtso,enable_sdhci1.dtso

11.7.10. Configuring Build Files and User Scripts for Disabled Devices

When you build a startup with specific devices disabled via overlays, the corresponding resource manager (RM) processes launched in the build file and user script must be synchronized with your device tree configuration. Mismatches between disabled devices and running RMs will cause errors during boot.

11.7.10.1. Overview

The device tree overlays define which hardware devices are initialized at the bootloader level. However, QNX processes (resource managers, and display servers) are launched separately:

  • Build file (bsp_800_j722s/images/j722s-evm-ti.build) — Defines RMs that run before QNX boots

  • User script (scripts/user_j722s.sh) — Defines resource managers and services that run after QNX boots

If a resource manager tries to access a disabled device, boot will fail or hang. Therefore, when you disable a device via overlays, you must comment out the corresponding launcher in both the build file and user script.

11.7.10.2. Device Launcher Mapping

The following table maps each disableable device to its disable overlay and the corresponding launcher lines:

Device Name

Disable Overlay

Build File Launcher

User.sh RM/

I2C 0 (Main)

disable_main_i2c0.dtso

i2c-tda4 -p0x20000000 -i193

(none)

I2C 0 Pins

disable_main_i2c0_pins

(part of i2c0 above)

(none)

I2C 1 (Main)

disable_main_i2c1.dtso

(commented - shared with R5F)

(none)

I2C 2 (Main)

disable_main_i2c2.dtso

(commented - not enabled)

(none)

eMMC

disable_sdhci0.dtso

devb-sdmmc-am65x addr=0x0fa10000

(none)

SD Card

disable_sdhci1.dtso

devb-sdmmc-am65x addr=0x0fa00000

(none)

MMC1 Power

disable_vdd_mmc1.dtso

(part of sdhci)

(none)

DSS0 Display

disable_dss0.dtso

(not launched)

screen -c ...

DSS0 VP1 Clock

disable_dss0_vp1_clk.dtso

(not launched)

screen -c ...

DSS1 Display

disable_dss1.dtso

(not launched)

screen -c ...

DSS Clock Control

disable_dss_clk_ctrl.dtso

(not launched)

screen -c ...

GPU

disable_gpu.dtso

(not launched)

screen -c ...

USB3SS0 (DWC3)

disable_usbss0.dtso

io-usb-otg dwc3 ioport=0x31000000

(none)

USB0 PHY Control

disable_usb0_phy_ctrl

(part of usbss0 above)

(none)

USB3SS1 (CDNS3)

disable_usbss1.dtso

io-usb-otg cdns3 ioport=0x31210000

(none)

USB1 Pins

disable_main_usb1_pins

(part of usbss1 above)

(none)

OSPI NOR Flash

disable_ospi0.dtso

(commented - not enabled)

(none)

11.7.10.3. Build File Configuration Examples

Example 1: Disable Display and GPU

If you build with DTS_OVERLAY=disable_dss0.dtso,disable_dss1.dtso,disable_gpu.dtso, display devices are disabled at the DT level. No changes are needed in the build file since dss and gpu are not launched there. However, if you launch the screen service in user.sh, it must be disabled:

# user_j722s.sh - comment out the screen service
# screen -c graphics-virtual-dpy.conf

Example 2: Disable I2C0

If you build with DTS_OVERLAY=disable_main_i2c0.dtso, I2C devices will not be initialized. Comment out the i2c RM in the build file:

# j722s-evm-ti.build - comment out i2c0 RM
# i2c-tda4 -p0x20000000 -i193

After disabling I2C0, any I2C bus operations in applications will fail. The i2c device nodes will not be created.

Example 3: Minimal Boot - Disable Most Peripherals

For a minimal system that boots QNX without display, GPUs, or USB:

# Build command
make all SOC=j722s DTS_OVERLAY=disable_dss0.dtso,disable_dss1.dtso,disable_gpu.dtso,disable_usbss0.dtso,disable_usbss1.dtso

# j722s-evm-ti.build - comment out USB RMs
# io-usb-otg dwc3 ioport=0x31000000
# io-usb-otg cdns3 ioport=0x31210000

# user_j722s.sh - comment out display service
# screen -c graphics-virtual-dpy.conf

This configuration keeps only I2C, eMMC, and SD card enabled, suitable for headless embedded systems.

Example 4: Disable SD Card Only

If your system uses only eMMC (no removable SD card), disable SD:

# Build command
make all SOC=j722s DTS_OVERLAY=disable_sdhci1.dtso,disable_vdd_mmc1.dtso

# j722s-evm-ti.build - comment out SD card RM
# devb-sdmmc-am65x addr=0x0fa00000

# Keep eMMC RM enabled
devb-sdmmc-am65x addr=0x0fa10000

11.7.10.4. Device Dependencies and Constraints

Some devices have interdependencies that you should be aware of:

  • eMMC/SD Card: Both controllers use the same power domain (vdd_mmc1). Disabling MMC1 power affects both. Disabling sdhci1 alone (SD card) does not require disabling vdd_mmc1 if eMMC is still in use.

  • USB SerDes: Both USB3SS controllers depend on shared SerDes PHY resources (serdes0, serdes_refclk, serdes_wiz0). Disabling SerDes overlays (disable_serdes0.dtso, disable_serdes_wiz0.dtso) will break USB functionality. Conversely, disabling both USB controllers makes SerDes unused, but SerDes overlays should still be managed explicitly.

  • I2C Constraints: I2C1 and I2C2 are reserved for R5F cores (ARM Cortex-R5F processors) in the default configuration. The code is commented with a TODO note indicating shared access. Do not enable i2c1 or i2c2 unless you have coordinated with R5F firmware to avoid conflicts.

  • Display/GPU: Display (DSS) and GPU are independent but share the graphics rendering pipeline if both are used. Disabling dss0 without disabling gpu will still consume GPU resources; the opposite is also true.

11.7.10.5. Failure Modes and Troubleshooting

Symptom: Resource Manager exits with “Permission denied” or “Device not found”

Cause: A RM in the build file or resource manager in user.sh is trying to access a device that has been disabled via DT overlays.

Resolution: 1. Check which overlay was applied during build 2. Identify the corresponding RM from the mapping table above 3. Comment out that RM line 4. Run make clean (important!) 5. Rebuild: make all SOC=j722s ...

Symptom: QNX boot hangs after device tree initialization

Cause: A launcher is trying to initialize hardware that has been disabled at the DT level. The RM may be waiting indefinitely for a device response.

Resolution: 1. Review the build file and user.sh for any RMs matching disabled devices 2. Ensure all disabled device launchers are commented out 3. Run make clean to remove stale headers 4. Rebuild and reboot

Symptom: I2C devices not responding even though i2c0 RM is running

Cause: I2C0 pins have been disabled via disable_main_i2c0_pins_default.dtso while the i2c RM is still launching.

Resolution: 1. If you disabled i2c0, comment out the i2c RM 2. If you only disabled pins (not the full i2c0 device), the controller exists but pins are not muxed - enable pin configuration overlay or comment out the i2c RM

11.7.10.6. Future Automation Consideration

Currently, you must manually synchronize overlay choices with launcher configuration in two separate files. A future enhancement could automate this process:

Note

Conceptual Automation (Not Implemented Yet)

A build system enhancement could: 1. Parse DTS_OVERLAY variable to extract disabled devices 2. Generate a filtered build file (commenting out matching device launchers) 3. Generate a filtered user.sh (commenting out matching resource managers) 4. Log all changes for verification

This would eliminate manual file edits and reduce errors. Implementation would require: - Python script to parse overlay filenames and extract device names - sed/awk-based filtering of build file and user.sh templates - Validation step to ensure all disabled devices have matching commented launchers - Integration into the top-level makefile as a pre-build step

11.7.10.6.1. Refinement: Limiting Disable-able Nodes to hw_init.c Peripherals

A key refinement for future automation should be to limit the available disable overlays to only the device nodes that are actually used by QNX hardware initialization (hw_init.c). This ensures users cannot inadvertently disable arbitrary device tree nodes that have no relevance to system boot.

Current State: - The minimal DTS (j722s-hw-init.dts) was specifically extracted to contain only nodes required by hw_init.c - However, the full preprocessed DTS contains many additional nodes that could theoretically be disabled - Users might disable unrelated nodes without realizing they have no effect on boot or functionality

Proposed Refinement: - Generate disable overlays only for nodes that appear in both:

  1. The minimal DTS (j722s-hw-init.dts)

  2. The corresponding hw_init.c driver initialization code

  • Document the 1:1 mapping between each disable overlay and the specific hw_init.c code section it affects

  • Optionally generate a constraint list preventing disabling of critical boot dependencies (e.g., cannot disable main clocks without disabling dependent devices)

Benefit: Users would only see device options relevant to their actual system boot configuration, reducing confusion and preventing accidental misconfiguration. The overlay list would be maintainable and directly traceable to source code.

11.7.11. Troubleshooting

Missing overlay file error:

If you receive an error like “Overlay file not found”, verify:

  1. The overlay file exists in ${PSDK_QNX_PATH}/qnx/utils/dt/dts/j722s/overlay/

  2. You spelled the overlay filename correctly

  3. You are running the build command from the QNX repository root

Conflicting overlays error:

If the build fails with a conflict error, run the validation script to identify which overlays are conflicting, then remove one of the conflicting pairs.

Device not responding after build:

If a peripheral that you expected to initialize is not responding:

  1. Verify that you did not accidentally disable it with a disable overlay

  2. Check that the device’s pin configuration overlay is enabled (if one exists)

  3. Verify the hardware connections and power supplies

11.7.12. Developer Note: Future Build System Enhancement

Note

The validation script (validate_overlay_conflicts.sh) is currently available as a manual step before building. Future versions of the build system should automatically integrate this validation into the build chain to prevent invalid configurations at build time. Users should manually run the validation script before invoking the make bsp command to catch configuration errors early.

11.7.13. Summary

QNX BSP Device Tree Build Modes:

  1. Legacy (default): make all SOC=j722s — All devices enabled, no device tree

  2. Base DT only: make all SOC=j722s DTS_OVERLAY=base — Base device tree, no overlays

  3. DT with overlays: make all SOC=j722s DTS_OVERLAY=<overlay_list> — Device tree with customization

For overlay builds:

  1. Choose the devices you want to enable or disable

  2. Validate your overlay list: utils/dt/scripts/validate_overlay_conflicts.sh "<overlay_list>"

  3. Build with overlays: make all SOC=j722s DTS_OVERLAY=<overlay_list>

Important reminders:

  • Specifying DTS_OVERLAY (with base or overlay filenames) automatically enables the device tree infrastructure and defines the USE_DT preprocessor macro

  • Run make clean when switching between build modes to ensure old headers are removed

  • The resulting startup file will initialize only the peripherals specified in your device tree configuration

  • You can build only the BSP with make bsp SOC=j722s ... instead of the full build with make all SOC=j722s ...

See also