STM32 USB VCP-помилка


8

Я працюю над проектом протягом останніх двох тижнів і налагодження цього питання займало цілий тиждень. Цікаво, чи може хтось допомогти, я постараюся бути максимально чітким і зрозумілим.

Я намагаюся реалізувати USB-порт Virtual Comm на MicroController на базі STM32F302K8 (Cortex M4). Я використовував STM32CubMX для створення коду, необхідного для налаштування USB-пристрою повної швидкості, що реалізує клас CDC. Мій пристрій відображається в Windows (Диспетчер пристроїв) та Linux. Я можу реалізувати просту ехо-функцію на основі прикладу коду, але коли я зараз намагаюся використовувати функцію USBD_CDC_SetTxBuffer для надсилання даних на ПК, це запускає Hard Fault Handler. Я звузив це до того, що поле UsbDeviceFS.pClass (який потрібен USBD_CDC_SetTxBuffer) поле ніколи не ініціалізується, оскільки USBD_CDC_Init () ніколи не викликається при ініціалізації USB-пристрою.

Я реалізував виправлення декількох помилок (включаючи зміну розміру купи, виправлення прапора передачі в USBD_CDC_TransmitPacket та зміну розміру CDC_DATA_HS_MAX_PACKET_SIZE до 256 з 512) у коді прикладу, як це зафіксовано на форумі ST, але все ще отримує ту саму помилку.

Код налаштування мого пристрою є

* USB Device Core handle declaration */
USBD_HandleTypeDef hUsbDeviceFS;

/* init function */                    
void MX_USB_DEVICE_Init(void)
{
  /* Init Device Library,Add Supported Class and Start the library*/
  USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS);

  USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC);

  USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS);

  USBD_Start(&hUsbDeviceFS);

}

Минуло деякий час, коли я востаннє працював з USB на STM, але я думаю, що USBD_CDC_Init () намагається зробити недолік. Проблема полягала в тому, що в купі не вистачає місця в налаштуваннях за замовчуванням, і вам потрібно збільшити її.
brhans

Привіт, я збільшив розмір купи до 0x600 і нічого не відбувається. Яка функція викликає malloc, оскільки коли я ставлю на неї точку розриву, вона здається, що її ніколи не викликають.
Галактика

Відповіді:


6

Щоб відповісти на моє власне питання, проблема полягає в тому, що мій код не чекав, коли USB закінчить ініціалізацію, і негайно почав надсилати дані. Включення активного очікування на булевий або додавання затримки (як вказував @ramez) вирішує проблему.

ОНОВЛЕННЯ Ця помилка була виправлена ​​у наступних версіях драйверів USB CDC від ST. Зараз у налаштуваннях є HAL_Delay. Застереження полягає в тому, що якщо з будь-якої причини Sys_Tick не працює / деактивовано / ще не ініціалізовано, ваш код зависне.


1
Так, ви повинні розмістити це як окреме запитання. Зберігайте в цій відповіді лише ту інформацію, яка стосується початкового питання.
м.Алін

2

Я використовував CubeMX для створення коду для відкриття STM32F4. Я використовував його як віртуальний COM-порт як ви. Я не використовував функцію USBD_CDC_SetTxBuffer () безпосередньо. У файлі usbd_cdc_if.c є функція під назвою CDC_Transmit_FS () . У генерованому коді була помилка, функція приймала буфер як параметр, і вона нічого не робила з цим. Виправлений код функції наступний:

uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
  uint8_t result = USBD_OK;
  memcpy(UserTxBufferFS, Buf, sizeof(char) * Len);
  USBD_CDC_SetTxBuffer(hUsbDevice_0, UserTxBufferFS, Len);   
  result = USBD_CDC_TransmitPacket(hUsbDevice_0);
  return result;
}

Насправді мені довелося додати memcpy до коду. Після цієї корекції я міг надсилати дані з мікрокотроляра на ПК із цією функцією передачі. Наприклад:

int main(void)
{
  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();
  MX_USB_DEVICE_Init();
  configureGPIOs();

  uint8_t Buf[] = "Test";

  HAL_Delay(1000);

  while (1)
  {
      CDC_Transmit_FS(Buf, 4);
      HAL_Delay(1000);
  }
}

Ініталізація в MX_USB_DEVICE_Init () у мене така ж, як і у вас.


1
Дякую, ramez Я виявив проблему, мені довелося перевірити, чи закінчився ініціалізація віртуального комунікаційного порту, я використав булевий файл в CDC_Init_FS, головний цикл якого чекав, щоб бути правдою, перш ніж викликати CDC_Transmit_FS. Я думаю, що HAL_DELAY у вашому коді досягає такого ж ефекту. Дякую за допомогу.
Галактика

1

Спочатку перевірте, чи hUsbDevice_0 є нульовим (пропущений елемент у вашому рішенні):

    if (hUsbDevice_0 == NULL)
            return USBD_FAIL;

Це не дозволить повісити ваш UC і не потребує зайнятого очікування у затримках.

Ви можете розмістити його десь у CDC_Transmit_FS:

USBD_StatusTypeDef CDC_Transmit_FS(uint8_t* Buf, uint16_t Len) {

    if (hUsbDevice_0 == NULL)
        return USBD_FAIL;

    USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) hUsbDevice_0->pClassData;

    if (hcdc->TxState != 0)
        return USBD_BUSY;

    uint8_t result = USBD_OK;

    USBD_CDC_SetTxBuffer(hUsbDevice_0, Buf, Len);
    result = USBD_CDC_TransmitPacket(hUsbDevice_0);

    return result;
}

0

У мене була така ж проблема, але виявилося, що єдине, що мені потрібно зробити - це підключити USB-з'єднання до комп'ютера. Більшість разів ви прошиваєте код і скидаєте мікроконтролер, але з боку ПК перерахування не оновлюється. USBD_CDC_Init викликається, коли хост починає зондувати ваш пристрій, і тому pClassData NULL.


1
Ви також можете примусити перерахувати програмне забезпечення. Другий тупий спосіб після повторного підключення - це відключення / включення вашого порту в диспетчері пристроїв, якщо у вас немає спеціального драйвера, який обробляє це більш вигадливим чином
stiebrs
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.