STALL конечной точки USB и тайм-аут bulk-передачи: чтение захвата до правки прошивки
Как отлаживать STALL конечных точек USB, тайм-ауты bulk-передач и сбои data-пути на стороне прошивки по данным захвата.
После успешного перечисления USB-устройства всё равно могут ломаться так, что это выглядит загадочно для разработчика приложения: "bulk-чтение тайм-аутит, записи не завершаются, HID-репорты перестают приходить, хост сообщает о STALL конечной точки. Эти сбои часто списывают на драйвер или случайные зависания прошивки. Захват почти всегда сужает проблему гораздо быстрее."
Сбои конечных точек — это доказательства на data-пути. Они случаются после того, как хост узнал форму устройства. Значит, дескрипторы могут быть корректными, а поведение конечной точки всё равно сломанным.
STALL — это сигнал, а не просто ошибка
Конечная точка USB может вернуть STALL, чтобы показать, что не может выполнить запрос, или что классовая/вендорная команда не поддерживается. Stall управляющей конечной точки во время классовых запросов может быть корректным, если запрос недействителен. Stall конечной точки данных во время нормального потока обычно требует более внимательного изучения.
Вопросы к захвату:
- какая конечная точка встала в stall?
- это был control, bulk, interrupt или isochronous?
- какой запрос или передача предшествовали stall?
- сбросил ли хост halt-условие?
- возобновился ли трафик после
CLEAR_FEATURE(ENDPOINT_HALT)? - намеренно ли прошивка ставила stall на неподдерживаемых командах?
Без этого контекста «endpoint stalled» — слишком расплывчато для действий.
Bulk-тайм-аутам нужен контекст направления и очереди
Тайм-аут bulk-передачи может означать очень разные вещи:
- хост ждал IN-данных, а у устройства не было готовых данных
- устройство ждало OUT-данных, а приложение перестало писать
- буфер конечной точки в прошивке не был подготовлен
- драйвер хоста отправил чтение большего размера, чем поддерживает прошивка
- устройство NAK-нуло до тайм-аута
- адрес или направление конечной точки были неверными
- предыдущий stall так и не был сброшен
Первое, что стоит проверить — направление. Тайм-аут bulk IN и bulk OUT — разные случаи. Для IN спросите, возвращало ли устройство хоть какие-то данные. Для OUT спросите, слал ли хост данные и подтверждало ли их устройство.
Корректность дескрипторов необходима, но не достаточна
Дескриптор может корректно объявить bulk IN-конечную точку, а устройство всё равно не сможет послать полезные данные. CDC-устройство может перечислиться как serial-порт и всё равно игнорировать line coding или control line state. Вендорный интерфейс может выставить конечные точки, но требовать команду инициализации до начала обмена данными.
Значит, отладка конечной точки должна сочетать:
- данные дескрипторов
- классовые или вендорные запросы настройки
- направление передачи
- длину полезной нагрузки
- результат статуса
- тайминги и повторные попытки
В захвате должно быть видно, требует ли хост что-то невозможное или прошивка не выполняет корректный запрос.
Команды прошивки должны захватывать «до» и «после» фикса
Для багов в конечных точках ценны сравнительные захваты. Первый захват доказывает сбой. Второй захват доказывает фикс. Хорошее сравнение показывает:
- то же устройство и конфигурация
- те же адреса конечных точек
- тот же паттерн запросов хоста
- старый захват ставит stall или тайм-аутит
- новый захват завершает передачи и несёт ожидаемую полезную нагрузку
Это сильно упрощает регрессионный разбор прошивки. И это даёт команде поддержки повторяемый артефакт, когда клиенты жалуются «USB сам зависает».
Место Bus Scope
Bus Scope нацелен на USB-доказательства, а не на растекание по generic-протоколам. Для случаев STALL и тайм-аута на конечной точке он держит рядом детали пакета, метаданные конечной точки, сырые байты, тип передачи и классовую интерпретацию.
Полезный вывод:
- конечная точка и направление
- тип передачи
- запрос или передача перед сбоем
- статусные данные
- сырая полезная нагрузка вокруг сбоя
- привязка проблемы к перечислению, настройке класса или трафику приложения
Это то, что нужно инженерам прошивки до того, как трогать логику буферов конечной точки или retry-логику на хосте.
Если ваш поиск — «USB bulk transfer timeout» или «USB endpoint stalled», не начинайте с переписывания всего стека устройства. Сначала захватите доказательства по конечной точке.