beeugene
12 просмотров0 комментариев0

OV5647 на Repka Pi 5: первый кадр после долгой диагностики MIPI-стека

TL;DR. Сначала мучил Repka Pi 5 (RK3588) с Arducam IMX519 — сенсор честно стримил, а кадр не приходил (ISP отваливался по таймауту). Нашёл и починил PM-баг в DPHY-драйвере (csi2_dphy_hw_stream_on зависал на MMIO из-за suspended runtime PM), разобрал по TRM RK3588 топологию MIPI-стека — разъём Repka MIPI_CSI0 идёт на INNO DPHY0 → CSI Host 2. Но IMX519 на 816 Мбит/с так и не прошёл: PHY_STATE bit0 (HS-clock) оставался нулём на всех трёх хостах. Подключил вместо него OV5647 (от AlphaBot 2) — и о чудо, кадр пошёл: через ISP с движком rkaiq получил цветное изображение (Y avg ≈ 120, нормальный баланс белого) на 640×480 и 1280×960, DPHY полностью корректен (THS_SETTLE=0x8 readback OK). Разводка Repka исправна — проблема была в совместимости высокоскоростного IMX519. Под катом — как завести OV5647, дотащить его до нормальной картинки через rkaiq, и какие у этого сенсора физические ограничения (спойлер: автофокуса там нет в принципе).

Комплект и задача #

Компонент Модель / значение
Платформа Repka Pi 5 (Rockchip RK3588)
ОС Repka OS (Ubuntu 25.10), ядро 6.1.115.1-repka-pi5
Камера (рабочая) OV5647, 5 Мпикс, от робота AlphaBot 2
Камера (проблемная) Arducam IMX519, 16 Мпикс
Шлейф 15-pin → 22-pin переходник (от AlphaBot 2)
Интерфейс MIPI-CSI, 2 data-lanes + clock

Задача: получить кадр с камеры на Repka Pi 5. До этого с IMX519 потратил полдня — сенсор стримил, но картинка не приходила (подробное расследование — в отдельном посте про IMX519). OV5647 подключил как проверочную камеру, чтобы ответить на главный вопрос: виновата разводка Repka или совместимость сенсора.

Что уже было сделано до OV5647 #

Чтобы не повторяться — кратко итоги расследования с IMX519 (полный разбор в соседнем посте):

  1. PM-фикс в DPHY-драйвере. Нашёл реальный баг: csi2_dphy_hw_stream_on зависал на первом MMIO-записи, потому что PHY-hw устройство оставалось в runtime suspended без resume-колбэка. Добавил pm_runtime_get_sync(hw->dev) перед MMIO — функция перестала зависать.
  2. Топология RK3588 по TRM. Разъём Repka MIPI_CSI0_* подключён к INNO DPHY0 (FEDC0000) → CSI Host 2. Не к DC-PHY (как я поначалу решил по названию).
  3. Все три CSI-host перепробованы с IMX519 — ни один не поймал HS-clock (PHY_STATE bit0 = 0 всегда). Вывод был: «сигнал физически не доходит до RK3588, нужна схема платы».

OV5647 должен был ответить: если он тоже не заработает — значит разводка Repka всё-таки виновата. Если заработает — проблема в совместимости IMX519.

💡 OV5647 vs IMX519. OV5647 — старая 5-мегапиксная камера (OmniVision), стоит в первой версии Raspberry Pi Camera Module и во множестве образовательных роботов. Работает на невысокой скорости MIPI (~350 Мбит/с при 2 lanes). IMX519 — 16-мегапиксный сенсор Sony, гонит данные на 816 Мбит/с — почти втрое быстрее. Высокоскоростные сенсоры куда капризнее к таймингам PHY и разводке платы.

Шаг 1. Подключение и определение сенсора #

Подключил OV5647 через переходник 15→22 pin к разъёму Repka (при выключенной плате — это обязательное правило для MIPI-камер, можно сжечь входы PHY). Сначала сканировал I²C-шины — на какой адрес сенсор откликнется:

for b in 0 1 2 3 4 5 6 7 8; do
  i2cdetect -y $b 2>/dev/null | awk '/^3[0-9a-f]:/{print "bus '$b': "$0}'
