QSG_3: Работа с GPIO (на примере Orange Pi)

QSG - quick start guide
SBC (single-board computer) - Одноплатный компьютер
GPIO (general-purpose input/output) - Интерфейс ввода/вывода общего назначения

Что необходимо:

  • SBC (Orange Pi) c GPIO выводами;
  • Возможность включить и подключиться к данному SBC;
  • Карта памяти с установленным образом ОС Armbian Bionic (или другим поддерживаемым дистрибутивом);
  • Доступный Интернет (может потребоваться установка доп. ПО и библиотек);
  • Базовые знания языка Си, ОС Linux, схемотехники и микроэлектроники;
  • Радиодетали - для сборки простой демонстрационной схемы (светодиоды, резисторы, кнопки);
  • Схему "распиновки" (pinout) GPIO вашего одноплатного компьютера;
  • Документация на чип, используемый в основе SBC, и умение ее читать.
  • Паяльник и умение паять (на некоторых платах GPIO выводы не распаяны)

Не забывайте о статическом электричестве - которое может быть опасным для микроэлектроники. Удостоверьтесь в правильности подключения схемы, используемых номиналов и т.д.

Что такое GPIO

GPIO (general-purpose input/output) - Интерфейс ввода/вывода общего назначения.

GPIO подключены напрямую к "процессору" SoC (System-on-a-Chip - Система на кристалле), и неграмотное использование может вывести его из строя.

Большинство одноплатных компьютеров, кроме обычных двунаправленных Input/Output портов, имеют один или более интерфесов: UART, SPI, I²C/TWI, PWM (ШИМ), но не имеют ADC (АЦП).

GPIO - порты обычно могут быть сконфигурированны на ввод или вывод (Input/Output), состояние по умолчанию обычно INPUT.

Некоторые "GPIO"-порты - являются просто питающими портами 3.3V, 5V и GND, они не связаны с SoC и не могут использоваться как либо еще.

Порты с альтернативной функцией - могут быть мультиплексированны с одним из соответствующих ему интерфейсов.

Некоторые выводы могут иметь подтягивающие pullup и pulldown резисторы, на некоторых портах они могут быть включены по умолчанию.

Во время загрузки ОС и инициализации драйверов - состояния портов могут меняться.

Порты в режиме INPUT могут генерировать прерывания - по спаду, по фронту, по логическому уровню, по изменению сигнала и в асинхронном режиме по фронту и спаду.

Порты в режиме INPUT имеют входную фильтрацию на триггере Шмитта (преобразовывают аналоговый сигнал в цифровой с резкими переходами между состояниями).

Электрические характеристики GPIO (Electrical Specification)

Не забывайте, что у любого порта - есть "ограничения" по току и напряжению. А т.к. GPIO - это просто выводы чипа SoC - очень важно знать и соблюдать эти характеристики. Вы всегда можете узнать их в документации на SoC (но не всегда есть официальная публикация документации).

Например, GPIO на Raspberry Pi имеет следующие характеристики:

  • 16 mA один из выводов GPIO;
  • 50 mA - максимально допустимый общий ток GPIO (т.е. на всех выводах суммарно);
  • 0.8V - максимальный уровень логического 0;
  • 1.3V - минимальный уровень логической 1;
  • 3.3V - максимальное входное/выходное напряжение GPIO

5 вольтовые выводы - могут давать ток до 300mA, т.к. они фактически не являются GPIO портами, а практически напрямую соединены с питанием всей платы (а не чипа SoC).

В данном примере, используется Orange Pi Zero на базе SoC: Allwinner H2(+) (примеры характеристик из документации):

Максимальный суммарный ток GPIO: 40 mA

Мин.Температура: -20C. Marc.Температура: 70C

Значения pull-up/pull-down, входной ток

Как можно заметить, характеристики похожи на Raspberry Pi, в любом случае - мы имеем достаточно маленькие допустимые значения тока на GPIO и максимальное напряжение логических уровней: не более 3.3V.

Подробности уточняйте в спецификации к вашему SBC и используемому в его основе SoC.


