Jump to content

    

Управление GPIO на Linux

Добрый день!

 

Меня интересует возможность управления gpio из linux.

По идее GPIO сначала нужно экспортировать, но как узнать, какой пин нужно экспортировать? Например, я хочу вывести 1 на 28-ой пин 3-его порта. При этом не хочется помнить, что GPIO3.28 - это включение питания USB.

Нельзя ли как-то дать понять системе, например через dts, что этот пин занят юзером и дать к нему доступ сразу, задав к тому же прерывания от этого пина или дефолтное состояние?

 

Ну и код dts для примера. Led-ы работают сразу через /sys/class/leds , а вот gpio нет.

    gpio {
        compatible = "mygpio";
        pinctrl-names = "default";
        pinctrl-0 = <&gpio_pins_3V3>;
        gpio_USBHOST_VCCEN {
            label = "usbvccen";
            gpios = <&gpio3 28 GPIO_ACTIVE_HIGH>;
            default-state = "on";
        };
    };
    leds {
        compatible = "gpio-leds";
        pinctrl-names = "default";
        pinctrl-0 = <&leds_pins>;
        power {/* POWER */
            label = "power";
            gpios = <&gpio3 29 GPIO_ACTIVE_HIGH>;
            default-state = "on";
        };
        status {/* ACT */
            label = "status";
            gpios = <&gpio2 26 GPIO_ACTIVE_HIGH>;
            default-state = "on";
        };
    };

Спасибо!

Share this post


Link to post
Share on other sites

Действительно. Перед началом работы с GPIO из userspace, соответствующий вывод должен быть прописан в DTS. Это нужно для того, что бы ядро знало, что с этой ножкой нужно/можно работать через gpio-драйвер.

Я это делаю так:

 

usergpio_pins: pinmux_usergpio_pins {
	pinctrl-single,pins = <

		/*button*/
		0x05C (PIN_INPUT_PULLUP | MUX_MODE7) 		/* SW1 gpmc_a7.gpio1_23 MODE7 */
		/*Vif vif_12v_fixed*/
		0x16C (PIN_OUTPUT_PULLUP | MUX_MODE7)		/* uart0_rtsn.gpio1_9 MODE7 */
		/*3V3_plc vif_3v3_plc_fixed*/
		0x190 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)		/* mcasp0_aclkx.gpio3_14 MODE7 */

	>;
};

Соответственно, потом указатель на usergpio_pins помещаю в секцию pinmux.

Собственно, для процессора из примера MUX_MODE7 -- режим работы вывода процесса, соответствующий GPIO. Что такое PIN_INPUT_PULLUP и PIN_OUTPUT_PULLDOWN, думаю, понятно и так.

Единственная проблема с адресом. Это нужно смотреть документацию на процессор. Причем, следует отметить, что используется не абсолютный адрес, о смещение относительно блока pinmux.

 

Как работать с этим в userspace. Допустим, хотим вывести 1 в gpio1.9. (объявлен в примере).

 

1. Инициализируем устройство gpio1.9:

 

echo 41 > /sys/class/gpio/export

 

Тонкий вопрос, как gpio1.9 превратился в 41 ?. В процессоре параллельные порты объединены в 32-битную шину. В обозначении gpio1.9 первая цифра "1" -- номер порта, вторая -- номер ножки в порту. Таким образом, абсолютный номер порта будет 32 + 9 = 41.

 

2. Устанавливаем направление порта.

После экспорта в директории /sys/class/gpio/ появляется директория gpio41. Там много чего интересного, но сейчас нам нужен файл direction. Записываем туда направление.

 

echo "out" > /sys/class/gpio/gpio41/direction

 

Понятно, что для входа, значение будет "in".

 

3. Устанавливаем уровень.

Теперь, через запись в файл value значения, мы управляем выводом:

 

echo "1" > /sys/class/gpio/gpio41/value

 

P.S.: в командах могут быть ошибки, под рукой нет боевой системы.

 

 

 

Share this post


Link to post
Share on other sites

Большое спасибо за разъяснения. А можно ли, допустим, назвать пин UsbOnGpio, и потом с ним работать из линукса, не экспортируя его каждый раз и не вспоминая, что же такое у нас GPIO125 ?

Share this post


Link to post
Share on other sites
Большое спасибо за разъяснения. А можно ли, допустим, назвать пин UsbOnGpio, и потом с ним работать из линукса, не экспортируя его каждый раз и не вспоминая, что же такое у нас GPIO125 ?

В Linux можно все, но не всегда целесообразно, а затраченные усилия, порой, не пропорциональны результату.

В своей практике, я в ПО, будь оно на Си или на Bash, порты описывал просто константами. Если проект объемный, то делал конфигурационный файл с настройками.

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

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

А вообще, если мне не изменяет память, посмотреть назначения GPIO можно где-то в /sys/kernel/debug/gpio . Считать файл, да распарсить.

Share this post


Link to post
Share on other sites
По идее GPIO сначала нужно экспортировать, но как узнать, какой пин нужно экспортировать?
shamrel в-основном уже ответил(а), а я дополню, что номер gpio, которому соответствует ваш пин, может быть разным в разных версиях линукса. Я наступил на эти грабли, когда после апгрейда линукса устройство перестало работать - оказалось, что вся нумерация сдвинулась на 32. Сейчас в программе стоит проверка версии ядра.

 

Например, я хочу вывести 1 на 28-ой пин 3-его порта. При этом не хочется помнить, что GPIO3.28 - это включение питания USB.

Нельзя ли как-то дать понять системе, например через dts, что этот пин занят юзером и дать к нему доступ сразу, задав к тому же прерывания от этого пина или дефолтное состояние?

Как Вам вариант сделать это в инит-скрипте? Пропишите там

echo 96 >/sys/clagg/gpio/export
... и т.д. ...

и будет ваш пин экспортироваться и настраиваться сразу при старте вашего устройства...

Про прерывание я не понял. Что за прерывание может быть от сигнала включения питания USB, если это выход, и ваша программа сама выдает в него сигналы? Какого рода события на этом пине Вы ожидаете?

 

И уж если Вы непременно хотите, чтобы при старте линукса пин сразу оказывался доступен без каких-либо дополнительных действий, что мешает объявить его как LED и работать с ним через /sys/class/leds, раз уж Вы говорите, что

Led-ы работают сразу через /sys/class/leds , а вот gpio нет.

 

Share this post


Link to post
Share on other sites

Через sys будет крайне медленно, если нужна скорость, понадобится ПДП. К сожалению, это требует рутовских прав (т.к. только он может с /dev/mem работать).

Но все ОК, я на "малинке" сделал так управление железякой.

Share this post


Link to post
Share on other sites
Через sys будет крайне медленно, если нужна скорость, понадобится ПДП. К сожалению, это требует рутовских прав (т.к. только он может с /dev/mem работать).

Но все ОК, я на "малинке" сделал так управление железякой.

 

Круто!

Я мои первые спектрографы на 8080 автоматизировал. На ассемблере писал в кооперативе "Поиск".

Share this post


Link to post
Share on other sites

А я с пиков начал, потом перешел на нормальные мелкоконтроллеры (STM8, STM32), а совсем уж элементарные системы, где хватит < десятка ног и не нужно всяких хитрых интерфейсов стал на одноплатниках делать — так проще и компактней.

Share this post


Link to post
Share on other sites
А я с пиков начал, потом перешел на нормальные мелкоконтроллеры (STM8, STM32), а совсем уж элементарные системы, где хватит < десятка ног и не нужно всяких хитрых интерфейсов стал на одноплатниках делать — так проще и компактней.

 

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

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now