done

Вывод:

bus 6: 30: -- -- -- -- -- -- 36 -- --  ← 0x36 = OV5647!

0x36 — это OV5647. Сенсор виден на шине I²C-6, значит шлейф воткнут правильно и I²C работает. (0x1a был бы IMX519, 0x10 — IMX219.)

Шаг 2. Оверлей для OV5647 #

Готового оверлея для OV5647 в системе не было — был только rk3588-csi-imx219.dtbo. Создал свой на основе рабочего пути для IMX519 (через Host 2, верный по TRM). Ключевые отличия от IMX519:

Параметр IMX519 OV5647
compatible sony,imx519 ovti,ov5647
reg (I²C адрес) 0x1a 0x36
xclk 24 МГц 25 МГц (строго!)
link-frequencies 408 МГц не используется
clock-noncontinuous да нет
data rate (фактический) 816 Мбит/с 350 Мбит/с

💡 Что такое оверлей? Device Tree Overlay (.dtbo) — «заплатка» поверх базового дерева устройств, которая подключает конкретную периферию (камеру на шине I²C, её параметры, путь к PHY→CSI-host→ISP) без пересборки ядра. Прописывается в repkaEnv.txt (overlays=csi-ov5647) и применяется u-boot'ом при загрузке через fdt apply.

Первая попытка — провал по xclk #

Сначала я по привычке оставил в оверлее xclk = 24 МГц (как у IMX519). OV5647 не привязался:

ov5647 6-0036: Unsupported clock frequency: 24000000
ov5647: probe of 6-0036 failed with error -22

Драйвер OV5647 требует строго 25 МГц (xclk_freq != 25000000-EINVAL). Это видно прямо в исходнике drivers/media/i2c/ov5647.c. Поправил в оверлее:

clk_cam_24m: external-camera-clock-24m {
    compatible = "fixed-clock";
    clock-frequency = <25000000>;   /* было 24000000 */
    ...
};

После этого сенсор привязался, появилась media-сущность m00_b_ov5647 6-0036.

Шаг 3. Стрим — кадр пошёл! #

Запускаю захват:

timeout 18 v4l2-ctl -d /dev/video11 \
  --set-fmt-video=width=640,height=480,pixelformat=NV12 \
  --stream-mmap --stream-count=3 \
  --stream-to=test.nv12

И проверяю файл:

$ ls -lh test.nv12
-rw-r--r-- 1 root root 1.4M ... test.nv12

$ python3 -c "print('3 кадра 640x480 NV12 =', 3 * 640*480*3//2, 'байт')"
3 кадра 640x480 NV12 = 1382400 байт

Размер точно совпадает с тремя полными кадрами 3 × 460800 = 1382400. Никаких «нулевых» буферов — данные реально текут. Это огромная разница с IMX519, где файл всегда получался пустым (0 байт).

В логе — идеальная последовательность:

DPHY_HW_STREAM_ON pm_runtime_get_sync ret=0     ← PM-фикс сработал!
DPHY_LANE_ENABLE wrote=0x4d readback=0x4d       ← lane-enable записан и подтверждён
DPHY_STREAM_ON data_rate=350 hsfreq=0x8          ← data_rate 350 Мбит/с, hsfreq=0x8
DPHY_THS_WR lane=0,2,3 → val=0x8 readback=0x8    ← THS_SETTLE все записаны
DPHY_HW_CHK Z: reached end of stream_on          ← функция дошла до конца
ov5647 6-0036: stream start
ov5647 6-0036: OV5647 power on

Шаг 4. Почему OV5647 работает, а IMX519 — нет #

Сравнение trace'ов двух камер на одном и том же пути (Host 2, INNO DPHY0):

Параметр OV5647 (работает) IMX519 (нет кадра)
data rate 350 Мбит/с 816 Мбит/с
hsfreq (THS_SETTLE) 0x8 0x16
Стрим сенсора стартует, power on стартует, MODE_SELECT ret=0
DPHY programmed ✅ readback OK ✅ readback OK
PHY_STATE bit0 (HS-clock) данные идут (кадр есть) 0 — clock не активен
Кадр ✅ 1.4 МБ (3 кадра) ❌ 0 байт

