Чтение GPIO-портов из C-программы

Я пытаюсь сделать следующее: - у нас есть AXIS-контроллер, который подключен к Linux (18.04) через чип CP2102 к USB-порту. Мы хотим прочитать значения GPIO 0-3-бит через C-программу на linux-машине.

В моей C-программе я вижу USB-порт, и когда я читаю конфигурацию, он показывает всю нужную информацию:

bLength: 12
bDescriptorType: 01
bcdUSB: 0200
bDeviceClass: 00
bDeviceSubClass: 00
bDeviceProtocol: 00
bMaxPacketSize: 40
idVendor: 10C4
idProduct: EA60
bcdDevice: 0100
biManufacturer: 01
iProduct: 02
iSerialNumber: 0003
iNumConfigurations: 01
Config descriptor CP210x
bLength: 09
bDescriptorType: 02
wTotalLength: 0020
bNumInterfaces: 01
bConfigurationValue: 01
iConfiguration: 00
bmAttributes: 0080
MaxPower: 32

Для меня это означает, что я подключен к правильному последовательному устройству (/ dev / ttyUSB0 в моем случае).

Теперь мне очень непонятно, какие звонки я могу сделать, чтобы прочитать эти GPIO-биты. Пока я не могу найти какие-либо вызовы linux-API, которые я могу использовать в своей программе.

Исходный код, который я написал (не идеальный, но он только для проверки. Когда он заработает, я его почистю)


#include <stdio.h>
#include <stdlib.h>
#include <usb.h>

int main()
{
    int nr_of_busses;
    int nr_of_devices;
    int j, r;

    struct usb_bus               *usb_busses;
    struct usb_bus               *ptr_usb_busses;
    struct usb_device            *ptr_usb_devices;
    struct usb_device_descriptor  desc;
    uint8_t                       path[8];

    usb_init();

    perror( "Init LibUSB" );

    nr_of_busses = usb_find_busses();
    fprintf( stderr, "Nr of busses found: %i\n", nr_of_busses );

    nr_of_devices = usb_find_devices();

    fprintf( stderr, "Nr of devices found: %i\n", nr_of_devices );

    usb_busses = usb_get_busses();

    if ( usb_busses == NULL ) {
        fprintf(stderr, "USB_busses = NULL\n");
        perror( "Get busses" );
    }
    else {

        ptr_usb_busses = usb_busses;

        while ( ptr_usb_busses != NULL ) {
            fprintf( stderr, "USB Buss : %s\n", ptr_usb_busses->dirname );
            fflush( stderr );

            ptr_usb_devices = ptr_usb_busses->devices;

            while (ptr_usb_devices != NULL) {
                fprintf( stderr, "FileName : %s\n", ptr_usb_devices->filename );
                fflush( stderr );

sleep(3);

// Check if this is the cp210x-device I´m looking for. If so print the information, just to be sure and to compare with the documentation

                if (ptr_usb_devices->descriptor.idProduct == 0xEA60 ) {
                    fprintf(stderr, "bLength: %02X\nbDescriptorType: %02X\nbcdUSB: %04X\nbDeviceClass: %02X\nbDeviceSubClass: %02X\n",
                                    ptr_usb_devices->descriptor.bLength,
                                    ptr_usb_devices->descriptor.bDescriptorType,
                                    ptr_usb_devices->descriptor.bcdUSB,
                                    ptr_usb_devices->descriptor.bDeviceClass,
                                    ptr_usb_devices->descriptor.bDeviceSubClass );

                    fprintf(stderr, "bDeviceProtocol: %02X\nbMaxPacketSize: %02X\nidVendor: %04X\nidProduct: %04X\nbcdDevice: %04X\n",
                                    ptr_usb_devices->descriptor.bDeviceProtocol,
                                    ptr_usb_devices->descriptor.bMaxPacketSize0,
                                    ptr_usb_devices->descriptor.idVendor,
                                    ptr_usb_devices->descriptor.idProduct,
                                    ptr_usb_devices->descriptor.bcdDevice );
                    fprintf(stderr, "biManufacturer: %02X\niProduct: %02X\niSerialNumber: %04X\niNumConfigurations: %02X\n",
                                    ptr_usb_devices->descriptor.iManufacturer,
                                    ptr_usb_devices->descriptor.iProduct,
                                    ptr_usb_devices->descriptor.iSerialNumber,
                                  ptr_usb_devices->descriptor.bNumConfigurations );

                    fprintf ( stderr, "Config descriptor CP210x\n");
                    fprintf( stderr, "bLength: %02X\nbDescriptorType: %02X\nwTotalLength: %04X\nbNumInterfaces: %02X\n",
                                    ptr_usb_devices->config->bLength,
                                    ptr_usb_devices->config->bDescriptorType,
                                    ptr_usb_devices->config->wTotalLength,
                                    ptr_usb_devices->config->bNumInterfaces   );
                    fprintf( stderr, "bConfigurationValue: %02X\niConfiguration: %02X\nbmAttributes: %04X\nMaxPower: %02X\n",
                                    ptr_usb_devices->config->bConfigurationValue,
                                    ptr_usb_devices->config->iConfiguration,
                                    ptr_usb_devices->config->bmAttributes,
                                    ptr_usb_devices->config->MaxPower   );
                    fflush( stderr );

                    usb_dev_handle *handle = usb_open( ptr_usb_devices );

// dev_dbg( ptr_usb_devices, "Test");
perror( "usb_open : ");

                    int stat = usb_set_configuration( handle, ptr_usb_devices->config->bConfigurationValue );

perror( "usb_set_configuration : ");

                    int interfaceNum = ptr_usb_devices->config->interface->altsetting->bInterfaceNumber;
                    stat = usb_claim_interface( handle, interfaceNum );

                    int altNum = ptr_usb_devices->config->interface->altsetting->bAlternateSetting;
                    stat = usb_set_altinterface( handle, altNum );

perror( "usb_set_altinterface : ");


// Now I need forever to read the GPIO-bits. How do I do that?

                    while (1) {


                    }
                }
                fprintf(stderr, "\n");
                fflush( stderr );
                ptr_usb_devices = ptr_usb_devices->next;
            }
            ptr_usb_busses = ptr_usb_busses->next;
        }

        fprintf( stderr, "All bus-names printed" );
        fflush( stderr );
    }

    exit(0);
}

После компиляции я запускаю вышеуказанную программу через sudo ./a.out.
Теперь у меня есть следующие проблемы:

  • Я получаю следующие сообщения об ошибках:
    • usb_open:: неподходящий ioctl для устройства
    • usb_set_configuration:: устройство или ресурс занят
    • usb_set_altinterface :: устройство или ресурс занят

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

2
задан 14 May 2019 в 07:03

2 ответа

Не то, чтобы Вы понимаете его превратно, Вы просто врезаетесь в стену времени. Совет, существует очень в возрасте документации в Интернете, Вы лучше начинаете проверять дату последнего изменения прежде, чем считать его.

Существует два способа сделать драйвер USB. Или мы можем сказать что два типа драйверов

  1. Драйвер пространства ядра, драйвер в дереве ядра или как модуль

    • Долгосрочное решение, но не легкий путь
  2. Драйвер пространства пользователя, использование драйвера libusb (который отдельно использует универсальный драйвер ядра),

    • Вид обходного решения, но более быстрый и относительно легче
    • Люди склонны использовать такой подход по нескольким причинам: инженерный анализ, разработка прототипа, короткий цикл выпуска для проекта конечного пользователя (как: нормальный для сканеров), как обходное решение для пропавших без вести драйвера ядра...

Вероятно, Вы нашли некоторые сообщения что, пытаясь получить доступ к USB-устройствам без драйвера ядра.

Однако для Вашего случая, CP210x имеет драйвер пространства ядра и уже реализовал функцию GPIO. Может быть это, не было ранее столько людей, узнают об этом. Никакая потребность пройти путь libusb, иначе необходимо реализовать много функций с нуля после таблицы данных CP210x.

Silicon Labs уже зарегистрировала его

Как управлять GPIOs CP210x во времени выполнения

25.07.2018 | 4:56

На Linux

Драйвер CP210x был распределен как часть ядра Linux с тех пор v2.6.12, и операции GPIO также поддерживаться Linux 4.10.0 ядер или позже.

При использовании более старой версии ядра загрузите последний Linux драйвер VCP со ссылки ниже и объедините GPIO связанный с операцией исходный код в ядро. .zip пакет содержит драйвер VCP и шоу примера кода, как управлять GPIOs.

https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers.

После слияния драйвера cp210x.c VCP скомпилируйте, это с делает команду и устанавливает его с командой "insmod". Обратите внимание, что команда "rmmod cp210x.ko" должна быть выполнена, если драйвер VCP уже существует прежде, чем установить драйвер та поддержка управление GPIO.

В cp210x_gpio_example.c используйте следующую функцию для открытия устройства CP210x.

fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);

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

ioctl(fd, IOCTL_GPIOGET, &gpioread);

Возвращенное значение фиксатора чтения представлено следующим образом: биты 0–7: Текущее состояние фиксатора, где бит 0 является GPIO0, кусает 1, GPIO1, и т.д. До GPIOn, где n является общим количеством контактов GPIO интерфейсные поддержки.

Используйте функцию ниже для записи фиксатора, где третий параметр gpio является значением фиксатора записи.

ioctl(fd, IOCTL_GPIOSET, &gpio);

Значение фиксатора записи, которое предоставляется в фазе Данных, представляет следующим образом:

биты 0–7: Маска состояния фиксатора (в битах 8-15) для записи, где бит 0 является GPIO0, кусает 1, GPIO1, и т.д. До GPIOn, где n является общим количеством контактов GPIO интерфейсные поддержки.

биты 8–15: состояние Фиксатора для записи, где бит 8 является GPIO0, кусает 9, GPIO1, и т.д. До GPIOn, где n является общим количеством контактов GPIO интерфейсные поддержки.

Получите больше информации от AN571.

Скомпилируйте приложение с “gcc cp210x_gpio_example.c”, исполняемый файл “a.out” сгенерирован. Выполните его с “./a.out”.

0
ответ дан 14 May 2019 в 07:03

Я пробовал много разных приложений, и это сделало мой день:

https://github.com/ondrej1024/crelay

Работает без каких-либо модификаций модуля cp210x на ядре 4.19 на моей малине!

1
ответ дан 7 July 2020 в 15:17

Другие вопросы по тегам:

Похожие вопросы: