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

Кто любит RISC в жизни, заходим, не стесняемся.
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

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

Сообщение COKPOWEHEU »

Так проблема в каком-то запросе с хоста на МК. И смотреть на обмен можно хоть с одной стороны (лог с МК), хоть с другой (wireshark), хоть вообще из середины (логический анализатор). Пока соединение не установлено, со стороны ПК ничего не увидеть. А зачастую и со стороны МК ничего не увидеть, ведь модуль USB - черный ящик. Но вот когда пошел обмен, смотреть можно где угодно. И выбирать соответственно где удобнее.
Реклама
Аватара пользователя
НАПАЛМ
Это не хвост, это антенна
Сообщения: 1314
Зарегистрирован: Пт ноя 27, 2009 19:47:13
Откуда: Казань

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

Сообщение НАПАЛМ »

Ну к аппаратной части USB в MCU вопросов как раз таки нет, ведь с Ubuntu все работает (данные отправляются и читаются программой-терминалом корректно). С виндой буду чуть позже отдельно разбираться, возможно (наверняка) упущение в логике стандартных ответов на стандартные запросы :dont_know:
Реклама
Аватара пользователя
НАПАЛМ
Это не хвост, это антенна
Сообщения: 1314
Зарегистрирован: Пт ноя 27, 2009 19:47:13
Откуда: Казань

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

Сообщение НАПАЛМ »

[uquote="VladislavS",url="/forum/viewtopic.php?p=4404351#p4404351"]Лог запросов при подключения 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
На всё это устройство должно уметь отвечать. Хорошо ещё выводить что вы отвечаете на каждый запрос.[/uquote]

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

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

И самое интересное, что в Ubuntu всё работало и так, с кодом, написанным по мотивам юсб ин натшелл.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

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

Сообщение VladislavS »

Логи вот отсюда
Спойлер

Код: Выделить всё

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));
}
Про неописанные дескрипторы не верю. Стандарт все их описывает до последнего бита. Последовательность запросов может быть разная у разных хостов. Задача устройства все их корректно обрабатывать в любой последовательности.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
НАПАЛМ
Это не хвост, это антенна
Сообщения: 1314
Зарегистрирован: Пт ноя 27, 2009 19:47:13
Откуда: Казань

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

Сообщение НАПАЛМ »

[uquote="VladislavS",url="/forum/viewtopic.php?p=4404351#p4404351"]Лог запросов при подключения 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
На всё это устройство должно уметь отвечать. Хорошо ещё выводить что вы отвечаете на каждый запрос.[/uquote]


У меня на вин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
Реклама
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

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

Сообщение VladislavS »

Ну не запрашивает, значит "не хочет". Устройство же работает? Чего тогда переживать?
Реклама
Аватара пользователя
НАПАЛМ
Это не хвост, это антенна
Сообщения: 1314
Зарегистрирован: Пт ноя 27, 2009 19:47:13
Откуда: Казань

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

Сообщение НАПАЛМ »

Да, работает отлично всё
jcxz
Мудрый кот
Сообщения: 1717
Зарегистрирован: Вт авг 15, 2017 10:51:13

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

Сообщение jcxz »

[uquote="НАПАЛМ",url="/forum/viewtopic.php?p=4406888#p4406888"]У меня на вин10 получаются вот такие логи, никак не могу понять, в чем может быть причина[/uquote]Какой режим: USB-LS, USB-FS, USB-HS?
Вангую, что в вашем дескрипторе устройства неверно указан размер control-ep0. На что намекают неверные размеры запросов стандартных дескрипторов. Для USB-FS/USB-HS должен быть == 64 байта.
Аватара пользователя
НАПАЛМ
Это не хвост, это антенна
Сообщения: 1314
Зарегистрирован: Пт ноя 27, 2009 19:47:13
Откуда: Казань

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

Сообщение НАПАЛМ »

2.0-FS, ep0 8b, протестирую на 64 потом, спасибо, что указали
danone78
Встал на лапы
Сообщения: 82
Зарегистрирован: Вт фев 15, 2022 21:28:35

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

Сообщение danone78 »

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

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

Сообщение danone78 »

всем спасибо, сам разобрался. Видимо этому коту надо видеть как в миску накладывают еду :wink:
danone78
Встал на лапы
Сообщения: 82
Зарегистрирован: Вт фев 15, 2022 21:28:35

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