И DPHY, и CSI-host, и CIF, и ISP — один и тот же софт-путь. Разница только в скорости MIPI: 350 vs 816 Мбит/с. OV5647 на низкой скорости проходит без проблем, а IMX519 на высокой — нет.

💡 HS-settle — почему скорость критична. У приёмника MIPI есть параметр T_HS_SETTLE — сколько тактов ждать после старта HS-передачи перед захватом данных. Он вычисляется по таблице в зависимости от data_rate. Для 350 Мбит/с это 0x8, для 816 — 0x16. Если разводка платы на высоких частотах вносит отражения/джиттер (а MIPI — гигагерцовый сигнал, дорожки критичны), «окно» захвата сужается, и приёмник не ловит clock-lane. На 350 Мбит/с запаса хватает, на 816 — уже нет. Это классическая проблема высокоскоростных MIPI-камер на платах, не рассчитанных под конкретный сенсор.

Вывод: разводка Repka Pi 5 для камеры исправна — OV5647 через неё работает. Проблема с IMX519 в том, что на 816 Мбит/с сигнал не доходит корректно (вероятно — длина/импеданс дорожек, отсутствует согласование, или нужна другая конфигурация lane/PHY).

Что осталось открытым: чёрный кадр → решается через rkaiq #

Кадр по размеру правильный, но содержимое — чёрное (средняя яркость Y-plane = 0.0). Проверил это так:

with open('test.nv12','rb') as f:
    data = f.read(640*480)   # Y-plane первого кадра
avg = sum(data) / len(data)
print(f'Средняя яркость: {avg:.1f}')   # → 0.0 (чёрный)

Размер кадра верный (значит DMA и MIPI работают), но данные нулевые. Самые вероятные причины:

  1. ISP не настроил экспозицию. В raw-режиме (как у нас через v4l2-ctl напрямую) ISP не прогоняет кадр через автоэкспозицию. Нужен движок rkaiq_3A (Rockchip camera engine), который настраивает выдержку/гейн сенсора. Без него OV5647 может отдавать полностью тёмные кадры (минимальная экспозиция по умолчанию).
  2. Несовпадение mbus-формата. Сенсор отдаёт RAW Bayer, а мы запрашиваем NV12 (YUV). Преобразование RAW→YUV делает ISP, и если он не в петле — получаем мусор/нули.
  3. Тайминги сенсора. OV5647 при первом старте может выдавать тёмные кадры, пока не настроишь регистры экспозиции.

Решение: движок rkaiq_3A #

💡 Что такое rkaiq? rkaiq_3A_server (Rockchip AI Image Quality) — пользовательский демон, который крутит петлю 3A (Auto-Exposure / Auto-White-Balance / Auto-Focus). Он читает статистику из ISP, считает нужную выдержку/гейн/баланс белого и прописывает их обратно в сенсор через V4L2. Без него ISP отдаёт сырой кадр «как есть» — а сенсор по умолчанию стоит на минимальной экспозиции, оттого и чёрный. Демон привязывается к сенсору по имени модуля (camera-module-name) и ищет под него калибровочный iqfile.

Главное условие — совпадение имени модуля с именем iqfile. rkaiq ищет файл по шаблону <sensor>_<module-name>_default.json. Сначала я оставил camera-module-name = "ov5647-cam", и демон в логах ругался:

rkaiq: iqfile ov5647_ov5647-cam_default.json NOT FOUND

Файла ov5647_ov5647-cam_default.json в системе нет. Зато есть ov5647_rpi-camera-v1p3_default.json. Поменял в оверлее:

rockchip,camera-module-name = "rpi-camera-v1p3";

rkaiq тут же нашёл свой калибр и заработал.

Первый цветной кадр #

После правки имени модуля запустил захват 10 кадров через ISP-ноду /dev/video11:

timeout 30 v4l2-ctl -d /dev/video11 \
  --set-fmt-video=width=640,height=480,pixelformat=NV12 \
  --stream-mmap --stream-count=10 \
  --stream-to=isp_10.nv12 --stream-poll

