Работа с GPIO в Linux на примере Banana Pi BPI-M64. Часть 3. Device Tree overlays. LED, ШИМ (PWM), КНОПКА

В предыдущей части работали с 1-Wire интерфейсом, подключали датчик DS18B20 для замера температуры. В этой публикации познакомимся как работать с устройством класса светодиод (LED), что такое ШИМ (PWM),  подключим кнопки и ответим на вопрос, можно ли обойтись без стандартной клавиатуры на USB интерфейсе. Драйвера периферии LED, PWM, BUTTON входят в состав ядра Linux, поэтому данное руководство, так же подойдет владельцам других плат, включая Raspberry Pi. Все указанную периферию будем подключать к плате Banana Pi BPI-M64, конфигурация:

LED (светодиод)

В Linux есть класс устройств — LED. Светодиод может находится в одном из двух состояниях: включен или выключен. Так же светодиод может светится с определенной яркостью. В большинстве случаев представлены обычные светодиоды которые могут только включены или выключены. Светодиоды с регулируемой яркостью встречаются редко, тем более если класс устройства заменить на ШИМ (PWM), то и обычный светодиод станет с управляемой яркостью, но про это будет в следующем разделе. Светодиодами можно управлять из пользовательского пространства (userspace), появляются в виртуальной файловой системе sysfs по пути  /sys/class/leds/ . Максимальная яркость определяется в файле  max_brightness . Дополнительно, в классе представлена концепция светодиодного триггера.

Триггер — это источник событий на основе ядра. Триггеры могут быть простыми или сложными. Простой триггер не настраивается и использует какой либо шаблон активности. Примерами являются триггеры:

  • heartbeat — сердцебиение, пульсация от событий ядра, говорящая что система «жива», работает, и не нуждается в принудительной перезагрузке (hard reset)
  • disk-activity — активность диска, срабатывает когда выполняются операции чтения/записи данных с диска.

Можно настроить светодиод с определенным периодом мигания, указав в файле  /sys/class/leds/<device>/delay_{on,off}  задержку в миллисекундах.

Именование светодиодных устройств задается по маске: “devicename:color:function”, где

  • devicename: имя устройства, должен быть уникальным идентификатором, и являться тем устройством к которому подключен светодиод, в случае платы Banana Pi BPI-M64 это: «bananapi-m64».
  • color: цвет, значение из LED_COLOR_ID_* в заголовочном файле include/dt-bindings/leds/common.h
  • function: функция, значение из LED_FUNCTION_ * в заголовочном файле include/dt-bindings/leds/common.h

Подсистема светодиодов, также имеет защиту от конфликта имен. Если обнаружится, что два устройства класса светодиодов создано с одинаковыми именами, то к секции имени будет добавлен числовой суффикс (например, «_1», «_2», «_3» и т. д.).

Примеры названий светодиодов:

  • “red:disk”
  • “white:flash”
  • “red:indicator”
  • “phy1:green:wlan”
  • “phy3::wlan”
  • “:kbd_backlight”
  • “input5::kbd_backlight”
  • “input3::numlock”
  • “input3::scrolllock”
  • “input3::capslock”
  • “mmc1::status”
  • “white:status”

Для практики работы с устройством, светодиод необязательно подключать, на самой плате Banana Pi BPI-M64 размещено три светодиода, цветом: красный, зеленый, синий. По умолчанию в дереве устройств (DT) они уже задействованы.

Светодиоды RED, GREEN, BLUE на плате Banana Pi BPI-M64

Светодиоды красный, зеленый, синий, располагаются на плате Banana Pi BPI-M64, возле 40-контактного разъема совместимого с Raspberry Pi 3.

Светодиоды красный, зеленый, синий в выключенном состоянии
Linux GPIO LED PWM BUTTON Banana Pi BPI-M64

Перейдем по пути  /sys/class/leds/  и посмотрим содержимое каталога:

root@bananapim64:~# cd /sys/class/leds/
root@bananapim64:/sys/class/leds# ls
bananapi-m64:blue:user bananapi-m64:green:user bananapi-m64:red:pwr
root@bananapim64:/sys/class/leds#

