Работа с портами GPIO через стандарный драйвер SYSFS




Здравствуйте, уважаемые читатели! Начиная с версии 2.6.26, в Linux появился стандартный интерфейс для работы с GPIO через файловую систему sysfs. Работа с GPIO проходит через каталог /sys/class/gpio путём обращения к файлам-указателям. Подробное описание на русском языке найти трудно, поэтому я сделал краткий перевод основных моментов из официальной документации.

Существует три типа записей в /sys/class/gpio:
- Интерфейсы управления пользовательскими GPIO;
- Сами GPIO;
- Порты ввода-вывода (gpio_chip).

Интерфейсы управления работают по пути /sys/class/gpio только на запись:

export - запрашивает экспорт управления GPIO пользователю с записью его номера в файл.
Например, команда echo 19 > export создаст файл gpio19.
unexport - отменяет экспорт.
Например, команда echo 19 > unexport удалит файл gpio19.

Сигналы GPIO имеют пути /sys/class/gpio/gpioN (N - номер GPIO) и имеют атрибуты чтения/записи:

direction - направление, может принимать зачения in (вход) или out (выход), как правило, пишется.
value - состояние, может принимать значение 0 (низкий) или 1 (высокий). Если GPIO настраивается на выход, то значение пишется. Ненулевое значение считается высоким.
edge - реакция на изменение состояния, может принимать значения none (нет), rising (фронт), falling (спад) или both (перепад).
active_low Инвертирование значения value, может принимать значение 0 (нет) или 1 (да). Ненулевое значение считается единицей.

Порты GPIO имеют пути /sys/class/gpio/gpiochipN (для порта GPIO начиная с вывода #N) и имеют атрибуты только для чтения:

base - номер первого GPIO управляемого портом.
label - диагностическая метка, но здесь нет стандарта.
ngpio - сколько выводов GPIO управляется портом.

Более подробно с работой GPIO через sysfs можно ознакомиться здесь.


Основные моменты работы с GPIO через sysfs ясны и понятны, теперь можно управлять любым из доступных выводов. Согласно документации, пользователю микрокомпьютера MB77.07 доступно 16 контактов ввода-вывода TS_DO0..TS_DO7 и GPIO0..GPIO7, которые прописаны в Raspbian соответсвенно как GPIO16..GPIO23 и GPIO24..GPIO31, и все они имеют возможность генерировать прерывания. Выводы TS_DO0..TS_DO7 порта демультиплексора транспортного потока достались микрокомпьютеру в наследство от цифрового телевидения, но их можно переключать в режим пользовательского ввода-вывода и использовать по своему усмотрению. Выводы GPIO0..GPIO7 - обычные линии ввода-вывода без каких-либо особенностей. Для экспериментов понадобится обычный светодиод и резистор, подключать его проще всего к выводу GPIO7, выведенному на контакт 16 разъёма X9, общим проводом будет контакт 16 того же разъёма X9:

Вывод GPIO7 прописан в Raspbian как GPIO31, а значит для управлением состояния светодиода обращаться нужно именно к виртуальному GPIO31. Также, чтобы не набирать каждый раз путь /sys/class/gpio, лучше сразу перейти в нужный каталог:

cd /sys/class/gpio

Для начала нужно передать управление виртуальным GPIO31 в распоряжение пользователя с помощью команды записи в файл echo:

echo 31 > export

В каталоге /sys/class/gpio должен появиться файл-указатель gpio31:

Это означает, что виртуальный GPIO31 теперь доступен для работы. Поскольку нужно управлять светодиодом, нужно порт настроить его на выход:

echo out > gpio31/direction

Хорошо, теперь виртуальный GPIO31 настроен на выход и можно зажечь светодиод, выведя в порт единицу:

echo 1 > gpio31/value

Работает! Светодиод загорелся:

Также можно погасить светодиод, просто обнулив порт:

echo 0 > gpio31/value

Наконец, можно закончить работу и передать управление виртуальным GPIO31 и реальным GPIO7 обратно Raspbian, но сперва лучше переключить его на ввод:

echo in > gpio31/direction

а уже потом возвращать контроль над ним операционной системе:

echo 31 > unexport

в заключение можно вернуться в корневой каталог командой cd


Это здорово! К выводам GPIO можно подключить через транзисторные ключи обычные электромагнитные реле, и управлять нагрузкой с подключённого к интернету микрокомпьютеру хоть через полмира! Но не набирать же вручную команды по списку! Лучше предоставить управление GPIO самому микрокомпьютеру, с помощью, хотя бы простейшего bash-скрипта. Например, нужно пять раз включить и выключить светодиод с периодом в одну секунду - на полсекунды зажечь светодиод, на полсекунды погасить его - и так пять раз. Пусть, местом хранения скриптов будет каталог /home:

cd /home

В нём нужно будет создать файл blink и записать в него весь список команд:

После сохранения скрипта нужно обязательно дать файлу право на выполнение:

Запускать скрипт нужно командой:

./blink

Светодиод пять раз мигнёт и погаснет. Отлично! А какое быстродействие у операций ввода-вывода через GPIO с помощью sysfs? Для проверки нужно только подправить предыдущий скрипт, без сожаления выбросив команды ожидания sleep и увеличив количество итераций до 10000. Сохранить скрипт можно под другим именем, например, blink!, не забыв дать файлу права на выполнение:

Остаётся, подключить параллельно светодиоду частотомер и запустить скрипт:

./blink!

В итоге, частота переключения равна 459 Гц, а время вывода в порт чуть меньше 1,1 мс и зависит от загрузки процессора! Причина кроется в невысокой скорости обработки операций открытия, закрытия, чтения и записи файлов-указателей GPIO.

bash-скрипт по большому счёту можно использовать разве что для проверки самой возможности управления GPIO, а для практического пременения лучше написать и скомпилировать программу:

gcc -o blinks blinks.c -O2

Запустить программу можно командой

./blinks

Далее, задаём количество циклов, например, 5 - в итоге светодиод десять раз загорится и погаснет. Программа выдаст сообщение об успешном завершении операции и вернёт управление операционной системе.

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


Как выяснилось, драйвер GPIO через файловую систему sysfs не только медленный - операция вывода в порт требует целых 1,1 мс, но и может кратковременно приостанавливать работу в момент запуска в Raspbian высокоприоритетных процессов! Увы, но sysfs для управления шаговыми двигателями совершенно не годится - из-за невысокого быстродействия файлового драйвера не удастся получить приемлемую скорость вращения ротора, а благодаря работе планировщика задач Raspbian, двигатель вдобавок начнёт пропускать шаги. На деле область работы с GPIO через sysfs ограничивается управлением электромагнитными и твердотельными реле, светодиодной иллюминацией и тому подобными задачам, не требующими высокого быстродействия и точной привязки по времени. Невысокая скорость работы - плата за простоту управления через файловую систему.


Обновлено - 5.06.2019. Добавлен файл авторского краткого перевода документации по sysfs.


Обновлено - 24.08.2020. Добавлен пример программы управления GPIO.


Благодарю за внимание, доброго здоровья!



Сайт работает на микрокомпьютере