|
STM32CubeMX и USB CDC, какие функции использовать? |
|
|
|
Jul 15 2014, 20:01
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(Integro @ Jul 15 2014, 14:38)  посмотрите в файле usbd_cdc_if.c, CDC_Transmit_FS и callback CDC_Receive_FS Пробовал эти функции, но ... их не видит проект. Кое-что получается с USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf_Ch, 4); USBD_CDC_TransmitPacket(&hUsbDeviceFS);
|
|
|
|
|
Jul 16 2014, 07:50
|

Частый гость
 
Группа: Свой
Сообщений: 167
Регистрация: 25-12-09
Из: Минск
Пользователь №: 54 460

|
Цитата(ViKo @ Jul 15 2014, 23:01)  Пробовал эти функции, но ... их не видит проект. Кое-что получается с USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf_Ch, 4); USBD_CDC_TransmitPacket(&hUsbDeviceFS); Что значит не видит проект? Файл исключен из сборки? Самый простой способ проверить работу, поставить брекпоинт в функцию CDC_Receive_FS, затем в терминале на PC что либо отправить
Сообщение отредактировал Integro - Jul 16 2014, 08:14
|
|
|
|
|
Jul 16 2014, 12:49
|

Частый гость
 
Группа: Свой
Сообщений: 167
Регистрация: 25-12-09
Из: Минск
Пользователь №: 54 460

|
Цитата(ViKo @ Jul 16 2014, 11:19)  Из мейн функции не видны. Можно инклюдами заголовок добавить. Но, если этого не сделано, значит их использовать не нужно. Если это не сделано значит это нужно сделать.) Не стоит доверять сырым либам от ST, мы в мае месяце не один баг у них нашли, благо обновления основную часть устранили. Для работы с Виртуальным портом необходимо использовать функции описанные выше. 1. Проверить приходят ли данные в CDC_Receive_FS для этого просто ставим бряк, как я писал выше, если приходят в данной функции вызываем вашу реализация функции обработки принятых данных. 2. Сделать обертку для CDC_Transmit_FS в каком ни-будь вашем файле ("Platform.c" или "hal_DeviceName.c" не суть что там у вас) CDC_Write. А вообще на данный момент не рекомендовал бы использовать Cube, подождите пару месяцев, а текущий проект доделайте на CMSIS.
Сообщение отредактировал Integro - Jul 16 2014, 12:53
|
|
|
|
|
Jul 17 2014, 15:06
|

Частый гость
 
Группа: Свой
Сообщений: 167
Регистрация: 25-12-09
Из: Минск
Пользователь №: 54 460

|
Цитата(ViKo @ Jul 16 2014, 19:18)  Кабы я умел программировать USB в STM32, стал бы я связываться с Кубами, Либами, Миддлеварами и пр. Мой путь обратный - от вышеперечисленного к своему. Те функции, что я использовал (см. выше), позволили передавать массив символов. Вокруг них и буду танцевать. Посмотрите на реализацию функции CDC_Transmit_FS а затем на ваш вариант, да! это одно и тоже. Теперь, с точки зрения работоспособности кода... можно писать говнокод. Но можно сделать красивее, практичнее и тд...
|
|
|
|
|
Jul 20 2014, 10:14
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Вот функция из usbd_cdc_if.c Код /** * @brief CDC_Transmit_FS * Data send over USB IN endpoint are sent over CDC interface * through this function. * @note * * * @param Buf: Buffer of data to be send * @param Len: Number of data to be send (in bytes) * @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY */ uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len) { uint8_t result = USBD_OK; /* USER CODE BEGIN 8 */ USBD_CDC_SetTxBuffer(hUsbDevice_0, UserTxBufferFS, Len); result = USBD_CDC_TransmitPacket(hUsbDevice_0); /* USER CODE END 8 */ return result; } Вопрос - как?! Как используется параметр Buf? А вот еще один шедевр оттуда же. Код /** * @brief CDC_Receive_FS * Data received over USB OUT endpoint are sent over CDC interface * through this function. * * @note * This function will block any OUT packet reception on USB endpoint * untill exiting this function. If you exit this function before transfer * is complete on CDC interface (ie. using DMA controller) it will result * in receiving more data while previous ones are still not sent. * * @param Buf: Buffer of data to be received * @param Len: Number of data received (in bytes) * @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL */ static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len) { /* USER CODE BEGIN 7 */ return (USBD_OK); /* USER CODE END 7 */ } Это означает, что мне нужно поработать там своей головой?
|
|
|
|
|
Jul 23 2014, 08:12
|