И проверил яркость каждого кадра:

Кадр 0:  avg=1.4    ← чёрный (rkaiq только стартует)
Кадр 1:  avg=26.0   ← rkaiq крутит экспозицию вверх
Кадр 2+: avg=216+   ← РЕАЛЬНОЕ ИЗОБРАЖЕНИЕ ✓

Кадр пошёл! Из чёрного → серый → нормальная сцена за три кадра. Это именно то, как должна выглядеть сходимость автоэкспозиции. Сохранил кадр 5 в JPG — repka_ov5647_ISP_COLOR.jpg (1280×960).

⚠️ Ловушка зависаний убрана. Когда я полез диагностировать переход «чёрный → нормальный», добавил в ядро отладочные workqueue, которые каждые 300 мс читали MMIO-регистры DPHY/CSI-host прямо во время стрима. Плата намертво зависала — DMA-движок и CPU-чтения конфликтуют на одной шине. Решение: чистое ядро с PM-фиксом, но без отладочных workqueue. С ним система полностью стабильна, все 40 кадров подряд без единого зависания. Текущее рабочее ядро лежит в репо как vmlinuz-6.1.115.1-repka-pi5.bak-noCSIDebug.

«Чёрный кадр» бывает разный — научился их различать #

По ходу отладки я поймал три принципиально разных вида «чёрного» кадра, и каждый означает свою проблему. По одной цифре средней яркости Y-plane уже можно понять, что сломалось:

Симптом avg Y Что это значит Причина Лекарство
Полностью чёрный 0.0 Данные физически не текут DMA/MIPI не работает, либо ISP вообще не в петле Проверять DPHY, путь в media-графе
Стартовый чёрный 1.4–4 Кадр идёт, но rkaiq ещё не настроил экспозицию Сенсор стоит на мин. выдержке Просто пропустить 2–3 первых кадра
«Точки на чёрном» ~5–15 Слабый сигнал/шум, экспозиция почти нулевая iqfile не загрузился, rkaiq крутится вхолостую Свести camera-module-name с именем iqfile
Пересвеченный (тоже «битый») 230+ rkaiq перебрал экспозицию AE-осцилляция в начале сходимости То же — взять кадр спустя 3–5 после старта

Как это выглядит на цифрах из реального захвата 40 кадров подряд (HD 1280×960):

Кадр  0: avg=3.9   ← стартовый чёрный (rkaiq просыпается)
Кадр  2: avg=233   ← ПЕРЕСВЕТ (AE дёрнул гейн вверх)
Кадр  6: avg=106   ← почти норма
Кадр  7: avg=121   ← ОПТИМУМ ✓
Кадр 39: avg=88    ← steady-state (AE передавил в темноту)

💡 Практический вывод. Если вы видите «чёрный кадр» — сначала измерьте avg яркости Y-plane, а не смотрите на превью. avg=0 и avg=4 — это разные поломки. И никогда не судите о качестве по первому кадру: rkaiq нужно 3–5 кадров на сходимость, первый всегда плохой. Длинный захват (30–40 кадров) и анализ каждого по яркости — единственный способ понять, что реально происходит.

Ложные следы (куда я зря копал с IMX519) #

  • «Разводка Repka битая». Главная гипотеза после неудачи с IMX519 — что пины разъёма идут не на те lanes RK3588. Уверился в этом после того, как перепробовал все три host (0/2/3) и ни один не поймал HS-clock. OV5647 опроверг эту гипотезу одной командой стрима — на той же разводке, через тот же шлейф, кадр пошёл. Мораль: прежде чем винить железо платы, проверь более простой/медленный сенсор.
  • «Host 0 / DC-PHY». По названию сигналов в схеме (MIPI_CSI0_RX) я решил, что разъём на CSI Host 0 (Samsung DC-PHY). Потратил несколько циклов «сборка+ребут» на DC-PHY путь, пока не полез в TRM и не увидел, что MIPI_CSI0_* — это INNO DPHY → Host 2.
  • xclk 24 vs 25 МГц. С OV5647 споткнулся на том же — оставил 24 МГц от IMX519. Драйвер чётко сказал Unsupported clock frequency: 24000000. Хороший урок: читай исходник драйвера, там часто зашиты точные требования.