Сообщение danone78 »

Что-то не так с регистром 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 байта и обратно ничего лишнего не прилетает.
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

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

Сообщение COKPOWEHEU »

[uquote="danone78",url="/forum/viewtopic.php?p=4477662#p4477662"]И... добавлю : при первом запросе дескриптора нужно отправить так называемый Malformed packet перве 8 байт[/uquote]
Всегда надо отправлять ровно столько, сколько запрашивают. У вас же есть поле wLength, предназначенное ровно для этого.
danone78 писал(а):Потом хост (в моем случае wiindows10) шлет set_address, с этим я еще не разобрался, но на следующий такой-же запрос дескриптора (01000680) уже можно отправить 32 байта и обратно ничего лишнего не прилетает.
Это процесс энумерации. Изначально устройству не назначен адрес, и оно отзывается на все пакеты с адресом 0. Запрос set_address как раз и говорит "теперь у тебя адрес такой-то". На него надо сначала ответить как "безымянное" устройство (пакетом нулевой длины), и только потом, когда хост прочитает ответ, действительно менять адрес.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

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

Сообщение VladislavS »

[uquote="COKPOWEHEU",url="/forum/viewtopic.php?p=4478044#p4478044"]и только потом, когда хост прочитает ответ, действительно менять адрес.[/uquote]В stm-ках с OTG можно сразу адрес ставить.
danone78
Встал на лапы
Сообщения: 82
Зарегистрирован: Вт фев 15, 2022 21:28:35

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

Сообщение danone78 »

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

Добавлено after 2 minutes 41 second:
[uquote="COKPOWEHEU",url="/forum/viewtopic.php?p=4478044#p4478044"][uquote="danone78",url="/forum/viewtopic.php?p=4477662#p4477662"]И... добавлю : при первом запросе дескриптора нужно отправить так называемый Malformed packet перве 8 байт[/uquote]
Всегда надо отправлять ровно столько, сколько запрашивают. У вас же есть поле wLength, предназначенное ровно для этого.
danone78 писал(а):Потом хост (в моем случае wiindows10) шлет set_address, с этим я еще не разобрался, но на следующий такой-же запрос дескриптора (01000680) уже можно отправить 32 байта и обратно ничего лишнего не прилетает.
Это процесс энумерации. Изначально устройству не назначен адрес, и оно отзывается на все пакеты с адресом 0. Запрос set_address как раз и говорит "теперь у тебя адрес такой-то". На него надо сначала ответить как "безымянное" устройство (пакетом нулевой длины), и только потом, когда хост прочитает ответ, действительно менять адрес.[/uquote]
ага! а я сразу пытаюсь ответить с новым адресом, спасибки..

Добавлено after 1 hour 27 minutes 33 seconds:
Спасибо еще раз за наводку, получил запрос на второй дескриптор, запрашивая длина почему-то 0xFF.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

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

Сообщение VladislavS »

[uquote="danone78",url="/forum/viewtopic.php?p=4478542#p4478542"]в смысле сразу?[/uquote]Сразу после того как хост выдал его.
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

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

Сообщение COKPOWEHEU »

[uquote="danone78",url="/forum/viewtopic.php?p=4478542#p4478542"]ага! а я сразу пытаюсь ответить с новым адресом, спасибки..
Спасибо еще раз за наводку, получил запрос на второй дескриптор, запрашивая длина почему-то 0xFF.[/uquote]
Так в wireshark смотрите какие запросы приходят и корректно ли они обрабатываются. Длина 0xFF это странно. Может, вы не то поле анализируете, или выравнивание у структуры неправильное, или еще какая ошибка. Ну как минимум, wLength длиной 2 байта, а не 1.
danone78
Встал на лапы
Сообщения: 82
Зарегистрирован: Вт фев 15, 2022 21:28:35

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

Сообщение danone78 »

Дошел до отправки hid report, на этом этапе надо включать конечную точку1, но на нее что-то ничего не приходит, никаких событий на EP1out.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

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

Сообщение VladislavS »

Какой такой out? EP1 Interrupt.
danone78
Встал на лапы
Сообщения: 82
Зарегистрирован: Вт фев 15, 2022 21:28:35

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

Сообщение danone78 »

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

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

Вернуться в «ARM»