21. 5.20: RGB LED через Device Tree и MMIO

21.1. Описание проекта

В этом упражнении мы реализовали драйвер для управления RGB-светодиодами на Raspberry Pi 3 с использованием:

  • Регистров MMIO (Memory-Mapped I/O)

  • Описания устройств в Device Tree (DT)

  • Создания трёх символических устройств /dev/ledred, /dev/ledgreen, /dev/ledblue

  • Работа через фреймворк miscdevice

  • Управление пинами напрямую через регистры (FSEL, SET, CLR)

Мы не использовали GPIO API (gpiod), а напрямую управляли GPIO на низком уровне через регистры SoC.

21.2. Физические соединения

RGB LED подключён к пинам:

  • R → GPIO16 (BCM)

  • G → GPIO20

  • B → GPIO21

Все пины конфигурируются как output в probe() функции.

21.3. Код драйвера

  1. В probe() мы:

  • читаем из DT: - метку устройства label - битовую маску led-mask — например, 1 << 16 (0x00010000) для GPIO16

  • вызываем ioremap() для диапазона регистров GPIO (0x3F200000, 0xB4)

  • конфигурируем FSEL регистр через set_gpio_output(gpio)

  • регистрируем miscdevice

  1. При write() в /dev/ledred:

  • строка „1“ вызывает iowrite32(mask, gpio_base + GPIO_SET_OFFSET)

  • строка „0“ вызывает iowrite32(mask, gpio_base + GPIO_CLR_OFFSET)

  1. При read() возвращается текущий символ: „1“ или „0“.

21.4. Device Tree (DT)

Пример узла для одного светодиода (вставляется в soc {}):

ledred@3 {
    compatible = "kontakts,rgb-led";
    label = "ledred";
    reg = <3>;
    status = "okay";
    led-mask = <0x10000>; // GPIO16
};

Устройства создаются на основании compatible и label, led-mask определяет нужный пин.

21.5. Проверка DT

ls /proc/device-tree/soc/ledred@3
cat /proc/device-tree/soc/ledred@3/label
hexdump -C /proc/device-tree/soc/ledred@3/led-mask

21.6. Проверка драйвера

Загрузка:

sudo insmod rgb_led_dt.ko

Проверка устройств:

ls -l /dev/ledred /dev/ledgreen /dev/ledblue

Включение и чтение:

echo "1" > /dev/ledred
cat /dev/ledred

21.7. Проверка GPIO через gpioinfo и raspi-gpio

gpioinfo | grep 16
gpioinfo | grep 20
gpioinfo | grep 21

Вывод:

line  16: unnamed unused output active-high
line  20: unnamed unused output active-high
line  21: unnamed unused output active-high

Или:

sudo raspi-gpio get 16
sudo raspi-gpio get 20
sudo raspi-gpio get 21

Результат:

GPIO 16: level=1 fsel=1 func=OUTPUT

21.8. Финальный вывод

  • Мы создали полноценный low-level RGB LED драйвер

  • Использовали MMIO напрямую

  • Применили Device Tree с масками пинов

  • Проверили работу через /dev/*, gpioinfo и raspi-gpio

  • Освободили пины, используя set_gpio_output()

21.9. Лицензия

GPL. Для обучения. Автор: ChatGPT + пользователь.