‮Сдвиг по фазе (kincajou) wrote,
‮Сдвиг по фазе
kincajou

Category:

worklog: USB - бессилие, ярость, отупение, триумф.

Я докопался до того, что передача данных (т.е. запрошенного дескриптора) в самом деле идёт и завершается успешно. После этого хост ещё раз сбрасывает шину и... всё. Таймаут, снова запрос того же дескриптора - в общем зачёте четыре раза так, затем шина отключается совсем.

И до настоящего триумфа ещё, конечно, далеко, но я наконец-то понял, почему прекращается обмен.

Это же элементарно.

Хотя нет, нихера не элементарно. Это ещё догадаться (или заметить, что это не очень внятно описано в RM) надо, что каждая конечная точка после завершения каждой транзакции автоматически сама себя отключает до следующего раза. И все запросы к ней, пока она отключена, отфуболиваются с квитком NAK. Чтобы получить следующую порцию вкусных данных, конечную точку надо снова принудительно включить тогда, когда мы к этому готовы.

И вот, после нескольких дней блужданий впотьмах, я нашёл -- обработка прерывания GINTSTS.IEPINT (точнее, DIEPINT.XFRC): этот флаг выскакивает, когда передача запрошенных данных (дескриптора, в рассматриваемом случае) завершена. Мы тут отключаем бит маски прерываний TxFIFO (DIEPEMPMSK), вызываем коллбэк (который будет, наверное, делать что-то чрезвычайно полезное) и... именно тут надо было бы включать конечную точку снова. Но это не было сделано и вообще есть некая путаница - для модуля USB в STM32F7 конечные точки IN и OUT, даже если они с одним и тем же номером, это разные сущности. Поэтому в обработчике события от IN0 нужно включать точку OUT0, чтобы контрольные запросы продолжали бы приниматься.

И вот, наконец, пришёл следующий setup:
bmRequestType: 00, bRequest: 05
wValue: 0006, wIndex: 0000, wLength: 0


А это самый настоящий SET_ADDRESS. Хост говорит мне, что нужно поставить адрес 6, по которому со мной и будут разговаривать после подтверждения операции.

Не совсем гора, но маленький такой камешек с плеч упал-таки.

И вот новая куча непонятных вещей: теперь процесс идёт чуточку дальше. Я сделал обработку установки адреса, причём он устанавливается сразу как только пришёл этот запрос, хотя вот тут написано, что адрес следует устанавливать после завершения фазы статуса (т.е. после отсылки IN нулевой длины. Во всяком случае, в HAL сделано именно так, если расплести их функции, вложенные во функции, вложенные во вложенные функции. И теперь я получаю нечто, что не совсем согласуется с моим пониманием стандарта USB в части описания Full-speed устройств: после SET_ADDRESS приходит запрос GET_DESCRIPTOR с wValue=0x0100 (т.е. запрошен дескриптор "DEVICE") и wLength 18 (как и должно быть), а вслед за ним тут же ещё два GET_DESCRIPTOR, у обоих wValue=0x0200 ("CONFIGURATION"), но wLength сначала 255, а затем (без паузы) вообще 512! Но этого ведь не может быть, потому что размер дескрипторов конфигурации всего 9 байт... я снова ничего не понимаю.

Upd Добавил дескриптор конфигурации, который задаёт.. ничего. Он описывает сам себя, больше ничего в нём нет. Высылаю его в ответ на тот запрос - и получаю следующий запрос, уже такой:
bmRequestType: 80, bRequest: 06
wValue: 03EE, wIndex: 0000, wLength: 18

Это запрос STRING-дескриптора.. но индекс дескриптора почему-то 0xEE (?!) и длина 18 байт, чем подозрительно совпадает с Device Descriptor. Видимо, подразумевается какой-то стандартный ответ
. Это был единичный случай, больше таких запросов я пока ещё не получил. Подозрительно.

Но всё равно - чудо! устройство больше не "сбойное", оно теперь просто "неизвестное" - система прочухала VID/PID/REV и показывает его в менеджере устройств именно с этими параметрами. Надежда снова воссияла!
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 33 comments