! ! !

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


Демонстрационная схема

Рассмотрев электрические характеристики GPIO - можно приступить к сборке тестовой схемы.

Для демонстрации будем использовать только светодиод. Вы можете также подключить кнопку. И светодиод и кнопку необходимо подключать через токоограничивающий резистор.

В данном примере - подключаем светодиод (через резистор 360 Ом: 3.3В / 360Ом = 9мА) к 6 выводу GPIO на Orange Pi Zero. На представленной схеме распиновки (рисунок ниже). - он обозначен, как PA06 - обратите внимание, что номер GPIO - не обязательно должен соответствовать физическому номеру вывода (7 физ. вывод - считать слева направо от ключа), т.к. это прямой вывод с чипа SoC и нумерация соответствует чипу (существует формула для расчета номер GPIO). И, PA - в данном случае обозначает PORTA, но для нас это не имеет значение (можно даже найти распиновку, где будет указанно просто GPIO06).
PWM1 - дополнительная функция порта ШИМ (PWM) модуль.

Формула для вычисления номер GPIOXX:

(позиция буквы в алфавите - 1) * 32 + позиция вывода  

PA06
PA = 1
P (PORT) - не учитывается

(1 - 1) * 32 + 06 = 0 * 32 + 06 = 06

Выводы GPIO не всегда распаяны на плате. На Orange Pi Zero - они обычно не распаяны (имеются только отверстия под штыревую линейку с шагом 2.54 мм).

Распиновка Orange Pi Zero:

Распиновка Orange Pi Zero

Схема подключения светодиода к GPIO:

Схема подключения светодиода к GPIO

Программирование GPIO

Существует несколько способов обращения к GPIO:

  • Через файловое представление GPIO;
  • Используя языки программирования:
    • Через прямое обращение к регистрам чипа;
    • Используя уже готовые библиотеки.

Каждый из методов имеет свои преимущества и недостатки.

Через файловое представление.

Философия операционных систем Unix гласит, что все есть файл. Это значит, что вся работа с этой операционной системой сводится к файлам. Поскольку Linux можно считать тоже потомком Unix, то эта концепция применима и здесь. Файлы это объекты, в которые мы записываем информацию, но кроме этих привычных нам понятий здесь есть файлы специального назначения - файлы устройств, файлы туннелей, сокетов и многое другое. Подробнее: https://losst.ru/tipy-fajlov-v-linux

Unix - торговая марка проприетарная ОС разработная 1970-х годах компанией AT&T. UNIX никогда не был программным обеспечением с открытым исходным кодом.
Linux - семейство Unix-подобных (используют сходные концепции и технологии c популярной тогда Unix) ОС на базе ядра Linux и включающих (теоретически не обязательно, но по факту) тот или иной набор утилит и программ проекта GNU (рекурсивный акроним GNU’s Not UNIX ). Существует даже целый фильм о истории GNU, Linux, Open Source и идеи появления свободного ПО: https://www.youtube.com/watch?v=n1F_MfLRlX0
История Unix (видео) или более сжатое изложение и логическое продолжение о Linux

Данный способ возможен благодаря наличию драйвера GPIO в ядре Linux.

Таким образом, мы можем управлять GPIO используя sysfs - виртуальная файловая система, находящаяся в памяти и доступная из пространства пользователя. Документация: https://www.kernel.org/doc/Documentation/gpio/sysfs.txt

Все операции будем выполнять от root-пользователя. Перейдем под root:
sudo su
Создадим файл доступа к пину (без этого шага им не получится управлять):
echo 6 > /sys/class/gpio/export

где, 6 - номер GPIO, к которому подключен светодиод.

Настраиваем его на вывод (OUTPUT):
echo out > /sys/class/gpio/gpio6/direction
Устанавливаем лог. 1 (3.3В) - светодиод зажегся:
echo 1 > /sys/class/gpio/gpio6/value
Смотрим текущее состояние GPIO 6:
cat /sys/class/gpio/gpio6/value
Устанавливаем лог. 0 (0В) - светодиод погас:
echo 0 > /sys/class/gpio/gpio6/value
Освобождение вывода GPIO:
echo 6 > /sys/class/gpio/unexport

Где:

  • gpio6 - используемый GPIO 6
  • value - указываем значение (0/1).
  • direction - указываем направление (out/in).

echo - команда оболочки Bash, которая просто выводит строку текста в терминал.
">"(знак больше) - перенаправление поток вывода (в данном случае с терминала в файл - перенаправляем вывод от команды echo)
cat - команда читает данные из файла (в данном случае) или стандартного ввода и выводит их на экран.


В Orange Pi Zero вы можете обращаться подобным образом и к светодиодам на плате (красный и зеленый), которые соответствуют GPIO17 и GPIO362

  • GPIO17 = PA17 - Красный светодиод (Status Led)
  • GPIO362 = PL10 - Зеленый светодиод (Power Led)

Но они имеют и свои собственные файлы:

  • /sys/class/leds/orangepi:green:pwr/brightness
  • /sys/class/leds/orangepi:red:status/brightness
echo 0 > /sys/class/leds/orangepi:green:pwr/brightness
echo 1 > /sys/class/leds/orangepi:red:status/brightness

Узнать необходимый порт - можно посмотрев на электрические принципиальные схемы. А номер GPIO вычислить по формуле (уже приводилась в данной статье). Или это можно найти в какой-либо другой "документации"


Таким образом, можно обращаться к GPIO, как к обычному текстовому файлу, что позволяет выполнять данные действия практически на любых языках программирования и сценарных языках, в том числе bash.

Недостатки:

  • Не максимальная возможная скорость работы с GPIO;
  • Невозможно включить выключить сразу несколько линий одним вызовом;
  • В случае краха приложения GPIO линии остаются в "инициализированном" состоянии.

Преимущества:

Будет работать на любом Linux-дистрибутиве и любом устройстве (GPIO имеют не только одноплатные компьютеры, но и некоторые роутеры и т.д. ) - если имеется драйвер GPIO в ядре Linux для данного SoC.
Существует некоторые готовые утилиты: https://github.com/torvalds/linux/tree/master/tools/gpio

Через прямое обращение к регистрам.

Данный метод похож на разработку для микроконтроллеров. Необходимо изучать спецификацию на используемый чип (SoC) и обращаться к конкретным адресам для выполнения тех или иных действий. Для обращения к физическим адресам - необходимо обращаться к файлу /dev/mem.

/dev/mem - это символьный файл устройства, в котором отображается главная память компьютера. Адресация байтов в mem точно та же, что и у физической памяти. Ссылки на несуществующие адреса приводят к ошибкам.

Подробнее можете ознакомиться в данной статье: https://habr.com/ru/company/dataart/blog/330536/

Преимущества:

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

Недостатки:

  • Высокая сложность разработки.
  • Сложно портировать ПО под другие устройства.

Используя библиотеки.

Существует несколько популярных библиотек для доступа к GPIO на разных языках программирования, некоторые из них:

WiringPi:

WiringPi - это библиотека для доступа к GPIO-контактам чипа BCM2835, используемого в Raspberry Pi. Написана на языке C, выпущена под лицензией GNU LGPLv3 (отсутствует обязательное требование предоставления исходного кода) и пригодна для использования в C, C++ и RTB (BASIC), а также в других языках (но для этого нужны специальные функции-обертки). Библиотека WiringPi создавалась с прицелом на схожесть с языком Wiring, который используется в Arduino.

WiringPi была портирована на другие платформы, однако автор (Gordon Henderson) оригинальной WiringPi поддержкой этих версий не занимается.

В комплекте с WiringPi идет devLib – это набор драйверов, обеспечивающих доступ к некоторым популярным периферийным устройствам. Среди поддерживаемых устройств: LCD-дисплеи (на базе чипов Hitachi HD44780U) и графические дисплеи (например, обычные дисплеи с разрешением 128х64, работающие на чипе-драйвере 12864H). Также поддерживаются DS1302 (чип, работающий как часы реального времени), датчики на базе чипов Maxdetect (например, RHT003), платы Gertboard/PiFace и т.д.

