den_po 0 31 июля, 2014 Опубликовано 31 июля, 2014 · Жалоба я прикрутил прием данных в USBD_LL_DataOutStage Вот этого не понял можете показать содержимое функции USBD_LL_DataOutStage, а то у меня там никакой USBD_CDC_DataOut нет, она фигурирует только в структуре Так там тоже через таблички всё идёт. Предложение. Проверьте свежесгенерированный кубом код, измените только эти две функции: static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len) { /* USER CODE BEGIN 7 */ CDC_Transmit_FS(Buf, *Len); USBD_CDC_ReceivePacket(hUsbDevice_0); return (USBD_OK); /* USER CODE END 7 */ } uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len) { uint8_t result = USBD_OK; /* USER CODE BEGIN 8 */ memcpy(UserTxBufferFS,Buf,Len); USBD_CDC_SetTxBuffer(hUsbDevice_0, UserTxBufferFS, Len); result = USBD_CDC_TransmitPacket(hUsbDevice_0); /* USER CODE END 8 */ return result; } Должно эхом возвращать то, что принимает. Хе, сейчас вот наткнулся на баг в F0 USBD_StatusTypeDef USBD_LL_Init (USBD_HandleTypeDef *pdev) { ... hpcd_USB_FS.Init.dev_endpoints = 8; PCD_EPTypeDef IN_ep[5]; /*!< IN endpoint parameters */ PCD_EPTypeDef OUT_ep[5]; /*!< OUT endpoint parameters */ Из-за этого херится чужая память. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dima1060 0 31 июля, 2014 Опубликовано 31 июля, 2014 (изменено) · Жалоба Вот этого не понял вот так USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata) { USBD_EndpointTypeDef *pep; if(epnum == 0) { pep = &pdev->ep_out[0]; if ( pdev->ep0_state == USBD_EP0_DATA_OUT) { if(pep->rem_length > pep->maxpacket) { pep->rem_length -= pep->maxpacket; USBD_CtlContinueRx (pdev, pdata, MIN(pep->rem_length ,pep->maxpacket)); } else { if((pdev->pClass->EP0_RxReady != NULL)&& (pdev->dev_state == USBD_STATE_CONFIGURED)) { pdev->pClass->EP0_RxReady(pdev); } USBD_CtlSendStatus(pdev); } } } else if((pdev->pClass->DataOut != NULL)&& (pdev->dev_state == USBD_STATE_CONFIGURED)) { pdev->pClass->DataOut(pdev, epnum); //my code if (UserRxBufferHS[1] == 3) { HAL_GPIO_WritePin(GPIOG, GPIO_PIN_14, GPIO_PIN_SET); UserRxBufferHS[1] = 0; USBD_CDC_ReceivePacket(hUsbDevice_1); } //end my code } return USBD_OK; } Так там тоже через таблички всё идёт. у меня - нет Предложение. Проверьте свежесгенерированный кубом код, измените только эти две функции: CDC_Transmit_FS - не знаю, по моему она у меня тоже нигде не вызывается. в принципе то она и не нужна в CDC_Receive_FS пробовал вставлять обработку данных, но чуда не произошло. если она нигде не вызывается, что поделаешь Изменено 31 июля, 2014 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
den_po 0 31 июля, 2014 Опубликовано 31 июля, 2014 (изменено) · Жалоба вот так Почему так? у меня - нет Неправда. В процитированном вами коде строчка pdev->pClass->DataOut(pdev, epnum); - это вызов функции из таблички и есть. Вызывает USBD_CDC_DataOut. В USBD_CDC_DataOut строчка ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Receive(hcdc->RxBuffer, &hcdc->RxLength); вызывает CDC_Receive_FS. CDC_Transmit_FS - не знаю, по моему она у меня тоже нигде не вызывается. в принципе то она и не нужна в CDC_Receive_FS пробовал вставлять обработку данных, но чуда не произошло. если она нигде не вызывается, что поделаешь Конкретно предложенный мной вариант не работает? Очень неприятный баг. Когда отправляю в МК данные из программы, написанной на c#, если за раз отправлено больше 6 байт, то на МК они приходят нормально, но в ответ от МК начинаю получать мусор. То же самое, если с МК передаю больше 8 байт, на комп приходит мусор. Изменено 31 июля, 2014 пользователем den_po Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dima1060 0 1 августа, 2014 Опубликовано 1 августа, 2014 · Жалоба Хе, сейчас вот наткнулся на баг в F0 USBD_StatusTypeDef USBD_LL_Init (USBD_HandleTypeDef *pdev) { ... hpcd_USB_FS.Init.dev_endpoints = 8; PCD_EPTypeDef IN_ep[5]; /*!< IN endpoint parameters */ PCD_EPTypeDef OUT_ep[5]; /*!< OUT endpoint parameters */ Из-за этого херится чужая память. у меня так hpcd_USB_OTG_HS.Init.dev_endpoints = 11; PCD_EPTypeDef IN_ep[15]; /*!< IN endpoint parameters */ PCD_EPTypeDef OUT_ep[15]; /*!< OUT endpoint parameters */ Конкретно предложенный мной вариант не работает? сейчас перетащил свою обработку в CDC_Receive_HS, хм все работает :blink: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dima1060 0 1 августа, 2014 Опубликовано 1 августа, 2014 (изменено) · Жалоба Проверьте свежесгенерированный кубом код, измените только эти две функции: В процитированном вами коде строчка pdev->pClass->DataOut(pdev, epnum); - это вызов функции из таблички и есть. Вызывает USBD_CDC_DataOut. В USBD_CDC_DataOut строчка ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Receive(hcdc->RxBuffer, &hcdc->RxLength); вызывает CDC_Receive_FS. это я понял, а вот CDC_Transmit_FS точно вроде не вызывается нигде, HAL_PCD_DataInStageCallback -> USBD_LL_DataInStage -> (pdev->pClass->DataIn(pdev, epnum)) -> USBD_CDC_DataIn и все static uint8_t USBD_CDC_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum) { USBD_CDC_HandleTypeDef *hcdc = pdev->pClassData; if(pdev->pClassData != NULL) { hcdc->TxState = 0; return USBD_OK; } else { return USBD_FAIL; } } Изменено 1 августа, 2014 пользователем Atlantis- Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
den_po 0 1 августа, 2014 Опубликовано 1 августа, 2014 · Жалоба CDC_Transmit_FS нужно вызывать самостоятельно, когда нужно передать что-то компьютеру. А USBD_CDC_DataIn просто делает отметку, мол данные переданы. А у меня всё равно данные портятся. Энное количество работает, а потом от МК приходит мусор =( Причём отправляются нормальные данные. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dima1060 0 1 августа, 2014 Опубликовано 1 августа, 2014 · Жалоба CDC_Transmit_FS нужно вызывать самостоятельно, когда нужно передать что-то компьютеру. А USBD_CDC_DataIn просто делает отметку, мол данные переданы. в библиотеке STM32F103 был колбэк, который вызывался каждые 1 мс, я в нем проверял есть ли данные и отправлял если они были. а свой счетчик отправлял каждые 1 мс для чего вот этот вызов? memcpy(UserTxBufferFS,Buf,Len); у меня если его использовать, тоже ерунда приходит Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
den_po 0 2 августа, 2014 Опубликовано 2 августа, 2014 · Жалоба Думаю, ерунда может приходить, если отправляются данные раньше, чем успевают передаться прошлые. Можно решить это например так: uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len) { uint8_t result = USBD_OK; /* USER CODE BEGIN 8 */ USBD_CDC_HandleTypeDef *hcdc = hUsbDevice_0->pClassData; if(!hcdc) return USBD_FAIL; if(hcdc->TxState) return USBD_BUSY; memcpy(UserTxBufferFS,Buf,Len); USBD_CDC_SetTxBuffer(hUsbDevice_0, UserTxBufferFS, Len); result = USBD_CDC_TransmitPacket(hUsbDevice_0); /* USER CODE END 8 */ return result; } Ну и в обязательном порядке проверять результат выполнения функции: если она возвращает USBD_BUSY, нужно передать данные повторно. У меня же на F0 мусор так и шёл, пока я не ограничил передачу 1 байтом за раз. Медленно получается. Буду ещё на F2 пробовать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
den_po 0 3 августа, 2014 Опубликовано 3 августа, 2014 (изменено) · Жалоба Баг с мусором в F0 почти убрал. В функции usbd_conf.c/USBD_LL_Init заменил HAL_PCDEx_PMAConfig(pdev->pData , 0x00 , PCD_SNG_BUF, 0x18); HAL_PCDEx_PMAConfig(pdev->pData , 0x80 , PCD_SNG_BUF, 0x58); на //0x10 == 2*CDC_CMD_PACKET_SIZE? HAL_PCDEx_PMAConfig(pdev->pData , 0x00 , PCD_SNG_BUF, 0x10+0*USB_FS_MAX_PACKET_SIZE); HAL_PCDEx_PMAConfig(pdev->pData , 0x80 , PCD_SNG_BUF, 0x10+1*USB_FS_MAX_PACKET_SIZE); HAL_PCDEx_PMAConfig(pdev->pData , 0x01 , PCD_SNG_BUF, 0x10+2*USB_FS_MAX_PACKET_SIZE); HAL_PCDEx_PMAConfig(pdev->pData , 0x81 , PCD_SNG_BUF, 0x10+3*USB_FS_MAX_PACKET_SIZE); Почти - потому что в среднем через 20-30 пакетов от МК к компу приходит пакет, который со второго байта хранит содержимое буфера приёма МК. Тестовая программа передаёт кучу буковок, МК меняет их регистр на противоположный и передаёт обратно. Результат (вывод данных, пришедших с МК) получается примерно такой: fghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklm ghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmn hijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmno ijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnop jKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQ Ошибка в пакете №35 должно быть: jklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopq Но в целом прогресс заметный. Можно передавать данные кусками до 63 байт длиной (CDC_DATA_FS_MAX_PACKET_SIZE == 64). (Предыдущий баг - должно быть 15, а не 5) Изменено 3 августа, 2014 пользователем den_po Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
den_po 0 6 августа, 2014 Опубликовано 6 августа, 2014 · Жалоба Последняя проблема - моя ошибка. Просто драйвер на компе иногда отдаёт не пакет полностью, а один байт. А я, дурак, читал в тот же буфер и не глядел длину прочитанного. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vgromov 0 15 октября, 2014 Опубликовано 15 октября, 2014 · Жалоба (Предыдущий баг - должно быть 15, а не 5) Ну, по моему не 15 там должно быть, а просто перепутано 5 и 8 местами. Т.е. МК поддерживает 8 endpoints, а для CDC используется 5. control in out bulk data in out command in Я тут по ходу пиесы прикручиваю плюсовые классы-адаптеры кубовых драйверов для freertos, ну и приходится разбираться с этими внутренностями. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
den_po 0 17 октября, 2014 Опубликовано 17 октября, 2014 · Жалоба Ну, по моему не 15 там должно быть, а просто перепутано 5 и 8 местами. Т.е. МК поддерживает 8 endpoints, а для CDC используется 5. control in out bulk data in out command in Я тут по ходу пиесы прикручиваю плюсовые классы-адаптеры кубовых драйверов для freertos, ну и приходится разбираться с этими внутренностями. Там должно быть не меньше, чем hpcd_USB_FS.Init.dev_endpoints. В коде от других серий микроконтроллеров везде 15. И тут по форматированию текста понятно, что было 15, но кто-то случайно удалил символ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dima1060 0 20 октября, 2014 Опубликовано 20 октября, 2014 · Жалоба Если кому ещё интересно, то вот: Внутри CDC_Transmit_FS нужно самостоятельно выполнить нужные действия. Например, скопировать или дописать содержимое Buf в UserTxBufferFS. Внутри CDC_Receive_FS нужно обработать пришедшие по USB данные. Чтобы следующий пакет успешно принялся, нужно после обработки данных (в главном цикле либо тут же в CDC_Receive_FS) вызвать USBD_CDC_ReceivePacket(hUsbDevice_0) я прописал в дескрипторах еще один Endpoint (0x83), инициализировал его в USBD_CDC_Init и загружаю 0x83 в USBD_LL_Transmit - ничего не передает! USBTrace показывает, что EP у меня 2 (0x81 и 0x83), но 0x83 не передает. что-то еще надо для второго EP прописать? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vgromov 0 20 октября, 2014 Опубликовано 20 октября, 2014 · Жалоба Там должно быть не меньше, чем hpcd_USB_FS.Init.dev_endpoints. Точнее, в hpcd_USB_FS.Init.dev_endpoints д.б. не больше, чем xx в PCD_EPTypeDef IN_ep[xx]; /*!< IN endpoint parameters */ PCD_EPTypeDef OUT_ep[xx]; /*!< OUT endpoint parameters */ Если смотреть код инициализации ендпоинтов, то видим, что там используется два цикла - по одному для EP_IN и EP_OUT. Индекс пробегает от 0 до hpcd_USB_FS.Init.dev_endpoints Например, у меня семейство МК stm32f37x. Оно поддерживает до 5 endpoints (т.о., xx=5) Для устройства CDC используем 3 точки - *контрольная (д. б. всегда, адреса 0x00 и 0x80) *блоковая передача данных (адреса 0х01 и 0х81 ) *управление линией (входная, адрес 0х82) В коде инициализации ставим: Init.dev_endpoints = 3; Кроме того, останется еще правильно настроить пакетный буфер, у меня используется низкоприоритетная конфигурация, с простыми буферами: // Offet from the beginning of PM memory, to actual packet buffers // The math is as follows: num of endpoints used * 2 (reserved for in and out pipes) * 2 (2 descriptors per pipe) * 2 (2 byte per descriptor) size_t pmaOffs = m_h.Init.dev_endpoints * 8; HAL_PCDEx_PMAConfig(&m_h, 0x00, PCD_SNG_BUF, pmaOffs ); // EP0 (control in) - always must be there, for USB to function properly pmaOffs += USB_FS_MAX_PACKET_SIZE; HAL_PCDEx_PMAConfig(&m_h, 0x80, PCD_SNG_BUF, pmaOffs ); // EP0 (control out) - always must be there, for USB to function properly pmaOffs += USB_FS_MAX_PACKET_SIZE; HAL_PCDEx_PMAConfig(&m_h, CDC_IN_EP, PCD_SNG_BUF, pmaOffs ); // CDC commuinication IN pmaOffs += CDC_DATA_FS_MAX_PACKET_SIZE; HAL_PCDEx_PMAConfig(&m_h, CDC_OUT_EP, PCD_SNG_BUF, pmaOffs ); // CDC commuinication OUT pmaOffs += CDC_DATA_FS_MAX_PACKET_SIZE; HAL_PCDEx_PMAConfig(&m_h, CDC_CMD_EP, PCD_SNG_BUF, pmaOffs ); // CDC command EP Прогнал CDC драйвер в FreeRTOS под стрессом, в отдельном треде запустил прием+передачу принятого, через терминал, выставил бодрейт 921600, и заслал файло на 20 мегов. Все ОК, скорость ориентировочно получается 700 килобод. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rudy_b 4 14 ноября, 2015 Опубликовано 14 ноября, 2015 · Жалоба Вопрос на ту же тему. Поднял Midware USB CDC (HAL) пришедшее с Stm32 CubeMX v1.0 (version 4.6.0) (Device), процессор Stm32f207. На всякий случай некоторые подробности. 1. При получении пакета CDC вызывается пользовательская (callback) функция CDC_Receive_FS (uint8_t* Buf, uint32_t *Len). Вызов идет на уровне прерываний. В ней я считываю данные и, обязательно, вызываю USBD_CDC_ReceivePacket(hUsbDevice_0), иначе следующий пакет не будет принят. Изначально, для контроля по Эхо, в ней же вызывалась функция посылки ответа CDC_Transmit_FS(...). Затем стал устанавливать флаг и вызывать ее в MainLoop. 2. Для отправки ответных данных служит пользовательская функция CDC_Transmit_FS(...) вызываемая из любого места, в частности из MainLoop. В ней сначала заполняется буфер, затем вызывается функция USBD_CDC_SetTxBuffer(hUsbDevice_0, UserTxBufferFS, Len), затем собственно отправка пакета USBD_CDC_TransmitPacket(hUsbDevice_0) (внутренняя функция HAL). Сначала CDC_Transmit_FS вызывалась прямо в CDC_Receive_FS (т.е. на уровне прерываний) для контроля эхо и все работало идеально. Затем, для анализа и формирования ответного пакета, перенес CDC_Transmit_FS в MainLoop. И вот тут начались проблемы. Т.е. все (эхо) работает нормально до какого-то момента, а, затем, затыкается навсегда из-за того, что передача пакета зависает навсегда - при попытке вызова USBD_CDC_TransmitPacket она возвращает USBD_BUSY. Всякие эксперименты дали следующее - все начинает работать прекрасно, если перед вызовом USBD_CDC_TransmitPacket запретить прерывания, а, потом, снова разрешить. Но это как-то слишком криво получается. Т.е. похоже, что если при выполнении USBD_CDC_TransmitPacket происходит прерывание, то HALовская система обалдевает. Никто с подобным не сталкивался? P.S. Да, сейчас прерывания "плоские", т.е. все на одном уровне приоритета. Может тут можно поиграться? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться