BiNome
BiNome
6526 просмотров12 комментариев0

Часть 1. Программное управление GPIO Repka Pi 3 через системные вызовы к драйверу символьных устройств. Общие понятия. Настройка RepkaOS. Использование инструментов управления GPIO из пользовательского режима

Настоящая статья посвящена вопросу программного управлению GPIO через системные вызовы к драйверу символьных устройств и познакомит вас с возможностью использования библиотеки libgpiod2 на Repka Pi 3. В статье приведены рекомендации по настройке ОС для использования этой библиотеки. Результаты тестовой эксплуатации libgpiod2 на Repka Pi 3 обобщены в виде справочной таблицы. В заключении статьи приводятся примеры использования инструментов управления GPIO из пользовательского интерфейса.

Общие сведения #

GPIO (General-Purpose Input/Output) интерфейс ввода/вывода общего назначения чаще всего используемый на платах микроконтроллеров и одноплатных компьютеров для программного управления цифровыми сигналами.

Во внутренней архитектуре ядро Linux реализует доступ к GPIO через модель производитель/потребитель. Существуют драйверы, которые предоставляют доступ к линиям GPIO (драйверы контроллеров GPIO) и драйверы, которые используют линии GPIO (клавиатура, сенсорный экран, датчики и т. д.).

Основные особенности GPIO:

  • Контакты GPIO могут быть сконфигурированы для ввода или вывода;
  • Контакты GPIO могут быть включены / выключены;
  • Контакты для ввода доступны для чтения значения;
  • Контакты для вывода доступны для записи / чтения значения;
  • Входные значения часто могут использоваться в качестве IRQs (обычно для событий пробуждения).

В ядре Linux система gpiolib занимается регистрацией и распределением GPIO. Эта структура доступна через API как для драйверов устройств, работающих в пространстве ядра (kernel space), так и для приложений пользовательского пространства (user space).

В Linux (в том числе и в RepkaOS) доступ к аппаратным устройствам осуществляется пользователем через специальные файлы устройств. Эти файлы сгруппированы в каталоге /dev, а системные вызовы перенаправляются операционной системой на драйвер устройства, связанного с физическим устройством. Драйвер устройства - это компонент ядра ОС Linux (обычно модуль), который взаимодействует с аппаратным устройством.

В Linux существуют две категории файлов устройств, и следовательно, драйверов устройств: символьные и блочные. К первой категории относятся медленные устройства, которые управляют небольшим объемом данных, а доступ к данным не требует частых запросов seek. Примерами могут служить такие устройства, как клавиатура, мышь, последовательные порты, звуковая карта, джойстик и т.д. В общем, операции с этими устройствами (чтение, запись) выполняются последовательно, байт за байтом. Ко второй категории относятся устройства, где объем данных велик, данные организованы по блокам, а поиск является обычным делом. Примерами таких устройств являются: жесткие диски, CD-ROM, диски в оперативной памяти и т.д. Для этих устройств чтение и запись выполняются на уровне блоков данных.

Для двух типов драйверов устройств ядро Linux предлагает разные API. Для символьных устройств используются системные вызовы (ioctl) непосредственно к драйверам устройств. Как правило, системные вызовы к драйверам устройств чаще всего используются в системном программировании, а для разработки приложений пользовательского режима используются библиотеки-обвертки. Одной из таких библиотек-обверток вокруг системных вызовов драйвера символьного устройства GPIO является библиотека libgpiod2.

Примечание: сообществом разработчиков ядра Linux, см. официальную документацию, рекомендуется использовать библиотеку libgpiod2 для разработки нативных и управляемых виртуальной машиной приложений.

Библиотека libgpiod2 #

Libgpiod (Library General Purpose Input/Output device) предоставляет набор API для вызова из своих программ и несколько утилит для управления линиями GPIO из пользовательского режима.

Контроллер GPIO (gpiochip) представляет собой символьное устройство, отображается в разделе /dev. Предназначен для управления и взаимодействия с линиями GPIO. Контроллеры GPIO отображаются в каталог  /dev/gpiochipN  или  /sys/bus/gpiochipN , где N — порядковый номер чипа.

Линия общего назначения контроллера GPIO (line) управляется контролером GPIO, сопоставлена с физическим контактом GPIO-разъема. Управление сигналами на контактах осуществляется через запись в линию или чтение из нее.

Библиотека libgpiod2 инкапсулирует вызовы ioctl и структуры данных за простым API. Библиотека разработана для замены доступа к GPIO через виртуальную файловую систему sysfs, так как начиная версии 4.8 ядра Linux интерфейс GPIO sysfs объявлен как устаревший (deprecated). Используемый в библиотеке новый интерфейс chardev гарантирует, что все выделенные ресурсы будут освобождены после закрытия файлового дескриптора устройства, и добавляет несколько новых функций, которых нет в устаревшем интерфейсе sysfs (например, опрос событий, установка/чтение нескольких значений одновременно).

Библиотека libgpiod2 обладает весомыми преимуществами по сравнению с интерфейсом sysfs, а именно:

  • При завершении процесса (в том числе аварийного) используемые процессом линии GPIO автоматически освобождаются;
  • Предоставляет возможность определить какой процесс в данное время использует определенную линию GPIO;
  • Доступно одновременное чтение и запись в несколько линий GPIO;
  • Контроллеры и линии GPIO можно найти по названию;
  • Позволяет настроить состояние вывода контакта;
  • Предоставляет надежные функции опроса прерываний от линий для перехвата событий изменения состояния сигнала.

В RepkaOS 1.0.14 (от 06.10.2023) библиотека libgpiod2 версии 1.3 установлена “из коробки”, но для начала работы с GPIO в пользовательском режиме необходимо дополнительно установить пакет gpiod. А использование библиотеки для разработки программ станет возможно только после установки пакета libgpiod-dev. Библиотека libgpiod2 может быть использована при написании программ на ЯП: C, C++, C#, Java (Kotlin), Python. В настоящее время разработчики библиотеки работают над реализацией ее поддержки в ЯП Rust.

Для полной установки libgpiod2 из общего репозитория в RepkaOS введите команду:

sudo apt install libgpiod2 gpiod libgpiod-dev

Для удаления:

sudo apt remove libgpiod2 gpiod libgpiod-dev

Для установки более новых бинарных версий версий библиотеки (актуальная версия 2.1) можно воспользоваться скриптом setup-libgpiod.sh, а для ее удаления remove-libgpiod.sh.

Для прямого доступа к линиям GPIO в RepkaOS пользователь должен обладать правами администратора (root) или получать привилегии администратора через команду sudo при работе с линиями GPIO.

Примечание: если вы не создавали нового пользователя и пользуетесь предустановленной учетной записью (root), то можете пропустить эту настройку.

  1. Создадим группу gpiod и добавим в нее обычного пользователя user (не обладающего административными правами, пользователь должен быть зарегистрирован в ОС заранее):

    sudo groupadd gpiod
    sudo usermod -G gpiod user
    
  2. Разрешим пользователям группы gpiod управлять контроллерами GPIO № 0 и 1, создадим файл 60-gpiod.rules в каталоге /etc/udev/rules.d следующего содержания:

    #udev rules for gpio port access
    SUBSYSTEM=="gpio", KERNEL=="gpiochip[0-1]", GROUP="gpiod", MODE="0660"
    
  3. Перезагрузите устройство:

    sudo reboot
    

Особенности управления GPIO из пользовательского режима #

Прежде чем начать работу с инструментами рассмотрим справочную таблицу (рис. 1), которая пригодится нам для работы с линиями GPIO.

Таблица составлена на основе опытного тестирования программного управления GPIO из приложения на ЯП Python с использованием библиотеки libgpiod2 версии 1.3. В процессе исследования проверялось:

  • переключение режимов работы линий ввод/вывод;
  • программное включение резистора для подтяжки линии вверх и вниз;
  • доступность обработчиков событий изменения состояния сигнала (высокое / низкое) в линии с программным включением резистора подтяжки вверх и вниз.

Примечание:

  • использовался первый вариант распиновки 40 pin разъема;
  • тестирования линий 4 и 5 контроллера gpiochip1 осуществлялось при выключенном выводе сообщений на UART0 (по умолчанию включена);
  • подтяжка вниз на линиях, сопоставленных с пинами 3, 5, 10, 27 и 28 GPIO работает как подтяжка вверх, соответственно обработка событий с подтяжкой вниз не доступна;
  • на линиях, сопоставленных с пинами 19, 21, 23 и 24, обработка событий не доступна;
  • пороговое напряжения вызова прерывания на изменение состояния сигнала высокое / низкое не измерялось, в виду отсутствия технической возможности;
  • состав используемого оборудования при тестировании: Repka Pi 3 1.4 GHz ОЗУ 2 Gb (версия платы 1.4), монитор, клавиатура, мышь, макетная плата, резистор 220 Ом, светодиод, кнопка, комплект проводов, мультиметр.

Рис. 1. Справочная таблица для работы с линиями контроллера GPIO с использованием библиотеки libgpiod2 на Repka Pi 3 (версия прошивки 1.0.8 и выше).

Для управления линиями GPIO через libgpiod2 из пользовательского режима можно использовать следующие утилиты (входят в пакет gpiod):

  • gpiodetect — выведет список всех чипов GPIO, их метки и количество линий;
  • gpioinfo — выводит информацию о линиях GPIO конкретного контроллера GPIO. Информация выводится в виде таблицы со следующими столбцами: номер линии, название контакта (для Repka Pi 3 к сожалению не заданы), направление ввода/вывода, текущее состояние;
  • gpioget — считывает текущее состояние линии GPIO;
  • gpioset — устанавливает значение для линии GPIO;
  • gpiomon — осуществляет мониторинг состояния линии GPIO и выводит значение при изменение состояния;
  • gpionotify — ожидает определенное состояние линии GPIO и выводит статус изменения в консоль.

Примечание: все перечисленные утилиты имеют параметр -h (—help) для вывода списка допустимых параметров, а также man-страницы с подробным описанием.

Тест работоспособности библиотеки libgpiod2 #

Для проверки работоспособности библиотеки libgpiod2 соберем макет схемы с двумя светодиодами (рис. 2).

Рис. 2. Макет схемы для теста (номера контактов: черный - 40, красный - 32, зеленый - 23).

Запросим информацию о доступных в Repka Pi 3 контролерах:

~/gpiodetect

и их линиях:

~/gpioinfo gpiochip0
~/gpioinfo 1

Примечание: в Repka Pi 3 контакты PL 2, 3, 10 и 11 управляются контроллером gpiochip0, все остальные контроллером gpiochip1.

Подадим питание на красный светодиод, подключенный к линии 11 gpiochip0 (контакт № 32)

~/gpioset gpiochip0 11=1

или

~/gpioset 0 11=1

Отключим питание от красного светодиода:

~/gpioset gpiochip0 11=0

или

~/gpioset 0 11=0

Задание для самостоятельного выполнения:

  1. Повторите операции включения и выключения питания для зеленого светодиода. Для определения номера контроллера и линии, к которой он подключен, используйте справочную таблицу (рис. 1).
  2. Посмотрите с помощью утилиты gpioinfo как изменяется информация о состоянии линии при включении и выключении светодиодов.
  3. Получите значения используемых вами линий с помощью утилиты gpioget, до и после включения светодиодов.

Примеры использования библиотеки в различных ЯП #

Ниже приведены примеры для мигания красным светодиодом (см. рис. 2), подключенным к 11 линии gpiochip0.

Python

import gpiod
import sys
import time

LED_CHIP = 0
LED_LINE_OFFSET = 11

chip = gpiod.chip(LED_CHIP)
led = chip.get_line(LED_LINE_OFFSET)

config = gpiod.line_request()
config.consumer = "Blink"
config.request_type = gpiod.line_request.DIRECTION_OUTPUT
led.request(config)

while True:
    led.set_value(0)
    time.sleep(0.1)
    led.set_value(1)
    time.sleep(0.1)

Для установки модуля gpiod для Python выполните следующую команду:

pip3 install gpiod

С++

// в разделе #include <> заменены на "" из-за некорректного вывода кода 
// (пропадают названия заголовочных файлов)
#include "chrono"
#include "cstdlib"
#include "gpiod.hpp"
#include "iostream"
#include "string"
#include "thread"

