|
STM32F4Discovery USB_HID, посылка данных в PC, непонятки |
|
|
|
Aug 26 2015, 11:39
|
Частый гость
 
Группа: Участник
Сообщений: 135
Регистрация: 9-09-11
Пользователь №: 67 084

|
Цитата(Kabdim @ Aug 26 2015, 13:55)  1. Очевидно её заполняет обработчик прерывний USB который не был найден. 2. Видимо функция сохраняет адрес буфера для последующего прерывания. В итоге если буфер лежит в стеке, то на момент реального использвоания там уже может быть мусор. 3. Могут быть разные причины. 1. Так ведь обращение к ней нигде не производится. Я даже указателя нигде на нее не нашел. Может кто знает сей фокус? 2. Более-менее понятно. 3. Пока тоже неясно, разбираюсь. Появился еще один вопрос: Для отправки данных используется функция USBD_HID_SendReport(&USB_OTG_dev, buff, count). И для того, чтобы послать буфер в 64 байта надо указывать count равным 65, а не 64 как казалось бы... Никто с таким не сталкивался?
|
|
|
|
|
Aug 27 2015, 04:50
|
Частый гость
 
Группа: Участник
Сообщений: 135
Регистрация: 9-09-11
Пользователь №: 67 084

|
Цитата(Golikov A. @ Aug 26 2015, 19:39)  64 байта - граница пакета, должна быть снабжена пустым пакетом с 0 данными, может дело в этом? Не совсем понял: т.е., чтобы отослать 64 байта, надо отослать 65 с последним нулевым? Или в 64 байтах последний болжен быть нулевой? Хорошо, давайте разбираться детально  Вот есть такой код отправки ответа: Код #define buf_size 8 uint8_t buf[buf_size];
static uint8_t USBD_HID_DataOut (void *pdev, uint8_t epnum) { uint16_t USB_Rx_Cnt; uint8_t i = 0; /* Get the received data buffer and update the counter */ USB_Rx_Cnt = ((USB_OTG_CORE_HANDLE*)pdev)->dev.out_ep[epnum].xfer_count; // pointer to usb packet
if(USB_Rx_Buffer[1] == 0x01) { TM_DISCO_LedOn(LED_GREEN); } else if(USB_Rx_Buffer[1] == 0x00) { TM_DISCO_LedOff(LED_GREEN); } for(i = 0; i<buf_size; i++) buf[i] = i; TM_USB_HIDDEVICE_SendCustom(buf, buf_size); /* Prepare Out endpoint to receive next packet */ DCD_EP_PrepareRx(pdev, HID_OUT_EP, USB_Rx_Buffer, MAX_DATA_LENGTH); return USBD_OK; } Т.е., в ответ на прием пакета я отправляю 8 байт со счетчиком внутри. TM_USB_HIDDEVICE_SendCustom() - это просто обертка над USBD_HID_SendReport(&USB_OTG_dev, buff, count). Я ожидаю, что на пк примется этот 8-байтный ответ, однако ничего не принимается. Смотрим сниффером что получается:
Ответы приходят (правда почему-то только с 3-го раза после включения девайса), длина 8 байт, вроде все как заказывали. Смотрим како-нить пакетик:
Сниффер говорит что пакет принят успешно. Однако, принимающая прога на компе в упор ничего не видит. Вот репу уже сломал, прям руки опускаются. И что-то мне подсказывает что дело, скорее всего, в дескрипторах. Вроде я их пилил-пилил, но может чего не допилил. Посмотрите опытным взглядом:
Там по идее заложено 64 байта туда, 64 байта обратно и все.
Сообщение отредактировал ilkz - Aug 27 2015, 04:53
|
|
|
|
|
Aug 27 2015, 06:25
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(ilkz @ Aug 27 2015, 09:06)  1. Если мы хотим отправить N Байт, то реально надо отправить на 1 байт больше, т.е. N+1. .... Теперь понятны слова Golikov A. про 65 байт. Вы поняли неправильно. Конечная точка имеет ограничение на длину пакета. В вашем случае оно равно 64 байта. Если вам нужно передать больше - вы передаете несколько пакетов. Но как вторая сторона определит, что вы уже закончили передачу? А очень просто: если пришел пакет с длиной, меньшей, чем максимальная длина для этой рабочей точки, то он последний. А что делать, если вам надо передать ровно столько данных, какова максимальная длина пакета? Получив такой пакет вторая сторона будет ждать продолжения. Поэтому передающая в этом и только в этом случае посылает следом пакет с нулевой длиной, т.е. без данных (zlp, zero-length payload). Но это все внутренние дела стека., вас они волновать не должны. REPORT ID - это совсем другая опера. Если вы в дескрипторах сообщили, что будете отсылать несколько разных типов сообщений (reports), то вы должны в начале каждого передавать дополнительный байт с идентификатором. Если вы анонсировали только один вид сообщений, то второй стороне не нужно отделять его от других и этот байт с идентификатором не передается.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Aug 27 2015, 06:39
|
Частый гость
 
