Lỗi VCP USB STM32


8

Tôi đã làm việc trên một dự án trong hai tuần qua và việc gỡ lỗi một vấn đề này đã chiếm hết cả tuần này. Tự hỏi nếu có ai có thể giúp đỡ, tôi sẽ cố gắng rõ ràng và rõ ràng nhất có thể.

Tôi đang cố gắng triển khai Cổng USB Virtual Comm trên MicroContoder dựa trên STM32F302K8 (Cortex M4). Tôi đã sử dụng STM32CubMX để tạo mã cần thiết để thiết lập Thiết bị tốc độ đầy đủ USB triển khai lớp CDC. Thiết bị của tôi xuất hiện trong cả Windows (Trình quản lý thiết bị) và Linux. Tôi có thể thực hiện một chức năng echo đơn giản dựa trên mã ví dụ nhưng khi tôi cố gắng sử dụng chức năng USBD_CDC_SetTxBuffer để gửi dữ liệu tới PC, điều này sẽ tắt Trình xử lý lỗi cứng. Tôi đã thu hẹp điều này xuống thực tế là trường USBDeviceFS.pClass (cần thiết bởi USBD_CDC_SetTxBuffer) không bao giờ được khởi tạo vì USBD_CDC_Init () không bao giờ được gọi trong quá trình khởi tạo Thiết bị USB.

Tôi đã thực hiện sửa một số lỗi (bao gồm thay đổi kích thước heap, sửa cờ truyền trong USBD_CDC_TransmitPacket và thay đổi kích thước của CDC_DATA_HS_MAX_PACKET_SIZE thành 256 từ 512) trong mã ví dụ như được ghi lại trên diễn đàn ST.

Mã thiết lập thiết bị của tôi là

* 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);

}

Đã được một thời gian kể từ lần cuối tôi làm việc với USB trên STM, nhưng tôi nghĩ rằng USBD_CDC_Init () cố gắng thực hiện một malloc. Vấn đề là không có đủ dung lượng trên heap trong thiết lập mặc định và bạn cần tăng nó.
Brhans

Xin chào, tôi đã tăng kích thước heap lên 0x600 và không có gì xảy ra. Hàm nào gọi malloc vì khi tôi đặt điểm dừng trên nó, nó xuất hiện không bao giờ được gọi.
Galaxy

Câu trả lời:


6

Để trả lời câu hỏi của riêng tôi, vấn đề là mã của tôi đã không đợi USB hoàn thành việc khởi tạo và ngay lập tức bắt đầu gửi dữ liệu. Chèn một chờ đợi hoạt động trên một boolean hoặc thêm một độ trễ (như được chỉ ra bởi @ramez) sẽ giải quyết vấn đề.

CẬP NHẬT Lỗi này đã được sửa trong các phiên bản trình điều khiển USB CDC tiếp theo từ ST. Hiện tại đã có HAL_Delay trong thiết lập. Hãy cẩn thận là nếu vì bất kỳ lý do nào, Sys_Tick không hoạt động / bị vô hiệu hóa / chưa được khởi tạo, mã của bạn sẽ bị treo.


1
Có, bạn nên đăng bài này như một câu hỏi riêng biệt. Giữ trong câu trả lời này chỉ những thông tin liên quan cho câu hỏi ban đầu.
m.Alin

2

Tôi đã sử dụng CubeMX để tạo mã cho khám phá STM32F4. Tôi đã sử dụng nó như cổng COM ảo như bạn. Tôi không sử dụng trực tiếp hàm USBD_CDC_SetTxBuffer () . Trong tệp usbd_cdc_if.c có một hàm có tên CDC_Transmit_FS () . Có một lỗi trong mã được tạo, hàm lấy một bộ đệm làm tham số và nó không làm gì với nó. Mã chức năng đã sửa là như sau:

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;
}

Thật ra tôi đã phải thêm memcpy vào mã. Sau khi hiệu chỉnh, tôi có thể gửi dữ liệu từ vi điều khiển đến PC với chức năng truyền này. Ví dụ:

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);
  }
}

Việc initalization trong MX_USB_DEVICE_Init () giống với tôi như của bạn.


1
Cảm ơn bạn ramez. Tôi đã tìm thấy vấn đề, tôi phải kiểm tra xem cổng comm ảo đã khởi tạo xong chưa, tôi đã sử dụng một boolean trong CDC_Init_FS mà vòng lặp chính chờ là đúng trước khi gọi CDC_Transmit_FS. Tôi nghĩ rằng HAL_DELAY trong mã của bạn đạt được hiệu quả tương tự. Cảm ơn bạn vì sự giúp đỡ.
Galaxy

1

Trước tiên, hãy kiểm tra xem hUsbDevice_0 có null không (phần tử bị thiếu trong giải pháp của bạn):

    if (hUsbDevice_0 == NULL)
            return USBD_FAIL;

Điều này sẽ ngăn việc treo uC của bạn và không cần phải chờ đợi trong sự chậm trễ.

Bạn có thể đặt nó ở đâu đó trong 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

Tôi gặp vấn đề tương tự nhưng hóa ra điều duy nhất tôi cần làm là cắm lại kết nối USB vào máy tính. Hầu hết thời gian bạn flash mã và thiết lập lại vi điều khiển nhưng ở phía PC, bảng liệt kê không được cập nhật. USBD_CDC_Init được gọi khi máy chủ bắt đầu thăm dò thiết bị của bạn và đó là lý do tại sao pClassData là NULL.


1
Bạn cũng có thể buộc liệt kê lại trong phần mềm. Cách ngu ngốc thứ hai sau khi cắm lại là vô hiệu hóa / bật cổng của bạn trong trình quản lý thiết bị, nếu bạn không có trình điều khiển tùy chỉnh xử lý việc này theo cách lạ mắt hơn
stiebrs
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.