Я пытаюсь разобраться с USB-модулем в STM32F103. На низком уровне, без библиотек.
Для начала настраиваю PLL с использованием внешнего кварца (бит RCC_CFGR_PLLSRC = 1) и с делением USB-частоты на 3 (бит RCC_CFGR_OTGFSPRE = 0), коэффициент умножения 9 (частота кварца 8 МГц, частота ядра 72 МГц). PLL точно успешно запускается, это видно по тому, что USART и SysTick работают адекватно.
Затем включаю тактирование USB, разрешаю прерывания USB_FS_WKUP_IRQ и CAN1_RX0_IRQ. Выполняю начальную инициализацию USB:
USB->CNTR = 0;
USB->ISTR = 0;
USB->BTABLE = 0;
USB->CNTR = USB_CNTR_RESETM | USB_CNTR_SUSPM | USB_CNTR_WKUPM | USB_CNTR_CTRM;
В обработчике прерывания (любого из двух) смотрим на USB->ISTR, чтобы понять что случилось. Сначала, разумеется, при подключении к компьютеру приходит RESET. Сбрасываем флаг прерывания и выполняем настройку 0-ой конечной точки, а также устанавливаем бит EF в USB->DADDR (теперь USB->ADDR = 0x80). В результате настройки конечной точки у нас в USB->EP0R оказывается 0x3220. По идее это значит, что EP0 готова работать, как на приём, так и на передачу, причём данных для передачи пока нет (NAK), а к приёму мы готовы (VALID).
Ну а ещё мы настроили дескриптор буфера (из-за BTABLE == 0, дескриптор нулевой точки находится в самом начале области буферов USB). Таким образом, USB_ADDR0_TX = 80, USB_COUNT0_TX = 0, USB_ADDR0_RX = 64, USB_COUNT0_RX = 0x2000. Что значит, что максимальный размер пакета для приёма 16 байт.
Готово. Выходим из обработчика прерывания.
Далее я ожидаю получить прерывание по состоянию CTR, что бы означало, что пришёл первый SETUP-пакет и с ним нужно что-то сделать. А получаю прерывание по состоянию WKUP и ESOF. И даже не одно, а очень много. Пока хосту не надоест ждать ответа и он не пошлёт новый RESET (предварительно плюнув в dmesg, что устройство отказывается принимать назначенный адрес функции), затем ситуация повторяется.
Что я забыл сделать?