STM32 и USB (практика)
- Z_h_e
- Собутыльник Кота
- Сообщения: 2708
- Зарегистрирован: Сб май 14, 2011 21:16:04
- Откуда: г. Чайковский
Re: STM32 и USB (практика)
Kellya, Вам пришли данные для для 1ой точки типа OUT и Вы их дешифровали как запрос дескриптора или для конечно точки 1 типа IN приходят фреймы с запросом данных?
Что-то я боюсь вопрос не совсем корректно сформулировал.
Что-то я боюсь вопрос не совсем корректно сформулировал.
- Реклама
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: STM32 и USB (практика)
Все дескрипторы через 0-ю точку отправляются. Тут очень важно правильно HIDReportDescriptor составить. Без этого ничего работать дальше не будет.
Весь обмен HID состоит из SetReport и GetReport. Первый передаёт данные от хоста к устройству и может приходить как в 0-ю точку, так и в 1-ю. Второй только через 1-ю interrupt точку работает. Отправлять репорты устройство может когда захочет. Обычно это происходит, если изменяется состояние устройства. Естественно, чаще чем хост опрашивает отправлять смысла не имеет.
Сама отправка репортов ни чем не отличается от отправки дескрипторов при энумерации, только производится в 1-ю точку. Для этого должна быть правильно заполнена таблица описания буферов приёма/передачи и писать правильно в буфер.
Одно из "заподлянских" мест в USB от STM (тот что не OTG) это правильно выставлять статусы с регистре конфигурации точки. Там непривычные для новичков toggle-биты есть.
Добавлено after 16 minutes 21 second:
Ещё насчёт дескрипторов. Я на прошлой странице выкладывал дескрипторы, которые правильно работают с STM-овской утилитой для тестирования HID. Там установка и считывание светодиодов реализовано. Для отладки за глаза.
Весь обмен HID состоит из SetReport и GetReport. Первый передаёт данные от хоста к устройству и может приходить как в 0-ю точку, так и в 1-ю. Второй только через 1-ю interrupt точку работает. Отправлять репорты устройство может когда захочет. Обычно это происходит, если изменяется состояние устройства. Естественно, чаще чем хост опрашивает отправлять смысла не имеет.
Сама отправка репортов ни чем не отличается от отправки дескрипторов при энумерации, только производится в 1-ю точку. Для этого должна быть правильно заполнена таблица описания буферов приёма/передачи и писать правильно в буфер.
Одно из "заподлянских" мест в USB от STM (тот что не OTG) это правильно выставлять статусы с регистре конфигурации точки. Там непривычные для новичков toggle-биты есть.
Добавлено after 16 minutes 21 second:
Ещё насчёт дескрипторов. Я на прошлой странице выкладывал дескрипторы, которые правильно работают с STM-овской утилитой для тестирования HID. Там установка и считывание светодиодов реализовано. Для отладки за глаза.
Re: STM32 и USB (практика)
"Kellya, Вам пришли данные для для 1ой точки типа OUT и Вы их дешифровали как запрос дескриптора"
Сначала эти данные пришли для 0ой точки, я их дешифровал как запрос дескриптора, обработал и отправил. Потом проделал тоже самое для остальных дескрипторов (конфигурации, интерфейса, строк, отчета и к.т.1). Все это через нулевую точку. На этом этапе у меня проблем не возникает. Устройство определилось в системе.
После всего этого, как только я передал дескриптор репорта мне начинают сыпаться фреймы с запросом данных для конечно точки 1 типа IN, на которые у меня не получается ответить, после парты попыток от хоста получить ответ, он начинает сыпать различными запросами на ресет пайпов (это успешно выполняется контроллером самостоятельно), а потом снова начинает сыпать запросы данных для конечно точки 1 типа IN
Добавлено after 5 minutes 40 seconds:
"Все дескрипторы через 0-ю точку отправляются. Тут очень важно правильно HIDReportDescriptor составить. Без этого ничего работать дальше не будет."
Все верно, хост съедает все дескрипторы, которые я ему шлю.
"Весь обмен HID состоит из SetReport и GetReport".
Когда хост хочет получить репорт он отправляет GetReport? Хм, у меня такого вроде бы нет. Я думал, что он отправляет URB_INTERRUPT in, когда хочет получить данные из точки
Сначала эти данные пришли для 0ой точки, я их дешифровал как запрос дескриптора, обработал и отправил. Потом проделал тоже самое для остальных дескрипторов (конфигурации, интерфейса, строк, отчета и к.т.1). Все это через нулевую точку. На этом этапе у меня проблем не возникает. Устройство определилось в системе.
После всего этого, как только я передал дескриптор репорта мне начинают сыпаться фреймы с запросом данных для конечно точки 1 типа IN, на которые у меня не получается ответить, после парты попыток от хоста получить ответ, он начинает сыпать различными запросами на ресет пайпов (это успешно выполняется контроллером самостоятельно), а потом снова начинает сыпать запросы данных для конечно точки 1 типа IN
Добавлено after 5 minutes 40 seconds:
"Все дескрипторы через 0-ю точку отправляются. Тут очень важно правильно HIDReportDescriptor составить. Без этого ничего работать дальше не будет."
Все верно, хост съедает все дескрипторы, которые я ему шлю.
"Весь обмен HID состоит из SetReport и GetReport".
Когда хост хочет получить репорт он отправляет GetReport? Хм, у меня такого вроде бы нет. Я думал, что он отправляет URB_INTERRUPT in, когда хочет получить данные из точки
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: STM32 и USB (практика)
[uquote="Kellya",url="/forum/viewtopic.php?p=3898704#p3898704"]Когда хост хочет получить репорт он отправляет GetReport? Хм, у меня такого вроде бы нет.[/uquote]Нет, это я так вольно процесс передачи данных описал. Что репорты туда-сюда бегают. Реально такого запроса конечно же нет.
[uquote="Kellya",url="/forum/viewtopic.php?p=3898704#p3898704"]Я думал, что он отправляет URB_INTERRUPT in, когда хочет получить данные из точки[/uquote]Всё верно. Только не когда хочет получить данные, а когда придёт время опроса. И если вы к этому моменту положили данные, то они их сам заберёт. Устройству не надо реагировать на эти запросы, как вы не поймёте. Просто положите репорт в ep-1 и хост сам их заберёт.
Добавлено after 14 minutes 6 seconds:
Если дескрипторы составлены правильно, то там реально всё примитивно.
Вот кусочек реализации HID. Тут ClassSpecificSetup это Setup-запросы в EP0, характерные только для HID. И обработка SetReport через EP0 и EP1.
А вот кусочек отправки репорта, я его уже приводил.
Это весь код HID, не считая дескрипторов (их я тоже чуть выше выкладывал), где тут можно запутаться?
[uquote="Kellya",url="/forum/viewtopic.php?p=3898704#p3898704"]Я думал, что он отправляет URB_INTERRUPT in, когда хочет получить данные из точки[/uquote]Всё верно. Только не когда хочет получить данные, а когда придёт время опроса. И если вы к этому моменту положили данные, то они их сам заберёт. Устройству не надо реагировать на эти запросы, как вы не поймёте. Просто положите репорт в ep-1 и хост сам их заберёт.
Добавлено after 14 minutes 6 seconds:
Если дескрипторы составлены правильно, то там реально всё примитивно.
Вот кусочек реализации HID. Тут ClassSpecificSetup это Setup-запросы в EP0, характерные только для HID. И обработка SetReport через EP0 и EP1.
Спойлер
Код: Выделить всё
class USB_HID : public USB_DEVICE
{
public:
USB_HID(){}
void Enumerate_Reset()
{
EPInit<1,EP_TYPE::Interrupt>();
}
inline void EP0_RX() { SetReport(0); }
inline void EP1_RX() { SetReport(1); }
inline void EP1_TX() {}
virtual bool ClassSpecificSetup(USB_SETUP_REQ *uSetReq, uint8_t *len, uint8_t **pbuf)
{
switch(HID_REQUEST(uSetReq->wRequest))
{
case HID_REQUEST::GET_DESCRIPTOR:
switch(DescriptorType(uSetReq->descType))
{
case DescriptorType::HID:
DEBUG_Print("HID_GET_Descriptor HID %d \r\n",uSetReq->wLength);
*len = sizeof(USB_CUSTOM_HID_DESCRIPTOR);
*pbuf = (uint8_t *)&ConfigDescriptor.HID_Descriptor;
break;
case DescriptorType::REPORT:
DEBUG_Print("HID_GET_Descriptor REPORT %d\r\n",uSetReq->wLength);
*len = sizeof(ReportDescriptor);
*pbuf = (uint8_t *)ReportDescriptor;
break;
default:
DEBUG_Print("HID_GET_Descriptor 0x%X not supported\r\n",uSetReq->wValue);
return false;
}
break;
case HID_REQUEST::SET_REPORT:
DEBUG_Print("HID_SET_REPORT %d\r\n",uSetReq->wLength);
break;
case HID_REQUEST::SET_IDLE:
DEBUG_Print("HID_Set_Idle 0x%X\r\n",uSetReq->wValue);
break;
default:
DEBUG_Print("HID_Request 0x%X\r\n not supported",uSetReq->wRequest);
return false;
}
return true;
}
private:
void SetReport(uint32_t ep)
{
DEBUG_Print("EP%d DATA:",ep);
for(uint32_t i=0; i<rx_len; i++) DEBUG_Print(" 0x%X",rx_buf[i]);
DEBUG_Print("\r\n");
switch(rx_buf[0])
{
case 1: // Report 1
if(rx_buf[1]) LED1::On(); else LED1::Off();
break;
case 2: // Report 2
if(rx_buf[1]) LED2::On(); else LED2::Off();
break;
case 3: // Report 3
if(rx_buf[1]) LED3::On(); else LED3::Off();
break;
case 4: // Report 4
if(rx_buf[1]) LED4::On(); else LED4::Off();
break;
}
}
};
Спойлер
Код: Выделить всё
uint8_t report[2]={5,0}; // Report ID 5
for(;;)
{
if(key.pressed())
{
report[1]=!report[1];
if(report[1]) LED0::On(); else LED0::Off();
usb.WriteEP<1>(report,sizeof(report));
}
};
- Eddy_Em
- Собутыльник Кота
- Сообщения: 2516
- Зарегистрирован: Пт июл 12, 2019 22:52:01
- Контактная информация:
Re: STM32 и USB (практика)
[uquote="VladislavS",url="/forum/viewtopic.php?p=3898689#p3898689"]Весь обмен HID состоит из SetReport и GetReport. Первый передаёт данные от хоста к устройству и может приходить как в 0-ю точку, так и в 1-ю. Второй только через 1-ю interrupt точку работает. Отправлять репорты устройство может когда захочет. Обычно это происходит, если изменяется состояние устройства. Естественно, чаще чем хост опрашивает отправлять смысла не имеет.[/uquote]
Что у вас за HID такой, который с interrupt работает? Я сколько ни ловил их - пусто... И wireshark не показывал, чтобы что-то в них происходило.
Единственное, когда в interrupt были какие-то данные - когда я подумывал ch340 сэмулировать. Но там оказалось, что по сути вообще никакой не CDC, даже обмен данными не так происходит, как у CDC. Поэтому забил (плюс к тому же, в ядре поддержка ch340 сделана реверсом и очень многие вещи не учитываются, ХЗ, как оно себя поведет в той же мастдайке).
Что у вас за HID такой, который с interrupt работает? Я сколько ни ловил их - пусто... И wireshark не показывал, чтобы что-то в них происходило.
Единственное, когда в interrupt были какие-то данные - когда я подумывал ch340 сэмулировать. Но там оказалось, что по сути вообще никакой не CDC, даже обмен данными не так происходит, как у CDC. Поэтому забил (плюс к тому же, в ядре поддержка ch340 сделана реверсом и очень многие вещи не учитываются, ХЗ, как оно себя поведет в той же мастдайке).
- Реклама
Re: STM32 и USB (практика)
SetReport и GetReport нормально работают через 0-ю.VladislavS писал(а):Весь обмен HID состоит из SetReport и GetReport. Первый передаёт данные от хоста к устройству и может приходить как в 0-ю точку, так и в 1-ю. Второй только через 1-ю interrupt точку работает.
Не совсем так. Инициатором обмена всегда выступает хост, а значит отправлять можно только если в конечной точке нет данных которые еще не запросил хост. То есть перед копированием в USB буфер нужно проверить состояние точки.VladislavS писал(а):Отправлять репорты устройство может когда захочет.
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: STM32 и USB (практика)
Eddy_Em, иди читай спецификацию HID, потом обсудим, если останутся вопросы.
Для ленивых.
Добавлено after 15 minutes 55 seconds:
[uquote="Мурик",url="/forum/viewtopic.php?p=3898872#p3898872"]SetReport и GetReport нормально работают через 0-ю.[/uquote]Ну это же легко проверятеся. Вот приведённый выше код меняет состояние отображения кнопки
А если отправлять через 0-ю точку
То уже ничего не приходит.
Добавлено after 17 minutes 17 seconds:
Я тут сам ещё раз спецификацию почитал. Пожалуй, через нулевую точку тоже будет работать. Надо просто Get_Report с хоста слать и на него отвечать. STM-овская USB HID Demonstrator просто так не умеет. Но в код обработку GET_REPORT, конечно, обязательно добавить.
Для ленивых.
Спойлер
[uquote="Мурик",url="/forum/viewtopic.php?p=3898872#p3898872"]SetReport и GetReport нормально работают через 0-ю.[/uquote]Ну это же легко проверятеся. Вот приведённый выше код меняет состояние отображения кнопки
Спойлер
Код: Выделить всё
usb.WriteEP<0>(report,sizeof(report));Добавлено after 17 minutes 17 seconds:
Я тут сам ещё раз спецификацию почитал. Пожалуй, через нулевую точку тоже будет работать. Надо просто Get_Report с хоста слать и на него отвечать. STM-овская USB HID Demonstrator просто так не умеет. Но в код обработку GET_REPORT, конечно, обязательно добавить.
Re: STM32 и USB (практика)
В общем удалось собрать рабочий проект для мышки в CubeMX, значит железо работает нормально. Но с их дескрипторами свой код мне все равно так и не удалось запустить. Видимо неправильно пытаюсь инициализировать первую точку. Можно ли как-то вообще её не инициализировать, и, например, чтобы она на каждый опрос от хоста просто отвечала STALLом? Или для обмена пакетами в любом случае необходимо инициализировать буферы приема/передачи?
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: STM32 и USB (практика)
Естественно, всё надо инициализировать правильно в соответствии с реализуемым классом и его дескрипторами.
Re: STM32 и USB (практика)
В общем ошибка была только в том, что я не указал для первой точки её адрес
. Для нулевой точки там все автоматически стояло, поэтому этот момент как-то вылетел из головы. Всем большое спасибо за помощь
Re: STM32 и USB (практика)
Столкнулся с ещё одной проблемой. После того как отправляю репорт, который описывает нажатие клавиши на клавиатуре, почему-то эта клавиша печатается не один раз, а много (не ждал пока остановятся), будто клавишу зажали и держат. Причем, как вызов функции отправки, так и прерывание о корректной передаче происходят только один раз. Wireshark тоже фиксирует только один ответ от устройства. Но клавиша почему-то остается нажатой. Не встречалась ни у кого такая проблема? Репорт состоит из 8 байт - [bModifier, bReserved, bKey1, bKey2, bKey3, bKey4, bKey5, bKey6]
Re: STM32 и USB (практика)
А вы проинформировали хост что она была отпущена? Нужно отправить пакет не содержащий код этой клавиши, иначе она считается нажатой.Kellya писал(а):Но клавиша почему-то остается нажатой.
Re: STM32 и USB (практика)
[uquote="Мурик",url="/forum/viewtopic.php?p=3922154#p3922154"]
Точно. Спасибо. Теперь вспомнил, что когда-то попадалось на глаза такое.
А вы проинформировали хост что она была отпущена? Нужно отправить пакет не содержащий код этой клавиши, иначе она считается нажатой.[/uquote]Kellya писал(а):Но клавиша почему-то остается нажатой.
Точно. Спасибо. Теперь вспомнил, что когда-то попадалось на глаза такое.
Re: STM32 и USB (практика)
Всех приветствую, надеюсь, ветка еще жива. Разбираюсь в USB на Stm32, пытаюсь приладить шаблоны C++ к USB (кому интересно, ВОТ пост про это). Без особых проблем (пятикратного перечитывания этой ветки, в общем-то, почти хватило. Отдельная благодарность @Z_h_e за предоставленные исходники) добился определения устройства в ОС. Далее перешел к реализации HID, девайс тоже определяется (хотя через раз, иногда ошибка "Код 10 Запуск этого устройства невозможен". Грешу или на питание, нет под рукой большого конденсатора, или частота гуляет).
Собственно, моя проблема в следующем: данные на конечную точку 1 (она типа Interrupt) прилетают (содержимое памяти правильное + бит CTR_RX взведен), но биты EP_ID в регистра ISTR всегда 0, соответственно, управление не заходит в обработчик прерывания конечной точки 1. Из RM я понял, что EP_ID заполняется номером конечной точки с наибольшим приоритетом, однако вроде как компьютер не должен настолько плотно обмениваться управляющими пакетами.
Мое предположение такое: я не сбрасываю бит CTR в регистре ISTR (как его сбросить, так и не понял, в некоторых МК он помечен read-only, в некторых - clear-only) и из-за этого постоянно срабатывает прерывание на 0 конечную точку.
Очень надеюсь на помощь, потому что уже не знаю, что делать.
Собственно, моя проблема в следующем: данные на конечную точку 1 (она типа Interrupt) прилетают (содержимое памяти правильное + бит CTR_RX взведен), но биты EP_ID в регистра ISTR всегда 0, соответственно, управление не заходит в обработчик прерывания конечной точки 1. Из RM я понял, что EP_ID заполняется номером конечной точки с наибольшим приоритетом, однако вроде как компьютер не должен настолько плотно обмениваться управляющими пакетами.
Мое предположение такое: я не сбрасываю бит CTR в регистре ISTR (как его сбросить, так и не понял, в некоторых МК он помечен read-only, в некторых - clear-only) и из-за этого постоянно срабатывает прерывание на 0 конечную точку.
Очень надеюсь на помощь, потому что уже не знаю, что делать.
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: STM32 и USB (практика)
[uquote="azhel12",url="/forum/viewtopic.php?p=4003881#p4003881"]Мое предположение такое: я не сбрасываю бит CTR в регистре ISTR (как его сбросить, так и не понял, в некоторых МК он помечен read-only, в некторых - clear-only) и из-за этого постоянно срабатывает прерывание на 0 конечную точку.[/uquote]Не надо его сбрасывать, он RO. Все делается в EPnR. Сбрасываются флаги CTR_RX и CTR_TX, устанавливаются статусы TX_STAT и RX_STAT. Большинство проблем с конечными точками - неправильная работа с EPnR, проверяйте.
Re: STM32 и USB (практика)
[uquote="VladislavS",url="/forum/viewtopic.php?p=4003961#p4003961"][uquote="azhel12",url="/forum/viewtopic.php?p=4003881#p4003881"]Мое предположение такое: я не сбрасываю бит CTR в регистре ISTR (как его сбросить, так и не понял, в некоторых МК он помечен read-only, в некторых - clear-only) и из-за этого постоянно срабатывает прерывание на 0 конечную точку.[/uquote]Не надо его сбрасывать, он RO. Все делается в EPnR. Сбрасываются флаги CTR_RX и CTR_TX, устанавливаются статусы TX_STAT и RX_STAT. Большинство проблем с конечными точками - неправильная работа с EPnR, проверяйте.[/uquote]
Спасибо за быстрый ответ, вечером перепроверю сброс CTR_RX/TX в EP0 и отпишу. Буду надеяться, что я действительно просто забыл это сделать и поэтому словил такую ситуацию.
Спасибо за быстрый ответ, вечером перепроверю сброс CTR_RX/TX в EP0 и отпишу. Буду надеяться, что я действительно просто забыл это сделать и поэтому словил такую ситуацию.
- COKPOWEHEU
- Говорящий с текстолитом
- Сообщения: 1525
- Зарегистрирован: Чт июн 10, 2010 20:11:19
Re: STM32 и USB (практика)
Можете сравнить с моим вариантом (HID клава + мышь) https://github.com/COKPOWEHEU/usb/tree/main/3.HID_L1 Вроде работает и не отваливается. Но у меня тактирование от кварца и с конденсаторами.
Вы, наверное, видели мою статью по ядру библиотеки https://habr.com/ru/post/548150/
Вы, наверное, видели мою статью по ядру библиотеки https://habr.com/ru/post/548150/
Для передачи пакета его надо записать в буфер endpoint'а, потом выставить в EPnR биты USB_EPTX_DTOG1 и USB_EPTX_DTOG2 в значение USB_EP_TX_VALID. И наконец сбросить флаг прерывания USB_EP_CTR_TX в том же EPnR. Осторожно, биты в EPnR наркоманские, их надо очень осторожно менять чтобы не задеть остальные.данные на конечную точку 1 (она типа Interrupt) прилетают (содержимое памяти правильное + бит CTR_RX взведен)
Проверьте размер репорта, он должен быть ровно такой, как указан в HID-дескрипторе. На 1 байт ошибетесь и винда вас пошлет далеко и надолго. (Линуксу, естественно, пофиг - они и не с таким работать умеет).девайс тоже определяется (хотя через раз, иногда ошибка "Код 10 Запуск этого устройства невозможен"
А Wireshark что говорит? Отправляет ли хост вообще interrupt запросы или нет?данные на конечную точку 1 (она типа Interrupt) прилетают
Re: STM32 и USB (практика)
Нет, честно говоря, на неделе некогда было заходить, но пробежался глазами сейчас, интересно. Очень рад, что появляются материалы по работе с USB (да и не только) на регистрах. Пытался обратиться за помощью "оффлайн" к коллегам, которые связаны с железом, в т.ч. микроконтроллерами, они отвечают "Мне хватает куба, ничем помочь не могу".Вы, наверное, видели мою статью по ядру библиотеки https://habr.com/ru/post/548150/
Тут не понял, USB_EP_TX_VALID - это же другое поле, а именно STAT_TX(STAT_RX)? с DTOG так и не разобрался, он, как я понял, работает в случае Bulk с двойной буферизацией. Или я что-то не понимаю?Для передачи пакета его надо записать в буфер endpoint'а, потом выставить в EPnR биты USB_EPTX_DTOG1 и USB_EPTX_DTOG2 в значение USB_EP_TX_VALID
А USB_EP_TX(RX)_VALID я записываю, собственно, нумерацию девайс проходит нормально (если бы накосячил, наверно, данные бы не улетали).
Спасибо за подсказку, проверю. Однако странно, в 3 случаях из 5 все-таки нормально определяется. Более склоняюсь к частотам, потому что сначала все эксперименты ставил на Disco-F072RB, там на самом МК вообще кварца нет, и было большой удачей "поймать" нумерацию. Сейчас перешел на BluePill, уже гораздо лучше.Проверьте размер репорта, он должен быть ровно такой, как указан в HID-дескрипторе.
Wireshark-ом так и не смог начать пользоваться, не могу нормально фильтры выставить. Но пока мне даже это рано, потому что у меня только OUT конечная точка в HID, соответственно, когда пытаюсь через HID-Demonstrator отправить команду через REPORT, то она 100% доходит, потому что у конечной точки взводится CTR_RX, в буфере тоже данные лежат. Проблема лишь в том, что в прилетающем прерывании всегда конечная точка 0, хотя я ожидаю, что будет 1, и в обработчике я обработаю.А Wireshark что говорит? Отправляет ли хост вообще interrupt запросы или нет?
- COKPOWEHEU
- Говорящий с текстолитом
- Сообщения: 1525
- Зарегистрирован: Чт июн 10, 2010 20:11:19
Re: STM32 и USB (практика)
Возможно, перепутал. Смотрел бегло по заголовочнику. Скорее всего, вы правы.Тут не понял, USB_EP_TX_VALID - это же другое поле, а именно STAT_TX(STAT_RX)?
Насколько я понимаю, поле DTOG это переключение между DATA0 / DATA1 / DATA2 / MDATA, то есть скорее для каких-то внутренних целей. Хотя с ST станется...
Я бы предложил моей библиотекой и воспользоватьсяОчень рад, что появляются материалы по работе с USB (да и не только) на регистрах.
Я им начал пользоваться когда одну endpoint0 мучил чтобы хоть энумерацию пройти.Wireshark-ом так и не смог начать пользоваться, не могу нормально фильтры выставить. Но пока мне даже это рано
Запускаете, выбираете захват usbmon0 (или какой там у вас) и запрещаете все лишнее по адресам на шине. Удобно для этого lsusb использовать, но можно и самые надоедливые адреса из самого wireshark'а прибить:
Код: Выделить всё
$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 051: ID 0458:003a KYE Systems Corp. (Mouse Systems) NetScroll+ Mini Traveler / Genius NetScroll 120
Bus 001 Device 004: ID 13d3:56a8 IMC Networks USB2.0 HD UVC WebCamКод: Выделить всё
!((usb.addr=="1.51.1")||(usb.addr=="1.52.1")||(usb.addr=="1.52.2"))Покажите ConfigurationDescriptor, функцию настройки endpoint'ов (если она читаемая, конечно: в шаблонах С++ я все равно не разберусь) и обработчик прерывания где вы накладываете маску USB_ISTR_EP_ID.Проблема лишь в том, что в прилетающем прерывании всегда конечная точка 0, хотя я ожидаю, что будет 1, и в обработчике я обработаю.
Ну и тот же wireshark поможет хотя бы понять шлет вам хост запросы вообще или нет. И если шлет, то куда.
Re: STM32 и USB (практика)
Дескриптор скину вечером (формируется он путем развертывания variadic template), просто из памяти выдерну в виде байтов, буду рад, если глянете и мб что-то найдете.Покажите ConfigurationDescriptor, функцию настройки endpoint'ов (если она читаемая, конечно: в шаблонах С++ я все равно не разберусь) и обработчик прерывания где вы накладываете маску USB_ISTR_EP_ID
Обработчик вот такой:
Код: Выделить всё
if(_Regs()->ISTR & USB_ISTR_RESET)
{
Reset();
}
if(_Regs()->ISTR & USB_ISTR_CTR)
{
uint8_t endpoint = _Regs()->ISTR & USB_ISTR_EP_ID;
EpHandlers::Handle(endpoint, ((_Regs()->ISTR & USB_ISTR_DIR) != 0 ? EndpointDirection::In : EndpointDirection::Out));
}
NVIC_ClearPendingIRQ(_IRQNumber);
Код: Выделить всё
if(_Ep0::Reg::Get() & USB_EP_CTR_RX)
{
_Ep0::ClearCtrRx();
if(_Ep0::Reg::Get() & USB_EP_SETUP)
{
SetupPacket* setup = reinterpret_cast<SetupPacket*>(_Ep0::RxBuffer);
switch (setup->Request) {
case StandartRequestCode::GetStatus: {
// Dummy answer. Remote wakeup and self-powered now not supported.
uint16_t status = 0;
_Ep0::Writer::SendData(&status, sizeof(status));
break;
}
case StandartRequestCode::SetAddress: {
TempAddressStorage = setup->Value;
_Ep0::Writer::SendData(0);
break;
}
case StandartRequestCode::GetDescriptor: {
switch (static_cast<GetDescriptorParameter>(setup->Value)) {
case GetDescriptorParameter::DeviceDescriptor: {
DeviceDescriptor tempDeviceDescriptor;
FillDescriptor(reinterpret_cast<DeviceDescriptor*>(&tempDeviceDescriptor));
_Ep0::Writer::SendData(&tempDeviceDescriptor, setup->Length < sizeof(DeviceDescriptor) ? setup->Length : sizeof(DeviceDescriptor));
break;
}
case GetDescriptorParameter::ConfigurationDescriptor: {
uint8_t temp[64];
uint16_t size = GetType<0, Configurations>::type::FillDescriptor(reinterpret_cast<ConfigurationDescriptor*>(&temp[0]));
_Ep0::Writer::SendData(reinterpret_cast<ConfigurationDescriptor*>(&temp[0]), setup->Length < size ? setup->Length : size);
break;
}
case GetDescriptorParameter::HidReportDescriptor: {
IO::Pc7::Clear();
uint16_t size = sizeof(GetType_t<0, Configurations>::HidReport::Data);
_Ep0::Writer::SendData(GetType_t<0, Configurations>::HidReport::Data, setup->Length < size ? setup->Length : size);
break;
}
default:
_Ep0::SetTxStatus(EndpointStatus::Stall);
break;
}
break;
}
case StandartRequestCode::SetConfiguration: {
_Ep0::Writer::SendData(0);
}
default:
_Ep0::SetTxStatus(EndpointStatus::Stall);
break;
}
}
_Ep0::SetRxStatus(EndpointStatus::Valid);
}
if(_Ep0::Reg::Get() & USB_EP_CTR_TX)
{
_Ep0::ClearCtrTx();
if(TempAddressStorage != 0)
{
_Regs()->DADDR = USB_DADDR_EF | (TempAddressStorage & USB_DADDR_ADD);
TempAddressStorage = 0;
}
_Ep0::SetRxStatus(EndpointStatus::Valid);
}
}



