5.19: Работа системной шины AMBA с MMIO ======================================= Введение -------- Когда драйвер в Linux вызывает `writel()` или `readl()` для доступа к GPIO или другим регистрам SoC, эти вызовы преобразуются в **низкоуровневые транзакции по системной шине**. На Raspberry Pi 3 в SoC Broadcom BCM2837 используется шина семейства **AMBA** (Advanced Microcontroller Bus Architecture). Шина AMBA (например, AHB или APB) имеет чёткое разделение на две фазы: - **Address phase** — передача адреса и управляющих сигналов - **Data phase** — передача или приём данных Это позволяет упростить архитектуру устройств и повысить пропускную способность. Фазы передачи на AHB/APB ------------------------ .. list-table:: :widths: 20 80 :header-rows: 1 * - Фаза - Действие * - Address Phase - Мастер (CPU) выставляет адрес, направление (чтение/запись), размер и другие управляющие сигналы. * - Data Phase - При `write` — мастер выставляет данные. При `read` — slave возвращает данные. Типичный цикл ------------- Пример записи: .. code-block:: c writel(1 << 21, gpio_base + 0x1C); // Установить GPIO21 .. code-block:: text Такты: T1 T2 ──────────────── HADDR: 0x3F20001C - HWRITE: 1 - HWDATA: - 0x00200000 (бит 21) Аналогично работает и чтение (`readl()`), только в фазе данных работает `HRDATA` (шина чтения). Зачем это нужно --------------- - Позволяет **разделить адрес и данные**, упрощая схемы устройств. - Устройство может **подготовиться к приёму/отправке данных**. - Можно **параллелить** несколько транзакций — в следующем такте подать адрес следующего доступа. GPIO Controller и MMIO ---------------------- При доступе к GPIO контроллеру, например: .. code-block:: c gpio_base = ioremap(0x3F200000, 0xB4); writel(1 << 21, gpio_base + GPSET0); Выполняется следующая последовательность: 1. CPU выставляет адрес `0x3F20001C` (регистр GPSET0) и сигнал записи 2. Во второй фазе передаются данные `0x00200000` (бит 21) 3. GPIO-контроллер принимает команду и выставляет HIGH на пине GPIO21 Таблица сигнальных линий AMBA AHB (базовая) -------------------------------------------- .. list-table:: :widths: 30 70 :header-rows: 1 * - Сигнал - Назначение * - `HADDR` - Адрес в MMIO-пространстве (32/64 бит) * - `HWDATA` - Данные на запись * - `HRDATA` - Данные на чтение * - `HWRITE` - Направление: 1 — запись, 0 — чтение * - `HTRANS` - Тип трансфера (IDLE, NONSEQ, SEQ) * - `HREADY` - Готовность к завершению текущей фазы * - `HSEL` - Выбор slave-устройства Вывод ----- - Каждая транзакция по AMBA состоит из **адресной и дата-фазы** - При работе с MMIO (например, GPIO), эти две фазы проходят на каждом `readl()` / `writel()` - Это позволяет Linux-драйверам обращаться к железу как к обычной памяти, через стандартные вызовы Следующая тема: проектируем собственный RGB-драйвер, работающий через MMIO.