Про пределы OV5647 — чего НЕ получить никакой калибровкой #

OV5647 выдаёт кадр, rkaiq сводит экспозицию — но картинка остаётся «не идеальной»: местами пересвечено, местами софт-фокус. Прежде чем лезть в iqfile, важно понять, что из этого программно правится, а что — физическое свойство модуля.

Проблема Программная? Причина Можно ли поправить
Пересвет первых кадров ✅ да AE-осцилляция rkaiq в начале сходимости Взять кадр 3–7, а не 0–1
Steady-state слишком тёмный (avg=88) ✅ да DySetpoint целится в 30–50 из 256 Поднять target в iqfile (см. ниже)
Автофокус отсутствует ❌ нет На чипе нет VCM-катушки Сменить сенсор
Мягкость/«софт» картинки ⚠️ частично Фиксированная линза + апскейл Раст до 1280×960, но предел линзы
Баланс белого R/G=0.84 (зеленоватый) ✅ да AWB ещё сводится / iqfile-калибр Правка AWB-секций iqfile

iqfile и DySetpoint — почему steady-state уходит в темноту #

rkaiq целится в целевую яркость кадра, которая лежит в калибровочном iqfile /etc/iqfiles/ov5647_rpi-camera-v1p3_default.json в секции LinearAeCtrl.DySetpoint:

"DySetpoint": {
    "ExpLevel":   [0, 0.023, 0.046, 0.14, 0.23, 0.33],   // уровень освещённости сцены
    "DySetpoint": [50, 48,    46,    43,   40,   30]      // целевая яркость (0..255)
}

💡 Что это значит. При ярком свете (ExpLevel 0.14–0.33) rkaiq целится в яркость 40–43 из 256 — это намеренно тёмная цель (чтобы не выжигать пересветы). На моих кадрах steady-state avg=88 — это как раз «rkaiq честно свёл к своей цели». А «оптимальный» кадр 7 (avg=121) — это момент, когда AE ещё не успел уйти в темноту.

Для сравнения — DySetpoint у разных сенсоров в той же системе (нормальный разброс, калибр OV5647 не «битый»):

ov5647_rpi-camera-v1p3:  [50, 48, 46, 43, 40, 30]   ← наш
ov5647_OKDO-5MP:         [50, 48, 46, 43, 40, 30]   ← идентично (заводской шаблон)
imx219_rpi-camera-v2:    [45, 43, 40, 38, 35, 32]
imx519_arducam-imx519:   [45, 43, 40, 38, 35, 32]
gc8034_default:          [60, 60, 55, 50, 45, 40]   ← самый «светлый» калибр

Если steady-state кажется слишком тёмным — можно поднять DySetpoint (например, до [60, 58, 55, 52, 48, 40]) после резервного копления iqfile. Но это уже тюнинг под вкус, а не починка бага.

Итоги #

Параметр Значение
Платформа Repka Pi 5 (RK3588), ядро 6.1.115.1
Камера OV5647 (AlphaBot 2) — работает
Путь ov5647 → csi2_dphy0 → mipi2_csi2 → rkcif → ISP (Host 2, верный по TRM)
xclk 25 МГц (строгое требование драйвера)
data rate 350 Мбит/с
PM-фикс pm_runtime_get_sync в csi2_dphy_hw_stream_on — нужен и помогает
Кадр цветное изображение через ISP + rkaiq (Y avg ≈ 120, BW R/G ≈ 0.9)
Вывод разводка Repka исправна; проблема IMX519 — в его высокой скорости 816 Мбит/с

Главный практический результат: OV5647 работает на Repka Pi 5, разводка и PM-фикс подтверждены. Для IMX519 проблема локализована — высокоскоростной MIPI на этой плате не проходит, нужен либо другой PHY/конфиг, либо плата с дорожками под 816 Мбит/с.

Как запустить у себя: тянем из репозитория #

Репозиторий со всеми патчами, оверлеями, собранным ядром и постами: https://gitflic.ru/project/beeugene/imx519-fo-repka-pi-patch (ветка ov5647-working).

