Так проблема в каком-то запросе с хоста на МК. И смотреть на обмен можно хоть с одной стороны (лог с МК), хоть с другой (wireshark), хоть вообще из середины (логический анализатор). Пока соединение не установлено, со стороны ПК ничего не увидеть. А зачастую и со стороны МК ничего не увидеть, ведь модуль USB - черный ящик. Но вот когда пошел обмен, смотреть можно где угодно. И выбирать соответственно где удобнее.
Ну к аппаратной части USB в MCU вопросов как раз таки нет, ведь с Ubuntu все работает (данные отправляются и читаются программой-терминалом корректно). С виндой буду чуть позже отдельно разбираться, возможно (наверняка) упущение в логике стандартных ответов на стандартные запросы
На всё это устройство должно уметь отвечать. Хорошо ещё выводить что вы отвечаете на каждый запрос.
Большое спасибо за логи, прямо пошагово по ним прошелся, исправил ошибки, теперь девайс видится диспетчером вин10 без каких-либо ошибок, программа-терминал корректно обменивается данными с моим девайсом Остались, правда некоторые вопросы, но попробую сам решить их, если что, задам здесь.
А вот что хочу сейчас спросить: откуда вы взяли эти логи? Я читал юсб ин натшелл, а так же доку по сдс с юсб.орг, там секвенция запросов отличается, а один тип дескриптора и вовсе не описан. Даже не представляю, как я бы отладил код без этой информации
И самое интересное, что в Ubuntu всё работало и так, с кодом, написанным по мотивам юсб ин натшелл.
switch(uSetReq.wRequest) { case STD_REQUEST::GET_DESCRIPTOR: //Запрос дескриптора switch(uSetReq.descType) { case DescriptorType::DEVICE: //Запрос дескриптора устройства DEBUG_Print("GET_Device_Descriptor %d bytes\r\n",uSetReq.wLength); reply_len = sizeof(Device_Descriptor); pbuf = (uint8_t *)&Device_Descriptor; break; case DescriptorType::CONFIGURATION: //Запрос дескриптора конфигурации DEBUG_Print("GET_Configuration_Descriptor %d bytes\r\n",uSetReq.wLength); reply_len = sizeof(Configuration_Descriptor); pbuf = (uint8_t *)&Configuration_Descriptor; break; case DescriptorType::DEVICE_QUALIFIER: //Запрос дескриптора device_qualifier DEBUG_Print("GET_Device_Qualifier_Descriptor %d bytes\r\n",uSetReq.wLength); reply_len = sizeof(Device_Qualifier_Descriptor); pbuf = (uint8_t *)&Device_Qualifier_Descriptor; break; case DescriptorType::STRING: //Запрос строкового дескриптора for(auto& it : descr_table) // Проходимся по таблице адресов дескрипторов (оптимизатор развернёт цикл) if(*it == uSetReq.descIndex) // По полю bIndex смотрим на совпадение { pbuf = (uint8_t *)it+1; // Адрес для отправки указывает на поле bLength reply_len = *pbuf; // Длина для отправки берётся из поля bLength DEBUG_Print("GET_String_Descriptor 0x%X %d bytes\r\n", uSetReq.descIndex, uSetReq.wLength); break; } if(pbuf==NULL) DEBUG_Print("GET_String_Descriptor 0x%X not supported\r\n",uSetReq.descIndex); break; default: DEBUG_Print("GET_Descriptor 0x%X not supported\r\n",uSetReq.wValue); return; } break; case STD_REQUEST::SET_ADDRESS: // Установка адреса устройства DEBUG_Print("SET_ADDRESS %d\r\n", uSetReq.wValue); TPort::SetAdr(uSetReq.wValue); // reply_len = 0 -> ZLP break; case STD_REQUEST::SET_CONFIGURATION: // Установка конфигурации устройства DEBUG_Print("SET_CONFIGURATION %d\r\n", uSetReq.wValue); CurrentConfiguration = uSetReq.wValue; break; // reply_len=0 -> ZLP case STD_REQUEST::GET_CONFIGURATION: DEBUG_Print("GET_CONFIGURATION:\r\n"); reply_len = 1; pbuf = (uint8_t *)&CurrentConfiguration; break; case STD_REQUEST::GET_DEVICE_STATUS: [[fallthrough]]; case STD_REQUEST::GET_INTERFACE_STATUS: [[fallthrough]]; case STD_REQUEST::GET_ENDPOINT_STATUS: DEBUG_Print("GET_STATUS\r\n"); reply_len = sizeof(get_status_reply); pbuf = (uint8_t *)get_status_reply; break; case STD_REQUEST::CLEAR_DEVICE_FEATURE: [[fallthrough]]; case STD_REQUEST::CLEAR_INTERFACE_FEATURE: [[fallthrough]]; case STD_REQUEST::CLEAR_ENDPOINT_FEATURE: DEBUG_Print("CLEAR_FEATURE\r\n"); // для простоты просто ZLP break; case STD_REQUEST::SET_DEVICE_FEATURE: [[fallthrough]]; case STD_REQUEST::SET_INTERFACE_FEATURE: [[fallthrough]]; case STD_REQUEST::SET_ENDPOINT_FEATURE: DEBUG_Print("SET_FEATURE\r\n"); // для простоты просто ZLP break; case STD_REQUEST::SET_INTERFACE: DEBUG_Print("SET_INTERFACE\r\n"); // для простоты просто ZLP break; case STD_REQUEST::SET_DESCRIPTOR: DEBUG_Print("SET_DESCRIPTOR\r\n"); // надо бы STALL, но для простоты просто ZLP break; case STD_REQUEST::SYNCH_FRAME: DEBUG_Print("SYNCH_FRAME\r\n"); // для простых устройств забьём break; default: if(!ClassSpecificSetup((USB_SETUP_REQ *)&uSetReq, &reply_len, &pbuf)) return; break; } TPort::template WriteEP<0>(pbuf, std::min((uint16_t)reply_len, (uint16_t)uSetReq.wLength)); }
Про неописанные дескрипторы не верю. Стандарт все их описывает до последнего бита. Последовательность запросов может быть разная у разных хостов. Задача устройства все их корректно обрабатывать в любой последовательности.
К конденсаторам источников питания высокой мощности предъявляются высокие требования по качеству и надежности. Пленочные – единственный тип конденсаторов, который может справиться с такой задачей. Компания Hongfa предлагает продукцию, которая подходит для применения практически во всех функциональных узлах типовых AC/DC- или DC/AC-преобразователей. Рассмотрим характеристики и применения плёночных конденсаторов Hongfa для различных решений.
На всё это устройство должно уметь отвечать. Хорошо ещё выводить что вы отвечаете на каждый запрос.
У меня на вин10 получаются вот такие логи, никак не могу понять, в чем может быть причина СпойлерInt_USBRST Int_SUSPEND Int_WKUP Int_USBRST GET_Device_Descriptor 64 bytes Int_USBRST SET_ADDRESS 24 GET_Device_Descriptor 18 bytes GET_Configuration_Descriptor 255 bytes GET_String_Descriptor 0x3 255 bytes GET_String_Descriptor 0x0 255 bytes GET_String_Descriptor 0x2 255 bytes GET_Device_Qualifier_Descriptor 10 bytes GET_Device_Descriptor 18 bytes
вот эти не заправшивает GET_String_Descriptor 0x0 255 bytes GET_String_Descriptor 0x3 255 bytes GET_String_Descriptor 0x1 255 bytes GET_String_Descriptor 0x2 255 bytes GET_Device_Descriptor 18 bytes
далее идут эти GET_Configuration_Descriptor 9 bytes GET_Configuration_Descriptor 67 bytes GET_Configuration_Descriptor 265 bytes SET_CONFIGURATION 1 GET_LINE_CODING SET_CONTROL_LINE_STATE 0
этого нет SET_LINE_CODING
идет сразу этот, с данными сразу на 256к битрейта SET_LINE_CODING DATA 256000 0 0 8 GET_LINE_CODING GET_String_Descriptor 0x0 255 bytes GET_String_Descriptor 0x1 255 bytes GET_String_Descriptor 0x2 255 bytes
а вот эти уже не запрашивается SET_CONTROL_LINE_STATE 0 GET_LINE_CODING SET_CONTROL_LINE_STATE 0 GET_LINE_CODING SET_LINE_CODING SET_LINE_CODING DATA 256000 0 0 8 GET_LINE_CODING SET_CONTROL_LINE_STATE 0
Вслед за сериями на DIN-рейку DDRH-60/120/240 и на шасси RSDH-150/300 компания MEAN WELL выпустила новые маломощные DC/DC-преобразователи DDRH-15/30/45 со сверхшироким входным напряжением 150…1500 В, и монтажом не только на DIN-рейку, но и печатную плату или винтовым соединением. Все преобразователи семейства DDRH и RSDH работают при температурах -40…80°C и обладают высокой изоляцией 4000 В AC между входом и выходом, что обеспечивает надежную защиту. Они подходят для использования на высоте до 5000 м и сертифицированы по стандарту IEC62109-1 для фотоэлектрических систем. Преобразователи DDRH/RSDH есть в наличии и под заказ.
У меня на вин10 получаются вот такие логи, никак не могу понять, в чем может быть причина
Какой режим: USB-LS, USB-FS, USB-HS? Вангую, что в вашем дескрипторе устройства неверно указан размер control-ep0. На что намекают неверные размеры запросов стандартных дескрипторов. Для USB-FS/USB-HS должен быть == 64 байта.
здравствуйте, может кто подскажет, почему не отправить по USB от stm32f407 больше 16 байт? Принимаю setup пакет(8байт 01000680 00400000), посылаю 8 или 16 байт одним пакетом, принимаю пакет setup phase done, потом пустой DataOUT пакет зачем-то приходит и завершение дата фазы. Получаю прерывания transfer complete на INEP0 и OUTEP0. Все вроде как надо, но не могу отправить 32/64 байта одним пакетом, отправляется 16, остальное остается в txFIFO.
Что-то не так с регистром DCFG на stm32f407, при записи в него происходит ремаппинг битов, например чтобы установить бит 7 нужно установить бит 3. Некоторые биты остаются на месте. Это уже совсем какой-то дом ку-ку
Добавлено after 9 hours 32 minutes 50 seconds: Ошибка при чтение значений регистра OTG_FS_DCFG Когда приложение выполняет запись в битовые поля DAD и PFIVL в регистре OTG_FS_DCFG, а затем считывает вновь записанные значения битовых полей, считанные значения могут быть неверными.Однако значения, записанные приложением, корректно сохраняются ядром, и это не влияет на нормальную работу устройства. Обходной путь: Не считывайте данные из битовых полей DAD и PFIVL регистра OTG_FS_DCFG сразу после их программирования. https://www.manualslib.com/manual/12705 ... ml?page=18
Добавлено after 18 minutes 8 seconds: И... добавлю : при первом запросе дескриптора нужно отправить так называемый Malformed packet перве 8 байт(два слова) дескриптора устройства, просто чтобы хосту узнать максимальный размер пакета. Если отправить больше то четвертое или пятое слово окажется в статусе конечной точки OUT, то есть прилетит обратно в rxFIFO. Потом хост (в моем случае wiindows10) шлет set_address, с этим я еще не разобрался, но на следующий такой-же запрос дескриптора (01000680) уже можно отправить 32 байта и обратно ничего лишнего не прилетает.
И... добавлю : при первом запросе дескриптора нужно отправить так называемый Malformed packet перве 8 байт
Всегда надо отправлять ровно столько, сколько запрашивают. У вас же есть поле wLength, предназначенное ровно для этого.
danone78 писал(а):
Потом хост (в моем случае wiindows10) шлет set_address, с этим я еще не разобрался, но на следующий такой-же запрос дескриптора (01000680) уже можно отправить 32 байта и обратно ничего лишнего не прилетает.
Это процесс энумерации. Изначально устройству не назначен адрес, и оно отзывается на все пакеты с адресом 0. Запрос set_address как раз и говорит "теперь у тебя адрес такой-то". На него надо сначала ответить как "безымянное" устройство (пакетом нулевой длины), и только потом, когда хост прочитает ответ, действительно менять адрес.
в смысле сразу? просто назначить себе его как ip-адрес в надежде что не будет конфликта? я пробовал назначить сразу, все то же как и с нулевым адресом, странно все это. Есть мысль выцепить дебагом кусочек кода из встроенного бутлодера, чем черт не шутит, просто глянуть может там логика какая есть.
И... добавлю : при первом запросе дескриптора нужно отправить так называемый Malformed packet перве 8 байт
Всегда надо отправлять ровно столько, сколько запрашивают. У вас же есть поле wLength, предназначенное ровно для этого.
danone78 писал(а):
Потом хост (в моем случае wiindows10) шлет set_address, с этим я еще не разобрался, но на следующий такой-же запрос дескриптора (01000680) уже можно отправить 32 байта и обратно ничего лишнего не прилетает.
Это процесс энумерации. Изначально устройству не назначен адрес, и оно отзывается на все пакеты с адресом 0. Запрос set_address как раз и говорит "теперь у тебя адрес такой-то". На него надо сначала ответить как "безымянное" устройство (пакетом нулевой длины), и только потом, когда хост прочитает ответ, действительно менять адрес.
ага! а я сразу пытаюсь ответить с новым адресом, спасибки..
Добавлено after 1 hour 27 minutes 33 seconds: Спасибо еще раз за наводку, получил запрос на второй дескриптор, запрашивая длина почему-то 0xFF.
ага! а я сразу пытаюсь ответить с новым адресом, спасибки.. Спасибо еще раз за наводку, получил запрос на второй дескриптор, запрашивая длина почему-то 0xFF.
Так в wireshark смотрите какие запросы приходят и корректно ли они обрабатываются. Длина 0xFF это странно. Может, вы не то поле анализируете, или выравнивание у структуры неправильное, или еще какая ошибка. Ну как минимум, wLength длиной 2 байта, а не 1.
да тип конечной точки ставлю intreupt, но есть же конечные точки IN и OUT. Я полностью копирую свою мышку, винда ее видит в диспетчере устройств, wireshark-ом все сходится, по логике должен придти пустой пакет на EP1, а я должен отправить 4 байта инфы, но приходит самый первый запрос дескриптора 0x01000680 00400000 на нулевую точку. Может на нулевой OUT точке NAK поставить чтобы как-то отфильтровать пакеты для EP0?
Добавлено after 5 minutes 15 seconds: а какой Endpoint Data PID ставить? это зависит от четности номера фрейма?
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 11
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения