Files
Button/docs/display-blank-investigation.md
T
GrigoandClaude Opus 5.5 66578a0925 displaywatch: panel takeover at boot, daily re-init, cold/warm boot log
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>
2026-11-11 00:50:37 +00:00

92 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Тёмный экран при горящей подсветке: расследование
Дата: 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.