⚠️ Предупреждение. Действия ниже затрагивают загрузчик и ядро. Делайте только при наличии SD-карты для восстановления (или возможности перепрошить). Ядро и оверлей — для Repka Pi 5 (RK3588), на других платах не проверялось. Прежде чем что-либо перезаписывать — сохраните оригиналы (команды ниже).

Что в репозитории #

drivers/                    изменённые исходники ядра (PM-фикс + trace)
dtb/rockchip/overlay/       готовые .dtbo + .dts оверлеи (imx519 и ov5647)
                            repkaEnv.imx519.txt — пример строки overlays= для IMX519
images/                     кадры-результаты (JPG)
blog/                       эти посты

💡 Скомпилированное ядро в репо не лежит — оно весит 13 МБ и привязано к версии. Ниже описано два пути: либо пересобрать из патчей (долго, но «по-честному»), либо взять готовый vmlinuz из бэкапа.

Вариант A. Только оверлей (ядро уже исправное) #

Если ваше ядро уже содержит PM-фикс или вы готовы обойтись без него (на OV5647 DPHY может заработать и так) — достаточно поставить только overlay:

# 1. Клонируем репо
git clone https://gitflic.ru/project/beeugene/imx519-fo-repka-pi-patch.git
cd imx519-fo-repka-pi-patch
git checkout ov5647-working

# 2. БЭКАП оригинального окружения (обязательно!)
cp /boot/repkaEnv.txt /boot/repkaEnv.txt.bak-mystart

# 3. Кладём overlay туда, где его ищет u-boot
cp dtb/rockchip/overlay/rk3588-csi-ov5647.dtbo \
   /boot/dtb/rockchip/overlay/

# 4. Прописываем overlay в repkaEnv.txt
#    (отредактируйте строку overlays=, добавьте csi-ov5647)
#    overlays=panthor-gpu csi-ov5647

# 5. Проверяем, что iqfile для OV5647 на месте
ls /etc/iqfiles/ | grep ov5647
# должно быть: ov5647_rpi-camera-v1p3_default.json
# (имя модуля в overlay жёстко прописано под этот файл)

# 6. Перезагрузка
sudo reboot

После загрузки проверяем, что сенсор привязался:

i2cdetect -y 6 | grep 36      # должно быть: 36, причём 'UU' = занят драйвером
dmesg | grep -i ov5647        # строки про power on / stream

Вариант B. Полная установка с исправленным ядром (PM-фикс) #

Если без PM-фикса DPHY зависает (OV5647 на некоторых ревизиях Repka OS этим страдает), нужно ядро с патчем. Полный путь — пересборка ядра, но это долго (1–1.5 часа на самой Repka):

# 1. Ставим исходники ядра Repka OS
#    (через apt: apt install linux-rockchip-source, либо качаем архив)

# 2. Накладываем патчи из репо поверх дерева linux-rockchip
cp -r drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c \
      /usr/src/linux-rockchip/drivers/phy/rockchip/
# ... и остальные файлы из drivers/ репо

# 3. Сборка (на самой Repka Pi 5, ~1 час)
cd /usr/src/linux-rockchip
make ARCH=arm64 rockchip_defconfig
make ARCH=arm64 -j$(nproc) Image dtbs modules

# 4. Установка (с БЭКАПОМ старого ядра!)
cp /boot/vmlinuz-6.1.115.1-repka-pi5 /boot/vmlinuz-6.1.115.1-repka-pi5.bak-orig
cp arch/arm64/boot/Image /boot/vmlinuz-6.1.115.1-repka-pi5
make ARCH=arm64 modules_install
make ARCH=arm64 dtbs_install

# 5. Ставим overlay (см. Вариант A, шаги 2–4)

sudo reboot

⚠️ Если ядро не грузится — это не смертельно. u-boot на Repka ищет vmlinuz-... по точному имени. Откат: загрузитесь с резервной SD-карты (или chroot с другой системы), верните vmlinuz-...bak-orig на место. Поэтому бэкап ядра перед установкой — обязателен.

Проверка после перезагрузки: один кадр #

