Wstęp
Devicetree jest przekazywane do kernela przez bootloader podczas procesu bootowania linuxa. W nim zawiera się mapa sprzętu podłączonego do procesora, dzięki temu kernel wie jak zainicjalizować sprzęt i jakie załadować sterowniki.
UWAGA: Materiał video uzupełniający ten wpis znajdziesz na YouTube:
Najpierw wyjaśnijmy po co zostało w ogóle stworzone devicetree. Na początku, cały opis podłączonego sprzętu zawierał się w kernelu, był w nim zahardkodowany. I miało to jedną, bardzo dużą wadę – na każdą wersję produktu trzeba było przygotować osobny obraz kernela, co było bardzo pracochłonne. Na przykładzie Raspberry pi – firma która je produkuje wspiera wiele różnych wersji. Raspberry Pi 3, 4, 5 poza tym są jeszcze różne wersje compute module i kilka innych. I na każde z tych urządzeń trzeba wykonać podobne kroki i przebudowywać kernel za każdym razem.

Obrazuje to powyższy diagram – każda wersja produkty wymaga przygotowania i utrzymania osobnego obrazu kernela.
Natomiast gdy mamy devicetree, możemy mieć jednego kernela i kilka różnych konfiguracji, które są wczytywane w zależności od tego, jaki mamy sprzęt.

Ważne skróty
DTS – Device Tree Structure
DTSI – Device Tree Structure Include
DTB – Device Tree Blob (skompilowane devicetree <DTS>)
DTBO – Device Tree Overlay
Modyfikacja DTS na Raspberry Pi
Co jeśli chcemy zmodyfikować istniejące devicetree, np. dla Raspberry Pi? Można zmienić kod konfiguracji bezpośrednio w źródłach, ale to bardziej skomplikowany sposób i częściej używany jeśli tworzymy własne płytki i musimy dostosować do nich devicetree.
Warto również pamiętać, że DT to standardowy mechanizm w systemach opartych na Linuxie i instrukcje dotyczące konkretniej platformy sprzętowej będą przydatne również na innych.
Raspberry Pi Foudation (twórcy płytek) wspiera wiele różnych opcji HW. Na przykład moduł uart jest dzielony między moduł bluetooth a działanie jako zwykła konsola. I żeby nie musieć za każdym razem zmieniać devicetree, to stosuje się „patche” na devicetree, które modyfikują tylko niektóre fragmenty głównego drzewa. Nazywa się je devicetree overlay, czyli dosłownie „nakładki na devicetree”.
Przykładowy overlay możesz znaleźć pod tym linkiem: https://github.com/raspberrypi/linux/blob/rpi-6.6.y/arch/arm/boot/dts/overlays/adafruit-st7735r-overlay.dts
Stworzymy teraz własny devicetree overlay, który włączy dodatkową diodę podłączoną do jednego z pinów GPIO, i ustawi jej tryb świecenia w heartbeat.
Kod devicetree overlay
Poniżej znajdziesz kod DT overlay:
/dts-v1/;
/plugin/;
/ {
compatible = "brcm,bcm2835";
fragment@0 {
// Configure the gpio pin controller
target = <&gpio>;
__overlay__ {
led_pin1: led_pins@23 {
brcm,pins = <23>; // gpio number
brcm,function = <1>; // 0 = input, 1 = output
brcm,pull = <0>; // 0 = none, 1 = pull down, 2 = pull up
};
};
};
fragment@1 {
target-path = "/";
__overlay__ {
leds1: leds@1 {
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&led_pin1>;
status = "okay";
led1: led {
label = "karol";
gpios = <&gpio 23 0>;
linux,default-trigger = "heartbeat";
};
};
};
};
};
Najważniejsze właściwości overlaya:
- /dts-v1/; – definiuje wersję składni devicetree. opis w specyfikacji,
- / – węzeł główny, czyli root node. opisuje ogólnie naszą platformę
- Węzły i właściwości, czyli nodes i properties:
- Węzły – reprezentują hierarchiczną strukturę drzewa, to są peryferia i magistrale podłączone do procesora i obecne na platformie.
- Właściwości – opisują węzły. Przykładowo property o nazwie compatible definiuje jaki sterownik będzie przyporządkowany danemy nodowi. np regulator-gpio.
- Definiując nody po prostu piszemy ich nazwę, jeśli chcemy się do nich odnieść to używamy &
- Najważniejsze properties:
- compatible – definicja zgodności, jaki sterownik będzie obsługiwał dany sprzęt
- status – oznacza czy sprzęt jest operacyjny na urządzeniu. okay – włączony, disabled – wyłączony, ale może zostać właczony jeśli trzeba (jest obecny w systemie)
- reg – jaki obszar pamięci będzie zajmował. większość peryferiów jest mapowana do pamięci i tutaj właśnie jest to definiowane
- /chosen – ważny parametr, to nie jest definicja sprzętowa, a oznacza jakie parametry będą przekazane w trakcie runtime do firmware’u, tutaj jest to parametr dla konsoli szeregowej. Musi to być child node root noda
Kompilacja
Stworzyliśmy nasz overlay – teraz musimy go skompilować. Można to zrobić za pomocą komendy:
dtc -@ -Hepapr -I dts -O dtb -o my_overlay.dtbo led_overlay.dts
Następnie plik wynikowy, my_overlay.dtbo przenosimy na partycję bootfs/ do katalogu overlays/
Następnie w pliku config.txt dodajemy:
dtoverlay=my_overlay
Po podłączeniu płytki do zasilania dioda podłączona o pinu GPIO23 zacznie migać.
Dokumentacja
Gdzie szukać informacji o DT i overlayach? Najlepiej w oficjalnej dokumentacji. Większość informacji jest zawarta w tzw. dt-bindings. Są to dokumenty utworzone dla każdego subsystemu kernela, gdzie znajduje się opis w jaki sposób opisywać dany sprzęt w devicetree.
Przykładowy dt-binding dla LEDów: https://github.com/raspberrypi/linux/tree/rpi-6.6.y/Documentation/devicetree/bindings/leds
Dodaj komentarz