Группа: Участник
Сообщений: 135
Регистрация: 9-09-11
Пользователь №: 67 084

|
Цитата(Сергей Борщ @ Aug 27 2015, 09:25)  Вы поняли неправильно. Конечная точка имеет...
REPORT ID - это совсем другая опера. Если вы в дескрипторах сообщили, что будете отсылать несколько разных типов сообщений (reports), то вы должны в начале каждого передавать дополнительный байт с идентификатором. Если вы анонсировали только один вид сообщений, то второй стороне не нужно отделять его от других и этот байт с идентификатором не передается. С первым понятно, спасибо за внятное разъяснение. Со вторым: если в репорте используется один IN и один OUT, то это считается за два вида сообщений или за один?
|
|
|
|
|
Aug 27 2015, 09:54
|
Частый гость
 
Группа: Участник
Сообщений: 135
Регистрация: 9-09-11
Пользователь №: 67 084

|
Искал - пусто. Сергей Борщ, хотите прикол? Было (это единственное объявление данной переменной на весь проект, сидит в том же файле что и код ниже): Код __ALIGN_BEGIN uint8_t USB_Rx_Buffer [MAX_DATA_LENGTH] __ALIGN_END; Меняю на: Код __ALIGN_BEGIN uint8_t SuperMegaBuffer [MAX_DATA_LENGTH] __ALIGN_END; , соответственно, в коллбеке приема: Код static uint8_t USBD_HID_DataOut (void *pdev, uint8_t epnum) { uint16_t USB_Rx_Cnt; uint8_t i = 0; USB_Rx_Cnt = ((USB_OTG_CORE_HANDLE*)pdev)->dev.out_ep[epnum].xfer_count; // pointer to usb packet
USB_Rx_Buffer[0] = 0x01; TM_USB_HIDDEVICE_SendCustom(USB_Rx_Buffer, 65);
DCD_EP_PrepareRx(pdev, HID_OUT_EP, USB_Rx_Buffer, MAX_DATA_LENGTH); return USBD_OK; } меняю на: Код static uint8_t USBD_HID_DataOut (void *pdev, uint8_t epnum) { uint16_t USB_Rx_Cnt; uint8_t i = 0; USB_Rx_Cnt = ((USB_OTG_CORE_HANDLE*)pdev)->dev.out_ep[epnum].xfer_count; // pointer to usb packet SuperMegaBuffer[0] = 0x01; TM_USB_HIDDEVICE_SendCustom(SuperMegaBuffer, 65); DCD_EP_PrepareRx(pdev, HID_OUT_EP, SuperMegaBuffer, MAX_DATA_LENGTH); return USBD_OK; } и все, больше ничего и нигде не трогаю. И что же я вижу? А то, что чудесным, мать его, образом - в SuperMegaBuffer оказываются принятые данные. КАААК?
|
|
|
|
|
Aug 27 2015, 11:53
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(ilkz @ Aug 27 2015, 12:54)  КАААК? Видимо как-то отсюда: Цитата(ilkz @ Aug 27 2015, 12:54)  Код TM_USB_HIDDEVICE_SendCustom(USB_Rx_Buffer, 65); Тут же вы передаете адрес этого буфера стеку. Копайте эту функцию.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Aug 27 2015, 13:18
|
Частый гость
 
Группа: Участник
Сообщений: 135
Регистрация: 9-09-11
Пользователь №: 67 084

|
Цитата(Сергей Борщ @ Aug 27 2015, 14:53)  Видимо как-то отсюда: Тут же вы передаете адрес этого буфера стеку. Копайте эту функцию. Весь цимес в том, что если убрать строки Код TM_USB_HIDDEVICE_SendCustom(USB_Rx_Buffer, 65); DCD_EP_PrepareRx(pdev, HID_OUT_EP, USB_Rx_Buffer, MAX_DATA_LENGTH); ,то волшебный буфер все равно оказывается заполнен принятыми данными )))
|
|
|
|
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|