Вопрос или проблема
Я написал программу на C, которая использует GPIO пины на Raspberry Pi. Когда я писал программу, она работала нормально на Ubuntu 18.04 armhf (32 бита). Теперь же, на моем Raspberry Pi 4 с Ubuntu 20.04 arm64 я получаю следующую ошибку при запуске с sudo:
initPeripherals: mmap gpio failed (Операция не разрешена)
Насколько я понимаю, эта ошибка возникает из-за того, что ядро было скомпилировано с опцией
CONFIG_STRICT_DEVMEM=y
Как я могу исправить эту проблему, не перекомпилируя ядро? Я попробовал установить iomem=relaxed и strict-devmem=0, но безрезультатно. Я также пробовал добавлять правила в /etc/udev/rules.d/, но это тоже не сработало. Кроме того, я пытался изменять членство групп, но опять же, я запускаю это от имени root с помощью sudo.
Правка: Ядро 18.04 arm64 работает без проблем. Думаю, я буду довольствоваться этим.
Похоже, это проблема с правами.
$ sudo apt install rpi.gpio-common
После этого вы должны быть в состоянии
$ echo "21" > /sys/class/gpio/export
$ echo "1" > /sys/class/gpio/gpio21
$ echo "21" > /sys/class/gpio/unexport
Если это так, не должно быть проблем с работой с GPIO из C кода.
Этот пакет просто устанавливает файл правил. Я видел в интернете решения, предоставляющие правила udev, но большинство из них не работают.
$ cat /lib/udev/rules.d/60-rpi.gpio-common.rules
SUBSYSTEM=="bcm2835-gpiomem", KERNEL=="gpiomem", GROUP="dialout", MODE="0660"
SUBSYSTEM=="gpio", KERNEL=="gpiochip*", ACTION=="add", PROGRAM="/bin/sh -c 'chown root:dialout /sys/class/gpio/export /sys/class/gpio/unexport ; chmod 220 /sys/class/gpio/export /sys/class/gpio/unexport'"
SUBSYSTEM=="gpio", KERNEL=="gpio*", ACTION=="add", PROGRAM="/bin/sh -c 'chown root:dialout /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value ; chmod 660 /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value'"
Вы также можете вручную поместить файл в /etc/udev/rules.d/
.
Ответ или решение
Управление GPIO на Ubuntu 20.04 64-битной ARM Raspberry Pi
Работа с GPIO на Raspberry Pi может вызвать некоторые трудности, особенно при переходе на более новые версии операционной системы, такие как Ubuntu 20.04. Проблема, с которой вы столкнулись, связана с ограничениями доступа к памяти устройств, установленными в ядре Linux, и будет рассмотрена ниже.
Проблема
При запуске вашей программы на C с использованием GPIO вы получили ошибку:
initPeripherals: mmap gpio failed (Operation not permitted)
Эта ошибка указывает на то, что ваше приложение пытается использовать mmap
для доступа к адресам GPIO, однако система не позволяет это делать из-за настроек, связанных с безопасностью памяти устройств.
Причина
Как вы правильно отметили, наличие опции CONFIG_STRICT_DEVMEM=y
в конфигурации ядра ограничивает доступ к определенным областям памяти, включая GPIO. Это было сделано для повышения безопасности системы, но может привести к проблемам при запуске приложений, нуждающихся в прямом доступе к железу.
Решение без перекомпиляции ядра
-
Установка необходимых пакетов
Первым шагом является установка пакета
rpi.gpio-common
, который содержит необходимые правила для работы с GPIO. Выполните следующую команду:sudo apt install rpi.gpio-common
Это установит необходимые правила доступа к GPIO, что упростит управление ими.
-
Проверка правил Udev
Проверьте содержимое файла правил Udev, который был установлен. Это можно сделать командой:
cat /lib/udev/rules.d/60-rpi.gpio-common.rules
Убедитесь, что в этом файле присутствуют правила, касающиеся доступа к GPIO. Правила должны выглядеть следующим образом:
SUBSYSTEM=="bcm2835-gpiomem", KERNEL=="gpiomem", GROUP="dialout", MODE="0660" SUBSYSTEM=="gpio", KERNEL=="gpiochip*", ACTION=="add", PROGRAM="/bin/sh -c 'chown root:dialout /sys/class/gpio/export /sys/class/gpio/unexport ; chmod 220 /sys/class/gpio/export /sys/class/gpio/unexport'" SUBSYSTEM=="gpio", KERNEL=="gpio*", ACTION=="add", PROGRAM="/bin/sh -c 'chown root:dialout /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value ; chmod 660 /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value'"
Эти правила позволяют корректно работать с GPIO от программы, запущенной от имени пользователя, входящего в группу
dialout
. -
Использование GPIO
После установки пакета и проверки правил Udev, попробуйте выполнить следующие команды для управления GPIO:
echo "21" > /sys/class/gpio/export echo "1" > /sys/class/gpio/gpio21/value echo "21" > /sys/class/gpio/unexport
Эти команды должны успешно выполняться без ошибок доступа.
-
Обновление групповой принадлежности пользователя (опционально)
Если вы предпочитаете запускать свою программу без
sudo
, убедитесь, что ваш пользователь включен в группуdialout
. Для этого выполните:sudo usermod -aG dialout $USER
После этого перезагрузите систему или выйдите и войдите обратно в сеанс.
Заключение
Правильная настройка доступа к GPIO на Raspberry Pi под управлением Ubuntu 20.04 требует установки необходимых пакетов и проверки правил Udev. Вышеобозначенные шаги должны помочь вам устранить проблему, связанную с ошибкой mmap при работе с GPIO. Надеюсь, это руководство окажется полезным и облегчит вам дальнейшую работу с GPIO на вашем Raspberry Pi.