Investigation on a returned unit (docs/display-blank-investigation.md): the dark-panel/backlight-on failure reproduces with a warm reboot or a 200 ms pulse on the panel reset line, with no kernel message. After the U-Boot logo hand-off the panel powers/avee GPIOs stay undriven inputs. - Fresh boot: DPMS off/on before the UI starts (unit Before=buttontask), so the driver runs the full panel power-on and drives those lines. - Daily preventive re-init (01:30 UTC, or every 24 h of uptime without NTP); not counted towards reboot escalation. - Previous boot found by saved boot_id, not 'journalctl -b -1' (clock jumps reorder boots); log cold/warm boot from the rk809 RTC (reset to 2017-08-04 on power loss); keep the RTC set from NTP; uptime in every incident line; loop timers on the monotonic clock. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
92 lines
13 KiB
Markdown
92 lines
13 KiB
Markdown
# Тёмный экран при горящей подсветке: расследование
|
||
|
||
Дата: 2026-11-11. Экземпляр: возврат с объекта (жалоба: «подсветка горит, картинки нет, лечится передёргиванием питания»), питание PoE.
|
||
Плата: `Rockchip RK3566 EVB2 LP4X V10 Board`, ядро 5.10.209 (сборка 2025-12-02), Debian 11. Панель MIPI-DSI 480×480, драйвер `simple-panel-dsi`, контроллер панели по init-последовательности ST7701S (`FF 77 01 00 00 10`).
|
||
|
||
## Коротко
|
||
|
||
1. **Сбой воспроизведён без PoE.** Достаточно (а) тёплой перезагрузки или (б) короткого импульса на линии сброса панели: панель гаснет, подсветка горит, SoC продолжает выводить кадры, ядро не пишет ни одной ошибки.
|
||
2. **Со стороны SoC сбой не виден.** Конвейер VOP2 → DSI активен, режим 480x480p60, кадр выводится, подсветка включена. DSI работает в video mode без подтверждений от панели, поэтому потерю инициализации панели ядро обнаружить не может.
|
||
3. **Панель после загрузки остаётся без управления по питанию.** Ядро принимает дисплей, инициализированный U-Boot (передача логотипа), и не выполняет последовательность включения панели. Линии питания панели остаются **входами без драйвера**:
|
||
|
||
| GPIO | назначение (DT) | после загрузки | после повторной инициализации драйвером |
|
||
|---|---|---|---|
|
||
| gpio-16 (GPIO0_C0) | `reset-gpios`, активный низкий | out, high | out, high |
|
||
| gpio-17 (GPIO0_C1) | `powers-gpios` | **in, low** | out, high |
|
||
| gpio-18 (GPIO0_C2) | `enable-gpios` | out, high | out, high |
|
||
| gpio-20 (GPIO0_C4) | `avee-gpios` | **in, high** | out, high |
|
||
|
||
Неуправляемая линия включения питания панели (`powers`, `avee`) уязвима к помехам. Импульсная помеха или просадка по PoE может снять питание или сбросить контроллер панели при живом SoC. Это совпадает с наблюдениями на объектах: ядро живо, тач работает, картинки нет.
|
||
4. **Лечится без перезагрузки:** `blank` / `unblank` дисплея (`/sys/class/graphics/fb0/blank`: 4, затем 0) при остановленном UI. Драйвер панели выполняет полную последовательность: питание, сброс, init-команды. После этого все четыре линии становятся управляемыми выходами.
|
||
|
||
## Как воспроизвести
|
||
|
||
Все команды выполняются от root на устройстве.
|
||
|
||
**А. Тёплая перезагрузка.** `systemctl reboot` (питание не снимается). После загрузки экран остался тёмным при горящей подсветке. Повторяемость уточняется (см. ниже).
|
||
|
||
**Б. Импульс сброса панели в обход драйвера** (имитация помехи на линии сброса):
|
||
```sh
|
||
busybox devmem 0xfdd60004 32 0x00010000 # GPIO0 SWPORT_DR_H: бит 0 (GPIO0_C0, reset) = 0, маска только на этот бит
|
||
sleep 0.2
|
||
busybox devmem 0xfdd60004 32 0x00010001 # вернуть 1
|
||
```
|
||
Результат: картинка пропала, подсветка горит, в `dmesg` ни одной строки.
|
||
|
||
**Проверка, что SoC выводит кадры:**
|
||
`cat /sys/kernel/debug/dri/0/summary`. В нём видно `Video Port1: ACTIVE`, `DSI-1`, `480x480p60`, `Smart0-win0: ACTIVE`.
|
||
|
||
**Восстановление** (обе ситуации А и Б, проверено визуально):
|
||
```sh
|
||
systemctl stop buttontask
|
||
echo 4 > /sys/class/graphics/fb0/blank
|
||
echo 0 > /sys/class/graphics/fb0/blank
|
||
systemctl start buttontask
|
||
```
|
||
(В прошивке это делает `bt-displaywatch recover` или жест «10 с в нижнем левом углу».)
|
||
|
||
## Что просить у производителя платы / BSP
|
||
|
||
1. В device tree и U-Boot: линии `powers-gpios` (GPIO0_C1) и `avee-gpios` (GPIO0_C4) должны с момента включения быть **выходами** в активном уровне. Не оставлять их входами после передачи дисплея от U-Boot ядру. Подтянуть их резисторами на плате, если это предусмотрено схемой.
|
||
2. Объяснить, почему после тёплой перезагрузки (питание панели не снималось) панель не инициализируется заново. Вероятно, U-Boot не выполняет сброс и init-последовательность панели, если она уже была включена, а ядро не делает этого из-за передачи логотипа.
|
||
3. Проверить помехоустойчивость линии сброса панели (GPIO0_C0) и питания панели при работе от PoE: просадки и импульсные помехи при включении других PoE-нагрузок.
|
||
4. По возможности: способ из ядра узнать, что панель жива. Например, периодическое DCS-чтение `get_power_mode` (0x0A), чтобы сбой обнаруживался автоматически.
|
||
|
||
## Что сделано в нашем ПО (обход)
|
||
|
||
- `bt-displaywatch` переинициализирует панель (blank/unblank) по ошибкам DRM/DSI в ядре, по пропаданию Ethernet-линка (признак просадки PoE), по запросу (жест, CLI). При повторяющихся сбоях он перезагружает устройство.
|
||
- Жест для персонала: удерживать нижний левый угол экрана 10 с.
|
||
- При каждой загрузке, до запуска UI, `bt-displaywatch` выполняет одну такую переинициализацию. Юнит запускается `Before=buttontask.service`, функция `boot_takeover`. Драйвер берёт линии питания панели под управление, и закрывается тёмный экран после тёплой перезагрузки. Проверено на возвращённом экземпляре: после загрузки `powers`/`avee` стали `out hi`, UI стартует после переинициализации (~0,5 с чёрного экрана до UI).
|
||
- Раз в сутки ночью (01:30 UTC = 04:30 МСК, настраивается через `DISPLAYWATCH_DAILY_UTC`) выполняется профилактическая переинициализация: экран моргает примерно на 6 с, приложение перезапускается. Тихий сбой панели (без ошибок ядра и без падения линка) со стороны SoC не обнаружить, поэтому так он длится не дольше суток. Без синхронизированного времени переинициализация выполняется раз в 24 часа аптайма.
|
||
- В журнале инцидентов (`/var/log/buttontask/display-incidents.log`) при каждом старте записывается `COLD boot` (питание пропадало) или `WARM boot`, а также как закончилась предыдущая загрузка.
|
||
|
||
## Прочие наблюдения
|
||
|
||
- Сетевая нагрузка не влияет: 5 минут UDP 80 Мбит/с (2,1 млн пакетов). Ошибок на `eth0` 0, нагрузка CPU < 1, перезагрузок нет.
|
||
- По часам rk809 (без батарейки) видно, пропадало ли питание перед загрузкой. Ядро пишет `rk808-rtc: setting system clock to …`: значение `2017-08-04T09:00:0x` означает, что питание пропадало, реальное время означает тёплый перезапуск. Все загрузки этого экземпляра в журнале начинались после пропадания питания.
|
||
- `kernel.panic = 0`: при панике ядра плата зависает, а не перезагружается (на прошивке без аппаратного вотчдога).
|
||
|
||
## Объяснение простыми словами
|
||
|
||
Внутри кнопки два «работника»: **компьютер** (плата) и **экран**.
|
||
|
||
Компьютер рисует картинку и всё время отправляет её на экран по проводу, как телевизионный сигнал. Экран эту картинку показывает. Но перед началом работы экран нужно **«разбудить»**: подать на него питание в правильном порядке и проговорить ему набор команд «проснись, вот твои настройки».
|
||
|
||
**Что идёт не так.** При включении экран будит загрузчик платы. После этого основная система не берёт экран под свой контроль: провода, которые держат питание экрана, остаются «брошенными», их никто не держит. Если в сети питания PoE случается короткий скачок или помеха, экран от этого «засыпает» или сбрасывается и забывает свои настройки. Компьютер при этом ничего не замечает: он продолжает отправлять картинку, а ответа от экрана не ждёт. Поэтому получается так:
|
||
|
||
- подсветка горит (она питается отдельно);
|
||
- картинки нет (экран «спит»);
|
||
- кнопка живая, тач работает, но ничего не видно;
|
||
- помогает только выдернуть и вставить питание: тогда всё будится заново.
|
||
|
||
**Почему это не наша программа.** Мы повторили сбой на возвращённой кнопке без всякого PoE: достаточно одного короткого импульса на проводе сброса экрана, и экран гаснет, а система не видит ни одной ошибки. Иногда то же самое происходит и после обычной перезагрузки. Это особенность платы и её начальной прошивки (U-Boot и device tree от производителя платы), а не приложения.
|
||
|
||
**Что мы сделали.**
|
||
- При каждом включении наша программа сразу «будит» экран сама и забирает его провода под контроль, чтобы они больше не болтались.
|
||
- Если в сети или в системе случился сбой, похожий на причину, экран будится заново автоматически.
|
||
- Раз в сутки ночью экран будится профилактически, на несколько секунд.
|
||
- У персонала есть «кнопка спасения»: подержать палец 10 секунд в нижнем левом углу экрана.
|
||
|
||
**Что должен сделать производитель платы.** Исправить начальную прошивку, чтобы провода питания экрана с самого включения были под управлением. Проверить, насколько плата и экран устойчивы к помехам по питанию PoE.
|
||
|