900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > USB Composite 组合设备之多路CDC实现

USB Composite 组合设备之多路CDC实现

时间:2021-07-25 20:49:16

相关推荐

USB Composite 组合设备之多路CDC实现

USB Composite 组合设备之多路CDC实现

USB复合设备与组合设备区别效果展示修改相关配置修改配置项修改设备描述符修改配置、接口、端点描述符接口修改FIFO配置知识点FIFO分配注意事项

USB复合设备与组合设备区别

其实多个接口组合在一起有2种情况

第一种叫做USB复合设备(Compound Device):

就是此类设备内部会集成一个HUD,然后多个USB连接到此HUD上,然后每个USB都会有自己独立的PID、VID

第二种叫做USB组合设备(Composite Device):

此类设备则内部只有一个PID、VID,通过定义多个接口描述符来实现多个功能的组合

参考原文链接

效果展示

修改相关配置

修改配置项

usbd_conf.h

#define USBD_MAX_NUM_INTERFACES6U

修改设备描述符

usbd_desc.c

__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END ={0x12, /*bLength */USB_DESC_TYPE_DEVICE, /*bDescriptorType*/0x00, /*bcdUSB */0x02,0xEF, /*bDeviceClass*/0x02, /*bDeviceSubClass*/0x01, /*bDeviceProtocol*/// 0x02, /*bDeviceClass*/// 0x02, /*bDeviceSubClass*/// 0x00, /*bDeviceProtocol*/USB_MAX_EP0_SIZE, /*bMaxPacketSize*/LOBYTE(USBD_VID), /*idVendor*/HIBYTE(USBD_VID), /*idVendor*/LOBYTE(USBD_PID_FS), /*idProduct*/HIBYTE(USBD_PID_FS), /*idProduct*/0x00, /*bcdDevice rel. 2.00*/0x02,USBD_IDX_MFC_STR, /*Index of manufacturer string*/USBD_IDX_PRODUCT_STR, /*Index of product string*/USBD_IDX_SERIAL_STR, /*Index of serial number string*/USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/};

修改配置、接口、端点描述符

usbd_cdc.h

头文件增加了:多路串口的宏定义

修改了:发送接收接口函数声明

/********************************************************************************* @file usbd_cdc.h* @author MCD Application Team* @brief header file for the usbd_cdc.c file.******************************************************************************* @attention** Copyright (c) STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************//* Define to prevent recursive inclusion -------------------------------------*/#ifndef __USB_CDC_H#define __USB_CDC_H#ifdef __cplusplusextern "C" {#endif/* Includes ------------------------------------------------------------------*/#include "usbd_ioreq.h"/** @addtogroup STM32_USB_DEVICE_LIBRARY* @{*//** @defgroup usbd_cdc* @brief This file is the Header file for usbd_cdc.c* @{*//** @defgroup usbd_cdc_Exported_Defines* @{*/#ifndef CDC_IN_EP#define CDC_IN_EP0x81U /* EP1 for data IN */#endif /* CDC_IN_EP */#ifndef CDC_OUT_EP#define CDC_OUT_EP 0x01U /* EP1 for data OUT */#endif /* CDC_OUT_EP */#ifndef CDC_CMD_EP#define CDC_CMD_EP 0x84U /* EP4 for CDC commands */#endif /* CDC_CMD_EP *//* 2 路 USB CDC */#define USE_CDC_IAD 1 /**< 使用多路CDC使能 */#define USE_CDC_NUM 3 /**< 使用2路 or 3路 */#ifndef CDC_IN_EP2#define CDC_IN_EP20x82U /* EP2 for data IN */#endif /* CDC_IN_EP */#ifndef CDC_OUT_EP2#define CDC_OUT_EP2 0x02U /* EP2 for data OUT */#endif /* CDC_OUT_EP */#ifndef CDC_CMD_EP5#define CDC_CMD_EP5 0x85U /* EP5 for CDC commands */#endif /* CDC_CMD_EP */#ifndef CDC_IN_EP3#define CDC_IN_EP30x83U /* EP3 for data IN */#endif /* CDC_IN_EP */#ifndef CDC_OUT_EP3#define CDC_OUT_EP3 0x03U /* EP3 for data OUT */#endif /* CDC_OUT_EP */#ifndef CDC_CMD_EP6#define CDC_CMD_EP6 0x86U /* EP6 for CDC commands */#endif /* CDC_CMD_EP */#ifndef CDC_HS_BINTERVAL#define CDC_HS_BINTERVAL 0x10U#endif /* CDC_HS_BINTERVAL */#ifndef CDC_FS_BINTERVAL#define CDC_FS_BINTERVAL 0x10U#endif /* CDC_FS_BINTERVAL *//* CDC Endpoints parameters: you can fine tune these values depending on the needed baudrates and performance. */#define CDC_DATA_HS_MAX_PACKET_SIZE 512U /* Endpoint IN & OUT Packet size */#define CDC_DATA_FS_MAX_PACKET_SIZE 64U /* Endpoint IN & OUT Packet size */#define CDC_CMD_PACKET_SIZE8U /* Control Endpoint Packet size */#if USE_CDC_IAD && USE_CDC_NUM == 2#define USB_CDC_CONFIG_DESC_SIZ ((67U - 9U + 8U) * 2U + 9U)#elif USE_CDC_IAD && USE_CDC_NUM == 3#define USB_CDC_CONFIG_DESC_SIZ ((67U - 9U + 8U) * 3U + 9U)#else#define USB_CDC_CONFIG_DESC_SIZ 67U#endif#define CDC_DATA_HS_IN_PACKET_SIZE CDC_DATA_HS_MAX_PACKET_SIZE#define CDC_DATA_HS_OUT_PACKET_SIZE CDC_DATA_HS_MAX_PACKET_SIZE#define CDC_DATA_FS_IN_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE#define CDC_DATA_FS_OUT_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE#define CDC_REQ_MAX_DATA_SIZE 0x7U/*---------------------------------------------------------------------*//* CDC definitions *//*---------------------------------------------------------------------*/#define CDC_SEND_ENCAPSULATED_COMMAND0x00U#define CDC_GET_ENCAPSULATED_RESPONSE0x01U#define CDC_SET_COMM_FEATURE 0x02U#define CDC_GET_COMM_FEATURE 0x03U#define CDC_CLEAR_COMM_FEATURE 0x04U#define CDC_SET_LINE_CODING0x20U#define CDC_GET_LINE_CODING0x21U#define CDC_SET_CONTROL_LINE_STATE 0x22U#define CDC_SEND_BREAK0x23U/*** @}*//** @defgroup USBD_CORE_Exported_TypesDefinitions* @{*//*** @}*/typedef struct{uint32_t bitrate;uint8_t format;uint8_t paritytype;uint8_t datatype;} USBD_CDC_LineCodingTypeDef;typedef struct _USBD_CDC_Itf{int8_t (* Init)(void);int8_t (* DeInit)(void);int8_t (* Control)(uint8_t cmd, uint8_t *pbuf, uint16_t length);int8_t (* Receive)(uint8_t *Buf, uint32_t *Len, uint8_t epnum);int8_t (* TransmitCplt)(uint8_t *Buf, uint32_t *Len, uint8_t epnum);} USBD_CDC_ItfTypeDef;typedef struct{uint32_t data[CDC_DATA_HS_MAX_PACKET_SIZE / 4U];/* Force 32-bit alignment */uint8_t CmdOpCode;uint8_t CmdLength;uint8_t *RxBuffer;uint8_t *TxBuffer;uint32_t RxLength;uint32_t TxLength;__IO uint32_t TxState;__IO uint32_t RxState;} USBD_CDC_HandleTypeDef;/** @defgroup USBD_CORE_Exported_Macros* @{*//*** @}*//** @defgroup USBD_CORE_Exported_Variables* @{*/extern USBD_ClassTypeDef USBD_CDC;#define USBD_CDC_CLASS &USBD_CDC/*** @}*//** @defgroup USB_CORE_Exported_Functions* @{*/uint8_t USBD_CDC_RegisterInterface(USBD_HandleTypeDef *pdev,USBD_CDC_ItfTypeDef *fops);uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff,uint32_t length);uint8_t USBD_CDC_SetRxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff);uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev, uint8_t epnum);uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev, uint8_t epnum);/*** @}*/#ifdef __cplusplus}#endif#endif /* __USB_CDC_H *//*** @}*//*** @}*/

usbd_cdc.c

1、修改了描述符,8个字节IAD描述符 * 3、2路接口配置

2、修改了初始化函数,反初始化函数接口

3、修改了数据流转接口增加了端点地址参数

/********************************************************************************* @file usbd_cdc.c* @author MCD Application Team* @brief This file provides the high layer firmware functions to manage the*following functionalities of the USB CDC Class:* - Initialization and Configuration of high and low layer* - Enumeration as CDC Device (and enumeration for each implemented memory interface)* - OUT/IN data transfer* - Command IN transfer (class requests management)* - Error management******************************************************************************** @attention** Copyright (c) STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.******************************************************************************** @verbatim**===================================================================* CDC Class Driver Description*===================================================================* This driver manages the "Universal Serial Bus Class Definitions for Communications Devices* Revision 1.2 November 16, " and the sub-protocol specification of "Universal Serial Bus* Communications Class Subclass Specification for PSTN Devices Revision 1.2 February 9, "* This driver implements the following aspects of the specification:* - Device descriptor management* - Configuration descriptor management* - Enumeration as CDC device with 2 data endpoints (IN and OUT) and 1 command endpoint (IN)* - Requests management (as described in section 6.2 in specification)* - Abstract Control Model compliant* - Union Functional collection (using 1 IN endpoint for control)* - Data interface class** These aspects may be enriched or modified for a specific user application.** This driver doesn't implement the following aspects of the specification* (but it is possible to manage these features with some modifications on this driver):* - Any class-specific aspect relative to communication classes should be managed by user application.* - All communication classes other than PSTN are not managed** @endverbatim********************************************************************************//* BSPDependencies- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c"- "stm32xxxxx_{eval}{discovery}_io.c"EndBSPDependencies *//* Includes ------------------------------------------------------------------*/#include "usbd_cdc.h"#include "usbd_ctlreq.h"/** @addtogroup STM32_USB_DEVICE_LIBRARY* @{*//** @defgroup USBD_CDC* @brief usbd core module* @{*//** @defgroup USBD_CDC_Private_TypesDefinitions* @{*//*** @}*//** @defgroup USBD_CDC_Private_Defines* @{*//*** @}*//** @defgroup USBD_CDC_Private_Macros* @{*//*** @}*//** @defgroup USBD_CDC_Private_FunctionPrototypes* @{*/static uint8_t USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);static uint8_t USBD_CDC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);static uint8_t USBD_CDC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);static uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);static uint8_t USBD_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum);static uint8_t USBD_CDC_EP0_RxReady(USBD_HandleTypeDef *pdev);#ifndef USE_USBD_COMPOSITEstatic uint8_t *USBD_CDC_GetFSCfgDesc(uint16_t *length);static uint8_t *USBD_CDC_GetHSCfgDesc(uint16_t *length);static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc(uint16_t *length);static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc(uint16_t *length);uint8_t *USBD_CDC_GetDeviceQualifierDescriptor(uint16_t *length);#endif /* USE_USBD_COMPOSITE */#ifndef USE_USBD_COMPOSITE/* USB Standard Device Descriptor */__ALIGN_BEGIN static uint8_t USBD_CDC_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END ={USB_LEN_DEV_QUALIFIER_DESC,USB_DESC_TYPE_DEVICE_QUALIFIER,0x00,0x02,0x00,0x00,0x00,0x40,0x01,0x00,};#endif /* USE_USBD_COMPOSITE *//*** @}*//** @defgroup USBD_CDC_Private_Variables* @{*//* CDC interface class callbacks structure */USBD_ClassTypeDef USBD_CDC ={USBD_CDC_Init,USBD_CDC_DeInit,USBD_CDC_Setup,NULL, /* EP0_TxSent */USBD_CDC_EP0_RxReady,USBD_CDC_DataIn,USBD_CDC_DataOut,NULL,NULL,NULL,#ifdef USE_USBD_COMPOSITENULL,NULL,NULL,NULL,#elseUSBD_CDC_GetHSCfgDesc,USBD_CDC_GetFSCfgDesc,USBD_CDC_GetOtherSpeedCfgDesc,USBD_CDC_GetDeviceQualifierDescriptor,#endif /* USE_USBD_COMPOSITE */};#ifndef USE_USBD_COMPOSITE/* USB CDC device Configuration Descriptor */__ALIGN_BEGIN static uint8_t USBD_CDC_CfgDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END ={/* Configuration Descriptor */0x09, /* bLength: Configuration Descriptor size */USB_DESC_TYPE_CONFIGURATION,/* bDescriptorType: Configuration */USB_CDC_CONFIG_DESC_SIZ,/* wTotalLength */0x00,#if USE_CDC_IAD && USE_CDC_NUM == 20x02 * 2,/* bNumInterfaces: 2 interfaces */#elif USE_CDC_IAD && USE_CDC_NUM == 30x02 * 3,/* bNumInterfaces: 2 interfaces */#else0x02, /* bNumInterfaces: 2 interfaces */#endif0x01, /* bConfigurationValue: Configuration value */0x00, /* iConfiguration: Index of string descriptordescribing the configuration */#if (USBD_SELF_POWERED == 1U)0xC0, /* bmAttributes: Bus Powered according to user configuration */#else0x80, /* bmAttributes: Bus Powered according to user configuration */#endif /* USBD_SELF_POWERED */USBD_MAX_POWER, /* MaxPower (mA) *//*---------------------------------------------------------------------------*/#if USE_CDC_IAD && USE_CDC_NUM >= 2/* Interface Association Descriptor IAD描述符 -- 控制接口 0 */0x08, /* bLength IAD描述符大小 */0x0B, /* bDescriptorType IAD描述符类型 */0x00, /* bFirstInterface 该IAD所聚合的多个接口中,首个索引编号 */0x02, /* bInferfaceCount 该功能包含接口的数目 */0x02, /* bFunctionClass 建议使用该IAD所聚合的多个interface中的第一个interface的对应参数,设备符中的bDeviceClass */0x02, /* bFunctionSubClass 建议使用该IAD所聚合的多个interface中的第一个interface的对应参数,设备符中的bDeviceSubClass */0x01, /* bFunctionProtocol 建议使用该IAD所聚合的多个interface中的第一个interface的对应参数,设备符中的bDeviceProtocol */0x00, /* iFunction 描述该功能的字符串编号 *//* 08 byte*/#endif/* Interface Descriptor */0x09, /* bLength: Interface Descriptor size */USB_DESC_TYPE_INTERFACE,/* bDescriptorType: Interface *//* Interface descriptor type */0x00, /* bInterfaceNumber: Number of Interface */0x00, /* bAlternateSetting: Alternate setting */0x01, /* bNumEndpoints: One endpoint used */0x02, /* bInterfaceClass: Communication Interface Class */0x02, /* bInterfaceSubClass: Abstract Control Model */0x01, /* bInterfaceProtocol: Common AT commands */0x00, /* iInterface *//* Header Functional Descriptor */0x05, /* bLength: Endpoint Descriptor size */0x24, /* bDescriptorType: CS_INTERFACE */0x00, /* bDescriptorSubtype: Header Func Desc */0x10, /* bcdCDC: spec release number */0x01,/* Call Management Functional Descriptor */0x05, /* bFunctionLength */0x24, /* bDescriptorType: CS_INTERFACE */0x01, /* bDescriptorSubtype: Call Management Func Desc */0x00, /* bmCapabilities: D0+D1 */0x01, /* bDataInterface *//* ACM Functional Descriptor */0x04, /* bFunctionLength */0x24, /* bDescriptorType: CS_INTERFACE */0x02, /* bDescriptorSubtype: Abstract Control Management desc */0x02, /* bmCapabilities *//* Union Functional Descriptor */0x05, /* bFunctionLength */0x24, /* bDescriptorType: CS_INTERFACE */0x06, /* bDescriptorSubtype: Union func desc */0x00, /* bMasterInterface: Communication class interface */0x01, /* bSlaveInterface0: Data Class Interface *//* Endpoint 2 Descriptor */0x07, /* bLength: Endpoint Descriptor size */USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */CDC_CMD_EP, /* bEndpointAddress */0x03, /* bmAttributes: Interrupt */LOBYTE(CDC_CMD_PACKET_SIZE),/* wMaxPacketSize */HIBYTE(CDC_CMD_PACKET_SIZE),CDC_FS_BINTERVAL, /* bInterval *//*---------------------------------------------------------------------------*//* Data class interface descriptor */0x09, /* bLength: Endpoint Descriptor size */USB_DESC_TYPE_INTERFACE,/* bDescriptorType: */0x01, /* bInterfaceNumber: Number of Interface */0x00, /* bAlternateSetting: Alternate setting */0x02, /* bNumEndpoints: Two endpoints used */0x0A, /* bInterfaceClass: CDC */0x00, /* bInterfaceSubClass */0x00, /* bInterfaceProtocol */0x00, /* iInterface *//* Endpoint OUT Descriptor */0x07, /* bLength: Endpoint Descriptor size */USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */CDC_OUT_EP, /* bEndpointAddress */0x02, /* bmAttributes: Bulk */LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize */HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),0x00, /* bInterval *//* Endpoint IN Descriptor */0x07, /* bLength: Endpoint Descriptor size */USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */CDC_IN_EP, /* bEndpointAddress */0x02, /* bmAttributes: Bulk */LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize */HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),0x00, /* bInterval */#if USE_CDC_IAD && USE_CDC_NUM >= 2/* Interface Association Descriptor IAD描述符 -- 控制接口 0 */0x08, /* bLength IAD描述符大小 */0x0B, /* bDescriptorType IAD描述符类型 */0x02, /* bFirstInterface 该IAD所聚合的多个接口中,首个索引编号 */0x02, /* bInferfaceCount 该功能包含接口的数目 */0x02, /* bFunctionClass 建议使用该IAD所聚合的多个interface中的第一个interface的对应参数,设备符中的bDeviceClass */0x02, /* bFunctionSubClass 建议使用该IAD所聚合的多个interface中的第一个interface的对应参数,设备符中的bDeviceSubClass */0x01, /* bFunctionProtocol 建议使用该IAD所聚合的多个interface中的第一个interface的对应参数,设备符中的bDeviceProtocol */0x00, /* iFunction 描述该功能的字符串编号 *//* 08 byte*//* Interface Descriptor */0x09, /* bLength: Interface Descriptor size */USB_DESC_TYPE_INTERFACE,/* bDescriptorType: Interface *//* Interface descriptor type */0x02, /* bInterfaceNumber: Number of Interface */0x00, /* bAlternateSetting: Alternate setting */0x01, /* bNumEndpoints: One endpoint used */0x02, /* bInterfaceClass: Communication Interface Class */0x02, /* bInterfaceSubClass: Abstract Control Model */0x01, /* bInterfaceProtocol: Common AT commands */0x00, /* iInterface *//* Header Functional Descriptor */0x05, /* bLength: Endpoint Descriptor size */0x24, /* bDescriptorType: CS_INTERFACE */0x00, /* bDescriptorSubtype: Header Func Desc */0x10, /* bcdCDC: spec release number */0x01,/* Call Management Functional Descriptor */0x05, /* bFunctionLength */0x24, /* bDescriptorType: CS_INTERFACE */0x01, /* bDescriptorSubtype: Call Management Func Desc */0x00, /* bmCapabilities: D0+D1 */0x01, /* bDataInterface *//* ACM Functional Descriptor */0x04, /* bFunctionLength */0x24, /* bDescriptorType: CS_INTERFACE */0x02, /* bDescriptorSubtype: Abstract Control Management desc */0x02, /* bmCapabilities *//* Union Functional Descriptor */0x05, /* bFunctionLength */0x24, /* bDescriptorType: CS_INTERFACE */0x06, /* bDescriptorSubtype: Union func desc */0x02, /* bMasterInterface: Communication class interface */0x03, /* bSlaveInterface0: Data Class Interface *//* Endpoint 2 Descriptor */0x07, /* bLength: Endpoint Descriptor size */USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */CDC_CMD_EP5, /* bEndpointAddress */0x03, /* bmAttributes: Interrupt */LOBYTE(CDC_CMD_PACKET_SIZE),/* wMaxPacketSize */HIBYTE(CDC_CMD_PACKET_SIZE),CDC_FS_BINTERVAL, /* bInterval *//*---------------------------------------------------------------------------*//* Data class interface descriptor */0x09, /* bLength: Endpoint Descriptor size */USB_DESC_TYPE_INTERFACE,/* bDescriptorType: */0x03, /* bInterfaceNumber: Number of Interface */0x00, /* bAlternateSetting: Alternate setting */0x02, /* bNumEndpoints: Two endpoints used */0x0A, /* bInterfaceClass: CDC */0x00, /* bInterfaceSubClass */0x00, /* bInterfaceProtocol */0x00, /* iInterface *//* Endpoint OUT Descriptor */0x07, /* bLength: Endpoint Descriptor size */USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */CDC_OUT_EP2, /* bEndpointAddress */0x02, /* bmAttributes: Bulk */LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize */HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),0x00, /* bInterval *//* Endpoint IN Descriptor */0x07, /* bLength: Endpoint Descriptor size */USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */CDC_IN_EP2, /* bEndpointAddress */0x02, /* bmAttributes: Bulk */LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize */HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),0x00, /* bInterval */#endif#if USE_CDC_IAD && USE_CDC_NUM >= 3/* Interface Association Descriptor IAD描述符 -- 控制接口 0 */0x08, /* bLength IAD描述符大小 */0x0B, /* bDescriptorType IAD描述符类型 */0x04, /* bFirstInterface 该IAD所聚合的多个接口中,首个索引编号 */0x02, /* bInferfaceCount 该功能包含接口的数目 */0x02, /* bFunctionClass 建议使用该IAD所聚合的多个interface中的第一个interface的对应参数,设备符中的bDeviceClass */0x02, /* bFunctionSubClass 建议使用该IAD所聚合的多个interface中的第一个interface的对应参数,设备符中的bDeviceSubClass */0x01, /* bFunctionProtocol 建议使用该IAD所聚合的多个interface中的第一个interface的对应参数,设备符中的bDeviceProtocol */0x00, /* iFunction 描述该功能的字符串编号 *//* 08 byte*//* Interface Descriptor */0x09, /* bLength: Interface Descriptor size */USB_DESC_TYPE_INTERFACE,/* bDescriptorType: Interface *//* Interface descriptor type */0x04, /* bInterfaceNumber: Number of Interface */0x00, /* bAlternateSetting: Alternate setting */0x01, /* bNumEndpoints: One endpoint used */0x02, /* bInterfaceClass: Communication Interface Class */0x02, /* bInterfaceSubClass: Abstract Control Model */0x01, /* bInterfaceProtocol: Common AT commands */0x00, /* iInterface *//* Header Functional Descriptor */0x05, /* bLength: Endpoint Descriptor size */0x24, /* bDescriptorType: CS_INTERFACE */0x00, /* bDescriptorSubtype: Header Func Desc */0x10, /* bcdCDC: spec release number */0x01,/* Call Management Functional Descriptor */0x05, /* bFunctionLength */0x24, /* bDescriptorType: CS_INTERFACE */0x01, /* bDescriptorSubtype: Call Management Func Desc */0x00, /* bmCapabilities: D0+D1 */0x01, /* bDataInterface *//* ACM Functional Descriptor */0x04, /* bFunctionLength */0x24, /* bDescriptorType: CS_INTERFACE */0x02, /* bDescriptorSubtype: Abstract Control Management desc */0x02, /* bmCapabilities *//* Union Functional Descriptor */0x05, /* bFunctionLength */0x24, /* bDescriptorType: CS_INTERFACE */0x06, /* bDescriptorSubtype: Union func desc */0x04, /* bMasterInterface: Communication class interface */0x05, /* bSlaveInterface0: Data Class Interface *//* Endpoint 2 Descriptor */0x07, /* bLength: Endpoint Descriptor size */USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */CDC_CMD_EP6, /* bEndpointAddress */0x03, /* bmAttributes: Interrupt */LOBYTE(CDC_CMD_PACKET_SIZE),/* wMaxPacketSize */HIBYTE(CDC_CMD_PACKET_SIZE),CDC_FS_BINTERVAL, /* bInterval *//*---------------------------------------------------------------------------*//* Data class interface descriptor */0x09, /* bLength: Endpoint Descriptor size */USB_DESC_TYPE_INTERFACE,/* bDescriptorType: */0x05, /* bInterfaceNumber: Number of Interface */0x00, /* bAlternateSetting: Alternate setting */0x02, /* bNumEndpoints: Two endpoints used */0x0A, /* bInterfaceClass: CDC */0x00, /* bInterfaceSubClass */0x00, /* bInterfaceProtocol */0x00, /* iInterface *//* Endpoint OUT Descriptor */0x07, /* bLength: Endpoint Descriptor size */USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */CDC_OUT_EP3, /* bEndpointAddress */0x02, /* bmAttributes: Bulk */LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize */HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),0x00, /* bInterval *//* Endpoint IN Descriptor */0x07, /* bLength: Endpoint Descriptor size */USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */CDC_IN_EP3, /* bEndpointAddress */0x02, /* bmAttributes: Bulk */LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize */HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),0x00, /* bInterval */#endif};#endif /* USE_USBD_COMPOSITE */static uint8_t CDCInEpAdd = CDC_IN_EP;static uint8_t CDCOutEpAdd = CDC_OUT_EP;static uint8_t CDCCmdEpAdd = CDC_CMD_EP;/*** @}*//** @defgroup USBD_CDC_Private_Functions* @{*//*** @brief USBD_CDC_Init* Initialize the CDC interface* @param pdev: device instance* @param cfgidx: Configuration index* @retval status*/static uint8_t USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx){UNUSED(cfgidx);USBD_CDC_HandleTypeDef *hcdc;static uint32_t mem[(sizeof(USBD_CDC_HandleTypeDef)/4)+1];/* On 32-bit boundary */hcdc = (USBD_CDC_HandleTypeDef *)mem;//USBD_malloc(sizeof(USBD_CDC_HandleTypeDef));if (hcdc == NULL){pdev->pClassDataCmsit[pdev->classId] = NULL;return (uint8_t)USBD_EMEM;}(void)USBD_memset(hcdc, 0, sizeof(USBD_CDC_HandleTypeDef));pdev->pClassDataCmsit[pdev->classId] = (void *)hcdc;pdev->pClassData = pdev->pClassDataCmsit[pdev->classId];#ifdef USE_USBD_COMPOSITE/* Get the Endpoints addresses allocated for this class instance */CDCInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK);CDCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK);CDCCmdEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_INTR);#endif /* USE_USBD_COMPOSITE */if (pdev->dev_speed == USBD_SPEED_HIGH){/* CDC1 *//* Open EP IN */(void)USBD_LL_OpenEP(pdev, CDCInEpAdd, USBD_EP_TYPE_BULK,CDC_DATA_HS_IN_PACKET_SIZE);pdev->ep_in[CDCInEpAdd & 0xFU].is_used = 1U;/* Open EP OUT */(void)USBD_LL_OpenEP(pdev, CDCOutEpAdd, USBD_EP_TYPE_BULK,CDC_DATA_HS_OUT_PACKET_SIZE);pdev->ep_out[CDCOutEpAdd & 0xFU].is_used = 1U;/* Set bInterval for CDC CMD Endpoint */pdev->ep_in[CDCCmdEpAdd & 0xFU].bInterval = CDC_HS_BINTERVAL;#if USE_CDC_IAD && USE_CDC_NUM >= 2/* CDC2 *//* Open EP IN */(void)USBD_LL_OpenEP(pdev, CDC_IN_EP2, USBD_EP_TYPE_BULK,CDC_DATA_HS_IN_PACKET_SIZE);pdev->ep_in[CDC_IN_EP2 & 0xFU].is_used = 1U;/* Open EP OUT */(void)USBD_LL_OpenEP(pdev, CDC_OUT_EP2, USBD_EP_TYPE_BULK,CDC_DATA_HS_OUT_PACKET_SIZE);pdev->ep_out[CDC_OUT_EP2 & 0xFU].is_used = 1U;/* Set bInterval for CDC CMD Endpoint */pdev->ep_in[CDC_CMD_EP5 & 0xFU].bInterval = CDC_HS_BINTERVAL;#endif#if USE_CDC_IAD && USE_CDC_NUM >= 3/* CDC3 *//* Open EP IN */(void)USBD_LL_OpenEP(pdev, CDC_IN_EP3, USBD_EP_TYPE_BULK,CDC_DATA_HS_IN_PACKET_SIZE);pdev->ep_in[CDC_IN_EP3 & 0xFU].is_used = 1U;/* Open EP OUT */(void)USBD_LL_OpenEP(pdev, CDC_OUT_EP3, USBD_EP_TYPE_BULK,CDC_DATA_HS_OUT_PACKET_SIZE);pdev->ep_out[CDC_OUT_EP3 & 0xFU].is_used = 1U;/* Set bInterval for CDC CMD Endpoint */pdev->ep_in[CDC_CMD_EP6 & 0xFU].bInterval = CDC_HS_BINTERVAL;#endif}else{/* Open EP IN */(void)USBD_LL_OpenEP(pdev, CDCInEpAdd, USBD_EP_TYPE_BULK,CDC_DATA_FS_IN_PACKET_SIZE);pdev->ep_in[CDCInEpAdd & 0xFU].is_used = 1U;/* Open EP OUT */(void)USBD_LL_OpenEP(pdev, CDCOutEpAdd, USBD_EP_TYPE_BULK,CDC_DATA_FS_OUT_PACKET_SIZE);pdev->ep_out[CDCOutEpAdd & 0xFU].is_used = 1U;/* Set bInterval for CMD Endpoint */pdev->ep_in[CDCCmdEpAdd & 0xFU].bInterval = CDC_FS_BINTERVAL;#if USE_CDC_IAD && USE_CDC_NUM >= 2/* CDC2 *//* Open EP IN */(void)USBD_LL_OpenEP(pdev, CDC_IN_EP2, USBD_EP_TYPE_BULK,CDC_DATA_FS_IN_PACKET_SIZE);pdev->ep_in[CDC_IN_EP2 & 0xFU].is_used = 1U;/* Open EP OUT */(void)USBD_LL_OpenEP(pdev, CDC_OUT_EP2, USBD_EP_TYPE_BULK,CDC_DATA_FS_OUT_PACKET_SIZE);pdev->ep_out[CDC_OUT_EP2 & 0xFU].is_used = 1U;/* Set bInterval for CDC CMD Endpoint */pdev->ep_in[CDC_CMD_EP5 & 0xFU].bInterval = CDC_FS_BINTERVAL;#endif#if USE_CDC_IAD && USE_CDC_NUM >= 3/* CDC3 *//* Open EP IN */(void)USBD_LL_OpenEP(pdev, CDC_IN_EP3, USBD_EP_TYPE_BULK,CDC_DATA_FS_IN_PACKET_SIZE);pdev->ep_in[CDC_IN_EP3 & 0xFU].is_used = 1U;/* Open EP OUT */(void)USBD_LL_OpenEP(pdev, CDC_OUT_EP3, USBD_EP_TYPE_BULK,CDC_DATA_FS_OUT_PACKET_SIZE);pdev->ep_out[CDC_OUT_EP3 & 0xFU].is_used = 1U;/* Set bInterval for CDC CMD Endpoint */pdev->ep_in[CDC_CMD_EP6 & 0xFU].bInterval = CDC_FS_BINTERVAL;#endif}/* Open Command IN EP */(void)USBD_LL_OpenEP(pdev, CDCCmdEpAdd, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE);pdev->ep_in[CDCCmdEpAdd & 0xFU].is_used = 1U;#if USE_CDC_IAD && USE_CDC_NUM >= 2(void)USBD_LL_OpenEP(pdev, CDC_CMD_EP5, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE);pdev->ep_in[CDC_CMD_EP5 & 0xFU].is_used = 1U;#endif#if USE_CDC_IAD && USE_CDC_NUM >= 3(void)USBD_LL_OpenEP(pdev, CDC_CMD_EP6, USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE);pdev->ep_in[CDC_CMD_EP6 & 0xFU].is_used = 1U;#endifhcdc->RxBuffer = NULL;/* Init physical Interface components */((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->Init();/* Init Xfer states */hcdc->TxState = 0U;hcdc->RxState = 0U;if (hcdc->RxBuffer == NULL){return (uint8_t)USBD_EMEM;}if (pdev->dev_speed == USBD_SPEED_HIGH){/* Prepare Out endpoint to receive next packet */(void)USBD_LL_PrepareReceive(pdev, CDCOutEpAdd, hcdc->RxBuffer,CDC_DATA_HS_OUT_PACKET_SIZE);#if USE_CDC_IAD && USE_CDC_NUM >= 2(void)USBD_LL_PrepareReceive(pdev, CDC_OUT_EP2, hcdc->RxBuffer,CDC_DATA_HS_OUT_PACKET_SIZE);#endif#if USE_CDC_IAD && USE_CDC_NUM >= 3(void)USBD_LL_PrepareReceive(pdev, CDC_OUT_EP3, hcdc->RxBuffer,CDC_DATA_HS_OUT_PACKET_SIZE);#endif}else{/* Prepare Out endpoint to receive next packet */(void)USBD_LL_PrepareReceive(pdev, CDCOutEpAdd, hcdc->RxBuffer,CDC_DATA_FS_OUT_PACKET_SIZE);#if USE_CDC_IAD && USE_CDC_NUM >= 2(void)USBD_LL_PrepareReceive(pdev, CDC_OUT_EP2, hcdc->RxBuffer,CDC_DATA_FS_OUT_PACKET_SIZE);#endif#if USE_CDC_IAD && USE_CDC_NUM >= 3(void)USBD_LL_PrepareReceive(pdev, CDC_OUT_EP3, hcdc->RxBuffer,CDC_DATA_FS_OUT_PACKET_SIZE);#endif}return (uint8_t)USBD_OK;}/*** @brief USBD_CDC_Init* DeInitialize the CDC layer* @param pdev: device instance* @param cfgidx: Configuration index* @retval status*/static uint8_t USBD_CDC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx){UNUSED(cfgidx);#ifdef USE_USBD_COMPOSITE/* Get the Endpoints addresses allocated for this CDC class instance */CDCInEpAdd = USBD_CoreGetEPAdd(pdev, CDC_IN_EP, USBD_EP_TYPE_BULK);CDCOutEpAdd = USBD_CoreGetEPAdd(pdev, CDC_OUT_EP, USBD_EP_TYPE_BULK);CDCCmdEpAdd = USBD_CoreGetEPAdd(pdev, CDC_CMD_EP, USBD_EP_TYPE_INTR);#endif /* USE_USBD_COMPOSITE *//* Close EP IN */(void)USBD_LL_CloseEP(pdev, CDCInEpAdd);pdev->ep_in[CDCInEpAdd & 0xFU].is_used = 0U;/* Close EP OUT */(void)USBD_LL_CloseEP(pdev, CDCOutEpAdd);pdev->ep_out[CDCOutEpAdd & 0xFU].is_used = 0U;/* Close Command IN EP */(void)USBD_LL_CloseEP(pdev, CDCCmdEpAdd);pdev->ep_in[CDCCmdEpAdd & 0xFU].is_used = 0U;pdev->ep_in[CDCCmdEpAdd & 0xFU].bInterval = 0U;#if USE_CDC_IAD && USE_CDC_NUM >= 2/* Close EP2 IN */(void)USBD_LL_CloseEP(pdev, CDC_IN_EP2);pdev->ep_in[CDC_IN_EP2 & 0xFU].is_used = 0U;/* Close EP2 OUT */(void)USBD_LL_CloseEP(pdev, CDC_OUT_EP2);pdev->ep_out[CDC_OUT_EP2 & 0xFU].is_used = 0U;/* Close Command IN EP5 */(void)USBD_LL_CloseEP(pdev, CDC_CMD_EP5);pdev->ep_in[CDC_CMD_EP5 & 0xFU].is_used = 0U;pdev->ep_in[CDC_CMD_EP5 & 0xFU].bInterval = 0U;#endif#if USE_CDC_IAD && USE_CDC_NUM >= 3/* Close EP3 IN */(void)USBD_LL_CloseEP(pdev, CDC_IN_EP3);pdev->ep_in[CDC_IN_EP3 & 0xFU].is_used = 0U;/* Close EP3 OUT */(void)USBD_LL_CloseEP(pdev, CDC_OUT_EP3);pdev->ep_out[CDC_OUT_EP3 & 0xFU].is_used = 0U;/* Close Command IN EP6 */(void)USBD_LL_CloseEP(pdev, CDC_CMD_EP6);pdev->ep_in[CDC_CMD_EP6 & 0xFU].is_used = 0U;pdev->ep_in[CDC_CMD_EP6 & 0xFU].bInterval = 0U;#endif/* DeInit physical Interface components */if (pdev->pClassDataCmsit[pdev->classId] != NULL){((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->DeInit();(void)USBD_free(pdev->pClassDataCmsit[pdev->classId]);pdev->pClassDataCmsit[pdev->classId] = NULL;pdev->pClassData = NULL;}return (uint8_t)USBD_OK;}/*** @brief USBD_CDC_Setup* Handle the CDC specific requests* @param pdev: instance* @param req: usb requests* @retval status*/static uint8_t USBD_CDC_Setup(USBD_HandleTypeDef *pdev,USBD_SetupReqTypedef *req){USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];uint16_t len;uint8_t ifalt = 0U;uint16_t status_info = 0U;USBD_StatusTypeDef ret = USBD_OK;if (hcdc == NULL){return (uint8_t)USBD_FAIL;}switch (req->bmRequest & USB_REQ_TYPE_MASK){case USB_REQ_TYPE_CLASS:if (req->wLength != 0U){if ((req->bmRequest & 0x80U) != 0U){((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->Control(req->bRequest,(uint8_t *)hcdc->data,req->wLength);len = MIN(CDC_REQ_MAX_DATA_SIZE, req->wLength);(void)USBD_CtlSendData(pdev, (uint8_t *)hcdc->data, len);}else{hcdc->CmdOpCode = req->bRequest;hcdc->CmdLength = (uint8_t)MIN(req->wLength, USB_MAX_EP0_SIZE);(void)USBD_CtlPrepareRx(pdev, (uint8_t *)hcdc->data, hcdc->CmdLength);}}else{((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->Control(req->bRequest,(uint8_t *)req, 0U);}break;case USB_REQ_TYPE_STANDARD:switch (req->bRequest){case USB_REQ_GET_STATUS:if (pdev->dev_state == USBD_STATE_CONFIGURED){(void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U);}else{USBD_CtlError(pdev, req);ret = USBD_FAIL;}break;case USB_REQ_GET_INTERFACE:if (pdev->dev_state == USBD_STATE_CONFIGURED){(void)USBD_CtlSendData(pdev, &ifalt, 1U);}else{USBD_CtlError(pdev, req);ret = USBD_FAIL;}break;case USB_REQ_SET_INTERFACE:if (pdev->dev_state != USBD_STATE_CONFIGURED){USBD_CtlError(pdev, req);ret = USBD_FAIL;}break;case USB_REQ_CLEAR_FEATURE:break;default:USBD_CtlError(pdev, req);ret = USBD_FAIL;break;}break;default:USBD_CtlError(pdev, req);ret = USBD_FAIL;break;}return (uint8_t)ret;}/*** @brief USBD_CDC_DataIn* Data sent on non-control IN endpoint* @param pdev: device instance* @param epnum: endpoint number* @retval status*/static uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum){USBD_CDC_HandleTypeDef *hcdc;PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef *)pdev->pData;if (pdev->pClassDataCmsit[pdev->classId] == NULL){return (uint8_t)USBD_FAIL;}hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];if ((pdev->ep_in[epnum & 0xFU].total_length > 0U) &&((pdev->ep_in[epnum & 0xFU].total_length % hpcd->IN_ep[epnum & 0xFU].maxpacket) == 0U)){/* Update the packet total length */pdev->ep_in[epnum & 0xFU].total_length = 0U;/* Send ZLP */(void)USBD_LL_Transmit(pdev, epnum, NULL, 0U);}else{hcdc->TxState = 0U;if (((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->TransmitCplt != NULL){((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->TransmitCplt(hcdc->TxBuffer, &hcdc->TxLength, epnum);}}return (uint8_t)USBD_OK;}/*** @brief USBD_CDC_DataOut* Data received on non-control Out endpoint* @param pdev: device instance* @param epnum: endpoint number* @retval status*/static uint8_t USBD_CDC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum){USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];if (pdev->pClassDataCmsit[pdev->classId] == NULL){return (uint8_t)USBD_FAIL;}/* Get the received data length */hcdc->RxLength = USBD_LL_GetRxDataSize(pdev, epnum);/* USB data will be immediately processed, this allow next USB traffic beingNAKed till the end of the application Xfer */((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->Receive(hcdc->RxBuffer, &hcdc->RxLength, epnum);return (uint8_t)USBD_OK;}/*** @brief USBD_CDC_EP0_RxReady* Handle EP0 Rx Ready event* @param pdev: device instance* @retval status*/static uint8_t USBD_CDC_EP0_RxReady(USBD_HandleTypeDef *pdev){USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];if (hcdc == NULL){return (uint8_t)USBD_FAIL;}if ((pdev->pUserData[pdev->classId] != NULL) && (hcdc->CmdOpCode != 0xFFU)){((USBD_CDC_ItfTypeDef *)pdev->pUserData[pdev->classId])->Control(hcdc->CmdOpCode,(uint8_t *)hcdc->data,(uint16_t)hcdc->CmdLength);hcdc->CmdOpCode = 0xFFU;}return (uint8_t)USBD_OK;}#ifndef USE_USBD_COMPOSITE/*** @brief USBD_CDC_GetFSCfgDesc* Return configuration descriptor* @param length : pointer data length* @retval pointer to descriptor buffer*/static uint8_t *USBD_CDC_GetFSCfgDesc(uint16_t *length){USBD_EpDescTypeDef *pEpCmdDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_CMD_EP);USBD_EpDescTypeDef *pEpOutDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_OUT_EP);USBD_EpDescTypeDef *pEpInDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_IN_EP);if (pEpCmdDesc != NULL){pEpCmdDesc->bInterval = CDC_FS_BINTERVAL;}if (pEpOutDesc != NULL){pEpOutDesc->wMaxPacketSize = CDC_DATA_FS_MAX_PACKET_SIZE;}if (pEpInDesc != NULL){pEpInDesc->wMaxPacketSize = CDC_DATA_FS_MAX_PACKET_SIZE;}*length = (uint16_t)sizeof(USBD_CDC_CfgDesc);return USBD_CDC_CfgDesc;}/*** @brief USBD_CDC_GetHSCfgDesc* Return configuration descriptor* @param length : pointer data length* @retval pointer to descriptor buffer*/static uint8_t *USBD_CDC_GetHSCfgDesc(uint16_t *length){USBD_EpDescTypeDef *pEpCmdDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_CMD_EP);USBD_EpDescTypeDef *pEpOutDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_OUT_EP);USBD_EpDescTypeDef *pEpInDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_IN_EP);if (pEpCmdDesc != NULL){pEpCmdDesc->bInterval = CDC_HS_BINTERVAL;}if (pEpOutDesc != NULL){pEpOutDesc->wMaxPacketSize = CDC_DATA_HS_MAX_PACKET_SIZE;}if (pEpInDesc != NULL){pEpInDesc->wMaxPacketSize = CDC_DATA_HS_MAX_PACKET_SIZE;}*length = (uint16_t)sizeof(USBD_CDC_CfgDesc);return USBD_CDC_CfgDesc;}/*** @brief USBD_CDC_GetOtherSpeedCfgDesc* Return configuration descriptor* @param length : pointer data length* @retval pointer to descriptor buffer*/static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc(uint16_t *length){USBD_EpDescTypeDef *pEpCmdDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_CMD_EP);USBD_EpDescTypeDef *pEpOutDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_OUT_EP);USBD_EpDescTypeDef *pEpInDesc = USBD_GetEpDesc(USBD_CDC_CfgDesc, CDC_IN_EP);if (pEpCmdDesc != NULL){pEpCmdDesc->bInterval = CDC_FS_BINTERVAL;}if (pEpOutDesc != NULL){pEpOutDesc->wMaxPacketSize = CDC_DATA_FS_MAX_PACKET_SIZE;}if (pEpInDesc != NULL){pEpInDesc->wMaxPacketSize = CDC_DATA_FS_MAX_PACKET_SIZE;}*length = (uint16_t)sizeof(USBD_CDC_CfgDesc);return USBD_CDC_CfgDesc;}/*** @brief USBD_CDC_GetDeviceQualifierDescriptor* return Device Qualifier descriptor* @param length : pointer data length* @retval pointer to descriptor buffer*/uint8_t *USBD_CDC_GetDeviceQualifierDescriptor(uint16_t *length){*length = (uint16_t)sizeof(USBD_CDC_DeviceQualifierDesc);return USBD_CDC_DeviceQualifierDesc;}#endif /* USE_USBD_COMPOSITE *//*** @brief USBD_CDC_RegisterInterface* @param pdev: device instance* @param fops: CD Interface callback* @retval status*/uint8_t USBD_CDC_RegisterInterface(USBD_HandleTypeDef *pdev,USBD_CDC_ItfTypeDef *fops){if (fops == NULL){return (uint8_t)USBD_FAIL;}pdev->pUserData[pdev->classId] = fops;return (uint8_t)USBD_OK;}/*** @brief USBD_CDC_SetTxBuffer* @param pdev: device instance* @param pbuff: Tx Buffer* @param length: Tx Buffer length* @retval status*/uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev,uint8_t *pbuff, uint32_t length){USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];if (hcdc == NULL){return (uint8_t)USBD_FAIL;}hcdc->TxBuffer = pbuff;hcdc->TxLength = length;return (uint8_t)USBD_OK;}/*** @brief USBD_CDC_SetRxBuffer* @param pdev: device instance* @param pbuff: Rx Buffer* @retval status*/uint8_t USBD_CDC_SetRxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff){USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];if (hcdc == NULL){return (uint8_t)USBD_FAIL;}hcdc->RxBuffer = pbuff;return (uint8_t)USBD_OK;}/*** @brief USBD_CDC_TransmitPacket* Transmit packet on IN endpoint* @param pdev: device instance* @param epnum: 输入端点地址* @retval status*/uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev, uint8_t epnum){USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];USBD_StatusTypeDef ret = USBD_BUSY;#ifdef USE_USBD_COMPOSITE/* Get the Endpoints addresses allocated for this class instance */CDCInEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK);#endif /* USE_USBD_COMPOSITE */if (pdev->pClassDataCmsit[pdev->classId] == NULL){return (uint8_t)USBD_FAIL;}if (hcdc->TxState == 0U){/* Tx Transfer in progress */hcdc->TxState = 1U;/* Update the packet total length */pdev->ep_in[epnum & 0xFU].total_length = hcdc->TxLength;/* Transmit next packet */(void)USBD_LL_Transmit(pdev, epnum, hcdc->TxBuffer, hcdc->TxLength);ret = USBD_OK;}return (uint8_t)ret;}/*** @brief USBD_CDC_ReceivePacket* prepare OUT Endpoint for reception* @param pdev: device instance* @param epnum: 输出端点地址* @retval status*/uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev, uint8_t epnum){USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];#ifdef USE_USBD_COMPOSITE/* Get the Endpoints addresses allocated for this class instance */CDCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK);#endif /* USE_USBD_COMPOSITE */if (pdev->pClassDataCmsit[pdev->classId] == NULL){return (uint8_t)USBD_FAIL;}if (pdev->dev_speed == USBD_SPEED_HIGH){/* Prepare Out endpoint to receive next packet */(void)USBD_LL_PrepareReceive(pdev, epnum, hcdc->RxBuffer,CDC_DATA_HS_OUT_PACKET_SIZE);}else{/* Prepare Out endpoint to receive next packet */(void)USBD_LL_PrepareReceive(pdev, epnum, hcdc->RxBuffer,CDC_DATA_FS_OUT_PACKET_SIZE);}return (uint8_t)USBD_OK;}/*** @}*//*** @}*//*** @}*/

接口修改

usbd_cdc_if.c

/* USER CODE BEGIN Header *//********************************************************************************* @file : usbd_cdc_if.c* @version : v1.0_Cube* @brief: Usb device for Virtual Com Port.******************************************************************************* @attention** Copyright (c) STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************//* USER CODE END Header *//* Includes ------------------------------------------------------------------*/#include "usbd_cdc_if.h"/* USER CODE BEGIN INCLUDE *//* USER CODE END INCLUDE *//* Private typedef -----------------------------------------------------------*//* Private define ------------------------------------------------------------*//* Private macro -------------------------------------------------------------*//* USER CODE BEGIN PV *//* Private variables ---------------------------------------------------------*//* USER CODE END PV *//** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY* @brief Usb device library.* @{*//** @addtogroup USBD_CDC_IF* @{*//** @defgroup USBD_CDC_IF_Private_TypesDefinitions USBD_CDC_IF_Private_TypesDefinitions* @brief Private types.* @{*//* USER CODE BEGIN PRIVATE_TYPES *//* USER CODE END PRIVATE_TYPES *//*** @}*//** @defgroup USBD_CDC_IF_Private_Defines USBD_CDC_IF_Private_Defines* @brief Private defines.* @{*//* USER CODE BEGIN PRIVATE_DEFINES *//* USER CODE END PRIVATE_DEFINES *//*** @}*//** @defgroup USBD_CDC_IF_Private_Macros USBD_CDC_IF_Private_Macros* @brief Private macros.* @{*//* USER CODE BEGIN PRIVATE_MACRO *//* USER CODE END PRIVATE_MACRO *//*** @}*//** @defgroup USBD_CDC_IF_Private_Variables USBD_CDC_IF_Private_Variables* @brief Private variables.* @{*//* Create buffer for reception and transmission *//* It's up to user to redefine and/or remove those define *//** Received data over USB are stored in this buffer*/uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];/** Data to send over USB CDC are stored in this buffer */uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];/* USER CODE BEGIN PRIVATE_VARIABLES *//* USER CODE END PRIVATE_VARIABLES *//*** @}*//** @defgroup USBD_CDC_IF_Exported_Variables USBD_CDC_IF_Exported_Variables* @brief Public variables.* @{*/extern USBD_HandleTypeDef hUsbDeviceFS;/* USER CODE BEGIN EXPORTED_VARIABLES *//* USER CODE END EXPORTED_VARIABLES *//*** @}*//** @defgroup USBD_CDC_IF_Private_FunctionPrototypes USBD_CDC_IF_Private_FunctionPrototypes* @brief Private functions declaration.* @{*/static int8_t CDC_Init_FS(void);static int8_t CDC_DeInit_FS(void);static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length);static int8_t CDC_Receive_FS(uint8_t* pbuf, uint32_t *Len, uint8_t epnum);static int8_t CDC_TransmitCplt_FS(uint8_t *pbuf, uint32_t *Len, uint8_t epnum);/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION *//* USER CODE END PRIVATE_FUNCTIONS_DECLARATION *//*** @}*/USBD_CDC_ItfTypeDef USBD_Interface_fops_FS ={CDC_Init_FS,CDC_DeInit_FS,CDC_Control_FS,CDC_Receive_FS,CDC_TransmitCplt_FS};/* Private functions ---------------------------------------------------------*//*** @brief Initializes the CDC media low layer over the FS USB IP* @retval USBD_OK if all operations are OK else USBD_FAIL*/static int8_t CDC_Init_FS(void){/* USER CODE BEGIN 3 *//* Set Application Buffers */USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0);USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBufferFS);return (USBD_OK);/* USER CODE END 3 */}/*** @brief DeInitializes the CDC media low layer* @retval USBD_OK if all operations are OK else USBD_FAIL*/static int8_t CDC_DeInit_FS(void){/* USER CODE BEGIN 4 */return (USBD_OK);/* USER CODE END 4 */}/*** @brief Manage the CDC class requests* @param cmd: Command code* @param pbuf: Buffer containing command data (request parameters)* @param length: Number of data to be sent (in bytes)* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL*/static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length){/* USER CODE BEGIN 5 */switch(cmd){case CDC_SEND_ENCAPSULATED_COMMAND:break;case CDC_GET_ENCAPSULATED_RESPONSE:break;case CDC_SET_COMM_FEATURE:break;case CDC_GET_COMM_FEATURE:break;case CDC_CLEAR_COMM_FEATURE:break;/*******************************************************************************//* Line Coding Structure*//*-----------------------------------------------------------------------------*//* Offset | Field | Size | Value | Description*//* 0| dwDTERate | 4 | Number |Data terminal rate, in bits per second*//* 4| bCharFormat | 1 | Number | Stop bits *//*0 - 1 Stop bit *//*1 - 1.5 Stop bits*//*2 - 2 Stop bits *//* 5| bParityType | 1 | Number | Parity *//*0 - None *//*1 - Odd*//*2 - Even *//*3 - Mark *//*4 - Space *//* 6| bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16).*//*******************************************************************************/case CDC_SET_LINE_CODING:break;case CDC_GET_LINE_CODING:break;case CDC_SET_CONTROL_LINE_STATE:break;case CDC_SEND_BREAK:break;default:break;}return (USBD_OK);/* USER CODE END 5 */}/*** @brief Data received over USB OUT endpoint are sent over CDC interface* through this function.** @note* This function will issue a NAK packet on any OUT packet received on* USB endpoint until exiting this function. If you exit this function* before transfer is complete on CDC interface (ie. using DMA controller)* it will result in receiving more data while previous ones are still* not sent.** @param Buf: Buffer of data to be received* @param Len: Number of data received (in bytes)* @param epnum: 输出端点地址* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL*/static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len, uint8_t epnum){/* USER CODE BEGIN 6 */USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);USBD_CDC_ReceivePacket(&hUsbDeviceFS, epnum);CDC_Transmit_FS(Buf, *Len, epnum);return (USBD_OK);/* USER CODE END 6 */}/*** @brief CDC_Transmit_FS* Data to send over USB IN endpoint are sent over CDC interface* through this function.* @note*** @param Buf: Buffer of data to be sent* @param Len: Number of data to be sent (in bytes)* @param epnum: 输入端点地址* @retval USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY*/uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len, uint8_t epnum){uint8_t result = USBD_OK;/* USER CODE BEGIN 7 */USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;if (hcdc->TxState != 0){return USBD_BUSY;}USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);result = USBD_CDC_TransmitPacket(&hUsbDeviceFS, epnum);/* USER CODE END 7 */return result;}/*** @brief CDC_TransmitCplt_FS* Data transmitted callback** @note* This function is IN transfer complete callback used to inform user that* the submitted Data is successfully sent over USB.** @param Buf: Buffer of data to be received* @param Len: Number of data received (in bytes)* @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL*/static int8_t CDC_TransmitCplt_FS(uint8_t *Buf, uint32_t *Len, uint8_t epnum){uint8_t result = USBD_OK;/* USER CODE BEGIN 13 */UNUSED(Buf);UNUSED(Len);UNUSED(epnum);/* USER CODE END 13 */return result;}/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION *//* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION *//*** @}*//*** @}*/

usbd_cdc_if.h

/* USER CODE BEGIN Header *//********************************************************************************* @file : usbd_cdc_if.h* @version : v1.0_Cube* @brief: Header for usbd_cdc_if.c file.******************************************************************************* @attention** Copyright (c) STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************//* USER CODE END Header *//* Define to prevent recursive inclusion -------------------------------------*/#ifndef __USBD_CDC_IF_H__#define __USBD_CDC_IF_H__#ifdef __cplusplusextern "C" {#endif/* Includes ------------------------------------------------------------------*/#include "usbd_cdc.h"/* USER CODE BEGIN INCLUDE *//* USER CODE END INCLUDE *//** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY* @brief For Usb device.* @{*//** @defgroup USBD_CDC_IF USBD_CDC_IF* @brief Usb VCP device module* @{*//** @defgroup USBD_CDC_IF_Exported_Defines USBD_CDC_IF_Exported_Defines* @brief Defines.* @{*//* Define size for the receive and transmit buffer over CDC */#define APP_RX_DATA_SIZE 512#define APP_TX_DATA_SIZE 512/* USER CODE BEGIN EXPORTED_DEFINES *//* USER CODE END EXPORTED_DEFINES *//*** @}*//** @defgroup USBD_CDC_IF_Exported_Types USBD_CDC_IF_Exported_Types* @brief Types.* @{*//* USER CODE BEGIN EXPORTED_TYPES *//* USER CODE END EXPORTED_TYPES *//*** @}*//** @defgroup USBD_CDC_IF_Exported_Macros USBD_CDC_IF_Exported_Macros* @brief Aliases.* @{*//* USER CODE BEGIN EXPORTED_MACRO *//* USER CODE END EXPORTED_MACRO *//*** @}*//** @defgroup USBD_CDC_IF_Exported_Variables USBD_CDC_IF_Exported_Variables* @brief Public variables.* @{*//** CDC Interface callback. */extern USBD_CDC_ItfTypeDef USBD_Interface_fops_FS;/* USER CODE BEGIN EXPORTED_VARIABLES *//* USER CODE END EXPORTED_VARIABLES *//*** @}*//** @defgroup USBD_CDC_IF_Exported_FunctionsPrototype USBD_CDC_IF_Exported_FunctionsPrototype* @brief Public functions declaration.* @{*/uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len, uint8_t epnum);/* USER CODE BEGIN EXPORTED_FUNCTIONS *//* USER CODE END EXPORTED_FUNCTIONS *//*** @}*//*** @}*//*** @}*/#ifdef __cplusplus}#endif#endif /* __USBD_CDC_IF_H__ */

FIFO配置

usbd_conf.c

/* EP_OUT: 0x00(64) 0x01(64) 0x02(64) 0x03(64) 0x04(NULL fill 64) 0x05(NULL fill 64) 0x06(NULL fill 64) 最小64Bytes,HAL_PCDEx_SetRxFiFo每个数值代表4Bytes */HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 16 + 16 * 6);/* EP_IN: 0x80(64) 0x81(64) 0x82(64) 0x83(64) 0x84(8) 0x85(8) 0x86(8) */HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 16);HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 16);HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 2, 16);HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 3, 16);HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 4, 16);HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 5, 16);HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 6, 16);