В каталоге будут доступны светодиоды с именами:

  • bananapi-m64:blue:user
  • bananapi-m64:green:user
  • bananapi-m64:red:pwr

Светодиод с именем «bananapi-m64:red:pwr» по умолчанию загорается при включение платы, служит индикатором подачи питания. Включим остальные светодиоды, командами:

echo 1 > /sys/class/leds/bananapi-m64:blue:user/brightness
echo 1 > /sys/class/leds/bananapi-m64:green:user/brightness

Посмотрим на получившуюся гирлянду, включены все три светодиода
Linux GPIO LED PWM BUTTON Banana Pi BPI-M64

Теперь выключим светодиоды, командами:

echo 0 > /sys/class/leds/bananapi-m64:blue:user/brightness
echo 0 > /sys/class/leds/bananapi-m64:green:user/brightness

В папке каждого светодиода есть файл  trigger , прочитав содержимое этого файла узнаем какие виды триггеров поддерживает драйвер:

root@bananapim64:~# cat /sys/class/leds/bananapi-m64:blue:user/trigger
[none] usb-gadget usb-host kbd-scrolllock kbd-numlock kbd-capslock kbd-kanalock kbd-shiftlock kbd-altgrlock kbd-ctrllock kbd-altlock kbd-shiftllock kbd-shiftrlock kbd-ctrlllock kbd-ctrlrlock usbport disk-activity disk-read disk-write ide-disk mtd nand-disk heartbeat cpu cpu0 cpu1 cpu2 cpu3 activity default-on panic mmc0 mmc1 mmc2 rfkill-any rfkill-none bluetooth-power axp813-ac-online axp20x-battery-charging-or-full axp20x-battery-charging axp20x-battery-full axp20x-battery-charging-blink-full-solid axp20x-usb-online rfkill0 hci0-power rfkill1 stmmac-0:01:link stmmac-0:01:1Gbps stmmac-0:01:100Mbps stmmac-0:01:10Mbps
root@bananapim64:~#

Среди доступных триггеров есть — heartbeat (сердцебиение). Назначим триггер heartbeat на светодиод с именем «bananapi-m64:blue:user»

echo "heartbeat" > /sys/class/leds/bananapi-m64:blue:user/trigger

Heartbeat (сердцебиение) системы:
Linux GPIO LED PWM BUTTON Banana Pi BPI-M64

Для выключения триггера светодиода необходимо выполнить команду:

echo "none" > /sys/class/leds/bananapi-m64:blue:user/trigger

После выполнения этой команды мигание светодиоды прекратится.

Добавление устройства LED с функцией heartbeat в дерево устройств (Device Tree)

В публикации Работа с GPIO на примере Banana Pi BPI-M64. Часть 1. Интерфейс sysfs LED и DS18B20 был подключен светодиод на 32-pin разъема типа Raspberry Pi, название контакта «PB7»:

Linux GPIO LED PWM BUTTON Banana Pi BPI-M64

Что такое дерево устройств и как формировать файлы DTS, можно почитать в публикации Работа с GPIO на примере Banana Pi BPI-M64. Часть 2. Device Tree overlays.

Создадим устройство gpio-leds с функцией «heartbeat» используя подключенный светодиод Gravity: Digital Blue LED Light Module на 32-pin разъема типа Raspberry Pi. Подключенный светодиод синего цвета, в соответствие со спецификацией зададим ему имя: bananapi-m64:blue:heartbeat. Создадим файл DTS, sun50i-a64-led-blue-heartbeat-pb7.dts:

/dts-v1/;
/plugin/;

/ {
	compatible = "allwinner,sun50i-a64";

	fragment@0 {
		target = <&pio>;
		__overlay__ {
			led_bluecustom_pin: led_bluecustom_pin {
				pins = "PB7";
				function = "gpio_out";
			};
		};
	};

	fragment@1 {
		target-path = "/leds/";
		__overlay__ {
			bluecustom_hb {
				compatible = "gpio-leds";
				label = "bananapi-m64:blue:heartbeat";			 	
				pinctrl-names = "default";
				pinctrl-0 = <&led_bluecustom_pin>;
				gpios = <&pio 1 7 1>; /* PB7 - for LED from DFrobot */
				/* gpios = <&pio 1 7 0>;  PB7 - for other LED */
				default-state = "off";
				linux,default-trigger = "heartbeat";
			};
		};
	};
};

Разместим файл по пути  /boot/dtb/allwinner/overlay . Затем компилирует файл .dts в .dtbo.

$ cd /boot/dtb/allwinner/overlay
$ dtc -I dts -O dtb sun50i-a64-led-blue-heartbeat-pb7.dts -o sun50i-a64-led-blue-heartbeat-pb7.dtbo

Запустим утилиту конфигурирования платы:  armbian-config . Перейдем по меню: System > Hardware, и включим слой (overlay): led-blue-heartbeat-pb7. И после перезагрузки платы, активируется функция heartbeat на светодиоде bananapi- m64:blue:heartbeat.

Список светодиодов системы пополнится новым устройством:

root@bananapim64:~# cd /sys/class/leds/
root@bananapim64:/sys/class/leds# ls
bananapi-m64:blue:heartbeat bananapi-m64:blue:user bananapi-m64:green:user bananapi-m64:red:pwr
root@bananapim64:/sys/class/leds#

Широтно-импульсная модуляция (Pulse Width Modulation, PWM)

ШИМ — процесс управления мощностью методом пульсирующего включения и выключения потребителя энергии. Упрощено, на выходе генерируется череда импульсов с двумя возможными значениями 0 и 1, сменяющими друг друга каждый такт T. Используется для управления подсветки LCD экранов, колебаний вибромоторов в телефонах, управления скорости вращения в двигателях.

Выделяют следующие характеристики ШИМ:

КОЭФФИЦИЕНТ ЗАПОЛНЕНИЯ (DUTY CYCLE)
Начнем с самого главного параметра — коэффициента заполнения D (он же duty cycle). Этот коэффициент равен отношению периода ШИМ сигнала к ширине импульса:

D = tвкл / T

где T — период импульсов (время), tвкл — длительность импульса, время включения (время).

Пример ШИМ сигнала для разных значений D:
Linux GPIO LED PWM BUTTON Banana Pi BPI-M64

Скважность и коэффициент заполнения — безразмерные величины, однако коэффициент заполнения часто указывают в процентах. Коэффициент заполнения в ряде применений более удобен, поскольку его относительное изменение происходит в интервале от 0 до 1. Получается что чем выше коэффициент заполнения, тем нам будет казаться, что светодиод горит ярче из-за более долгого времени включения.

Коэффициент заполнения в 50% при напряжение в 5V приведет к такой же яркости светодиода, если бы ему подавалось питание в 2.5 V постоянно.50% — эквивалент 2,5 В
Linux GPIO LED PWM BUTTON Banana Pi BPI-M64

10% — эквивалент 0,5 В
Linux GPIO LED PWM BUTTON Banana Pi BPI-M64

90% — эквивалент 4,5 В
Linux GPIO LED PWM BUTTON Banana Pi BPI-M64

 

Расчет скважности: S = 1/D , где D — коэффициент заполнения. Скважность может принимать значения от 1 до бесконечности.

Пример при ШИМ меняется длительность импульса при неизменном периоде и амплитуде:Linux GPIO LED PWM BUTTON Banana Pi BPI-M64

ЧАСТОТА ШИМ
количество пиков, логической «1» за одну секунду. Русское обозначение: Гц, международное обозначение: Hz. Требования к частоте диктуются несколькими факторами, в зависимости от типа управляемого устройства.В случае управления светодиодами одним из главных факторов становится видимость мерцания. Чем выше частота, тем менее заметно мерцание излучаемого света. Высокая частота также помогает снизить влияние температурных скачков, которые светодиоды не любят. На практике для светодиодов достаточно иметь частоту ШИМ в пределах 100-300 Гц.

РАЗРЕШЕНИЕ ШИМ
Ещё один важный параметр — разрешение ШИМ сигнала. Этот параметр показывает, с какой точностью мы можем менять коэффициент заполнения. Чем больше разрешение, тем плавнее будет меняться мощность на управляемом устройстве.

Интерфейс Pulse Width Modulation (PWM) в ядре Linux

