#linux #GPIO #i2c #spi #hardware #userspase #libgpiod Контроль и управление периферией в Linux Все устройства в Linux живут тут: `/dev` ## GPIO Полезная информация: https://devdotnet.org/post/rabota-s-gpio-v-linux-chast-6-biblioteka-libgpiod/ Способы управления: 1. Userspace driver -прямое управление 2. Libgpiod - управление через библиотеку 3. #### User Space Прямой доступ к регистрам, минуя медленные системные вызовы. Посредством открытия `/dev/mem` и мапирование базового адреса GPIO. ==Подводные камни:== 1. Обход GPIO Subsystem 2. Нет контроля конкуренции (может управлять несколько процессов) 3. Можно сломать драйвер 4. Нет безопасности ```cpp title:userspace_gpio_control.cpp #include // вывод сообщений #include // открытие файлов #include // mmap и munmap #include // usleep и close #include // perror #include // для uint32_t /* 1. Userspace драйвер GPIO. Управление GPIO Raspberry Pi через mmap обеспечивает прямой доступ к регистрам периферии, минуя медленные системные вызовы. Это реализуется через открытие /dev/mem, мапирование базового адреса GPIO */ #define GPIO_BASE 0x3F200000 // физический адрес начала блока регистров GPIO на SoC BCM2835 #define BLOCK_SIZE 4096 // Размер отображ. памяти Регистры GPIO занимают 41 байт, но мы отображаем целую страницу для простоты. #define TIME_SLEEP 500000 // Время задержки в микросекундах int main() { // открытие спец.файла физической памяти. Флаги - чтение и запись + отключение кэширования int mem_fd = open("/dev/mem", O_RDWR | O_SYNC); // Если не удалось открыть - вывод ошибки if (mem_fd < 0) { perror("open"); return 1; } /* Отображение памяти регистров в виртуальное адресное пространство mmap создаёт отображение физической памяти, начиная с адреса GPIO_BASE, размером BLOCK_SIZE, в виртуальную память процесса. NULL – ядро само выбирает адрес для отображения. BLOCK_SIZE – количество байт. PROT_READ | PROT_WRITE – разрешено чтение и запись. MAP_SHARED – изменения видны другим процессам и синхронизируются с файлом (важно для доступа к реальной памяти). mem_fd – файловый дескриптор /dev/mem. GPIO_BASE – смещение в файле (физический адрес). */ void* gpio_map = mmap( NULL, BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, GPIO_BASE ); if (gpio_map == MAP_FAILED) { perror("mmap"); return 1; } // Указатель приводится к типу volatile uint32_t*, чтобы: // Обращаться к памяти 32-битными словами. // volatile запрещает компилятору оптимизировать обращения, т.к. значения регистров могут меняться аппаратно. volatile uint32_t* gpio = (volatile uint32_t*)gpio_map; // GPIO17 = бит 21 в GPFSEL1 gpio[1] &= ~(7 << 21); // очистить gpio[1] |= (1 << 21); // output while (true) { gpio[7] = (1 << 17); // set usleep(TIME_SLEEP); gpio[10] = (1 << 17); // clear usleep(TIME_SLEEP); } // освобождение ресурсов, при выходе munmap(gpio_map, BLOCK_SIZE); close(mem_fd); } ``` #### libgpiod - library control Library General Purpose Input/Output device - Библиотека и набор утилит в Linux для управления пинами GPIO (ввод/вывод общего назначения) через символьные устройства (`/dev/gpiochip*`) или контроллеры GPIO Состав библиотеки: - **gpiodetect** - **gpioinfo** - **gpioset** - **gpioget** Установка: ``` bash sudo apt-get update sudo apt-get install -y libgpiod-dev libgpiod-doc gpiod ``` Проверка корректности установки: ``` bash pkg-config --cflags --libs libgpiod ``` Компиляция: ``` bash g++ -o gpio_control gpio_control.cpp -lgpiod ``` `` 3. Компиляция: 4. API для Python и C/C++ ``` cpp title:libgpiod_control.cpp ``` ## I2C. Integrates `/sys/bus/i2c/devices/` По умолчанию шина отключена. Включить можно следующими способами: 1. `sudo raspi-config` 2. Корректировкой `/boot/firmware/config.txt` 1. Необходимо раскомментировать параметр `dtparam=i2c_arm=on` Затем в устройство должно появиться в `/dev` как `i2c-1` Для работы с шиной и периферией есть библиотека `i2c-tools` ## SPI Команды для работы: `cat /proc/device-tree/model` - модель платы для которой device tree создан `ls /proc/device-tree/` - дерево устройств, которое kernel получил от GPU `ls /sys/bus/platform/devices` - вывод устройств, которые kernel создал на основе DT `lsmod` - просмотр загруженных модулей св ## Commands Система: `vcgencmd get_config int` - параметры, которые передает GPU `cat /etc/os-release` - просмотр версии системы