Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

Re: STM32 и USB (практика)

Пт апр 21, 2023 20:54:21

Так проблема в каком-то запросе с хоста на МК. И смотреть на обмен можно хоть с одной стороны (лог с МК), хоть с другой (wireshark), хоть вообще из середины (логический анализатор). Пока соединение не установлено, со стороны ПК ничего не увидеть. А зачастую и со стороны МК ничего не увидеть, ведь модуль USB - черный ящик. Но вот когда пошел обмен, смотреть можно где угодно. И выбирать соответственно где удобнее.

Re: STM32 и USB (практика)

Пт апр 21, 2023 22:05:41

Ну к аппаратной части USB в MCU вопросов как раз таки нет, ведь с Ubuntu все работает (данные отправляются и читаются программой-терминалом корректно). С виндой буду чуть позже отдельно разбираться, возможно (наверняка) упущение в логике стандартных ответов на стандартные запросы :dont_know:

Re: STM32 и USB (практика)

Вс апр 23, 2023 19:25:08

Лог запросов при подключения CDC к Win10.
Спойлер
Код:
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
SET_LINE_CODING DATA 0 0 0 0
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

Открытие порта
Спойлер
Код:
SET_CONTROL_LINE_STATE 0
GET_LINE_CODING
SET_LINE_CODING
SET_LINE_CODING DATA 2000000 0 0 8
GET_LINE_CODING
SET_CONTROL_LINE_STATE 1
SET_LINE_CODING
SET_LINE_CODING DATA 2000000 0 1 8
GET_LINE_CODING

На всё это устройство должно уметь отвечать. Хорошо ещё выводить что вы отвечаете на каждый запрос.


Большое спасибо за логи, прямо пошагово по ним прошелся, исправил ошибки, теперь девайс видится диспетчером вин10 без каких-либо ошибок, программа-терминал корректно обменивается данными с моим девайсом :music:
Остались, правда некоторые вопросы, но попробую сам решить их, если что, задам здесь.

А вот что хочу сейчас спросить: откуда вы взяли эти логи? Я читал юсб ин натшелл, а так же доку по сдс с юсб.орг, там секвенция запросов отличается, а один тип дескриптора и вовсе не описан. Даже не представляю, как я бы отладил код без этой информации :dont_know:

И самое интересное, что в Ubuntu всё работало и так, с кодом, написанным по мотивам юсб ин натшелл.

Re: STM32 и USB (практика)

Вс апр 23, 2023 23:11:06

Логи вот отсюда
Спойлер
Код:
void Enumerate_Setup()
{
  uint32_t reply_len=0;
  uint8_t *pbuf=NULL;

  TPort::ReadEP(0,(uint8_t *)&uSetReq,8);
 
  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));
}

Про неописанные дескрипторы не верю. Стандарт все их описывает до последнего бита. Последовательность запросов может быть разная у разных хостов. Задача устройства все их корректно обрабатывать в любой последовательности.

Re: STM32 и USB (практика)

Вт апр 25, 2023 22:45:34

Лог запросов при подключения CDC к Win10.
Спойлер
Код:
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
SET_LINE_CODING DATA 0 0 0 0
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

Открытие порта
Спойлер
Код:
SET_CONTROL_LINE_STATE 0
GET_LINE_CODING
SET_LINE_CODING
SET_LINE_CODING DATA 2000000 0 0 8
GET_LINE_CODING
SET_CONTROL_LINE_STATE 1
SET_LINE_CODING
SET_LINE_CODING DATA 2000000 0 1 8
GET_LINE_CODING

На всё это устройство должно уметь отвечать. Хорошо ещё выводить что вы отвечаете на каждый запрос.



У меня на вин10 получаются вот такие логи, никак не могу понять, в чем может быть причина :dont_know:
Спойлер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

Re: STM32 и USB (практика)

Ср апр 26, 2023 06:39:42

Ну не запрашивает, значит "не хочет". Устройство же работает? Чего тогда переживать?

Re: STM32 и USB (практика)

Ср апр 26, 2023 09:48:42

Да, работает отлично всё

Re: STM32 и USB (практика)

Ср апр 26, 2023 18:28:36

У меня на вин10 получаются вот такие логи, никак не могу понять, в чем может быть причина
Какой режим: USB-LS, USB-FS, USB-HS?
Вангую, что в вашем дескрипторе устройства неверно указан размер control-ep0. На что намекают неверные размеры запросов стандартных дескрипторов. Для USB-FS/USB-HS должен быть == 64 байта.

Re: STM32 и USB (практика)

Ср апр 26, 2023 21:54:23

2.0-FS, ep0 8b, протестирую на 64 потом, спасибо, что указали

Re: STM32 и USB (практика)

Чт сен 14, 2023 18:45:36

здравствуйте, может кто подскажет, почему не отправить по USB от stm32f407 больше 16 байт?
Принимаю setup пакет(8байт 01000680 00400000), посылаю 8 или 16 байт одним пакетом, принимаю пакет setup phase done, потом пустой DataOUT пакет зачем-то приходит и завершение дата фазы.
Получаю прерывания transfer complete на INEP0 и OUTEP0. Все вроде как надо, но не могу отправить 32/64 байта одним пакетом, отправляется 16, остальное остается в txFIFO.

Re: STM32 и USB (практика)

Пт сен 15, 2023 17:52:44

всем спасибо, сам разобрался. Видимо этому коту надо видеть как в миску накладывают еду :wink:

Re: STM32 и USB (практика)

Вс сен 17, 2023 18:37:33

Что-то не так с регистром DCFG на stm32f407, при записи в него происходит ремаппинг битов, например чтобы установить бит 7 нужно установить бит 3. Некоторые биты остаются на месте. Это уже совсем какой-то дом ку-ку :evil:

Добавлено 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 байта и обратно ничего лишнего не прилетает.

Re: STM32 и USB (практика)

Пн сен 18, 2023 12:19:15

И... добавлю : при первом запросе дескриптора нужно отправить так называемый Malformed packet перве 8 байт

Всегда надо отправлять ровно столько, сколько запрашивают. У вас же есть поле wLength, предназначенное ровно для этого.
danone78 писал(а):Потом хост (в моем случае wiindows10) шлет set_address, с этим я еще не разобрался, но на следующий такой-же запрос дескриптора (01000680) уже можно отправить 32 байта и обратно ничего лишнего не прилетает.

Это процесс энумерации. Изначально устройству не назначен адрес, и оно отзывается на все пакеты с адресом 0. Запрос set_address как раз и говорит "теперь у тебя адрес такой-то". На него надо сначала ответить как "безымянное" устройство (пакетом нулевой длины), и только потом, когда хост прочитает ответ, действительно менять адрес.

Re: STM32 и USB (практика)

Вт сен 19, 2023 07:13:50

и только потом, когда хост прочитает ответ, действительно менять адрес.
В stm-ках с OTG можно сразу адрес ставить.

Re: STM32 и USB (практика)

Вт сен 19, 2023 19:38:32

в смысле сразу? просто назначить себе его как ip-адрес в надежде что не будет конфликта? я пробовал назначить сразу, все то же как и с нулевым адресом, странно все это. Есть мысль выцепить дебагом кусочек кода из встроенного бутлодера, чем черт не шутит, просто глянуть может там логика какая есть.

Добавлено after 2 minutes 41 second:
И... добавлю : при первом запросе дескриптора нужно отправить так называемый Malformed packet перве 8 байт

Всегда надо отправлять ровно столько, сколько запрашивают. У вас же есть поле wLength, предназначенное ровно для этого.
danone78 писал(а):Потом хост (в моем случае wiindows10) шлет set_address, с этим я еще не разобрался, но на следующий такой-же запрос дескриптора (01000680) уже можно отправить 32 байта и обратно ничего лишнего не прилетает.

Это процесс энумерации. Изначально устройству не назначен адрес, и оно отзывается на все пакеты с адресом 0. Запрос set_address как раз и говорит "теперь у тебя адрес такой-то". На него надо сначала ответить как "безымянное" устройство (пакетом нулевой длины), и только потом, когда хост прочитает ответ, действительно менять адрес.

ага! а я сразу пытаюсь ответить с новым адресом, спасибки..

Добавлено after 1 hour 27 minutes 33 seconds:
Спасибо еще раз за наводку, получил запрос на второй дескриптор, запрашивая длина почему-то 0xFF.

Re: STM32 и USB (практика)

Вт сен 19, 2023 21:25:13

в смысле сразу?
Сразу после того как хост выдал его.

Re: STM32 и USB (практика)

Ср сен 20, 2023 04:34:49

ага! а я сразу пытаюсь ответить с новым адресом, спасибки..
Спасибо еще раз за наводку, получил запрос на второй дескриптор, запрашивая длина почему-то 0xFF.

Так в wireshark смотрите какие запросы приходят и корректно ли они обрабатываются. Длина 0xFF это странно. Может, вы не то поле анализируете, или выравнивание у структуры неправильное, или еще какая ошибка. Ну как минимум, wLength длиной 2 байта, а не 1.

Re: STM32 и USB (практика)

Вс окт 01, 2023 07:19:13

Дошел до отправки hid report, на этом этапе надо включать конечную точку1, но на нее что-то ничего не приходит, никаких событий на EP1out.

Re: STM32 и USB (практика)

Вс окт 01, 2023 08:18:10

Какой такой out? EP1 Interrupt.

Re: STM32 и USB (практика)

Вс окт 01, 2023 09:00:38

да тип конечной точки ставлю intreupt, но есть же конечные точки IN и OUT. Я полностью копирую свою мышку, винда ее видит в диспетчере устройств, wireshark-ом все сходится, по логике должен придти пустой пакет на EP1, а я должен отправить 4 байта инфы, но приходит самый первый запрос дескриптора 0x01000680 00400000 на нулевую точку. Может на нулевой OUT точке NAK поставить чтобы как-то отфильтровать пакеты для EP0?

Добавлено after 5 minutes 15 seconds:
а какой Endpoint Data PID ставить? это зависит от четности номера фрейма?
Ответить