Наш канал в telegram

Микрокомпьютер Omega2. Часть 2. Использование GPIO.

Как и любой другой микроконтроллер, MT7688 (на котором собран модуль Omega2) имеет некоторое количество линий GPIO. GPIO — это такие выводы, каждым из которых пользователь может управлять непосредственно, в отдельности от всех остальных выводов. Их можно настраивать «на вход», — чтобы считывать с вывода логический уровень напряжения установленный внешней схемой, или «на выход» — чтобы контроллер мог сам устанавливать на соответствующем выводе логический уровень напряжения, подключая этот вывод к своей нулевой или питающей шине.

В этой статье будет подробно описано как настраивать выводы GPIO в модулях Omega2, как ими управлять, какие команды и инструменты для этого используются, но для начала давайте рассмотрим электрические характеристики выводов GPIO.

Электрические характеристики GPIO

Parameter Минимум (В) Максимум (В)
Input HIGH 2.0 3.6
Input LOW -0.3 0.8
Output HIGH 2.4 3.3
Output LOW -/- 0.4

Как видите, Omega2 использует логику с уровнями напряжения 3,3 Вольта. Стандартные устройства 5-вольтовой логики обычно воспринимают входной сигнал 3.3В как HIGH, однако их выходной сигнал HIGH соответствует уровню 4.4-5В. Это означает, что выходы модулей Omega2 можно подключать напрямую ко входам устройств 5-Вольтовой логики, однако попытка подключить выходы устройств 5-Вольтовой логики ко входам модулей Omega2 приведет к повреждению последних. Вот здесь можно почитать про устройства сопряжения различных логических уровней.

Количество GPIO, мультиплексирование

Теперь давайте посчитаем, а сколько же всего выводов GPIO нам доступно в модулях Omega2. Здесь нужно учесть следующее:

  • во-первых, на внешние выводы модулей Omega выводятся не все ноги контроллеров MT7688 (у него аж 156 ног). Количество выведенных наружу ног контроллера зависит от версии модуля (Omega2 или Omega2S).
  • во-вторых, у контроллеров MT7688 (как и у большинства остальных контроллеров) существуют выводы, которые мультиплексированы с какими-либо другими функциями помимо GPIO. Такие выводы, в зависимости от настроек, могут использоваться для работы не в качестве GPIO, а в качестве чего-то другого (UART, I2C, SPI и тому подобное).
  • ну и в-третьих, на официальной картинке GPIO подписаны не совсем правильно (не все подписанные как GPIO ноги могут использоваться в качестве таковых и не все ноги помеченные только как GPIO ни с чем не мультиплексированы).

Поскольку модулей Omega2S у меня нет, далее я буду рассказывать только о модулях Omega2. Ниже приведена исправленная картинка с распиновкой:

выводы GPIO модуля Omega2

Видно, что в этом модуле в качестве GPIO может использоваться 17 ног (GPIO 0,1,2,3,4,5,6,11,12,13,15,16,17,18,19,45,46), при этом всего одна нога не используется более ни для чего (GPIO11), а остальные 16 ног могут быть помимо GPIO сконфигурированы для других задач.

Конфигурирование мультиплексированных выводов

Для конфигурирования мультиплексированных выводов можно использовать инструмент omega2-ctrl.

Чтобы узнать как пользоваться этим инструментом — просто наберите в командной строке omega2-ctrl ? и нажмите Enter (так можно получить подсказку практически по всем командам):

root@Omega-XXXX:/# omega2-ctrl ?
Usage: omega2-ctrl gpiomux get
Functionality:
	List the current GPIO muxing configuration
Usage: omega2-ctrl gpiomux set <GPIO group> <mux setting>
Functionality:
	Set the gpio muxing for the specified GPIO signal
Usage: omega2-ctrl refclk get
Functionality:
	Display the current refclk setting
Usage: omega2-ctrl refclk set <frequency (MHz)>
Functionality:
	Set the refclk to the specified frequency if possible

Итак, получить текущую конфигурацию мультиплексированных выводов Omega2 можно с помощью команды:

omega2-ctrl gpiomux get

В результате её выполнения вы получите ответ следующего вида:

root@Omega-XXXX:/# omega2-ctrl gpiomux get
Group i2c - [i2c] gpio
Group uart0 - [uart] gpio
Group uart1 - [uart] gpio
Group uart2 - [uart] gpio pwm
Group pwm0 - [pwm] gpio
Group pwm1 - [pwm] gpio
Group refclk - refclk [gpio]
Group spi_s - spi_s [gpio]
Group spi_cs1 - [spi_cs1] gpio refclk
Group i2s - i2s [gpio] pcm
Group ephy - [ephy] gpio
Group wled - wled [gpio]

Текущая конфигурация для каждой группы выводов отмечена квадратными скобками — []. Если посмотреть на приведенный выше пример, то можно сказать, что для группы uart1 доступны режимы uart и gpio, при этом в текущий момент выбран режим uart.

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

omega2-ctrl gpiomux set <HARDWARE PIN GROUP> <MODE>

Например, приведённая ниже команда настраивает группу выводов UART1 для работы в режиме GPIO:

omega2-ctrl gpiomux set uart1 gpio

Если проверить результат работы этой команды с помощью команды gpiomux get, то мы увидим следующее:

root@Omega-XXXX:/# omega2-ctrl gpiomux get
Group i2c - [i2c] gpio
Group uart0 - [uart] gpio
Group uart1 - uart [gpio]
Group uart2 - [uart] gpio pwm
Group pwm0 - [pwm] gpio
Group pwm1 - [pwm] gpio
Group refclk - refclk [gpio]
Group spi_s - spi_s [gpio]
Group spi_cs1 - [spi_cs1] gpio refclk
Group i2s - i2s [gpio] pcm
Group ephy - [ephy] gpio
Group wled - wled [gpio]

То есть текущая конфигурация выводов Group uart1 изменилась с uart на gpio.

Обратите внимание, что в выдаваемом командой gpiomux get списке групп выводов, вообще-то говоря не все группы выведены на разъёмы модуля Omega2. Группы uart2 (GPIO20, GPIO21), refclk (GPIO37), ephy и wled (GPIO44) на внешние разъёмы модулей Omega2 не выводятся, они актуальны только для модулей Omega2S. Хотя выводом wled поиграться всё же можно, к нему подключен расположенный на плате модуля светодиод.

Важные замечания и особенности GPIO

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

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

GPIO Description
GPIO1 I2S SDO
GPIO6 SPI CS1
GPIO7 SPI CLK
GPIO8 SPI MOSI
GPIO12 UART TX0
GPIO45 UART TX1

Расположенная на плате модуля Omega2 флэш-память подключена к контроллеру с помощью интерфейса SPI. При этом в качестве сигнала Chip Select она использует сигнал с вывода Chip Select 0. Поскольку у контроллера есть два сигнала Chip Select для шины SPI, то к модулю Omega2 можно подключить дополнительное устройство SPI, которое будет использовать сигнал Chip Select 1.

Выводы SPI — CLK, MOSI и MISO — выводятся на контакты модуля Omega2 и вообще-то могут быть специальными средствами (но не через omega2-ctrl) настроены как GPIO 7,8 и 9. Однако делать этого категорически не следует, поскольку это может привести (и обязательно приведёт) к проблемам с флэш-памятью.

Управление GPIO через sysfs, инструмент gpioctl

Во все linux-системы встроена виртуальная файловая система sysfs, предоставляющая пользователю интерфейс к структурам ядра. Информация обо всех устройствах, модулях и компонентах ядра представлена в этой псевдофайловой системе в виде файлов. Неожиданно, да? На самом деле это конечно не настоящие файлы в привычном понимании (поэтому далее я буду брать их в кавычки). Но суть не в этом. Суть в том, что читая/записывая эти «файлы», мы можем управлять соответствующими компонентами, в том числе и GPIO.

«Файлы» необходимые для управления GPIO содержатся в директории /sys/class/gpio. В первую очередь нас интересуют «файлы» export и unexport. Они доступны только для записи и используются чтобы запросить у ядра linux доступ к управлению через sysfs каким-либо выводом GPIO или отменить такую возможность.

Для получения доступа к управлению выводом GPIO — нужно записать в «файл» export номер этого GPIO. Из командной строки это может выглядеть так (например, для GPIO19):

echo 19 > export

В случае, если всё пройдёт успешно, в папке /sys/class/gpio появится папка gpioN (N — номер вывода, то есть в нашем примере это будет папка GPIO19), содержащая доступные для чтения/записи «файлы» для работы с запрошенным выводом : direction, value, edge, active_low.

Файл «direction» используется чтобы задать или определить направление работы вывода. Если мы хотим сконфигурировать вывод для работы в качестве входа (например, чтобы определять состояние подключенной к выводу кнопки) — в этот файл нужно записать значение in. Для конфигурирования вывода на работу в качестве выхода (например, чтобы включать/выключать подключенный к выводу светодиод) — нужно записать в этот файл значение out. По умолчанию, при переключении вывода на выход, на нём установится значение low. Для обеспечения безаварийной работы в файл «direction» могут быть вместо out записаны значения low или high, что приведёт к конфигурированию вывода на выход с соответствующим начальным значением. Узнать текущее направление работы вывода можно прочитав содержимое файла direction.

Файл «value» используется чтобы считать состояние вывода или переключить вывод в состояние 0 (low) или 1 (high). Считывание доступно при любой конфигурации направления работы вывода, а установка актуальна только для выводов сконфигурированных на выход. При установке состояния любое записываемое в файл «value» значение отличное от нуля будет трактоваться как high.

Файл «edge» используется для настройки прерываний от изменения состояния вывода, а файл «active_low» — для настройки соответствия значений low и high высокому и низкому уровням сигнала на выводе (можно сделать так, чтобы высокий уровень напряжения считался нулём, а низкий — единицей). Более подробно мы на sysfs останавливаться не будем, иначе статья получится слишком большой. Теперь вы по крайней мере знаете в каком направлении копать, а мы идём дальше.

В модулях Omega2 для нашего удобства (ну по крайней мере так объявлено) сделан специальный инструмент командной строки gpioctl, работающий как раз на основе описанного выше механизма sysfs. Ну то есть, мы с его помощью можем писать команды не напрямую системе sysfs, а этому инструменту, а уже он за нас будет обращаться в sysfs.

В чём тут удобство и почему мы не можем работать напрямую через sysfs? Хм… ну, видимо удобство в синтаксисе. Так или иначе, инструмент есть и я про него напишу.

Синтаксис командной строки gpioctl показан ниже:

gpioctl <OPTION> <GPIO NUMBER>

Всего для этого инструмента доступны 7 опций: dirin, dirout, dirout-low, dirout-high, get, set, clear. Ниже описано назначение и примеры использования каждой из этих опций.

Опция dirin позволяет задать направление работы вывода на вход. Пример (конфигурирование GPIO19 на вход):

root@Omega-XXXX:/# gpioctl dirin 19
Using gpio pin 19.

Опция dirout позволяет задать направление работы вывода на выход. Пример (конфигурирование GPIO19 на выход):

root@Omega-XXXX:/# gpioctl dirout 19
Using gpio pin 19.

Опция dirout-low позволяет задать направление работы вывода на выход с начальным значением low на выходе. Пример (конфигурирование GPIO19 на выход с начальным значением low):

root@Omega-XXXX:/# gpioctl dirout-low 19
Using gpio pin 19.

Опция dirout-high позволяет задать направление работы вывода на выход с начальным значением high на выходе. Пример (конфигурирование GPIO19 на выход с начальным значением high):

root@Omega-XXXX:/# gpioctl dirout-high 19
Using gpio pin 19.

Опция get позволяет позволяет прочитать текущий логический уровень на соответствующем выводе. Пример (чтение логического уровня на выводе GPIO19):

root@Omega-XXXX:/# gpioctl get 19
Using gpio pin 19.
Pin 19 is LOW

Опция set позволяет позволяет установить логический уровень 1 (high) на соответствующем выводе, если он настроен на выход. Пример (установка логического уровня 1 на выводе GPIO19):