Устройствами PWM можно управлять из пользовательского пространства (userspace), появляются в виртуальной файловой системе sysfs по пути  /sys/class/pwm/ . Каждый PWM контроллер/чип будет экспортирован как pwmchipN, где N — номер основного чипа. Внутри каталога вы найдете:

  • npwm — количество каналов ШИМ, которые поддерживает этот чип (read-only)
  • export — экспортирует канал ШИМ для использования с sysfs (write-only)
  • unexport — отключает канал PWM из sysfs (write-only)

PWM каналы нумеруются в соответствие от каждого чипа от 0 до npwm-1.

Использование ШИМ (PWM) на плате Banana Pi BPI-M64

Для ШИМ определены контакты с названиями: PD22 (PWM0) и PL10 (S_PWM). Контакт PD22 не распаян на плате, поэтому остается использовать только PL10.

Контакт  PL10 находится на разъеме MIPI DSI, для получения доступа к контакту необходимо его развести с помощью Адаптера с кабеля FPC на гребенку 2.54 мм, как это делается смотрите в публикации Распиновка GPIO для Banana Pi BPI-M64. Контакт PL10 по номеру 35-pin обозначен как: CN6-P35, функция LCD-PWM.

Для работы с контактом PL10, подключим на 35-pin зеленый светодиод.

В дереве устройств sun50i-a64-bananapi-m64.dts, PWM на 35-pin обозначен как r_pwm. По умолчанию PWM добавлен в дерево устройств, поэтому потребуется лишь его включить. Создадим файл DTS для включения PWM , sun50i-a64-r-pwm-pl10.dts:

/dts-v1/;
/plugin/;

/ { 
	compatible = "allwinner,sun50i-a64","allwinner,sun50i-a64-pwm";

	fragment@0 {
		target = <&r_pwm>; /* PL10 */ 
		__overlay__ {
				status = "okay";			
		};
	};
};

Полный вариант фрагмента PWM из файла DTS, sun50i-a64-bananapi-m64.dts:

pwm@1f03800 {
			compatible = "allwinner,sun50i-a64-pwm";
			reg = <0x1f03800 0x400>;
			clocks = <0x32>;
			pinctrl-names = "default";
			pinctrl-0 = <0x50>;
			#pwm-cells = <0x3>;
			status = "disabled";
			phandle = <0x97>;
		};

r-pwm-pin {
				pins = "PL10";
				function = "s_pwm";
				phandle = <0x50>;
			};
};

Разместим файл sun50i-a64-r-pwm-pl10.dts по пути  /boot/dtb/allwinner/overlay . Затем компилирует файл .dts в .dtbo.

$ cd /boot/dtb/allwinner/overlay
$ dtc -I dts -O dtb sun50i-a64-r-pwm-pl10.dts -o sun50i-a64-r-pwm-pl10.dtbo

Запустим утилиту конфигурирования платы:  armbian-config . Перейдем по меню: System > Hardware, и включим слой (overlay): sun50i-a64-r-pwm-pl10. И после перезагрузки платы, активируется PWM.

После перезагрузки убедимся что устройство включено, перейдем в каталог  /sys/class/pwm/ :

root@bananapim64:~# cd /sys/class/pwm/
root@bananapim64:/sys/class/pwm# ls -l
total 0
lrwxrwxrwx 1 root root 0 Mar 4 23:52 pwmchip0 -> ../../devices/platform/soc/1f03800.pwm/pwm/pwmchip0
root@bananapim64:/sys/class/pwm#

В каталоге будет новое устройство PWM:  pwmchip0 

Работа с PWM с помощью виртуальной файловой системы Sysfs

Процессор Allwinner A64, поддерживает ШИМ со следующими характеристиками:

  • Коэффициент заполнения (duty cycle) от 0% до 100%
  • Выходная частота до 24 МГц

Узнаем какое количество каналов ШИМ доступно, командой:

root@bananapim64:~# cat /sys/class/pwm/pwmchip0/npwm
1

Доступен только один канал ШИМ. Для использования ШИМ необходимо выполнить экспорт, командой:

$ echo 0 > /sys/class/pwm/pwmchip0/export

После экспорта в каталоге  pwmchip0  появится непосредственно интерфейс PWM, каталог  pwm0 :

