Дерево устройств (Device Tree, DT) — это структура данных в системе Linux, состоящая из именованных узлов и свойств, описывающих оборудование, которое невозможно обнаружить путем опроса оборудования. Дерево должно включать имя базового процессора, конфигурацию его памяти и любые периферийные устройства (внутренние и внешние). DT не используется для описания программного обеспечения, хотя перечисление аппаратных модулей вызывает загрузку модулей драйверов. Пост раскрывает принцип формирования DT на примере отладочной платы Banana Pi BPI-M64, по итогу Вы сможете самостоятельно конфигурировать периферийные устройства GPIO, включая другие платы, например Raspberry Pi.
Сердцем любой отладочной платы или одноплатного компьютера является SoC. SoC имеет множество контактов (ног) для подключения линий электропитания и различных устройств.
Контакты могут быть объедены вместе для формирования интерфейса, например MIPI DSI(MIPI Display Serial Interface). Интерфейс MIPI DSI предназначен для подключения LCD панелей, активно используется в смартфонах и планшетах. Но если к устройству не планируется подключать дисплей по MIPI DSI, то эти линии можно использовать для других целей, путем изменения DT. В отличие от архитектуры x86 в системах построенных на SoC нет возможности произвести полностью опознание всех устройств в режиме Plug and Play. Поэтому необходимо явное декларирование какие контакты используются для интерфейсов и какие именно устройства подключены к этим интерфейсам.
До появления DT информация об устройствах в Linux являлась неотъемлемой частью ядра, и в случае изменения состава периферийных устройств требовалось пересобрать образ системы. Это было крайне неудобно, и поэтому описание периферийных устройств перенесли в конфигурационные файлы, которые собираются на логическом уровне в дерево. Где ветвь — устройство с указанием драйвера необходимого для работы этого устройства.
После использования DT отпала необходимость в формирование индивидуального образа для каждого набора периферии устройств. Теперь достаточно сформировать один образ, включить в него набор драйверов для различных устройств, и для каждого устройства сформировать свой DT.
Наложения дерева устройств (Device Tree overlays)
Device Tree overlays (наложения дерева устройств) — добавление к DT принципа наложения слоев устройств. Если конфигурация описывает интерфейс UART к которому был подключен Bluetooth, и необходимо Bluetooth заменить на GPS модуль, то можно не удалять существующие настройки Bluetooth а добавить дополнительный слой для GPS модуля который переопределит предыдущие настройки.
Для работы с DT используются следующие термины:
DT | Дерево устройств |
DTB (*.dtb) | Бинарный файл дерева устройств |
DTBO (*.dtbo) | Бинарный файл дерева устройств для наложения |
DTC | Компилятор дерева устройств |
DTO | Наложения дерева устройств |
DTS (*.dts) | Исходный файл для дерева устройств |
FDT | Flattened Device Tree, двоичный формат, содержащийся в файле .dtb |
Аппаратная конфигурация описывается в файлах исходниках DT ( .dts ) затем они компилируется в бинарные файлы DT ( .dtb ) уже для конечного использования в системе. Так же можно выполнить обратную процедуру декомпиляции файлов *. dtb в *. dts, компилятор/декомпилятор присутствует в системе.
Реализация DTO включает разделение дерева устройств, построение, разбиение на разделы и исполнение.
Разделение DT
DT разделяются на две части:
- Main DT (основное дерево устройств). Предоставляет разработчик SoC и является настройкой по умолчанию. В данном случае предоставляет компания Allwinner разработчик процессора Allwinner A64.
- Overlay DT (Накладываемое дерево устройств). Специфическая конфигурация производителя платы, включает периферийные устройства которые размещены на плате. Для платы Banana Pi BPI-M64 предоставляет компания SinoVoip Co.,
Видео с конференции Linux Piter 2016. Ходырев Дмитрий и Олейников Иван: «Device Tree Overlay» [RUS]
На конференции Linux Piter 2016, разработчики FPGA из компании НТЦ Метротек Ходырев Дмитрий и Олейников Иван рассказали про Device Tree Overlay» [RUS]. Доклад рассказывает о основах технологии device tree, позволяющей абстрагироваться от аппаратной специфики при работе с ядром Linux.
В этом докладе мы будем говорить о файлах Device Tree, структуре и синтаксисе, о поддержке структуры Device Tree в ядре Linux.Рассмотрим несколько простых примеров решения практических задач используя Device Tree. Доклад расчитан на слушателей, которые хотели бы больше узнать о особенностях ядра Linux. Более всего доклад будет полезен разработчикам ARM-платформ, разработчикам систем с FPGA, разработчикам драйверов.
Построение основного и накладываемого дерева устройств
Построение основного дерева устройств:
- Скомпилируйте основное DT *.dts в *.dtb файл.
- Поместите файл *.dtd в раздел загрузчика(bootloader) системы
Построение накладываемого дерева устройств(DTO)
- Скомпилируйте накладываемые файлы DT *.dts в файлы *.dtbo. Несмотря на совпадение структур файла .dtb и .dtbo, файл .dtb является основным в системе, в то время как файлы .dtbo добавочные.
- Поместите файл *.dtd в раздел загрузчика(bootloader) системы
Файлы DT не монолитны, они могут быть разделены на несколько частей в нескольких файлах, включая каждый из них. .dtsi файлы включают файлы платформы, пока .dts файлы не определят конечный вид дерева устройств. Типичная связь, .dtsi файлы будут включать информацию для SoC уровня(или иногда общее определение к некоторым почти идентичным платам). .dts файл включает информацию уровня отладочной платы (платы разработки). Присоединение работает следующим образом, происходит наложение файлов описывающих платформу (включенных файлов в проект) и формирование единого описания для платформы.
Пример присоединение дерева устройств
Использование дерева устройств в загрузчике (bootloader)
Принцип работы объединения дерева устройств в загрузчике (bootloader):
- Загрузка .dtb с носителя данных в оперативную память
- Загрузка .dtbo с носителя данных в оперативную память
- Наложение файла .dtb с файлами .dtbo для слияния DT
- Запуск ядра с указателем в памяти на адрес объединенного DT
Синтаксис DTO
Device Tree Source (.dts) текстовый формат файлов для представления дерева устройств. Компилятор дерева устройств (DTC) преобразует этот формат в бинарный вид .dtd который непосредственно читается ядром Linux.
Использование Ссылок
Проект DTC (Device Tree compiler + overlay patches) содержит описание формата DTS в dtc-format.txt и manual.txt . Формат и правила DTO описаны в dt-object-internal.txt . В этих документах описывается, как обновить основное DT, используя узел fragment@x и синтаксис __overlay__ в накладываемом DT. Например:
Google настоятельно рекомендует не использовать fragment@x и синтаксис __overlay__ , а вместо этого использовать синтаксис ссылки. Например:
Ссылочный синтаксис компилируется DTS в тот же объект, что и выше, с использованием синтаксиса __overlay__ . Этот синтаксис не заставляет вас нумеровать фрагменты, что упрощает чтение и запись DTS.
Использование Меток
Для построения компилятором накладываемого дерева устройств файл *.dts должен содержать метку /plugin/ в заголовке. . Например:
/dts-v1/;
/plugin/;
Здесь вы можете ссылаться на узлы в основном дереве устройств. Ссылки должны начинаться с амперсанда (&). Например, для node@0 в основном дереве устройств:
Перезапись
Если свойство в узле существует в DTO и DT, то оно переопределяется в DTO; в противном случае если его нет в DTO то добавляется. Например:
Добавление
Если ссылочное целевое свойство не существует в основном DT, оно добавляется после DTO. Например:
Дочерние узлы
Примеры синтаксиса дочернего узла:
Компиляция
Получение файла .dts из .dtb:
dtc -I dtb -O dts /boot/dtb/allwinner/sun50i-a64-bananapi-m64.dtb -o /boot/dtb/allwinner/sun50i-a64-bananapi-m64.dts
Компилирует файл .dts в .dtb
dtc -I dts -O dtb /boot/dtb/allwinner/sun50i-a64-bananapi-m64.dts -o /boot/dtb/allwinner/sun50i-a64-bananapi-m64.dtb
Плагин DeviceTree Language Support для Visual Studio Code
Редактировать DTS файлы в блокноте крайне неудобно из-за отсутствия подсветки синтаксиса, и возможности сворачивать/разворачивать узлы. Для редактирования DTS можно загрузить бесплатную Visual Studio Code и установить плагин DeviceTree Language Support.
DeviceTree Language Support for Visual Studio Code
Дерево устройств в образе Armbian для Banana Pi BPI-M64
Для рассмотрения взята версия Armbian_20.08.2_Bananapim64_bionic_current_5.8.6_minimal.img.xz, основанная на Ubuntu 18.04.5 LTS Linux bananapim64 5.8.6-sunxi64 #20.08.2 SMP Fri Sep 4 08:52:31 CEST 2020 aarch64 aarch64 aarch64 GNU/Linux. Исходники DTS в репозитории Linux располагаются по пути: /linux/arch/arm/boot/dts. Ссылка на зеркало Linux-Armbian.
Все бинарные файлы дерева устройств (DTB) располагаются по пути: /boot/dtb/allwinner
В этом каталоге располагаются DTB всех плат которые поддерживаются Armbian. В зависимости от модели платы загружается нужный файл DTB.
Для платы Banana Pi BPI-M64 в каталоге предназначен файл: sun50i-a64-bananapi-m64.dtb, из него получим файл DTS, командой (файл sun50i-a64-bananapi-m64.dts):
dtc -I dtb -O dts /boot/dtb/allwinner/sun50i-a64-bananapi-m64.dtb -o /boot/dtb/allwinner/sun50i-a64-bananapi-m64.dts
В каталоге /boot/dtb/allwinner/overlay располагаются DTBO. Для платы Banana Pi BPI-M64 в каталоге предназначены файлы с префиксом: sun50i-a64-*.dtbo
В предыдущей публикации Работа с GPIO на примере Banana Pi BPI-M64. Часть 1. Интерфейс sysfs LED и DS18B20 на 18-контакте разъема типа Raspberry Pi в утилите конфигурирования
armbian-config
был включен интерфейс 1-Wire, в меню называется: w1-gpio. При включение пункта w1-gpio активируется слой в файле sun50i-a64-w1-gpio.dtbo. Конфигурация о подключенных DTBO располагается в файле /boot/armbianEnv.txt. Как раз в строке с ключем overlays= указан файл w1-gpio. Префикс sun50i-a64-* — настроен в конфигурационном файле(параметр overlay_prefix=) и является обязательным для всех DTBO платы Banana Pi BPI-M64
Если помимо w1-gpio включить интерфейс uart1 файл: sun50i-a64-uart1.dtbo
то в файле /boot/armbianEnv.txt строка overlays измениться: overlays=uart1 w1-gpio:. названия файлов:
Использование компилятора DTC
Файл sun50i-a64-w1-gpio.dtbo представлен в бинарном виде и редактировать его напрямую затруднительно, поэтому конвертируем файл формата DTBO в DTS:
dtc -I dtb -O dts /boot/dtb/allwinner/overlay/sun50i-a64-w1-gpio.dtbo -o /boot/dtb/allwinner/overlay/sun50i-a64-w1-gpio.dts
На выходе получим файл: sun50i-a64-w1-gpio.dts. После изменений DTS необходимо обратно его перевести в формат DTBO командой:
cd /boot/dtb/allwinner/overlay dtc -O dtb -o sun50i-a64-w1-gpio.dtbo sun50i-a64-w1-gpio.dts
Структура файла sun50i-a64-w1-gpio.dts
Файлы DT доступны в GitHub armbian/sunxi-DT-overlays.
Если получать файл DTS из DTBO, то в нем будут содержаться ссылочные секции и символьные понятные метки будут заменены на шестнадцатеричный вид. Поэтому файл sun50i-a64-w1-gpio.dts лучше взять из GitHub sun50i-a64-w1-gpio.dts. Рассмотрим sun50i-a64-w1-gpio.dts:
Очень интересно получилось, но абсолютно непонятно. Выше был получен файл sun50i-a64-bananapi-m64.dts основного DT процессора AllWinner A64, поэтому составим понятную диаграмму, со ссылками к основному DT, и добавим результирующее DT Linux после загрузки:
Замечание: по мере изучения литературы этот раздел будет в дальнейшем дополняться. Учитывая что новая ветка ядра мало документирована в части GPIO, то потребуется некоторое время на чтение исходников.
Создание своего DTBO для протокола 1-Wire
В предыдущей публикации Работа с GPIO на примере Banana Pi BPI-M64. Часть 1. Интерфейс sysfs LED и DS18B20 на 18-контакте разъема типа Raspberry Pi, был включен интерфейс 1-Wire. Из схемы, 18-контакт называется «PD4«, этот контакт мультиплексирован и также имеет функцию UART4_RTS. При включение 1-Wire лишись полноценного UART4, поэтому перенесем интерфейс на другой контакт. Удалять файл sun50i-a64-w1-gpio.dtbo нет необходимости т.к. в конфигурации его выключим после создания своего DTBO. В качестве шаблона возьмем GitHub sun50i-a64-w1-gpio.dts, и переименуем в sun50i-a64-w1-gpio-custom.dts.
Из схемы возьмем 22-контакт, название «PC0«, никакие функции с этим контактом не связаны.
Внесем изменения в файл sun50i-a64-w1-gpio-custom.dts:
Компилирует файл .dts в .dtb
cd /boot/dtb/allwinner/overlay dtc -I dts -O dtb sun50i-a64-w1-gpio-custom.dts -o sun50i-a64-w1-gpio-custom.dtbo
Запустим утилиту конфигурирования платы:
armbian-config
Перейдем по меню: System > Hardware. Список дополнился новым пунктом w1-gpio-custom, выберем его:
Затем сохранить <Save> и < Back >. Будет предложено перезагрузить палату, соглашаемся и ждем перезагрузки:
После перезагрузки выполняем команду:
dmesg | grep -E 'w1|wire'
В результате должны получить примерно такой результат:
Из которого следует что драйвер 1-Wire был включен на контактах gpio-100 и gpio-64. Теперь можем посмотреть какие контакты использованы в устройстве /soc/pinctrl@1c20800:
cat /sys/kernel/debug/gpio
Получим значения температуры:
cat /sys/bus/w1/devices/28-0000034aa0ba/w1_slave
Устройства зарегистрированные в системе, в том числе onewire@0 и onewire@1, можно посмотреть командой:
cd /proc/device-tree/ ls -l
Добавление cron задачи
Но как видим точность вывода установлена по умолчанию, а хотелось бы получать более точные значения, без ручной настройки. Узнать как установить точность на уровне скрипта к драйверу, не удалось. Поэтому настройку будем выполнять через привычный интерфейс sysfs и добавим команду выполнения после загрузки ОС через cron задачи:
Проверка работы демона cron
systemctl status cron
Редактировать cron задачи
crontab -e
Вставить строку, сохранить изменения и перезагрузить плату:
@reboot sleep 5 && sudo echo 12 > /sys/bus/w1/devices/28-0000034aa0ba/w1_slave
Ссылки
- GitHub armbian/sunxi-DT-overlays
- Android Наложения дерева устройств
- Petazzoni Device tree for dummies PDF
- Device Tree Customization
- Device Tree Overview
- Device Tree Overlays
- OSD335x Lesson 2: Linux Device Tree
- Linux Device tree
- Analysis of the device tree of Linux driver development 24
- Building a device tree overlay for your new PocketCape design
- Linux Kernel notes
- meizu Device Tree
- COM iMX6 Linux
- The DeviceTree Specification
- Boot-time Device Tree Overlays with U-Boot
- Specifying GPIO information for devices
- Armbian: Device Tree overlays
- Enabling new hardware on Raspberry Pi with Device Tree Overlays
- New feature highlights in Elixir Cross Referencer v2.0 and v2.1
- GPIO_ACTIVE_HIGH /include/dt-bindings/gpio/gpio.h
- Visual Studio Code
- DeviceTree Language Support for Visual Studio Code