root@Omega-XXXX:/# gpioctl set 19
Using gpio pin 19.

Опция clear позволяет позволяет установить логический уровень 0 (low) на соответствующем выводе, если он настроен на выход. Пример (установка логического уровня 0 на выводе GPIO19):

root@Omega-XXXX:/# gpioctl clear 19
Using gpio pin 19.

Хотелось бы отметить, что для мультиплексированных выводов все переключения gpio с помощью sysfs (как и с помощью основанного на sysfs инструмента gpioctl) будут выполняться только в случае, если соответствующий вывод сконфигурирован в качестве gpio. В противном случае переключения реально выполняться не будут, хотя считывание значений из файла value или командой get будет показывать, что переключение вроде бы выполнено и уровень установился такой, как мы хотели. Видимо это связано с тем, из какого реального регистра контроллера читаются данные при подобной проверке состояния. Обычно у контроллера существуют регистры PINx, из которых можно считать реальное состояние выводов и PORTx, из которых можно прочитать состояние, которое установится при конфигурировании выводов на выход. Ну и, судя по всему, через файл value и команду gpioctl get считываются данные из регистра PORTx, а не из регистра PINx.

Кроме того, хотелось бы отметить отсутствие у инструмента gpioctl отдельной опции для определения направления работы вывода, хотя sysfs позволяет это сделать (нужно просто прочитать значение из файла direction). То ли не доделали, то ли… В общем, нет такой опции.

Инструмент Fast-GPIO

Команда fast-gpio подобна команде gpioctl в том смысле, что она также используется для управления GPIO. Различия заключаются в том, что gpioctl работает через sysfs, а fast-gpio работает непосредственно с регистрами GPIO контроллера и является более быстрой.

Использование команды:

Для получения списка вариантов использования команды, просто выполните fast-gpio из командной строки:

root@Omega-XXXX:/# fast-gpio
Usage:
 fast-gpio set-input <gpio>
 fast-gpio set-output <gpio>
 fast-gpio get-direction <gpio>
 fast-gpio read <gpio>
 fast-gpio set <gpio> <value: 0 or 1>
 fast-gpio pwm <gpio> <freq in Hz> <duty cycle percentage>

С помощью опций set-input, set-output можно сконфигурировать направление работы выводов GPIO. Примеры:

fast-gpio set-input 19
> Set direction GPIO19: input
fast-gpio set-output 19
> Set direction GPIO19: output

Опция get-direction позволяет определить направление работы выводов GPIO. Пример:

fast-gpio get-direction 19
> Get direction GPIO19: output

Опция read позволяет прочитать состояние вывода, то есть установленный на нём логический уровень (независимо от сконфигурированного направления работы). Пример:

root@Omega-XXXX:/# fast-gpio read 19
> Read GPIO19: 0

Опция set позволяет установить на выбранном выводе необходимое значение. Примеры:

fast-gpio set 19 0
> Set GPIO19: 0
fast-gpio set 19 1
> Set GPIO19: 1

Если вывод не настроен на выход, то fast-gpio принудительно изменит его направление на выход перед установкой значения.

Опция pwm предназначена для организации программного ШИМ на выбранном выводе. В качестве дополнительных параметров с этой опцией задаются: — номер GPIO, — частота ШИМ в Герцах, — коэффициент заполнения в процентах. Пример для меандра 1 кГц на GPIO19:

fast-gpio pwm 19 1000 50

Команда с опцией pwm запускает фоновый процесс, который генерирует ШИМ-сигнал, переключая выход GPIO через определённые заданные промежутки времени. Этот метод потенциально неточен, поскольку CPU может быть прерван другим процессом или задачей. Программного ШИМа может быть достаточно для диммирования LED, но недостаточно для операций, требующих большой точности, таких как управление сервоприводом.

Чтобы остановить ШИМ нужно выполнить для этого же вывода команду fast-gpio с любой другой опцией вместо pwm или переключить вывод на вход командой gpioctl.

  1. Часть 1. Первое знакомство
  2. Часть 2. Использование GPIO
  3. Часть 3. Док-плата

Добавить комментарий