Частый гость
 
Группа: Свой
Сообщений: 167
Регистрация: 25-12-09
Из: Минск
Пользователь №: 54 460

|
Цитата(ViKo @ Jul 20 2014, 13:14)  ... Ха, ща разберемся, у меня не так) это последняя версия Cube? Говорю сырой этот куб еще....
Сообщение отредактировал IgorKossak - Jul 24 2014, 13:46
Причина редактирования: бездумное цитирование
|
|
|
|
|
Jul 24 2014, 12:19
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(Integro @ Jul 23 2014, 11:12)  Ха, ща разберемся, у меня не так) это последняя версия Cube? Говорю сырой этот куб еще.... Крайняя (не последняя, надеюсь  ) Я тут решил взяться за изучение всех функций по-порядку, закопался... Пытался отладчик запустить, трассировку - ничего не видит. Пытался другой проект запустить - тоже самое. И логический анализатор ничего не показывает. А ведь показывал. Обновил Keil - не помогло. Обновил прошивку ST-Link на Discovery - вообще не программируется, не отлаживается. Вернул назад Keil, и ST-Link. По-прежнему, трассировка не работает. Кто сбил мой ераплан прицел? Горячие дни.
|
|
|
|
|
Jul 24 2014, 14:51
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(Tahoe @ Jul 24 2014, 17:32)  Ну да, колбэки - они такие, прямолинейный подход не поможет.  Нет, я другой проектик запустил, там нет таких страхов. Но все равно ЛА не работает. В окне "Watch 1" вижу, что переменная меняется, а в окне Logic Analyzer - нет. Она по разным цепям попадает. Хотя на SWO вижу, что-то выдается. P.S. не ползет время в ЛА. P.P.S. Да, и перемычку SB10 на F3Discovery я давно запаял. И что-то видел раньше, не помню, то ли, что хочу сейчас, или другое...
|
|
|
|
|
Jul 30 2014, 20:37
|
Частый гость
 
Группа: Участник
Сообщений: 139
Регистрация: 9-11-12
Из: Санкт-Петербург
Пользователь №: 74 315