root@bananapim64:~# cd /sys/class/pwm/pwmchip0
root@bananapim64:/sys/class/pwm/pwmchip0# ls -l
total 0
lrwxrwxrwx 1 root root 0 Mar 4 23:53 device -> ../../../1f03800.pwm
--w------- 1 root root 4096 Mar 5 01:00 export
-r--r--r-- 1 root root 4096 Mar 4 23:53 npwm
drwxr-xr-x 2 root root 0 Mar 4 23:49 power
drwxr-xr-x 3 root root 0 Mar 5 01:01 pwm0
lrwxrwxrwx 1 root root 0 Mar 4 23:53 subsystem -> ../../../../../../class/pwm
-rw-r--r-- 1 root root 4096 Mar 4 23:49 uevent
--w------- 1 root root 4096 Mar 4 23:53 unexport
root@bananapim64:/sys/class/pwm/pwmchip0#

Каталог  pwm0  содержит файлы:

root@bananapim64:~# cd /sys/class/pwm/pwmchip0/pwm0
root@bananapim64:/sys/class/pwm/pwmchip0/pwm0# ls -l
total 0
-r--r--r-- 1 root root 4096 Mar 5 01:05 capture
-rw-r--r-- 1 root root 4096 Mar 5 01:05 duty_cycle
-rw-r--r-- 1 root root 4096 Mar 5 01:05 enable
-rw-r--r-- 1 root root 4096 Mar 5 01:05 period
-rw-r--r-- 1 root root 4096 Mar 5 01:05 polarity
drwxr-xr-x 2 root root 0 Mar 5 01:05 power
-rw-r--r-- 1 root root 4096 Mar 5 01:05 uevent
root@bananapim64:/sys/class/pwm/pwmchip0/pwm0#

Рассмотрим свойства PWM:

  • period — общий период сигнала PWM (чтение/запись). Значение выражается в наносекундах и представляет собой сумму активного и неактивного времени PWM. Наносекунда (нс) — единица времени, равная одной миллиардной доле секунды (10^9 или 1/1.000.000.000 с).
  • duty_cycle — время активности PWM (чтение/запись). Значение указывается в наносекундах и должно быть меньше периода.
  • polarity — изменяет полярность сигнала PWM (чтение/запись). Полярность можно изменить, только если PWM не включен. Принимает значение «normal» (нормальная) или «inversed» (инвертированная).
  • enable — включает/выключает PWM (чтение/запись). 0 — disabled, 1 — enabled.

Практическая задача: мигать светодиодом раз в пол секунды

Рассмотрим практическую задачу для PWM, подавать сигнал раз в 0.5 секунды, на время 0.5 секунды. Получается, что в период T = 1 секунды входит,  0.5 — секунды светодиод горит, 0.5 — секунды светодиод не горит. Рассчитаем значения period и duty_cycle:

  • period = 1 c = 1.000.000.000 нс = >  1000000000
  • duty_cycle = 0.5 c = 1/2* 1.000.000.000 = 500.000.000 нс = > 500000000

Полярность нормальная, polarity = «normal»

Включим PWM, не забываем что значение duty_cycle должно быть меньше чем period:

$ echo 0 > /sys/class/pwm/pwmchip0/export
$ echo 1000000000 > /sys/class/pwm/pwmchip0/pwm0/period
$ echo 500000000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle
$ echo "normal" > /sys/class/pwm/pwmchip0/pwm0/polarity
$ echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable

Мигание светодиода раз в пол секунды
Linux GPIO LED PWM BUTTON Banana Pi BPI-M64

Практическая задача: установить яркость светодиода на 40%

Рассмотрим практическую задачу для PWM, установить яркость светодиода на 40% без мерцания. Для исключения мерцания светодиода, необходимо выставить период T  на значения в пределах пределах 100-300 Гц,  максимальное поддерживаемое значение составляет 24 МГц. Коэффициент заполнения D будет равен 40%. Рассчитаем значения period и duty_cycle:

  • period = 200 Гц = 1/200 c = 1/200 * 1.000.000.000 нс = 5.000.000 нс  => 5000000
  • duty_cycle = 40% * 200 Гц = 1/40 * 5.000.000 нс = 125.000 нс = > 125000