int main(int argc, char **argv) {
    std::string LED_CHIP = "gpiochip0";
    int         LED_LINE_OFFSET = 11;

    gpiod::chip chip(LED_CHIP);
    gpiod::line led = chip.get_line(LED_LINE_OFFSET);

    gpiod::line_request config;
    config.consumer     = "Blink";
    config.request_type = gpiod::line_request::DIRECTION_OUTPUT;
    led.request(config);

    while(1) {
        led.set_value(0);
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        led.set_value(1);
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}
gcc -o blink blink.o -lgpiod
./blink

C# & .NET 6

dotnet new console dotnet_iot_blink
vim ./dotnet_iot_blink/Program.cs
using System;
using System.Device.Gpio;
using System.Device.Gpio.Drivers;
using System.Threading;
namespace dotnet_iot_blink
{
 class Program
 {
  static void Main(string[] args)
  {   
   const int GPIOCHIP = 0;
   const int LED_PIN = 11;
   GpioController controller;
   var drvGpio = new LibGpiodDriver(GPIOCHIP);
   controller = new GpioController(PinNumberingScheme.Logical, drvGpio);
   controller.OpenPin(LED_PIN, PinMode.Output);
   bool ledOn = true;
   while (true)
   {
    controller.Write(LED_PIN, ((ledOn) ? PinValue.High : PinValue.Low));
    Thread.Sleep(100);
    ledOn = !ledOn;
   }
  }
 }
}
cd ./dotnet_iot_blink
dotnet run

Для работы на Repka Pi 3 с GPIO в .NET 6 и выше рекомендуется обновить библиотеку libgpiod-dev до версии 1.6.3.

Примечание: из личного опыта, .NET 6 отлично работает с libgpiod-dev версии 1.3, установленной в RepkaOS 1.4 по умолчанию.

Заключение #

В следующих статьях будут опубликованы учебные материалы по управлению GPIO на Repka Pi 3 с примерами на ЯП Python в связке с библиотекой libgpiod2. В частности, рассмотрим вопросы настройки линий для вывода сигнала, помигаем светодиодами и решим несколько интересных задач с ними.

Часть 2. Программное управление линиями GPIO Repka Pi 3 в режиме вывода с примерами на Python (libgpiod).


0

Комментарии (12)

Для участия в обсуждении Вы должны быть авторизованным пользователем
Команда Репки
Команда Репки  

Это мега крутая статья!
Лучший пятничный подарок проекту Репка! Спасибо Вам большое!!!!

0
BiNome
BiNome  

Грех не помочь такому смелому проекту, тем более отечественному. Главное чтобы впрок пошло.

0
BiNome
BiNome  

Добавлен раздел "Примеры использования библиотеки в различных ЯП"

0
Denis-pimenov  

Скажите, а в чём код писать то? Не vscode же на репку ставить! И... я ведь могу прям на репке писать? Вопросы наверно глупые, я второй день с ней вожусь.
ЗЫ. накатил на репку alt linux, т.к. на ноуте он же

0
BiNome
BiNome  

Я пишу в VS Code (непосредственно на Репке, 1,4 гГц, 2 Гб ОЗУ). Можно использовать предустановленный Geany. Если планируете писать на Python, то можно установить Thonny из репозитория, он адаптирован для одноплатников. Во второй части статьи (п. 4.1, https://repka-pi.ru/blog/post/59), описан порядок настройки VS Code (в примечаниях). Если в двух словах, после установки нужно отключить аппаратное ускорение графики, так как из-за него некорректно работает отображение текста в терминале.

0
Denis-pimenov  

Спасибо! Меня как раз больше плюсы и шарп интересует. Пойду пытаться! :)

0
BiNome
BiNome  

Дополнительно по VS Code. Расширения для Python и C/C++ (в т.ч. CMake) работают без нареканий. Для работы с C# нужно ставить расширения C# (base language support), который за собой тянет .NET Install Tool тянет за собой .NET 7 Runtime. Настоятельно (пока) не рекомендую ставить C# Dev Kit и IntelliCode for C# Dev Kit, так как они очень ресурсоемкие, даже не все настольники с ними справляются. P.s. последние 2 расширения используются для интеллектуального анализа кода и умных подсказок (не путать с обычным IntelliSense, который включен в первое расширение).

0
k_s_corp
k_s_corp  

Для того, чтобы gpiod заработал "без рута" сделал:
sudo chmod a+rw /dev/gpiochip0
так как ругался что нет прав...

0
BiNome
BiNome  

Как один из вариантов подойдет, но у него есть минус - после перезагрузки придется это делать снова... лучше воспользоваться способом описанным в подразделе "Линия общего назначения контроллера GPIO (line) " настоящей статьи

0
k_s_corp
k_s_corp  

Для С++ правильно (у меня только так заработало)
g++ -o name name.cpp -lgpiodcxx (name - имя файла)

0
Foras
Foras  

"Для установки модуля gpiod для Python выполните следующую команду:

pip3 gpiod"

pip3 install gpiod?

0
BiNome
BiNome  

Спасибо, исправил.

0

Еще посты по теме

Новые посты

Наиболее интересные по мнению читателей



Темы

Навигация

ВойтиРегистрация