最近有空测试了一下官方的VCP例程,使用感觉不错,将其稍微改动做了一个CDC回环测试,速率也不错,就是安装驱动有些麻烦,于是想直接将CDC改写成WINUSB不就不需要驱动了吗?于是抽空从之前写的STM32 WINUSB移植到HC32F460。一、移植的方法
修改的话主要是在CDC的基础上添加有关描述符的发送等函数。修改方法如下:
1.修改头文件usb_core_driver.h中的结构体usb_dev_class_func,添加如下成员:
2.修改usb_dev_stdreq.c中的void hd_usb_getdesc(usb_core_instance *pdev, const USB_SETUP_REQ *req),添加如下语句:
3.添加宏定义USBD_SUPPORT_USER_STRING_DESC:
4.修改usb_dev_cdc_class.c中的usb_dev_class_func class_cdc_cbk,添加成员变量:
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):
6.修改配置描述符:
7.修改usb_dev_core.c中的void hd_usb_setup_process(usb_core_instance *pdev),添加如下语句:
8.继续在usb_dev_cdc_class.c中添加有关描述符的函数:
9.至此WINUSB修改完毕。为了测试发送速度,在做一些修改:
由于之前做STM32 WINUSB+CDC时将系统的驱动弄崩了,于是需要安装驱动。驱动安装完毕,电脑识别了USB设备:
测试USB上传速度HC32F460->PC:
速度相当不错。
二、遇到的问题
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总线繁忙而丢失。
可以看出很多数据并没有成功发送。
2.每次系统复位后,都会出现掉驱动的情况:
查看设备信息,发现有CM_PROB_FAILED_START问题,String Descriptors读不到:
- =========================== 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)。就是这个差异导致掉驱动。实际调试可以定位到这个问题:
修改void hd_usb_setup_process(usb_core_instance *pdev)中的hd_usb_standarddevreq (pdev, &req)和hd_usb_standarditfreq(pdev, &req):
从新安装驱动之后,不再掉驱动了:
设备工作正常。
WINUSB代码:
HC32F460_WINUSB.zip
(1.06 MB, 下载次数: 86)
CDC代码:
HC32F460_CDC.zip
(1.06 MB, 下载次数: 75)
INF文件:
Driver Package1.zip
(11.77 KB, 下载次数: 64)
上位机测速软件:
WINUSB.zip
(9.79 MB, 下载次数: 95)
|
|