Финальная проверка, что всё работает — захватить кадр и посмотреть его яркость:

# Захват 10 кадров через ISP
timeout 30 v4l2-ctl -d /dev/video11 \
  --set-fmt-video=width=640,height=480,pixelformat=NV12 \
  --stream-mmap --stream-count=10 \
  --stream-to=/tmp/test.nv12 --stream-poll

# Проверяем яркость каждого кадра
python3 -c "
fs=640*480*3//2
d=open('/tmp/test.nv12','rb').read()
for i in range(10):
    y=d[i*fs:i*fs+640*480]
    print(f'кадр {i}: avg={sum(y)/len(y):.1f}')
"
# Ожидаемый результат:
#   кадр 0: avg≈1-4    (стартовый чёрный — НОРМА)
#   кадр 2-3: avg≈200+ (пересвет — AE сошёл с ума, тоже НОРМА)
#   кадр 5+: avg≈90-130 (нормальная картинка ✓)

Если кадр 5+ показывает avg между 80 и 150 — всё работает. Если avg=0 во всех кадрах — смотрите раздел про «типы чёрных кадров» выше.

Уроки, которые я вынес #

  1. Проверяй разводку простой камерой. Прежде чем винить плату в «битых MIPI», подключи самый медленный/совместимый сенсор (OV5647, IMX219) — если он заработает, значит разводка ок, и проблема в конкретном сенсоре.
  2. Читай исходник драйвера. Точные требования к xclk, lane-config, регистрам — всё там. xclk_freq != 25000000 спасло бы мне полчаса, если бы я сразу глянул ov5647.c.
  3. TRM RK3588 — лучший друг. Названия сигналов в схеме платы обманчивы (MIPI_CSI0 ≠ «Host 0»). Только официальный TRM даёт точное соответствие host↔PHY↔пины.
  4. PM-фикс нужен всем. csi2_dphy_hw_stream_on без pm_runtime_get_sync зависает на любой камере — это баг драйвера, не конкретного сенсора. После фикса DPHY программируется корректно (подтверждено readback).

Шпаргалка команд #

# Поиск сенсора на I²C-шинах (OV5647=0x36, IMX219=0x10, IMX519=0x1a)
for b in 0 1 2 3 4 5 6 7 8; do i2cdetect -y $b 2>/dev/null | awk '/^3[0-9a-f]:/{print}'; done

# Проверка привязки драйвера
dmesg | grep -i ov5647
i2cdetect -y 6 | grep 36    # UU = занят драйвером, 36 = виден но не привязан

# Стрим с захватом кадра (ISP + rkaiq должны быть активны)
timeout 30 v4l2-ctl -d /dev/video11 \
  --set-fmt-video=width=640,height=480,pixelformat=NV12 \
  --stream-mmap --stream-count=10 \
  --stream-to=isp_10.nv12 --stream-poll

# Проверка размера (NV12 640x480 = 460800 байт/кадр)
python3 -c "print('ожидаемый размер 10 кадров:', 10*640*480*3//2, 'байт')"
ls -l isp_10.nv12

# Проверка яркости по кадрам (найти момент сходимости rkaiq)
python3 -c "
import sys
fs=640*480*3//2
d=open('isp_10.nv12','rb').read()
for i in range(10):
    y=d[i*fs:i*fs+640*480]
    print(f'кадр {i}: avg={sum(y)/len(y):.1f}')
"

# Проверка, что rkaiq нашёл iqfile (имя модуля должно совпадать)
ls /etc/iqfiles/ | grep ov5647
# лог rkaiq: journalctl -u rkaiq_3A_server, либо tail /tmp/rkaiq*.log

# Пересборка оверлея OV5647
dtc -@ -I dts -O dtb -o rk3588-csi-ov5647.dtbo rk3588-csi-ov5647.dts

# Включение оверлея
# в /boot/repkaEnv.txt:
#   overlays=panthor-gpu csi-ov5647

Ссылки #


0

Комментарии (0)

Для участия в обсуждении Вы должны быть авторизованным пользователем

Еще посты по теме

Наиболее интересные по мнению читателей



Темы

Навигация

ВойтиРегистрация