Полярность нормальная, polarity = «normal»

Включим PWM, если выполняли пример выше, то сначала нужно выставить duty_cycle, т.к. в предыдущем примере значение duty_cycle больше, чем выставляемое значение period, а должно быть period > duty_cycle :

$ echo 0 > /sys/class/pwm/pwmchip0/export
$ echo 5000000 > /sys/class/pwm/pwmchip0/pwm0/period
$ echo 125000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle
$ echo "normal" > /sys/class/pwm/pwmchip0/pwm0/polarity
$ echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable

Светодиод горит на 40% от максимальной яркости
Linux GPIO LED PWM BUTTON Banana Pi BPI-M64

Светодиод горит на 100% от максимальной яркости
Linux GPIO LED PWM BUTTON Banana Pi BPI-M64

Создание светодиода с управляемой яркостью на базе PWM

В Linux для PWM-светодиодов определен класс pwm-leds, свойства этого класса соответствуют классу LED. Так же появляется в в виртуальной файловой системе sysfs по пути  /sys/class/leds/ . Максимальная яркость определяется в файле  max_brightness . Для использования устройства pwm-leds обязательно должен быть включен pwm —  /sys/class/pwm/pwmchip0 . Для создания leds-pwm создадим DTS с названием sun50i-a64-pwm-led-pl10.dts:

/dts-v1/;
/plugin/;

/ {
	
	fragment@0 {
		target = <&r_pwm>; /* PL10 */
		__overlay__ {
				status = "okay";
		};
	};
	
	fragment@1{
		target-path = "/";
		__overlay__ {
				pwmleds {
				compatible = "pwm-leds";
				led0 {
						label = "bananapi-m64:green:status";
						pwms = <&r_pwm 0 5000000 1>; /* for LED from DFrobot */
						/*pwms = <&r_pwm 0 5000000 0>; for other LED */
						max-brightness = <255>;
						brightness = <0>;						
                };
			};
		};
	};
	
};

Рассмотрим содержимое sun50i-a64-pwm-led-pl10.dts:

  • fragment@0 — необходим для включения pwm.
  • fragment@1 — создание устройства led0 класса «pwm-leds» в разделе DT /pwmleds.
  • label — метка для обращения к устройству, как и в классе устройств LED.
  • pwms — параметр из четырех аргументов: &r_pwm — ссылка на устройство pwm, 0 — номер канала от 0 до n (выше по тексту использовался в команде export), 5000000 — параметр period, 1 — полярность (0 или 1).
  • max-brightness — максимальная яркость (максимальное задаваемое значение 255) коэффициент заполнения автоматически  масштабируеся к этому значению, т.е. 100% = 255.
  • brightness — яркость задаваемая при включение устройства.

Запустим утилиту конфигурирования платы:  armbian-config . Перейдем по меню: System > Hardware, и включим слой (overlay): pwm-led-pl10. И после перезагрузки платы, активируется светодиод с меткой  bananapi-m64:green:status .

Список светодиодов системы пополнится новым устройством, bananapi-m64:green:status:

root@bananapim64:~# cd /sys/class/leds/
root@bananapim64:/sys/class/leds# ls
bananapi-m64:blue:user bananapi-m64:green:status bananapi-m64:green:user bananapi-m64:red:pwr
root@bananapim64:/sys/class/leds#

Теперь в отличие от обычных LED, при задание свойства  brightness  будем оперировать значениями от 0 до 255. Если свойству  brightness  задать значение «1», то светодиод будет гореть с яркостью 1/255 ~ 0.3% от максимальной яркости.

Зададим максимальную яркость (значение 255) светодиоду bananapi-m64:green:status:

$ echo 255 > /sys/class/leds/bananapi-m64:green:status/brightness

Linux GPIO LED PWM BUTTON Banana Pi BPI-M64

Зададим половину яркости от максимального значения светодиоду bananapi-m64:green:status:

$ echo 127 > /sys/class/leds/bananapi-m64:green:status/brightness

Linux GPIO LED PWM BUTTON Banana Pi BPI-M64

Кнопки (gpio-keys)

Кнопки являются устройство ввода данных, драйвер gpio-keys. Различаются два вида кнопок: цифровые и аналоговые. На цифровую кнопку назначается определенный только один код из таблицы, т.е. зарегистрированный контакт (pin) может быть либо кнопкой «A» или «1», и др. Для аналоговых кнопок требуется АЦП. В зависимости от нажатой кнопки, на входе будет регистрироваться определенное значение напряжения, пример описан в файле allwinner sun4i-a10-lradc-keys.yaml. Подключать кнопку к плате необходимо на контакт поддерживающий прерывание, на схеме Распиновка GPIO для Banana Pi BPI-M64, такие контакты помещены меткой PH_EINT*.

Исходя из схемы, для кнопки задействуем 35-pin разъема типа Raspberry Pi, название контакта «PB6», прерывание «PB_EINT6». Исходя из файла input-event-codes.h назначим на кнопку функцию, которая будет выключать устройство: KEY_POWER. Сформируем файл с названием sun50i-a64-button-pb6.dts:

/dts-v1/;
/plugin/;

/ {
	compatible = "allwinner,sun4i-a10", "allwinner,sun7i-a20", "allwinner,sun8i-h3", "allwinner,sun50i-a64", "allwinner,sun50i-h5";
	
	fragment@0 {
		target = <&pio>;
		__overlay__ {
			gpio_keys: gpio-keys {
				pins = "PB6";
				/* for many: pins = "PA7","PA8","PA9","PA10","PA21"; */
				function = "gpio_in";
				/*bias-pull-up;*/
			};
		};
	};

	fragment@1 {
		target-path = "/";
		__overlay__ {
			gpio-keys-user {				
				compatible = "gpio-keys";
				//autorepeat;
				pinctrl-names = "default";
				pinctrl-0 = <&gpio_keys>;

				g-keys_power {
					label = "GPIO Key Power";
					linux,code = <116>; /* KEY_POWER, see include/uapi/linux/input-event-codes.h */					
					gpios = <&pio 1 6 1>; /* PA10 GPIO_ACTIVE_LOW */
					debounce-interval= <10>; /* Debouncing interval time in milliseconds. defaults to 5 */										
				};
			};
		};
	};
};

Рассмотрим параметры:

  • linux,code — код кнопки, из списка input-event-codes.h.
  • debounce-interval — интервал игнорирования сигнала, защита от дребезга. После нажатия кнопки, все нажатия до 10 миллисекунд будут игнорироваться. Более подробнее почитать Что такое Throttling и Debouncing?.

После перезагрузки выполним проверку подключения кнопки, найдем устройство в списке устройств, командой  dmesg | grep -E ‘key’ :

root@bananapim64:~# dmesg | grep -E 'key'
[ 2.270480] input: gpio-keys-user as /devices/platform/gpio-keys-user/input/input1
root@bananapim64:~#

Устройство gpio-keys зарегистрировано, можно нажимать на кнопку!

Теперь ответим на вопрос, можно ли обойтись без клавиатуры USB? Частично, если требуется использовать не все кнопки. Использовать контакт GPIO для каждой кнопки, достаточно расточительное мероприятие. Лучше для этих задач использовать расширитель GPIO контактов или использовать аналоговый вход, а к каждой кнопке в цепь подключить по одному резистору разного номинала, для получения разного напряжения при нажатие на кнопку.

Литература

  1. LEDs connected to GPIO lines — kernel.org
  2. LED handling under Linux — kernel.org
  3. linux/include/dt-bindings/leds/common.h — torvalds/linux
  4. Pulse Width Modulation (PWM) interface — kernel.org
  5. Pulse Width Modulation (PWM) interface — kernel.org
  6. LED connected to PWM — kernel.org
  7. Device-Tree bindings for input/keyboard/gpio_keys.c keyboard driver — kernel.org
  8. linux/include/uapi/linux/input-event-codes.h — torvalds/linux
  9. Широтно-импульсная модуляция — Амперка Вики
  10. Широтно-импульсная модуляция (ШИМ) — Олег Евсегнеев Robotclass
  11. Practical usage of timer counters in Linux, illustrated on Microchip platforms — bootlin
  12. PWM (Linux) — Toradex
  13. PWM (Fan) — Kobol Wiki

Вам также может понравиться

About the Author: Anton

Programistik