libc/kbd: recovery по Rx-overrun SIO (залипание клавиш) + kbd_raw_sync
Симптом (интермиттентный): при отпускании shift+стрелка иногда стрелка залипает. Диагностика: на чистом одновременном release break-коды обрабатываются верно (проверено MCP) → drain-логика ISR корректна. Остаточное залипание = переполнение 3-байтного аппаратного FIFO SIO при пачке скан-кодов (F0 12 E0 F0 74 = 5 байт) во время длинных DI-окон → потерян break → залипание. Фикс: трамплин после drain читает RR1 SIO (бит5 = Rx Overrun), при overrun делает Error Reset (WR0=0x30) и взводит _kbdraw_overrun. Новый kbd_raw_sync() (звать раз в кадр) по флагу сбрасывает всё held-состояние _kbdraw_down (какой break потерян — неизвестно; реально зажатые перечитаются). pop_ctrl_tick зовёт kbd_raw_sync(). Буфер W2- трамплина 288→320 (трамплин 244 Б). ВНИМАНИЕ: путь overrun НЕ проверен детерминированно (баг интермиттентный, зависит от тайминга DI) — ТРЕБУЕТ ПРОВЕРКИ на железе/в длинной сессии. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* kbd_raw_sync.c — восстановление held-состояния после Rx-overrun SIO.
|
||||
*
|
||||
* Аппаратный приёмный FIFO SIO — 3 байта. Если прерывания запрещены
|
||||
* достаточно долго (DI-окна графики/кадрового IRQ), а в этот момент
|
||||
* приходит пачка скан-кодов (напр. одновременное отпускание shift+стрелка
|
||||
* = F0 12 E0 F0 74, 5 байт) — FIFO переполняется, байт(ы) теряются
|
||||
* аппаратно. Потерянный break → клавиша «залипает» в _kbdraw_down.
|
||||
*
|
||||
* Трамплин ловит overrun (RR1 бит5) и взводит _kbdraw_overrun. Приложение
|
||||
* зовёт kbd_raw_sync() раз в кадр: при взведённом флаге сбрасывает ВСЁ
|
||||
* held-состояние (какой именно break потерян — неизвестно). Реально
|
||||
* зажатые клавиши «перечитаются» их make-повтором/следующим нажатием.
|
||||
*
|
||||
* ВНИМАНИЕ: путь overrun-recovery НЕ проверен детерминированно (баг
|
||||
* интермиттентный, зависит от тайминга DI) — требует проверки на железе.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "_kbdraw.h"
|
||||
|
||||
void kbd_raw_sync(void)
|
||||
{
|
||||
if (_kbdraw_overrun) {
|
||||
_kbdraw_overrun = 0;
|
||||
memset(_kbdraw_down, 0, sizeof(_kbdraw_down));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user