Работа с GPIO: различия между версиями

Материал из Wiren Board
Строка 2: Строка 2:
<translate>
<translate>
<!--T:1-->
<!--T:1-->
В Wiren Board часть GPIO выведена на клеммники, часть выведена на разъёмы расширения, часть используется для служебных целей.
Статья рассчитана на разработчиков или опытных пользователей и даёт общие рекомендации того, как использовать gpio в обход официального ПО WirenBoard.
GPIO также используются для управления транзисторами для коммутации низковольтной нагрузки.  


<!--T:4-->
<!--T:2-->
Каноничный способ взаимодействия с gpio контроллеров WirenBoard - это драйвер '''wb-homa-gpio''' с [https://github.com/wirenboard/wb-homa-gpio открытым исходным кодом]. В readme репозитория можно почитать о конфигурации драйвера для специализированных нужд.
 
<!--T:3-->
Описание доступных ножек gpio для конкретной ревизии контроллера можно найти в статье [[GPIO]].
 
=Меры предосторожности=<!--T:4-->
 
<!--T:5-->
* '''Все GPIO (как и остальные порты Wiren Board) работают с напряжением 3.3V.'''  
* '''Все GPIO (как и остальные порты Wiren Board) работают с напряжением 3.3V.'''  
* '''Подключение сигнала с напряжением > 3.3V к ножке GPIO грозит выходом из строя процессорного модуля.'''
* '''Подключение сигнала с напряжением > 3.3V к ножке GPIO грозит выходом из строя процессорного модуля.'''
<!--T:6-->
В случае необходимости подключения устройств, работающих с более высоким напряжением, необходимо использовать схемы согласования или подключать (для 5V) через резистор в 20 кОм и более </b>
В случае необходимости подключения устройств, работающих с более высоким напряжением, необходимо использовать схемы согласования или подключать (для 5V) через резистор в 20 кОм и более </b>


<!--T:2-->
=Именование gpio=<!--T:7-->
Описание использующихся ножек gpio для конкретной ревизии контроллера можно найти в статье [[GPIO]].


=Именование gpio=<!--T:6-->
<!--T:8-->
К сожалению, четкого стандарта по именованию gpio не существует, но при работе с контроллерами WirenBoard стоит придерживаться следующих правил:
К сожалению, четкого стандарта по именованию gpio не существует, но при работе с контроллерами WirenBoard стоит придерживаться следующих правил:
* выводы gpio сгруппированы по банкам (''banks''; эквивалентно ''gpiochips'')
* выводы gpio сгруппированы по банкам (''banks''; эквивалентно ''gpiochips'')
* каждый банк содержит 32 gpio. Нумерация банков начинается с 0.
* каждый банк содержит 32 gpio. Нумерация банков начинается с 0.


==Вычисление номера gpio==<!--T:6-->
==Вычисление номера gpio==<!--T:9-->
Для управления ножкой gpio нужно знать её номер. В рассматриваемых примерах будем работать с gpio ''A1_IN'' контроллера WB6.7 (номер: 109; gpiochip 3, offset 13):
 
<!--T:10-->
Для управления ножкой gpio нужно знать её номер. В рассматриваемых примерах будем работать с gpio ''A1_IN'' контроллера WB6.7 (''номер: 109; gpiochip 3, offset 13''):


<!--T:7-->
<!--T:11-->
Вычислим банк gpio и offset, зная номер (109):
Вычислим банк gpio и offset, зная номер (109):
<pre>
<pre>
Строка 28: Строка 38:
</pre>
</pre>


<!--T:12-->
То же самое справедливо и наоборот. Зная банк и offset (3 и 13, соответственно), можно вычислить номер gpio:
То же самое справедливо и наоборот. Зная банк и offset (3 и 13, соответственно), можно вычислить номер gpio:
<pre>
<pre>
Строка 34: Строка 45:
</pre>
</pre>


=Работа из userspace=<!--T:6-->
=Работа из userspace=<!--T:13-->


<!--T:7-->
<!--T:14-->
Перед началом работы из userspace, необходимо убедиться, в том, что нужный gpio - свободен. Для этого можно посмотреть на вывод команды
Перед началом работы из userspace, необходимо убедиться, в том, что нужный gpio - свободен. Для этого можно посмотреть на вывод команды
<pre>
<pre>
Строка 42: Строка 53:
</pre>
</pre>


<!--T:7-->
<!--T:15-->
В выводе команды видим примерно следующее:
В выводе команды видим примерно следующее:
<pre>
<pre>
Строка 54: Строка 65:
</pre>
</pre>


<!--T:7-->
<!--T:16-->
Это значит, что gpio 0, 26 и 27 уже экспортированы в sysfs и доступны для управления. Gpio 11 и 13 заняты ядерным драйвером onewire и недоступны для использования. Остальные gpio банка 0 доступны для экспорта.
Это значит, что gpio 0, 26 и 27 уже экспортированы в sysfs и доступны для управления. Gpio 11 и 13 заняты ядерным драйвером onewire и недоступны для использования. Остальные gpio банка 0 - свободны.


<!--T:7-->
<!--T:17-->
Если эти gpio нужны по каким-то причинам, то можно остановить драйвер:
Если нужный gpio - занят, то можно остановить драйвер:
<pre>
<pre>
lsmod | grep w1 # узнаем название драйвера
lsmod | grep w1 # узнаем название драйвера
Строка 64: Строка 75:
</pre>
</pre>


<!--T:7-->
<!--T:18-->
'''Остановка драйверов может привести к неожиданному поведению контроллера'''. Теперь желаемый gpio свободен до следующей перезагрузки.
'''Остановка драйверов может привести к неожиданному поведению контроллера'''. Теперь нужный gpio свободен до следующей перезагрузки.


==Работа из Bash==<!--T:6-->
==Bash==<!--T:19-->


<!--T:7-->
<!--T:20-->
В настоящий момент, для работы с gpio в userspace доступны 2 интерфейса: ''sysfs'' и ''chardev'' (начиная с версии ядра 4.8).  
В настоящий момент, для работы с gpio в userspace доступны 2 интерфейса: ''sysfs'' и ''chardev'' (начиная с версии ядра 4.8).  


<!--T:7-->
<!--T:21-->
Различия между ''chardev'' и ''sysfs'' хорошо описаны в [https://embeddedbits.org/new-linux-kernel-gpio-user-space-interface/ этой статье]. Sysfs имеет статус deprecated, поэтому, по возможности, стоит работать через chardev.
Различия между ''chardev'' и ''sysfs'' хорошо описаны в [https://embeddedbits.org/new-linux-kernel-gpio-user-space-interface/ этой статье]. Sysfs имеет статус deprecated, поэтому, по возможности, <u>стоит работать через chardev</u>.


===Интерфейс sysfs===<!--T:6-->
===Интерфейс sysfs===<!--T:22-->


<!--T:8-->
<!--T:23-->
Для работы через sysfs c определённым GPIO его надо экспортировать:
Для работы через sysfs c определённым GPIO его надо экспортировать:


<!--T:9-->
<!--T:24-->
Здесь и далее N - номер gpio
Здесь и далее N - номер gpio


<!--T:10-->
<!--T:25-->
<pre>
<pre>
echo N > /sys/class/gpio/export
echo N > /sys/class/gpio/export
</pre>
</pre>


<!--T:11-->
<!--T:26-->
Экспортированные gpio появляются в каталоге /sys/class/gpio :
Экспортированные gpio появляются в каталоге /sys/class/gpio :


<!--T:12-->
<!--T:27-->
<pre>
<pre>
root@wirenboard:~# ls -1 /sys/class/gpio/
root@wirenboard:~# ls -1 /sys/class/gpio/
Строка 103: Строка 114:
</pre>
</pre>


<!--T:13-->
<!--T:28-->
В директории <b>/sys/class/gpioN</b> теперь находятся файлы для работы с GPIO (где N - номер GPIO, как и было сказано ранее):
В директории <b>/sys/class/gpioN</b> теперь находятся файлы для работы с GPIO (где N - номер GPIO, как и было сказано ранее):


<!--T:14-->
<!--T:29-->
<pre>
<pre>
root@wirenboard:~# ls -1 /sys/class/gpio/gpioN/
root@wirenboard:~# ls -1 /sys/class/gpio/gpioN/
Строка 119: Строка 130:
</pre>
</pre>


<!--T:15-->
<!--T:30-->
Установка направления GPIO (ввод/вывод) производится с помощью записи в файл <b>direction</b>
Установка направления GPIO (ввод/вывод) производится с помощью записи в файл <b>direction</b>


<!--T:16-->
<!--T:31-->
<pre>
<pre>
echo in > /sys/class/gpio/gpioN/direction # установим GPIO номер N на ввод
echo in > /sys/class/gpio/gpioN/direction # установим GPIO номер N на ввод
Строка 128: Строка 139:
</pre>
</pre>


<!--T:17-->
<!--T:32-->
Чтение и установка значения GPIO производится с помощью файла <b>value</b>.  
Чтение и установка значения GPIO производится с помощью файла <b>value</b>.  


<!--T:18-->
<!--T:33-->
Чтение:
Чтение:


<!--T:19-->
<!--T:34-->
<pre>
<pre>
echo in > /sys/class/gpio/gpioN/direction # установим GPIO номер N на ввод
echo in > /sys/class/gpio/gpioN/direction # установим GPIO номер N на ввод
Строка 140: Строка 151:
</pre>
</pre>


<!--T:20-->
<!--T:35-->
Запись:
Запись:


<!--T:21-->
<!--T:36-->
<pre>
<pre>
echo out > /sys/class/gpio/gpioN/direction # установим GPIO номер N на вывод
echo out > /sys/class/gpio/gpioN/direction # установим GPIO номер N на вывод
Строка 150: Строка 161:
</pre>
</pre>


<!--T:13-->
<!--T:37-->
Пример:
Пример:
# Находим номер GPIO, соответсвующий вашей версии контролера нужному клеммнику в таблице [[GPIO|WB2.8]]. Для клеммника номер 2 в версии 2.8 это GPIO 32.
# Находим номер GPIO, соответсвующий вашей версии контролера нужному клеммнику в таблице [[GPIO|WB2.8]]. Для клеммника номер 2 в версии 2.8 это GPIO 32.
Строка 162: Строка 173:
#:<pre>root@wirenboard:~# echo 0 > /sys/class/gpio/gpio32/value</pre>
#:<pre>root@wirenboard:~# echo 0 > /sys/class/gpio/gpio32/value</pre>


====Работа с прерываниями====<!--T:22-->
====Работа с прерываниями====<!--T:38-->


<!--T:23-->
<!--T:39-->
Через интерфейс sysfs можно запросить прерывания по изменению состояния процессора.
Через интерфейс sysfs можно запросить прерывания по изменению состояния процессора.


<!--T:24-->
<!--T:40-->
Установка прерывания производится путём записи значения в файл "edge". Значения могут быть:
Установка прерывания производится путём записи значения в файл "edge". Значения могут быть:
* "none" - отключить прерывание
* "none" - отключить прерывание
Строка 174: Строка 185:
* "both" - включить прерывание по обеим фронтам.
* "both" - включить прерывание по обеим фронтам.


<!--T:25-->
<!--T:41-->
Пример работы с прерываниями:
Пример работы с прерываниями:
<pre>
<pre>
Строка 186: Строка 197:
  26:        76  gpio-mxs  3  gpiolib
  26:        76  gpio-mxs  3  gpiolib


<!--T:26-->
<!--T:42-->
</pre>
</pre>


<!--T:27-->
<!--T:43-->
Прерывания можно ловить из userspace с помощью системного вызова epoll() и select() на файл value.
Прерывания можно ловить из userspace с помощью системного вызова epoll() и select() на файл value.
Пример работы см. [https://github.com/contactless/wiegand-linux-sysfs]
Пример работы см. [https://github.com/contactless/wiegand-linux-sysfs]


<!--T:28-->
<!--T:44-->
См. также [http://elinux.org/GPIO elinux.org]
См. также [http://elinux.org/GPIO elinux.org]


===Работа через chardev===<!--T:29-->
===Работа через chardev===<!--T:45-->
Представленный в ядре 4.8 интерфейс chardev имеет C/Python библиотеку libgpiod и userspace-утилиты для работы с gpio. Исходный код библиотеки и документация доступны в [https://github.com/brgl/libgpiod репозитории libgpiod].
 
<!--T:46-->
Представленный в ядре 4.8 интерфейс chardev имеет C/Python библиотеку ''libgpiod'' и userspace-утилиты для работы с gpio. Исходный код библиотеки и документация доступны в [https://github.com/brgl/libgpiod репозитории libgpiod].


<!--T:28-->
<!--T:47-->
Утилиты распространяются в составе debian-пакетов ''gpiod'' и ''libgpiod-dev'' для debian buster и новее. К сожалению, для stretch пакетов в репозитории и бекпортах нет.
Утилиты распространяются в составе debian-пакетов ''gpiod'' и ''libgpiod-dev'' для debian buster и новее. К сожалению, '''для stretch пакетов в официальных репозиториях нет'''.


<!--T:28-->
<!--T:48-->
Если нужно установить libgpiod в debian stretch, можно воспользоваться сторонними репозиториями (например, [https://github.com/rcn-ee/repos этим]). '''Используйте сторонние репозитории на свой страх и риск; компания WirenBoard не контролирует их содержимое'''.
Если нужно установить libgpiod в debian stretch, можно воспользоваться сторонними репозиториями (например, [https://github.com/rcn-ee/repos этим]). '''Используйте сторонние репозитории на свой страх и риск; компания WirenBoard не контролирует их содержимое'''.


<!--T:28-->
<!--T:49-->
Для работы с gpio из bash в пакете ''gpiod'' поставляются следующие утилиты:
Для работы с gpio из bash в пакете ''gpiod'' поставляются следующие утилиты:
* gpiodetect - информация обо всех банках gpio в системе
* gpiodetect - информация обо всех банках gpio в системе
Строка 214: Строка 227:
* gpiomon - отслеживание событий gpio
* gpiomon - отслеживание событий gpio


<!--T:28-->
<!--T:50-->
Примеры использования gpiod можно посмотреть в [https://www.acmesystems.it/gpiod] и [https://github.com/brgl/libgpiod]
Примеры использования gpiod можно посмотреть в [https://www.acmesystems.it/gpiod] и [https://github.com/brgl/libgpiod]


===Работа из python===<!--T:29-->
==Python==<!--T:51-->


<!--T:29-->
<!--T:52-->
Для управления gpio из python был написан модуль wb_common.gpio, представляющий собой обёртку вокруг sysfs. Исходный код доступен [https://github.com/wirenboard/wb-common/blob/master/wb_common/gpio.py на нашем github.]
Для управления gpio из python был написан модуль <pre>wb_common.gpio</pre>, представляющий собой обёртку вокруг sysfs. Исходный код доступен [https://github.com/wirenboard/wb-common/blob/master/wb_common/gpio.py на нашем github.]


Модуль позволяет работать с gpio в синхронном и асинхронном (с регистрацией коллбэков) режимах.
Модуль позволяет работать с gpio в синхронном и асинхронном (с регистрацией коллбэков) режимах.


===Прямое обращение через память процессора===<!--T:29-->
===Прямое обращение через память процессора===<!--T:53-->


<!--T:30-->
<!--T:54-->
<b>Этот метод настоятельно НЕ РЕКОМЕНДУЕТСЯ для использования без достаточных оснований. Для работы из С/C++ стоит использовать работу через файлы в sysfs или chardev, как описано в предыдущих разделах</b>.
<b>Этот метод настоятельно НЕ РЕКОМЕНДУЕТСЯ для использования без достаточных оснований. Для работы из С/C++ стоит использовать работу через файлы в sysfs или chardev, как описано в предыдущих разделах</b>.


<!--T:31-->
<!--T:55-->
Управлять GPIO можно с помощью прямого доступа к регистрам процессора, в обход Linux, через интерфейс /dev/mem. При этом, по сравнению с работой через sysfs минимизируются накладные расходы. Этот метод можно использовать,  
Управлять GPIO можно с помощью прямого доступа к регистрам процессора, в обход Linux, через интерфейс /dev/mem. При этом, по сравнению с работой через sysfs минимизируются накладные расходы. Этот метод можно использовать,  
если вам необходим очень быстрый доступ к GPIO, например bitbang протоколов или ШИМ. Стоит иметь в виду, что планировщик процессов всё ещё может вносить в работу программы значительные задержки.
если вам необходим очень быстрый доступ к GPIO, например bitbang протоколов или ШИМ. Стоит иметь в виду, что планировщик процессов всё ещё может вносить в работу программы значительные задержки.
Рекомендуется выносить критичные ко времени задачи в ядро.
Рекомендуется выносить критичные ко времени задачи в ядро.


<!--T:32-->
<!--T:56-->
См. [http://olimex.wordpress.com/2012/09/11/imx233-olinuxino-gpios-faster-and-faster/] , [https://github.com/OLIMEX/OLINUXINO/blob/master/SOFTWARE/iMX233/gpio-mmap.h]
См. [http://olimex.wordpress.com/2012/09/11/imx233-olinuxino-gpios-faster-and-faster/] , [https://github.com/OLIMEX/OLINUXINO/blob/master/SOFTWARE/iMX233/gpio-mmap.h]


=Работа из ядра Linux=<!--T:44-->
=Работа в ядре Linux=<!--T:57-->
Ознакомиться с ядром Linux, использующимся в контроллерах WirenBoard можно в нашем [https://github.com/wirenboard/linux репозитории ядра].


===Рекомендации по Device Tree=== <!--T:33-->
===Рекомендации по Device Tree=== <!--T:58-->


<!--T:5-->
<!--T:59-->
На некоторых GPIO можно программно установить 47к подтяжку к +3.. См. [[Special:MyLanguage/Pin_pull-up|Pin_pull-up]].
Device-tree, использующиеся на контроллерах WirenBoard, доступны в репозитории ядра.
Разные аппаратные ревизии контроллера используют разные dts (например, dts для WB6.X можно найти [https://github.com/wirenboard/linux/blob/dev/v4.9.x/arch/arm/boot/dts/imx6ul-wirenboard61.dts здесь])


<!--T:34-->
<!--T:60-->
Указывать GPIO в Device Tree необходимо для настройки работы GPIO в режиме программного SPI, I2C, для использования GPIO в качестве источника прерываний и т.д.
Указывать GPIO в Device Tree необходимо для настройки работы GPIO в режиме программного SPI, I2C, для использования GPIO в качестве источника прерываний и т.д.
Так, например, на пин 10@UEXT1 (CS) и пины 5@UEXT2 (SCL), 6@UEXT2 (SDA), 10@UEXT2 (CS) выведены линии GPIO процессора. Их можно сконфигурировать для использования, например, в качестве chip-select для SPI или в качестве I2C.
Так, например, на пин 10@UEXT1 (CS) и пины 5@UEXT2 (SCL), 6@UEXT2 (SDA), 10@UEXT2 (CS) выведены линии GPIO процессора. Их можно сконфигурировать для использования, например, в качестве chip-select для SPI или в качестве I2C.


<!--T:35-->
<!--T:61-->
GPIO процессора и периферийных устройств разбиты на банки (gpiochip). GPIO процессора разбиты на 3 банка по 32 GPIO: gpio0, gpio1, gpio2. Адресация GPIO в Device Tree происходит по номеру банка и номеру GPIO *внутри* банка.
GPIO процессора и периферийных устройств разбиты на банки (gpiochip). GPIO процессора разбиты на 3 банка по 32 GPIO: gpio0, gpio1, gpio2. Адресация GPIO в Device Tree происходит по номеру банка и номеру GPIO *внутри* банка.


====Пример 1==== <!--T:36-->
====Пример device-tree node==== <!--T:62-->


<!--T:37-->
<!--T:63-->
Определим сигнал 6@UEXT2 (SDA) в качестве источника прерываний для драйвера mrf24j40. Согласно таблице [[Special:MyLanguage/Список GPIO|Список GPIO]], сигнал соответствует GPIO 53 процессора. 53 принадлежит второму банку gpio (от 32 до 63). Номер GPIO внутри банка 53-32=21 :
Определим сигнал 6@UEXT2 (SDA) в качестве источника прерываний для драйвера mrf24j40. Согласно таблице [[Special:MyLanguage/Список GPIO|Список GPIO]], сигнал соответствует GPIO 53 процессора. 53 принадлежит второму банку gpio (от 32 до 63). Номер GPIO внутри банка 53-32=21 :



Версия 19:11, 26 марта 2021

Другие языки:

Статья рассчитана на разработчиков или опытных пользователей и даёт общие рекомендации того, как использовать gpio в обход официального ПО WirenBoard.

Каноничный способ взаимодействия с gpio контроллеров WirenBoard - это драйвер wb-homa-gpio с открытым исходным кодом. В readme репозитория можно почитать о конфигурации драйвера для специализированных нужд.

Описание доступных ножек gpio для конкретной ревизии контроллера можно найти в статье GPIO.

Меры предосторожности

  • Все GPIO (как и остальные порты Wiren Board) работают с напряжением 3.3V.
  • Подключение сигнала с напряжением > 3.3V к ножке GPIO грозит выходом из строя процессорного модуля.

В случае необходимости подключения устройств, работающих с более высоким напряжением, необходимо использовать схемы согласования или подключать (для 5V) через резистор в 20 кОм и более

Именование gpio

К сожалению, четкого стандарта по именованию gpio не существует, но при работе с контроллерами WirenBoard стоит придерживаться следующих правил:

  • выводы gpio сгруппированы по банкам (banks; эквивалентно gpiochips)
  • каждый банк содержит 32 gpio. Нумерация банков начинается с 0.

Вычисление номера gpio

Для управления ножкой gpio нужно знать её номер. В рассматриваемых примерах будем работать с gpio A1_IN контроллера WB6.7 (номер: 109; gpiochip 3, offset 13):

Вычислим банк gpio и offset, зная номер (109):

# Поделим 109 на 32. Целая часть - номер банка, остаток - offset:
109.0 / 32.0 = 3, остаток 13

То же самое справедливо и наоборот. Зная банк и offset (3 и 13, соответственно), можно вычислить номер gpio:

# Умножим номер банка на 32 и прибавим offset:
3 * 32 + 13 = 109

Работа из userspace

Перед началом работы из userspace, необходимо убедиться, в том, что нужный gpio - свободен. Для этого можно посмотреть на вывод команды

cat /sys/kernel/debug/gpio

В выводе команды видим примерно следующее:

gpiochip0: GPIOs 0-31, parent: platform/209c000.gpio, 209c000.gpio:
 gpio-0   (                    |sysfs               ) in  hi IRQ
 gpio-10  (                    |?                   ) in  lo    
 gpio-11  (                    |w1                  ) in  hi    
 gpio-13  (                    |w1 strong pullup    ) out lo    
 gpio-26  (                    |sysfs               ) out lo    
 gpio-27  (                    |sysfs               ) out hi    

Это значит, что gpio 0, 26 и 27 уже экспортированы в sysfs и доступны для управления. Gpio 11 и 13 заняты ядерным драйвером onewire и недоступны для использования. Остальные gpio банка 0 - свободны.

Если нужный gpio - занят, то можно остановить драйвер:

lsmod | grep w1 # узнаем название драйвера
rmmod w1_gpio # выгружаем драйвер, название которого узнали

Остановка драйверов может привести к неожиданному поведению контроллера. Теперь нужный gpio свободен до следующей перезагрузки.

Bash

В настоящий момент, для работы с gpio в userspace доступны 2 интерфейса: sysfs и chardev (начиная с версии ядра 4.8).

Различия между chardev и sysfs хорошо описаны в этой статье. Sysfs имеет статус deprecated, поэтому, по возможности, стоит работать через chardev.

Интерфейс sysfs

Для работы через sysfs c определённым GPIO его надо экспортировать:

Здесь и далее N - номер gpio

echo N > /sys/class/gpio/export

Экспортированные gpio появляются в каталоге /sys/class/gpio :

root@wirenboard:~# ls -1 /sys/class/gpio/
export
gpio32
gpiochip0
gpiochip120
gpiochip32
gpiochip64
unexport

В директории /sys/class/gpioN теперь находятся файлы для работы с GPIO (где N - номер GPIO, как и было сказано ранее):

root@wirenboard:~# ls -1 /sys/class/gpio/gpioN/
active_low
device
direction
edge
power
subsystem
uevent
value

Установка направления GPIO (ввод/вывод) производится с помощью записи в файл direction

echo in > /sys/class/gpio/gpioN/direction # установим GPIO номер N на ввод
echo out > /sys/class/gpio/gpioN/direction # установим GPIO номер N на вывод

Чтение и установка значения GPIO производится с помощью файла value.

Чтение:

echo in > /sys/class/gpio/gpioN/direction # установим GPIO номер N на ввод
cat /sys/class/gpio/gpioN/value # вернёт 1 или 0

Запись:

echo out > /sys/class/gpio/gpioN/direction # установим GPIO номер N на вывод
echo 0 > /sys/class/gpio/gpioN/value # установим логический 0  (низкое напряжение) на GPIO номер N
echo 1 > /sys/class/gpio/gpioN/value # установим логический 1  (высокое напряжение) на GPIO номер N

Пример:

  1. Находим номер GPIO, соответсвующий вашей версии контролера нужному клеммнику в таблице WB2.8. Для клеммника номер 2 в версии 2.8 это GPIO 32.
  2. Экспортируем GPIO в sysfs
    root@wirenboard:~# echo 32 > /sys/class/gpio/export
  3. Устанавливаем GPIO в режим вывода для управления транзистором. Это обязательно, т.к. GPIO может находится в режиме ввода и иметь высокий импенданс, оставляя транзистор в неопределённом состоянии.
    root@wirenboard:~# echo out > /sys/class/gpio/gpio32/direction
  4. Открываем транзистор, подавая логический высокий уровень на затвор:
    root@wirenboard:~# echo 1 > /sys/class/gpio/gpio32/value
  5. Закрываем транзистор, подавая логический ноль на затвор:
    root@wirenboard:~# echo 0 > /sys/class/gpio/gpio32/value

Работа с прерываниями

Через интерфейс sysfs можно запросить прерывания по изменению состояния процессора.

Установка прерывания производится путём записи значения в файл "edge". Значения могут быть:

  • "none" - отключить прерывание
  • "rising" - включить прерывание по нисходящему фронту
  • "falling" - включить прерывание по восодящему фронту
  • "both" - включить прерывание по обеим фронтам.

Пример работы с прерываниями:

root@wirenboard:~# echo 3 >  /sys/class/gpio/export # экспортируем GPIO номер 3 (TB10 на WB3.3)
root@wirenboard:~# cat /sys/class/gpio/gpio3/edge   # проверяем состояние прерывания
none
root@wirenboard:~# echo falling > /sys/class/gpio/gpio3/edge # устанавливаем прерывание по нисходящему фронту
root@wirenboard:~# cat /proc/interrupts  | grep gpiolib # прерывание появилось в списке. 26 - внутренний номер прерывания, 0 - количество событий
 26:          0  gpio-mxs   3  gpiolib
root@wirenboard:~# cat /proc/interrupts  | grep gpiolib # после нескольких собтий, 76 - количество событий
 26:         76  gpio-mxs   3  gpiolib

Прерывания можно ловить из userspace с помощью системного вызова epoll() и select() на файл value. Пример работы см. [1]

См. также elinux.org

Работа через chardev

Представленный в ядре 4.8 интерфейс chardev имеет C/Python библиотеку libgpiod и userspace-утилиты для работы с gpio. Исходный код библиотеки и документация доступны в репозитории libgpiod.

Утилиты распространяются в составе debian-пакетов gpiod и libgpiod-dev для debian buster и новее. К сожалению, для stretch пакетов в официальных репозиториях нет.

Если нужно установить libgpiod в debian stretch, можно воспользоваться сторонними репозиториями (например, этим). Используйте сторонние репозитории на свой страх и риск; компания WirenBoard не контролирует их содержимое.

Для работы с gpio из bash в пакете gpiod поставляются следующие утилиты:

  • gpiodetect - информация обо всех банках gpio в системе
  • gpioinfo - подробная информация обо всех линиях gpio определённого банка
  • gpioget <чип> <линия> - возвращает значение определённого gpio
  • gpioset <чип> <линия1>=<значение1> <линия2>=<значение2> - устанавиливает состояние на определенные линии gpio
  • gpiofind <название> - возвращает номер gpio
  • gpiomon - отслеживание событий gpio

Примеры использования gpiod можно посмотреть в [2] и [3]

Python

Для управления gpio из python был написан модуль

wb_common.gpio

, представляющий собой обёртку вокруг sysfs. Исходный код доступен на нашем github.

Модуль позволяет работать с gpio в синхронном и асинхронном (с регистрацией коллбэков) режимах.

Прямое обращение через память процессора

Этот метод настоятельно НЕ РЕКОМЕНДУЕТСЯ для использования без достаточных оснований. Для работы из С/C++ стоит использовать работу через файлы в sysfs или chardev, как описано в предыдущих разделах.

Управлять GPIO можно с помощью прямого доступа к регистрам процессора, в обход Linux, через интерфейс /dev/mem. При этом, по сравнению с работой через sysfs минимизируются накладные расходы. Этот метод можно использовать, если вам необходим очень быстрый доступ к GPIO, например bitbang протоколов или ШИМ. Стоит иметь в виду, что планировщик процессов всё ещё может вносить в работу программы значительные задержки. Рекомендуется выносить критичные ко времени задачи в ядро.

См. [4] , [5]

Работа в ядре Linux

Ознакомиться с ядром Linux, использующимся в контроллерах WirenBoard можно в нашем репозитории ядра.

Рекомендации по Device Tree

Device-tree, использующиеся на контроллерах WirenBoard, доступны в репозитории ядра. Разные аппаратные ревизии контроллера используют разные dts (например, dts для WB6.X можно найти здесь)

Указывать GPIO в Device Tree необходимо для настройки работы GPIO в режиме программного SPI, I2C, для использования GPIO в качестве источника прерываний и т.д. Так, например, на пин 10@UEXT1 (CS) и пины 5@UEXT2 (SCL), 6@UEXT2 (SDA), 10@UEXT2 (CS) выведены линии GPIO процессора. Их можно сконфигурировать для использования, например, в качестве chip-select для SPI или в качестве I2C.

GPIO процессора и периферийных устройств разбиты на банки (gpiochip). GPIO процессора разбиты на 3 банка по 32 GPIO: gpio0, gpio1, gpio2. Адресация GPIO в Device Tree происходит по номеру банка и номеру GPIO *внутри* банка.

Пример device-tree node

Определим сигнал 6@UEXT2 (SDA) в качестве источника прерываний для драйвера mrf24j40. Согласно таблице Список GPIO, сигнал соответствует GPIO 53 процессора. 53 принадлежит второму банку gpio (от 32 до 63). Номер GPIO внутри банка 53-32=21 :

				6lowpan@0 {
					compatible = "microchip,mrf24j40";
					spi-max-frequency = <100000>;
					reg = <6>;
					interrupt-parent = <&gpio1>;
					interrupts = <21 0>;
				};