Orange Pi Lite2: 1-Wire

Приобрел одноплатный компьютер с самым новым на сегодня чипом H6 и увы, не нашел так необходимой мне поддержки протокола OneWire для чтения датчиков температуры DS18b20. Т.е. она то в чипе есть, а драйверов нет. И даже стандартного софтварного драйвера w1-gpio нет в предлагаемых дистрибутивах ОС. Решаем.

Для начала добавим библиотеку WiringOP — fork WiringPI

# apt-get install git
# git clone https://github.com/orangepi-xunlong/WiringOP
# cd WiringOP

В файлах gpio/Makefile и WiringPI/Makefile раскомментируем строчку PLATFORM = OrangePi_LITE2

# ./build
# cd gpio
# gpio readall
+------+-----+----------+------+---+OrangePiH6+---+------+----------+-----+------+
| GPIO | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | GPIO |
+------+-----+----------+------+---+----++----+---+------+----------+-----+------+
| | | 3.3v | | | 1 || 2 | | | 5v | | |
| 230 | 0 | SDA.1 | IN | 1 | 3 || 4 | | | 5V | | |
| 229 | 1 | SCL.1 | IN | 1 | 5 || 6 | | | 0v | | |
| 228 | 2 | PWM1 | IN | 1 | 7 || 8 | 1 | IN | PD21 | 3 | 117 |
| | | 0v | | | 9 || 10 | 1 | IN | PD22 | 4 | 118 |
| 120 | 5 | RxD3 | IN | 1 | 11 || 12 | 1 | IN | PC09 | 6 | 73 |
| 119 | 7 | TxD3 | IN | 1 | 13 || 14 | | | 0v | | |
| 122 | 8 | CTS3 | IN | 1 | 15 || 16 | 1 | IN | PC08 | 9 | 72 |
| | | 3.3v | | | 17 || 18 | 1 | IN | PC07 | 10 | 71 |
| 66 | 11 | MOSI.0 | IN | 1 | 19 || 20 | | | 0v | | |
| 67 | 12 | MISO.0 | IN | 1 | 21 || 22 | 1 | IN | RTS3 | 13 | 121 |
| 64 | 14 | SCLK.0 | IN | 1 | 23 || 24 | 1 | IN | CE.0 | 15 | 69 |
| | | 0v | | | 25 || 26 | 1 | IN | PH03 | 16 | 227 |
+------+-----+----------+------+---+----++----+---+------+----------+-----+------+
| GPIO | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | GPIO |
+------+-----+----------+------+---+OrangePiH6+---+------+----------+-----+------+

Уже хорошо. Можно дергать пинами, как это сделано в библиотеке OneWire. Или продолжить танцы с бубном, чтобы повысить приоритет выполнения кода эмуляции протокола 1-wire до уровня модуля ядра linux. К сожалению, в текущей версии дистрибутивов нет скомпилированных драйверов w1-gpio. Чтобы добавить придется самому их компилировать.
Качаем User Manual отсюда и зачитываемся IV.Linux Environment Construction, 4. Linux SDK Usage Sample. Но! собрать ядро на Orange Pi Lite 2 у меня не получилось из-за ошибки отсутствия библиотеки и невозможности ее получить под данную платформу AArch64. Получилось только на взрослой машине. Для этого пришлось на Windows 10 поставить VirtualBox, а на него Ubuntu 18. После скачивания исходников и установки всех необходимых инструментов для компиляции:

# cd OrangePiH6/kernel
# make menuconfig ARCH=arm64

Указание на то, что должно быть в ядре для поддержки 1-wire есть тут. В меню ищем:

Device Drivers --> Dallas's 1-wire support --> 1-wire Bus Masters  ---> 1-wire Bus Masters  ---> M
Device Drivers --> Dallas's 1-wire support --> 1-wire Slaves ---> Thermal family implementation ---> M

Сохраняем .config

# cd ..
# ./build.sh

Далее по мануалу Build Linux. Но внимательно читаем вывод скрипта. Там будут скрытые ошибки недостающих библиотек, которые нужно будет поставить чтобы полностью скомпилировать ядро. На выходе получаем нужные модули в папке output/lib/modules/3.10.65+/kernel/drivers/w1 Переносим всю папку w1 на наш одноплатник в папку /lib/modules/3.10.65/kernel/drivers Делаю это по сети через sftp, но можно просто примонтировать SD-карту прямо в виртуальной машине. Как только файлы окажутся на Orange Pi выполняем на ней

# insmod /lib/modules/3.10.65/kernel/drivers/w1/wire.ko
# insmod /lib/modules/3.10.65/kernel/drivers/w1/masters/w1-gpio.ko
# insmod /lib/modules/3.10.65/kernel/drivers/w1/slaves/w1_therm.ko
# depmod
# lsmod
Module Size Used by
bcmdhd 721630 0
vin_io 45127 0
ss 44426 0
sunxi_keyboard 5432 0
w1_therm 3331 0
w1_gpio 3299 0
wire 24411 2 w1_gpio,w1_therm

Для автоматического запуска выбранных модулей добавляем их в файл /etc/modules

# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
wire
w1-gpio
w1_therm

Далее нужно обновить конфигурацию дерева устройств и задать номер пина, который будет слушать наш драйвер. Описание процедуры на офф. сайте несколько устарело.

# apt-get install device-tree-compiler
# cd /boot/orangepi
# dtc -b 0 -O dts -I dtb -o OrangePiH6.dts OrangePiH6.dtb
# vi OrangePiH6.dts
# dtc -b 0 -O dtb -I dts -o OrangePiH6.dtb OrangePiH6.dts

Если что, то оригинальные файлы сохранены в папке /boot/backup/orangepi В сети много примеров для более старых чипов. Например, если попытаться в конец файла перед завершающей фигурной скобкой дописать:

onewire_device {
compatible = "w1-gpio";
gpios = <&pio 3 21 0>; /* PD21 */
pinctrl-names = "default";
pinctrl-0 = <&my_w1_pin>;
};

В середине текста найти pinctrl@0300b000 и изменить на

pio:    pinctrl@0300b000 {
compatible = "allwinner,sun50iw6p1-pinctrl";
reg = <0x0 0x300b000 0x0 0x400>;
interrupts = <0x0 0x33 0x4 0x0 0x35 0x4 0x0 0x36 0x4 0x0 0x3b 0x4>;
device_type = "pio";
clocks = <0xb>;
gpio-controller;
interrupt-controller;
#interrupt-cells = <0x2>;
#size-cells = <0x0>;
#gpio-cells = <0x6>;
linux,phandle = <0x7e>;
phandle = <0x7e>;
my_w1_pin: w1@0 {
allwinner,pins = "PD21";
allwinner,function = "gpio_in";
};

То получим ошибки

# dmesg |grep w1
[ 7.923073] sun50iw6p1-pinctrl pio: missing allwinner,function property in node my_w1_pin
[ 7.937340] sun50iw6p1-pinctrl pio: missing allwinner,function property in node my_w1_pin
[ 7.950447] w1-gpio onewire_device.10: unable to select pin group
[ 8.056444] Modules linked in: w1_gpio(+) wire
[ 8.199790] [] w1_gpio_probe+0x17c/0x2c4 [w1_gpio]
[ 8.302643] [] $x+0x10/0x1c [w1_gpio]
[ 8.358783] w1-gpio onewire_device.10: gpio_request (pin) failed
[ 8.369472] w1-gpio: probe of onewire_device.10 failed with error -22

Дерево в формате DTB для меня темный лес. В документации на w1-gpio вроде всё просто, но вот ссылка на gpio в версии OrangePiH6.dtb описывается аж 7 параметрами вместо двух, как можно найти в доступных примерах. Например:

    onewire@0 {
compatible = "w1-gpio";
gpios = <0x7e 0x07 0x03 0x1 0xffffffff 0xffffffff 0x0>; /* PH3 */
};

Изрядно порывшись, догадался как сформировать правильную ссылку. Здесь 0x7e — это ссылка (phandle) на блок gpio-controler под именем pinctrl@0300b000; 0x07 — порядковый номер буквы H в имени пина PH3; 0x03 — номер в имени пина PH3; следующие 3 числа на результат не влияют и стоят в состоянии по умолчанию; 0x00 — состояние подтягивающего резистора — выключен, т.е. нужен внешний резистор 4,7 кОм между шиной 3.3 В и нашим пином PH3. Однако, этого оказалось мало. Просто стало меньше ошибок.

[    7.940948] w1-gpio onewire.10: unable to select pin group
[ 7.951144] w1-gpio onewire.10: gpio_request (pin) failed
[ 7.971122] w1-gpio: probe of onewire.10 failed with error -16

Нужно добавить правильное описание пина в секцию
pinctrl@0300b000

        w1@0 {
allwinner,pins = "PH3";
allwinner,function = "gpio_in";
allwinner,muxsel = <0x0>;
allwinner,drive = <0x0>;
allwinner,pull = <0x0>;
linux,phandle = <0xf33>;
phandle = <0xf33>;
};

И сделать ссылку на него из описания устройства

onewire@0 {
compatible = "w1-gpio";
gpios = <0x7e 0x07 0x03 0x1 0xffffffff 0xffffffff 0x0>; /* PH3 */
pinctrl-names = "default";
pinctrl-0 = <0xf33>;
status = "okay";
};

После этого все заработало. Подключив среднюю ногу DS18b20 на Pin26 (PH03) получил список датчиков (добавлять датчики можно в любой момент, а не обязательно до старта Orange Pi)

# ls /sys/bus/w1/devices/
28-000005e35fb9 28-000005e37f9d w1_bus_master1

Прочитать температуру

# cat  /sys/bus/w1/devices/28-000005e37f9d/w1_slave
68 01 4b 46 1f ff 08 10 95 : crc=95 YES
68 01 4b 46 1f ff 08 10 95 t=22500

Температура 22.5 градуса. Задачка решена. Ссылка на скомпилированные модули и полный исправленный файл дерева ниже. Актуально для ядра 3.10.65

Orange Pi Lite2: 1-Wire: 2 комментария

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *