Device tree source buddy to help people compile & load DTBOs at runtime in Elixir
DtsBuddy is meant to provide utilities to handle runtime loading of device tree overlays, while reducing the ceremony required by the configfs interface.
# import the sigil
import DtsBuddy.Sigil
# enable runtime overlays
DtsBuddy.enable_overlays()
# should return true
DtsBuddy.overlays_enabled?()
# call the sigil, which compiles the overlay through dtc
compiled =
~DTS"""
/dts-v1/;
/plugin/;
&{/soc/pinctrl@2000000} {
pwm7_pb10: pwm7-pb10 { pins = "PB10"; function = "pwm7"; };
};
&{/soc/pwm@2000c00} {
pinctrl-names = "default";
pinctrl-0 = <&pwm7_pb10>;
status = "okay";
};
"""pwm7ch
# load it
DtsBuddy.load(compiled)
# on a properly configured system, it will return :applied
DtsBuddy.status("pwm7ch")Nerves systems must be compiled with those options for this to work :
BR2_PACKAGE_DTC=y
BR2_PACKAGE_DTC_PROGRAMS=y
CONFIG_OF_CONFIGFS=y
The overlays configfs must first be enabled :
iex> DtsBuddy.enable_overlays()
:ok
This has the same effect as running this command (and does behind the scenes) :
System.cmd("mount" , ["-t", "configfs", "none", "/sys/kernel/config"])
iex> DtsBuddy.overlays_enabled?()
true
If your source is fully static, you can either call DtsBuddy.compile/2 or use
the sigil provided by DtsBuddy.Sigil. The source of the following examples was
provided by Frank Hunleth.
iex> import DtsBuddy.Sigil
iex> ~DTS"""
/dts-v1/;
/plugin/;
/* Compile:
dtc -@ -I dts -O dtb -o gpio_led.dtbo gpio_led.dts
*/
&{/} {
gpios_leds {
compatible = "gpio-leds";
test_led@36 {
label = "test-led-gpio36";
gpios = <&pio 1 4 0>; /* GPIO36/PB4 */
/* Blink LED at 1 Hz (500 ms on, off) */
linux,default-trigger = "pattern";
led-pattern = <1 500 1 0 0 500 0 0>;
};
};
};
"""test_led
{:ok, "/data/test_led.dtbo", "test_led"}
You should provide both the heredoc contents (inside triple quotes) and modifiers (after the heredoc closes, here "test_led"). We use the modifiers as the overlay name later.
Using the sigil is strictly equivalent to calling DtsBuddy.compile/2.
DtsBuddy does not immediately load this overlay.
If your source is not static, you can either manually build it to call DtsBuddy.compile/2,
or use DtsBuddy.compile_eex/3 to use an EEX template string.
The DtsBuddy.load function is thought to use the compilation result coming from either
DtsBuddy.compile/2 or DtsBuddy.compile_eex/3 directly, that is, a tuple having
the form {:ok, dtbo_file, name}.
Loading the overlay with the name will create the directory /sys/kernel/config/device-tree/overlays/<name>,
and write the contents of the compiled dtbo file to /sys/kernel/config/device-tree/overlays/<name>/dtbo.
After loading an overlay, calling DtsBuddy.status/1 with the overlay name should return :applied.