|
Цитата(ViKo @ Jul 20 2014, 14:14)  Вот функция из usbd_cdc_if.c Код /** uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len) ... Вопрос - как?! Как используется параметр Buf? А вот еще один шедевр оттуда же. Код static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len) ... Это означает, что мне нужно поработать там своей головой? Если кому ещё интересно, то вот: Внутри CDC_Transmit_FS нужно самостоятельно выполнить нужные действия. Например, скопировать или дописать содержимое Buf в UserTxBufferFS. Внутри CDC_Receive_FS нужно обработать пришедшие по USB данные. Чтобы следующий пакет успешно принялся, нужно после обработки данных (в главном цикле либо тут же в CDC_Receive_FS) вызвать USBD_CDC_ReceivePacket(hUsbDevice_0)
Сообщение отредактировал den_po - Jul 30 2014, 20:41
|
|
|
|
|
Jul 31 2014, 06:17
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(den_po @ Jul 31 2014, 00:37)  Если кому ещё интересно, то вот: Внутри CDC_Transmit_FS нужно самостоятельно выполнить нужные действия. Например, скопировать или дописать содержимое Buf в UserTxBufferFS. Внутри CDC_Receive_FS нужно обработать пришедшие по USB данные. Чтобы следующий пакет успешно принялся, нужно после обработки данных (в главном цикле либо тут же в CDC_Receive_FS) вызвать USBD_CDC_ReceivePacket(hUsbDevice_0) очень интересно! с передачей более менее понятно, а вот с приемом данных не совсем. где у Вас вызывается CDC_Receive_FS? у меня в проекте, например, эта функция вызывается один раз - при инициализации, в функии MX_USB_DEVICE_Init.
|
|
|
|
|
Jul 31 2014, 07:49
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(den_po @ Jul 31 2014, 11:33)  Её не нужно самостоятельно вызывать, это колбэк, он вызывается при поступлении данных. А вот сообщать, что мы готовы принимать очередной пакет, нужно уже самому с помощью USBD_CDC_ReceivePacket. так я и спрашиваю, где она у Вас вызывается? весь путь по которому CDC_Transmit_FS вызывается, он ведь должен вести в конце концов к OTG_HS_IRQHandler? там обрабатывается флаг прихода данных, вызывается куча функций и в конце концов CDC_Transmit_FS, так ведь должно быть? у меня CDC_Transmit_FS из OTG_FS_IRQHandler не вызывается.
|
|
|
|
|
Jul 31 2014, 08:08
|
Частый гость
 
Группа: Участник
Сообщений: 139
Регистрация: 9-11-12
Из: Санкт-Петербург
Пользователь №: 74 315

|
Цитата(Atlantis- @ Jul 31 2014, 11:49)  так я и спрашиваю, где она у Вас вызывается? весь путь по которому CDC_Transmit_FS вызывается, он ведь должен вести в конце концов к OTG_HS_IRQHandler? там обрабатывается флаг прихода данных, вызывается куча функций и в конце концов CDC_Transmit_FS, так ведь должно быть? у меня CDC_Transmit_FS из OTG_FS_IRQHandler не вызывается. Давайте для начала определимся, CDC_Transmit_FS или CDC_Receive_FS. CDC_Transmit_FS вызывается по желанию. Я пробовал и из главного цикла, и из CDC_Receive_FS. CDC_Receive_FS в моём случае (stm32f072) вызывается по такой цепочке: USB_IRQHandler -> HAL_PCD_IRQHandler -> PCD_EP_ISR_Handler -> HAL_PCD_DataOutStageCallback -> USBD_LL_DataOutStage -> USBD_CDC_DataOut -> CDC_Receive_FS. Вызывается колбэк не напрямую, а через табличку указателей, которая регистрируется в функции MX_USB_DEVICE_Init (usb_device.c)
|
|
|
|
|
Jul 31 2014, 08:29
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(den_po @ Jul 31 2014, 12:08)  Давайте для начала определимся, CDC_Transmit_FS или CDC_Receive_FS. CDC_Transmit_FS вызывается по желанию. Я пробовал и из главного цикла, и из CDC_Receive_FS. CDC_Receive_FS в моём случае (stm32f072) вызывается по такой цепочке: USB_IRQHandler -> HAL_PCD_IRQHandler -> PCD_EP_ISR_Handler -> HAL_PCD_DataOutStageCallback -> USBD_LL_DataOutStage -> USBD_CDC_DataOut -> CDC_Receive_FS. Вызывается колбэк не напрямую, а через табличку указателей, которая регистрируется в функции MX_USB_DEVICE_Init (usb_device.c) извините перепутал, CDC_Receive_FS конечно. у меня проект для STM32F429ZI (точнее для платы Discovery с ним), так вот там CDC_Receive_FS вызывается только при инициализации, а в прерывании - нет. теперь, зная Вашу цепочку, я наверное смогу прописать вызов CDC_Receive_FS куда надо)) Цитата(den_po @ Jul 31 2014, 12:08)  Вызывается колбэк не напрямую, а через табличку указателей, которая регистрируется в функции MX_USB_DEVICE_Init (usb_device.c) что за табличка кстати?
|
|
|
|
|
Jul 31 2014, 10:05
|
Частый гость
 
Группа: Участник
Сообщений: 139
Регистрация: 9-11-12
Из: Санкт-Петербург
Пользователь №: 74 315

|
Цитата(Atlantis- @ Jul 31 2014, 12:29)  извините перепутал, CDC_Receive_FS конечно. у меня проект для STM32F429ZI (точнее для платы Discovery с ним), так вот там CDC_Receive_FS вызывается только при инициализации, а в прерывании - нет. теперь, зная Вашу цепочку, я наверное смогу прописать вызов CDC_Receive_FS куда надо)) А может, при инициализации срабатывает прерывание? Данные в МК чем посылаются? Я писал уже, после вызова CDC_Receive_FS нужно вызывать USBD_CDC_ReceivePacket, иначе следующий пакет не примется. Точно дело не в этом? Цитата(Atlantis- @ Jul 31 2014, 12:29)  что за табличка кстати? Код USBD_CDC_ItfTypeDef USBD_Interface_fops_FS = { CDC_Init_FS, CDC_DeInit_FS, CDC_Control_FS, CDC_Receive_FS };
|
|
|
|
|
Jul 31 2014, 10:42
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(den_po @ Jul 31 2014, 14:05)  А может, при инициализации срабатывает прерывание? Данные в МК чем посылаются? хм, может, ну и что. данные посылаю из фирменной тестовой программы Цитата(den_po @ Jul 31 2014, 14:05)  Я писал уже, после вызова CDC_Receive_FS нужно вызывать USBD_CDC_ReceivePacket, иначе следующий пакет не примется. Точно дело не в этом? я прикрутил прием данных в USBD_LL_DataOutStage, после отправки второго пакета тестовая программа виснет, видимо нет подтверждения или еще чего. причем USBD_CDC_ReceivePacket меня не спас. ой, сейчас поробовал - уже не виснет=))) можете показать содержимое функции USBD_LL_DataOutStage, а то у меня там никакой USBD_CDC_DataOut нет, она фигурирует только в структуре Код /* CDC interface class callbacks structure */ USBD_ClassTypeDef USBD_CDC = { USBD_CDC_Init, USBD_CDC_DeInit, USBD_CDC_Setup, NULL, /* EP0_TxSent, */ USBD_CDC_EP0_RxReady, USBD_CDC_DataIn, USBD_CDC_DataOut, NULL, NULL, NULL, USBD_CDC_GetHSCfgDesc, USBD_CDC_GetFSCfgDesc, USBD_CDC_GetOtherSpeedCfgDesc, USBD_CDC_GetDeviceQualifierDescriptor, }; причем USBD_CDC опять нигде не фигурирует, только в Код #define USBD_CDC_CLASS &USBD_CDC , а USBD_CDC_CLASS нигде больше нет Цитата(den_po @ Jul 31 2014, 14:05)  Код USBD_CDC_ItfTypeDef USBD_Interface_fops_FS = { CDC_Init_FS, CDC_DeInit_FS, CDC_Control_FS, CDC_Receive_FS }; такая табличка у меня есть
Сообщение отредактировал Atlantis- - Jul 31 2014, 11:32
|
|
|
|
|
Jul 31 2014, 12:18
|
Частый гость
 