知识点

FIFO分配

TXn最小大小= 16个字。TXn min size = 16 words.(n:发送FIFO索引)(n : Transmit FIFO index)当不使用TxFIFO时,配置如下:When a TxFIFO is not used, the Configuration should be as follows:情况1:n > m and Txn未被使用(n,m: Transmit FIFO indexes)case 1 : n > m and Txn is not used (n,m : Transmit FIFO indexes)——> Txm可以使用分配给Txn的空间。--> Txm can use the space allocated for Txn.case2: n < m, Txn未被使用(n,m:发送FIFO索引)case2 : n < m and Txn is not used (n,m : Transmit FIFO indexes)——> Txn应配置为16个word的最小空间,即64Bytes--> Txn should be configured with the minimum space of 16 words当使用txfifo在顶部分配时,FIFO被最优地使用The FIFO is used optimally when used TxFIFOs are allocated in the topFIFO。of the FIFO.例如:使用“EP1”和“EP2”作为IN,不使用“EP1”和“EP3”作为IN。Ex: use EP1 and EP2 as IN instead of EP1 and EP3 as IN ones.当使用DMA时,3n * FIFO位置应该为内部DMA寄存器保留When DMA is used 3n * FIFO locations should be reserved for internal DMA registers

上面的意思是:在我们使用的端点地址中,存在某些未被使用的端点地址,分为两种情况:

比如多路CDC中,我们使用了 (有数字的代表该端点地址数据包大小,NULL代表未使用,NULL fill代表未使用但需要填充):

EP_OUT: 0x00(64) 0x01(64) 0x02(64) 0x03(64) 0x04(NULL) 0x05(NULL) 0x06(NULL)

EP_IN: 0x80(64) 0x81(64) 0x82(64) 0x83(64) 0x84(8) 0x85(8) 0x86(8)

4、5、6三个EP_IN未使用,它属于:

情况1:n > m and Txn未被使用(n,m: Transmit FIFO indexes)

—> Txm可以使用分配给Txn的空间

如果我们不用1、2、3,而使用4、5、6,则我们需要预留最小的空间给1 、2 、3

不同芯片,对应USB FIFO空间大小不同需要对照手册

HAL_PCDEx_SetRxFiFo需要先设置,接收缓冲区共用一块大小,函数接口大小设置单位是:word,即设置1代表4个字节大小

注意事项

CDC配置的包大小,需要根据实际数据通讯场景,如果设的每包大小,小于实际每次传输的包那就会丢包,如果设大,不能超过FIFO的总大小!

参考引用:/Gvr4P

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。