реклама на сайте
подробности

 
 
> STM32CubeMX и USB CDC, какие функции использовать?
ViKo
сообщение Jul 14 2014, 18:00
Сообщение #1


Универсальный солдатик
******

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



Уже появилась в CubeMX поддержка STM32F3. Сделал проект для STM32F3Discovery. Подключаю к компьютеру - обнаруживается Virtual COM Port. Но как его использовать? В main программе на месте пользовательского кода - пустые места. Наверное, где-то описаны пара функций для работы - принять, послать. И буферы создать нужно. Не вижу ни в документации, ни в примерах. Поможите, люди добрые!
Go to the top of the page
 
+Quote Post
3 страниц V  < 1 2 3  
Start new topic
Ответов (30 - 44)
den_po
сообщение Jul 31 2014, 12:18
Сообщение #31


Частый гость
**

Группа: Участник
Сообщений: 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            */

Из-за этого херится чужая память.
Go to the top of the page
 
+Quote Post
Atlantis-
сообщение Jul 31 2014, 12:33
Сообщение #32


Местный
***

Группа: Участник
Сообщений: 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] - для короткого!!!
Go to the top of the page
 
+Quote Post
den_po
сообщение Jul 31 2014, 13:53
Сообщение #33


Частый гость
**

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
Atlantis-
сообщение Aug 1 2014, 05:55
Сообщение #34


Местный
***

Группа: Участник
Сообщений: 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, хм все работает blink.gif
Go to the top of the page
 
+Quote Post
Atlantis-
сообщение Aug 1 2014, 11:08
Сообщение #35


Местный
***

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
den_po
сообщение Aug 1 2014, 11:29
Сообщение #36


Частый гость
**

Группа: Участник
Сообщений: 139
Регистрация: 9-11-12
Из: Санкт-Петербург
Пользователь №: 74 315



CDC_Transmit_FS нужно вызывать самостоятельно, когда нужно передать что-то компьютеру.
А USBD_CDC_DataIn просто делает отметку, мол данные переданы.

А у меня всё равно данные портятся. Энное количество работает, а потом от МК приходит мусор =( Причём отправляются нормальные данные.
Go to the top of the page
 
+Quote Post
Atlantis-
сообщение Aug 1 2014, 12:02
Сообщение #37


Местный
***

Группа: Участник
Сообщений: 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);

у меня если его использовать, тоже ерунда приходит
Go to the top of the page
 
+Quote Post
den_po
сообщение Aug 2 2014, 13:01
Сообщение #38


Частый гость
**

Группа: Участник
Сообщений: 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 пробовать.
Go to the top of the page
 
+Quote Post
den_po
сообщение Aug 3 2014, 00:16
Сообщение #39


Частый гость
**

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
den_po
сообщение Aug 6 2014, 12:19
Сообщение #40


Частый гость
**

Группа: Участник
Сообщений: 139
Регистрация: 9-11-12
Из: Санкт-Петербург
Пользователь №: 74 315



Последняя проблема - моя ошибка. Просто драйвер на компе иногда отдаёт не пакет полностью, а один байт. А я, дурак, читал в тот же буфер и не глядел длину прочитанного.
Go to the top of the page
 
+Quote Post
Vsevolod Gromov
сообщение Oct 15 2014, 16:29
Сообщение #41





Группа: Новичок
Сообщений: 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, ну и приходится разбираться с этими внутренностями.
Go to the top of the page
 
+Quote Post
den_po
сообщение Oct 17 2014, 20:26
Сообщение #42


Частый гость
**

Группа: Участник
Сообщений: 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, но кто-то случайно удалил символ.
Go to the top of the page
 
+Quote Post
Atlantis-
сообщение Oct 20 2014, 08:12
Сообщение #43


Местный
***

Группа: Участник
Сообщений: 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 прописать?
Go to the top of the page
 
+Quote Post
Vsevolod Gromov
сообщение Oct 20 2014, 10:23
Сообщение #44





Группа: Новичок
Сообщений: 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 килобод.
Go to the top of the page
 
+Quote Post
rudy_b
сообщение Nov 14 2015, 16:43
Сообщение #45


Знающий
****

Группа: Свой
Сообщений: 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. Да, сейчас прерывания "плоские", т.е. все на одном уровне приоритета. Может тут можно поиграться?
Go to the top of the page
 
+Quote Post

3 страниц V  < 1 2 3
Reply to this topicStart new topic
3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 22:19
Рейтинг@Mail.ru


Страница сгенерированна за 0.01526 секунд с 7
ELECTRONIX ©2004-2016