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-программа и предназначена для запуска из терминала. Она:

  1. Принимает аргумент командной строки — байт, задающий цвет в формате 0xXY.

  2. Открывает /dev/uio0 с правами O_RDWR.

  3. Выполняет отображение одного байта памяти (mmap()) из устройства в адресное пространство процесса.

  4. Записывает полученное значение в отображённую память.

  5. Это значение читается ядром и используется для управления состояниями 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-интерфейсом.