35. Программа test_rgb_user.c и UIO-драйвер rgb_uio.ko
35.1. Введение
В данной системе реализовано управление RGB-светодиодом с помощью пользовательского приложения test_rgb_user.c, использующего интерфейс UIO (Userspace I/O) к модулю ядра rgb_uio.ko. Такое разделение позволяет управлять оборудованием напрямую из пользовательского пространства без написания специфического ioctl-интерфейса, используя mmap().
35.2. UIO-драйвер rgb_uio.ko
Драйвер реализован как platform_driver и использует интерфейс uio_info, предоставляемый ядром Linux для создания пользовательских I/O-устройств. Он:
Получает из Device Tree описания GPIO-пинов red-gpios, green-gpios, blue-gpios.
Инициализирует эти пины в режиме вывода (GPIOD_OUT_LOW).
Выделяет один байт памяти в kernel space (kmalloc() через devm_kzalloc()), который затем отображается в userspace с помощью mmap().
Регистрирует структуру uio_info, чтобы создать /dev/uio0.
Младшие три бита выделенного байта отвечают за включение каналов:
Бит 0 — красный светодиод
Бит 1 — зелёный светодиод
Бит 2 — синий светодиод
Изменение значения этого байта изменяет состояния пинов, тем самым включая или выключая соответствующие цвета.
35.3. Файл устройства /dev/uio0
После загрузки драйвера ядро автоматически создаёт символьное устройство /dev/uio0, которое пользователь может открыть с правами на read/write и использовать mmap() для доступа к зарезервированной области памяти.
35.4. Программа test_rgb_user.c
Данная утилита компилируется как обычная C-программа и предназначена для запуска из терминала. Она:
Принимает аргумент командной строки — байт, задающий цвет в формате 0xXY.
Открывает /dev/uio0 с правами O_RDWR.
Выполняет отображение одного байта памяти (mmap()) из устройства в адресное пространство процесса.
Записывает полученное значение в отображённую память.
Это значение читается ядром и используется для управления состояниями GPIO-пинов.
Пример использования:
./test_rgb_user 0x01 # Включить только красный
./test_rgb_user 0x02 # Включить только зелёный
./test_rgb_user 0x04 # Включить только синий
./test_rgb_user 0x07 # Все три цвета включены
./test_rgb_user 0x00 # Все выключены
35.5. Связь с железом
Светодиод подключён к GPIO-пинам Raspberry Pi:
Красный — GPIO 16
Зелёный — GPIO 20
Синий — GPIO 21
Сами пины определяются в Device Tree и передаются драйверу через devm_gpiod_get() в rgb_uio.c. Установка значений с помощью gpiod_set_value_cansleep() позволяет безопасно управлять пинами в любых условиях.
35.6. Заключение
Данная реализация UIO-драйвера и пользовательской утилиты показывает, как можно легко и эффективно связать ядро Linux, пользовательское пространство и реальное оборудование. Это прекрасная демонстрация low-level управления без необходимости писать сложные драйверы с ioctl-интерфейсом.