Группа: Участник
Сообщений: 139
Регистрация: 9-11-12
Из: Санкт-Петербург
Пользователь №: 74 315

|
Цитата(Atlantis- @ Jul 31 2014, 14:42)  я прикрутил прием данных в USBD_LL_DataOutStage Вот этого не понял Цитата(Atlantis- @ Jul 31 2014, 14:42)  можете показать содержимое функции 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 */ Из-за этого херится чужая память.
|
|
|
|
|
Jul 31 2014, 12:33
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(den_po @ Jul 31 2014, 16:18)  Вот этого не понял вот так CODE 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 пробовал вставлять обработку данных, но чуда не произошло. если она нигде не вызывается, что поделаешь
Сообщение отредактировал IgorKossak - Jul 31 2014, 12:34
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
|
Jul 31 2014, 13:53
|
Частый гость
 
Группа: Участник
Сообщений: 139
Регистрация: 9-11-12
Из: Санкт-Петербург
Пользователь №: 74 315

|
Цитата(Atlantis- @ Jul 31 2014, 16:33)  вот так Почему так? Цитата(Atlantis- @ Jul 31 2014, 16:33)  у меня - нет Неправда. В процитированном вами коде строчка pdev->pClass->DataOut(pdev, epnum); - это вызов функции из таблички и есть. Вызывает USBD_CDC_DataOut. В USBD_CDC_DataOut строчка ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Receive(hcdc->RxBuffer, &hcdc->RxLength); вызывает CDC_Receive_FS. Цитата(Atlantis- @ Jul 31 2014, 16:33)  CDC_Transmit_FS - не знаю, по моему она у меня тоже нигде не вызывается. в принципе то она и не нужна в CDC_Receive_FS пробовал вставлять обработку данных, но чуда не произошло. если она нигде не вызывается, что поделаешь Конкретно предложенный мной вариант не работает? Очень неприятный баг. Когда отправляю в МК данные из программы, написанной на c#, если за раз отправлено больше 6 байт, то на МК они приходят нормально, но в ответ от МК начинаю получать мусор. То же самое, если с МК передаю больше 8 байт, на комп приходит мусор.
Сообщение отредактировал den_po - Jul 31 2014, 19:13
|
|
|
|
|
Aug 1 2014, 05:55
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(den_po @ Jul 31 2014, 16:18)  Хе, сейчас вот наткнулся на баг в 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, хм все работает
|
|
|
|
|
Aug 1 2014, 11:08
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата Проверьте свежесгенерированный кубом код, измените только эти две функции: Цитата В процитированном вами коде строчка 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; } }
Сообщение отредактировал Atlantis- - Aug 1 2014, 11:09
|
|
|
|
|
Aug 1 2014, 12:02
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(den_po @ Aug 1 2014, 15:29)  CDC_Transmit_FS нужно вызывать самостоятельно, когда нужно передать что-то компьютеру. А USBD_CDC_DataIn просто делает отметку, мол данные переданы. в библиотеке STM32F103 был колбэк, который вызывался каждые 1 мс, я в нем проверял есть ли данные и отправлял если они были. а свой счетчик отправлял каждые 1 мс для чего вот этот вызов? Код memcpy(UserTxBufferFS,Buf,Len); у меня если его использовать, тоже ерунда приходит
|
|
|
|
|
Aug 2 2014, 13:01
|
Частый гость
 
Группа: Участник
Сообщений: 139
Регистрация: 9-11-12
Из: Санкт-Петербург
Пользователь №: 74 315

|
Думаю, ерунда может приходить, если отправляются данные раньше, чем успевают передаться прошлые. Можно решить это например так: Код 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 пробовать.
|
|
|
|
|
Aug 3 2014, 00:16
|
Частый гость
 
Группа: Участник
Сообщений: 139
Регистрация: 9-11-12
Из: Санкт-Петербург
Пользователь №: 74 315

|
Баг с мусором в 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)
Сообщение отредактировал den_po - Aug 3 2014, 00:18
|
|
|
|
|
Oct 15 2014, 16:29
|
Группа: Новичок
Сообщений: 2
Регистрация: 15-10-14
Пользователь №: 83 154

|
Цитата ( Предыдущий баг - должно быть 15, а не 5) Ну, по моему не 15 там должно быть, а просто перепутано 5 и 8 местами. Т.е. МК поддерживает 8 endpoints, а для CDC используется 5. control in out bulk data in out command in Я тут по ходу пиесы прикручиваю плюсовые классы-адаптеры кубовых драйверов для freertos, ну и приходится разбираться с этими внутренностями.
|
|
|
|
|
Oct 17 2014, 20:26
|
Частый гость
 
Группа: Участник
Сообщений: 139
Регистрация: 9-11-12
Из: Санкт-Петербург
Пользователь №: 74 315

|
Цитата(Vsevolod Gromov @ Oct 15 2014, 20:29)  Ну, по моему не 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, но кто-то случайно удалил символ.
|
|
|
|
|
Oct 20 2014, 08:12
|
Местный
  
Группа: Участник
Сообщений: 491
Регистрация: 18-05-11
Пользователь №: 65 102

|
Цитата(den_po @ Jul 31 2014, 00:37)  Если кому ещё интересно, то вот: Внутри 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 прописать?
|
|
|
|
|
Oct 20 2014, 10:23
|
Группа: Новичок
Сообщений: 2
Регистрация: 15-10-14
Пользователь №: 83 154

|
Цитата(den_po @ Oct 18 2014, 00:26)  Там должно быть не меньше, чем 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 килобод.
|
|
|
|
|
Nov 14 2015, 16:43
|
Знающий
   
Группа: Свой
Сообщений: 888
Регистрация: 25-09-08
Из: Питер
Пользователь №: 40 458

|
Вопрос на ту же тему. Поднял 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. Да, сейчас прерывания "плоские", т.е. все на одном уровне приоритета. Может тут можно поиграться?
|
|
|
|
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|