Недостатки:

  • Будет работать только на платформах, для которых существуют библиотеки;
  • Не максимально возможная скорость работы с GPIO (зависит от реализации библиотеки, не редко используют sysfs)
  • Могут быть ошибки портирования (Особенно у WiringPi на Orange Pi).

Преимущества:

  • Высокая популярность данных библиотек (существуют для многих популярных SBC);
  • Проще портировать ПО на другие SBC;
  • Достаточно простая документация и примеры кода;
  • Простые функции для работы с GPIO и не только (прерывания, потоки, SPI, I2C и т.д.).
  • И, как итог, высокая скорость разработки.

WiringOP - WiringPi для Orange Pi

1) Найдите необходимую библиотеку для вашей версии: WiringOP-Zero;

2) Скачайте библиотеку (будем использовать git): WiringOP-Zero git clone

3) Копируем ссылку для клонирования и выполняем команду:

git clone https://github.com/xpertsavenue/WiringOP-Zero.git

Если используете Armbian Bionic - git должен быть уже установлен. Иначе можете установить его сами.

4) После клонирования появиться каталог "WiringOP-Zero", переходим в него и выполняем установку библиотеки:

cd WiringOP-Zero
chmod +x ./build
sudo ./build

chmod - изменяет права файла ("+x" - даем право на выполнение)
build - сценарий автоматической сборки (компиляция, установка и т.д.)

5) Вместе с библиотекой - установиться утилита gpio:

gpio readall

gpio readall - команда выводит таблицу соответствия выводов GPIO.

Таблица соответствия GPIO (gpio readall):

Вывод команды gpio readall

  • Physical - обозначение физических выводов одноплатного компьютера. (нумерация выводов штыревой линейки - по порядку);
  • wPi - номер вывода используемый в библиотеке WiringPi WiringOP-Zero (этот номер будем указывать в программе);
  • H2+ - физический вывод на чипе SoC >Иногда обозначен, как BCM - т.к. библиотека портирована с Raspberry Pi, а там используется чип BCM2835
  • V - логический уровень на выводе;
  • MODE - в каком режиме используется порт (in/out/pwm/clock/up/down/tri/ALT);
  • Name - Имя вывода GPIO.

Напишем тестовую программу:

1) Перейдем в директорию пользователя и создадим файл "blink.c"

cd
nano blink.c

2) Вставим следующий код:

/*
 * Тестовая программа WiringPi на Orange Pi Zero
 */

#include <stdio.h>

//Подключите библиотеку (заголовочный файл) WiringPi
#include <wiringPi.h>

//Укажите порт GPIO соответствующий столбцу wPi
#define LED     30

int main (void)
{
  printf ("Orange Pi: Status Led blink\n") ;

  wiringPiSetup (); // Инициализация GPIO
  pinMode (LED, OUTPUT); //PIN OUTPUT

  while (1)
  {
    digitalWrite (LED, HIGH);  // PIN ON
    delay (500);               // mS
    digitalWrite (LED, LOW);   // PIN OFF
    delay (500);
  }
  return 0;
}

3) Компилируем:

gcc -Wall blink.c -o blink -lwiringPi -lpthread
  • gcc - компилятор (в Armbian Bionic - уже установлен);
  • -Wall - вывод сообщений о всех предупреждениях или ошибках;
  • blink.c -o blink - создаем исполняемый файл "blink" из исходного файла "blink.c";
  • -l - подключить библиотеку wiringPi и pthread (библиотека для многопоточности, необходима для некоторых возможностей WiringPi);

4) Запускаем программу от root-пользователя:

sudo ./blink

5) Можете ознакомиться с примерами в директории WiringOP-Zero/examples/ и документацией на сайте WiringPi. Так же можете посмотреть код в директориях: WiringOP-Zero/wiringPi/ и WiringOP-Zero/devLib/

Полезные ссылки:

Report abuse