[方案相关] 【华大测评】+ HC32F460 WINUSB移植、遇到的问题与解决方法

[复制链接]
7210|4
手机看帖
扫描二维码
随时随地手机跟帖
纪国圣|  楼主 | 2021-10-2 10:19 | 显示全部楼层 |阅读模式
最近有空测试了一下官方的VCP例程,使用感觉不错,将其稍微改动做了一个CDC回环测试,速率也不错,就是安装驱动有些麻烦,于是想直接将CDC改写成WINUSB不就不需要驱动了吗?于是抽空从之前写的STM32 WINUSB移植到HC32F460。一、移植的方法
修改的话主要是在CDC的基础上添加有关描述符的发送等函数。修改方法如下:

1.修改头文件usb_core_driver.h中的结构体usb_dev_class_func,添加如下成员:
1.PNG
2.修改usb_dev_stdreq.c中的void hd_usb_getdesc(usb_core_instance *pdev, const USB_SETUP_REQ *req),添加如下语句:
2.PNG

3.添加宏定义USBD_SUPPORT_USER_STRING_DESC:
3.PNG
4.修改usb_dev_cdc_class.c中的usb_dev_class_func  class_cdc_cbk,添加成员变量:

4.PNG
5.添加extern __USB_ALIGN_BEGIN uint8_t usb_dev_strdesc[USB_MAX_STR_DESC_SIZ] __USB_ALIGN_END、__USB_ALIGN_BEGIN uint8_t USBD_WINUSB_OSFeatureDesc[USB_LEN_OS_FEATURE_DESC] __USB_ALIGN_END、uint8_t *USBD_WinUSBOSFeatureDescriptor(uint16_t *length):
5.PNG
6.PNG
6.修改配置描述符:
7.PNG
8.PNG
7.修改usb_dev_core.c中的void hd_usb_setup_process(usb_core_instance *pdev),添加如下语句:
9.PNG
8.继续在usb_dev_cdc_class.c中添加有关描述符的函数:
10.PNG
11.PNG
12.PNG
13.PNG
14.PNG
9.至此WINUSB修改完毕。为了测试发送速度,在做一些修改:
15.PNG
15_1.PNG
16.PNG
29.PNG
30.PNG
由于之前做STM32 WINUSB+CDC时将系统的驱动弄崩了,于是需要安装驱动。驱动安装完毕,电脑识别了USB设备:
17.PNG
测试USB上传速度HC32F460->PC:
18.PNG
速度相当不错。
二、遇到的问题
1.相比于STM32的uint8_t USBD_WinUSB_TransmitPacket(USBD_HandleTypeDef *pdev),由于HC32F460的USB发送函数void hd_usb_deveptx( usb_core_instance *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t buf_len)
是没有提供是否成功发送的状态值,因此不能保证数据因为USB总线繁忙而丢失。
19.PNG
可以看出很多数据并没有成功发送。
2.每次系统复位后,都会出现掉驱动的情况:
20.PNG
查看设备信息,发现有CM_PROB_FAILED_START问题,String Descriptors读不到:
21.PNG
22.PNG

    =========================== USB Port2 ===========================

Connection Status        : 0x01 (Device is connected)
Port Chain               : 1-5-2
Properties               : 0x01
IsUserConnectable       : yes
PortIsDebugCapable      : no
PortHasMultiCompanions  : no
PortConnectorIsTypeC    : no

      ======================== USB Device ========================

        +++++++++++++++++ Device Information ++++++++++++++++++
Device Description       : WinUSB 设备
Device ID                : USB\VID_07E9&PID_07E9\00000000050C
Hardware IDs             : USB\VID_07E9&PID_07E9&REV_0200 USB\VID_07E9&PID_07E9
Driver KeyName           : {88bae032-5a81-49f0-bc3d-a4ff138216d6}\0008 ({88BAE032-5A81-49F0-BC3D-A4FF138216D6})
Driver                   : \SystemRoot\System32\drivers\WinUsb.sys (Version: 6.3.9600.18088  Date: 2015-10-11)
Driver Inf               : C:\Windows\inf\winusb.inf
Legacy BusType           : PNPBus
Class                    : USBDevice
Class GUID               : {88bae032-5a81-49f0-bc3d-a4ff138216d6}
Service                  : WINUSB
Enumerator               : USB
Location Info            : Port_#0002.Hub_#0003
Location IDs             : PCIROOT(0)#PCI(1400)#USBROOT(0)#USB(5)#USB(2), ACPI(_SB_)#ACPI(PCI0)#ACPI(XHC_)#ACPI(RHUB)#ACPI(HS05)#USB(2)
Container ID             : {73a183c8-3781-5e8a-93bc-38be9dd6928c}
Manufacturer Info        : WinUSB 设备
Capabilities             : 0x14 (Removable, UniqueID)
Status                   : 0x01806400 (DN_HAS_PROBLEM, DN_DISABLEABLE, DN_REMOVABLE, DN_NT_ENUMERATOR, DN_NT_DRIVER)
Problem Code             : 10 (CM_PROB_FAILED_START)
Power State              : D3 (supported: D0, D2, D3, wake from D0, wake from D2)

        +++++++++++++++++ Registry USB Flags +++++++++++++++++
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\UsbFlags\07E907E90200
osvc                    : REG_BINARY 01 A0
SkipContainerIdQuery    : REG_BINARY 01 00

        ---------------- Connection Information ---------------
Connection Index         : 0x02 (2)
Connection Status        : 0x01 (DeviceConnected)
Current Config Value     : 0x00
Device Address           : 0x3E (62)
Is Hub                   : 0x00 (no)
Number Of Open Pipes     : 0x00 (0)
Device Bus Speed         : 0x01 (Full-Speed)
Data (HexDump)           : 02 00 00 00 12 01 00 02 00 00 00 40 E9 07 E9 07   ...........@....
                           00 02 01 02 03 01 00 01 00 3E 00 00 00 00 00 01   .........>......
                           00 00 00                                          ...

        --------------- Connection Information V2 -------------
Connection Index         : 0x02 (2)
Length                   : 0x10 (16 bytes)
SupportedUsbProtocols    : 0x03
Usb110                  : 1 (yes)
Usb200                  : 1 (yes)
Usb300                  : 0 (no)
ReservedMBZ             : 0x00
Flags                    : 0x00
DevIsOpAtSsOrHigher     : 0 (Is not operating at SuperSpeed or higher)
DevIsSsCapOrHigher      : 0 (Is not SuperSpeed capable or higher)
DevIsOpAtSsPlusOrHigher : 0 (Is not operating at SuperSpeedPlus or higher)
DevIsSsPlusCapOrHigher  : 0 (Is not SuperSpeedPlus capable or higher)
ReservedMBZ             : 0x00
Data (HexDump)           : 02 00 00 00 10 00 00 00 03 00 00 00 00 00 00 00   ................

    ---------------------- Device Descriptor ----------------------
bLength                  : 0x12 (18 bytes)
bDescriptorType          : 0x01 (Device Descriptor)
bcdUSB                   : 0x200 (USB Version 2.00)
bDeviceClass             : 0x00 (defined by the interface descriptors)
bDeviceSubClass          : 0x00
bDeviceProtocol          : 0x00
bMaxPacketSize0          : 0x40 (64 bytes)
idVendor                 : 0x07E9
idProduct                : 0x07E9
bcdDevice                : 0x0200
iManufacturer            : 0x01 (String Descriptor 1)
iProduct                 : 0x02 (String Descriptor 2)
iSerialNumber            : 0x03 (String Descriptor 3)
bNumConfigurations       : 0x01 (1 Configuration)
Data (HexDump)           : 12 01 00 02 00 00 00 40 E9 07 E9 07 00 02 01 02   .......@........
                           03 01                                             ..

    ------------------ Configuration Descriptor -------------------
bLength                  : 0x09 (9 bytes)
bDescriptorType          : 0x02 (Configuration Descriptor)
wTotalLength             : 0x0020 (32 bytes)
bNumInterfaces           : 0x01 (1 Interface)
bConfigurationValue      : 0x01 (Configuration 1)
iConfiguration           : 0x00 (No String Descriptor)
bmAttributes             : 0xC0
D7: Reserved, set 1     : 0x01
D6: Self Powered        : 0x01 (yes)
D5: Remote Wakeup       : 0x00 (no)
D4..0: Reserved, set 0  : 0x00
MaxPower                 : 0x32 (100 mA)
Data (HexDump)           : 09 02 20 00 01 01 00 C0 32 09 04 00 00 02 FF 00   .. .....2.......
                           00 00 07 05 01 02 40 00 00 07 05 81 02 40 00 00   ......@......@..

        ---------------- Interface Descriptor -----------------
bLength                  : 0x09 (9 bytes)
bDescriptorType          : 0x04 (Interface Descriptor)
bInterfaceNumber         : 0x00
bAlternateSetting        : 0x00
bNumEndpoints            : 0x02 (2 Endpoints)
bInterfaceClass          : 0xFF (Vendor Specific)
bInterfaceSubClass       : 0x00
bInterfaceProtocol       : 0x00
iInterface               : 0x00 (No String Descriptor)
Data (HexDump)           : 09 04 00 00 02 FF 00 00 00                        .........

        ----------------- Endpoint Descriptor -----------------
bLength                  : 0x07 (7 bytes)
bDescriptorType          : 0x05 (Endpoint Descriptor)
bEndpointAddress         : 0x01 (Direction=OUT EndpointID=1)
bmAttributes             : 0x02 (TransferType=Bulk)
wMaxPacketSize           : 0x0040 (64 bytes)
bInterval                : 0x00 (ignored)
Data (HexDump)           : 07 05 01 02 40 00 00                              ....@..

        ----------------- Endpoint Descriptor -----------------
bLength                  : 0x07 (7 bytes)
bDescriptorType          : 0x05 (Endpoint Descriptor)
bEndpointAddress         : 0x81 (Direction=IN EndpointID=1)
bmAttributes             : 0x02 (TransferType=Bulk)
wMaxPacketSize           : 0x0040 (64 bytes)
bInterval                : 0x00 (ignored)
Data (HexDump)           : 07 05 81 02 40 00 00                              ....@..

    ----------------- Device Qualifier Descriptor -----------------
Error                    : ERROR_GEN_FAILURE

      -------------------- String Descriptors -------------------
String descriptors are not available  (because the device has problem code CM_PROB_FAILED_START)
重新安装驱动设备工作正常。
三、解决方法
对于第一个问题,暂且希望官方能做一个修改。下面重点讲解一下解决的方法。
首先对比一下STM32与HC32F460关于USB的Setup阶段的处理方法:
STM32:
USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup)
{
  USBD_StatusTypeDef ret;

  USBD_ParseSetupRequest(&pdev->request, psetup);

  pdev->ep0_state = USBD_EP0_SETUP;

  pdev->ep0_data_len = pdev->request.wLength;

  switch (pdev->request.bmRequest & 0x1FU)
  {
    case USB_REQ_RECIPIENT_DEVICE:
      ret = USBD_StdDevReq(pdev, &pdev->request);
      break;

    case USB_REQ_RECIPIENT_INTERFACE:
      ret = USBD_StdItfReq(pdev, &pdev->request);
      break;

    case USB_REQ_RECIPIENT_ENDPOINT:
      ret = USBD_StdEPReq(pdev, &pdev->request);
      break;

    default:
      ret = USBD_LL_StallEP(pdev, (pdev->request.bmRequest & 0x80U));
      break;
  }

  return ret;
}
USBD_StatusTypeDef USBD_StdDevReq(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
  USBD_StatusTypeDef ret = USBD_OK;

  switch (req->bmRequest & USB_REQ_TYPE_MASK)
  {
    case USB_REQ_TYPE_CLASS:
    case USB_REQ_TYPE_VENDOR:
      ret = (USBD_StatusTypeDef)pdev->pClass->Setup(pdev, req);
      break;

    case USB_REQ_TYPE_STANDARD:
      switch (req->bRequest)
      {
        case USB_REQ_GET_DESCRIPTOR:
          USBD_GetDescriptor(pdev, req);
          break;

        case USB_REQ_SET_ADDRESS:
          USBD_SetAddress(pdev, req);
          break;

        case USB_REQ_SET_CONFIGURATION:
          ret = USBD_SetConfig(pdev, req);
          break;

        case USB_REQ_GET_CONFIGURATION:
          USBD_GetConfig(pdev, req);
          break;

        case USB_REQ_GET_STATUS:
          USBD_GetStatus(pdev, req);
          break;

        case USB_REQ_SET_FEATURE:
          USBD_SetFeature(pdev, req);
          break;

        case USB_REQ_CLEAR_FEATURE:
          USBD_ClrFeature(pdev, req);
          break;

        default:
          USBD_CtlError(pdev, req);
          break;
      }
      break;

    default:
      USBD_CtlError(pdev, req);
      break;
  }

  return ret;
}

HC32F460:
void hd_usb_setup_process(usb_core_instance *pdev)
{
    USB_SETUP_REQ req;

    hd_usb_parsesetupreq(pdev , &req);

    switch (req.bmRequest & 0x1Fu)
    {
        case USB_REQ_RECIPIENT_DEVICE:
            hd_usb_standarddevreq (pdev, &req);
            break;

        case USB_REQ_RECIPIENT_INTERFACE:
            hd_usb_standarditfreq(pdev, &req);
            break;

        case USB_REQ_RECIPIENT_ENDPOINT:
            hd_usb_standardepreq(pdev, &req);
            break;

        default:
            hd_usb_stalldevep(pdev, req.bmRequest & 0x80u);
            break;
    }
}
void hd_usb_standarddevreq(usb_core_instance *pdev, USB_SETUP_REQ *req)
{
    if(req->bRequest == USB_REQ_GET_DESCRIPTOR)
    {
        hd_usb_getdesc (pdev, req) ;
    }
    else if(req->bRequest == USB_REQ_SET_ADDRESS)
    {
        hd_usb_setaddr(pdev, req);
    }
    else if(req->bRequest == USB_REQ_SET_CONFIGURATION)
    {
        hd_usb_setconfig (pdev , req);
    }
    else if(req->bRequest == USB_REQ_GET_CONFIGURATION)
    {
        hd_usb_getconfig (pdev , req);
    }
    else if(req->bRequest == USB_REQ_GET_STATUS)
    {
        hd_usb_getstatus (pdev , req);
    }
    else if(req->bRequest == USB_REQ_SET_FEATURE)
    {
        hd_usb_setfeature (pdev , req);
    }
    else if(req->bRequest == USB_REQ_CLEAR_FEATURE)
    {
        hd_usb_clrfeature (pdev , req);
    }
    else
    {
        if (pdev->dev.class_callback->ep0_setup (pdev, req))
        {
            hd_usb_ctrlerr(pdev);
        }
    }
}
可以看出STM32在USBD_StdDevReq中遍历常见情况后会直接抛出USBD_CtlError(pdev, req);,而HC32F460则是判断pdev->dev.class_callback->ep0_setup (pdev, req)才抛出hd_usb_ctrlerr(pdev)。就是这个差异导致掉驱动。实际调试可以定位到这个问题:
23.PNG
修改void hd_usb_setup_process(usb_core_instance *pdev)中的hd_usb_standarddevreq (pdev, &req)和hd_usb_standarditfreq(pdev, &req):
24.PNG
25.PNG
26.PNG
27.PNG
从新安装驱动之后,不再掉驱动了:
28.PNG
设备工作正常。
WINUSB代码:
HC32F460_WINUSB.zip (1.06 MB)

使用特权

评论回复
精灵魔仙| | 2021-10-3 14:43 | 显示全部楼层
看了下好像是OS 1.0的,何不同时移植BOS Descriptor OS 2.0的版本?

使用特权

评论回复
duo点| | 2021-10-4 14:34 | 显示全部楼层
讲解超详细的

使用特权

评论回复
纪国圣|  楼主 | 2021-10-30 09:29 | 显示全部楼层
上传一份Microsoft_OS_2.0_Descriptors版本:
1.PNG
2.PNG
3.PNG
Microsoft_OS_2.0_Descriptors_Specification.pdf (593.95 KB)

使用特权

评论回复
kiwis66| | 2021-11-1 10:07 | 显示全部楼层
学习了,比较详细,
感谢

使用特权

评论回复
您需要登录后才可以回帖 登录 | 注册

本版积分规则