cube中USB只有两个入口。
/* 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_COMPOSITE_CLASS);USBD_MSC_RegisterStorage(&hUsbDeviceFS, &USBD_Storage_FS);USBD_Start(&hUsbDeviceFS);
}
void USB_LP_CAN1_RX0_IRQHandler(void)
{/* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 0 *//* USER CODE END USB_LP_CAN1_RX0_IRQn 0 */HAL_PCD_IRQHandler(&hpcd_USB_FS);/* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 1 *//* USER CODE END USB_LP_CAN1_RX0_IRQn 1 */
}
看一下中断响应函数的内容
/*** @brief This function handles PCD interrupt request.* @param hpcd: PCD handle* @retval HAL status*/
void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
{uint32_t wInterrupt_Mask = 0;if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_CTR)){/* servicing of the endpoint correct transfer interrupt *//* clear of the CTR flag into the sub */PCD_EP_ISR_Handler(hpcd);}if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_RESET)){__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_RESET);HAL_PCD_ResetCallback(hpcd);HAL_PCD_SetAddress(hpcd, 0);}if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_PMAOVR)){__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_PMAOVR);}if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_ERR)){__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ERR);}if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_WKUP)){hpcd->Instance->CNTR &= ~(USB_CNTR_LP_MODE);/*set wInterrupt_Mask global variable*/wInterrupt_Mask = USB_CNTR_CTRM | USB_CNTR_WKUPM | USB_CNTR_SUSPM | USB_CNTR_ERRM | USB_CNTR_ESOFM | USB_CNTR_RESETM;/*Set interrupt mask*/hpcd->Instance->CNTR = wInterrupt_Mask;HAL_PCD_ResumeCallback(hpcd);__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_WKUP);}if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_SUSP)){/* clear of the ISTR bit must be done after setting of CNTR_FSUSP */__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SUSP);/* Force low-power mode in the macrocell */hpcd->Instance->CNTR |= USB_CNTR_FSUSP;hpcd->Instance->CNTR |= USB_CNTR_LP_MODE;if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_WKUP) == 0){HAL_PCD_SuspendCallback(hpcd);}}if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_SOF)){__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SOF);HAL_PCD_SOFCallback(hpcd);}if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_ESOF)){/* clear ESOF flag in ISTR */__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ESOF);}
}
可以看出来,中断响应函数根据各个不同的中断源做出不同的操作。这点在参考手册也有提到
在USB插入之后,主机开始进行枚举,复位USB,触发复位中断,会进入下面一个if语句。
if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_RESET))
{__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_RESET);HAL_PCD_ResetCallback(hpcd);HAL_PCD_SetAddress(hpcd, 0);
}
这两个函数主要是设置总线速度,复位USB,以及设置USB地址。分析了这两个函数,基本了解了程序的流程,主要是两个关键的结构体
/*** @brief PCD Handle Structure definition*/
typedef struct
{PCD_TypeDef *Instance; /*!< Register base address */PCD_InitTypeDef Init; /*!< PCD required parameters */__IO uint8_t USB_Address; /*!< USB Address: not used by USB OTG FS */PCD_EPTypeDef IN_ep[15]; /*!< IN endpoint parameters */PCD_EPTypeDef OUT_ep[15]; /*!< OUT endpoint parameters */HAL_LockTypeDef Lock; /*!< PCD peripheral status */__IO PCD_StateTypeDef State; /*!< PCD communication state */uint32_t Setup[12]; /*!< Setup packet buffer */void *pData; /*!< Pointer to upper stack Handler */
} PCD_HandleTypeDef;/* USB Device handle structure */
typedef struct _USBD_HandleTypeDef
{uint8_t id;uint32_t dev_config;uint32_t dev_default_config;uint32_t dev_config_status;USBD_SpeedTypeDef dev_speed;USBD_EndpointTypeDef ep_in[15];USBD_EndpointTypeDef ep_out[15];uint32_t ep0_state;uint32_t ep0_data_len;uint8_t dev_state;uint8_t dev_old_state;uint8_t dev_address;uint8_t dev_connection_status;uint8_t dev_test_mode;uint32_t dev_remote_wakeup;USBD_SetupReqTypedef request;USBD_DescriptorsTypeDef *pDesc;USBD_ClassTypeDef *pClass;void *pClassData;void *pUserData;void *pData;
} USBD_HandleTypeDef;
这两个结构体很关键,看下复位操作的函数
/*** @brief Reset callback.* @param hpcd: PCD handle* @retval None*/
void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
{USBD_SpeedTypeDef speed = USBD_SPEED_FULL;/*Set USB Current Speed*/switch (hpcd->Init.speed){case PCD_SPEED_FULL:speed = USBD_SPEED_FULL;break;default:speed = USBD_SPEED_FULL;break;}USBD_LL_SetSpeed((USBD_HandleTypeDef*)hpcd->pData, speed);/*Reset Device*/USBD_LL_Reset((USBD_HandleTypeDef*)hpcd->pData);
}
这里有一个强制类型转换,将一个void指针强制转换为USBD_HandleTypeDef,那么这个指针必然一早就指向了一个实体的USBD_HandleTypeDef,向上追朔调用关系
main->MX_USB_DEVICE_Init->USBD_Init->USBD_LL_Init->pdev->hpcd_USB_FS.pData = pdev
然后,hpcd_USB_FS作为中断处理函数的参数被传进来。
/**
* @brief USBD_LL_Reset
* Handle Reset event
* @param pdev: device instance
* @retval status
*/USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev)
{/* Open EP0 OUT */USBD_LL_OpenEP(pdev,0x00,USBD_EP_TYPE_CTRL,USB_MAX_EP0_SIZE);pdev->ep_out[0].maxpacket = USB_MAX_EP0_SIZE;/* Open EP0 IN */USBD_LL_OpenEP(pdev,0x80,USBD_EP_TYPE_CTRL,USB_MAX_EP0_SIZE);pdev->ep_in[0].maxpacket = USB_MAX_EP0_SIZE;/* Upon Reset call user call back */pdev->dev_state = USBD_STATE_DEFAULT;if (pdev->pClassData)pdev->pClass->DeInit(pdev, pdev->dev_config);return USBD_OK;
}/**
* @brief USBD_LL_Reset
* Handle Reset event
* @param pdev: device instance
* @retval status
*/
USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev, USBD_SpeedTypeDef speed)
{pdev->dev_speed = speed;return USBD_OK;
}
SetSpeed比较简单,只是将hUsbDeviceFs中的dev_speed设置一下。
Reset函数则是将端点0的IN OUT端点打开,然后有一句
pdev->pClass->DeInit(pdev,pdev->dev_config)
这里又是一个USBD_ClassTypeDef类型的指针
typedef struct _Device_cb
{uint8_t (*Init) (struct _USBD_HandleTypeDef *pdev , uint8_t cfgidx);uint8_t (*DeInit) (struct _USBD_HandleTypeDef *pdev , uint8_t cfgidx);/* Control Endpoints*/uint8_t (*Setup) (struct _USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req);uint8_t (*EP0_TxSent) (struct _USBD_HandleTypeDef *pdev );uint8_t (*EP0_RxReady) (struct _USBD_HandleTypeDef *pdev );/* Class Specific Endpoints*/uint8_t (*DataIn) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum);uint8_t (*DataOut) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum);uint8_t (*SOF) (struct _USBD_HandleTypeDef *pdev);uint8_t (*IsoINIncomplete) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum);uint8_t (*IsoOUTIncomplete) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum);uint8_t *(*GetHSConfigDescriptor)(uint16_t *length);uint8_t *(*GetFSConfigDescriptor)(uint16_t *length);uint8_t *(*GetOtherSpeedConfigDescriptor)(uint16_t *length);uint8_t *(*GetDeviceQualifierDescriptor)(uint16_t *length);
#if (USBD_SUPPORT_USER_STRING == 1)uint8_t *(*GetUsrStrDescriptor)(struct _USBD_HandleTypeDef *pdev ,uint8_t index, uint16_t *length);
#endif} USBD_ClassTypeDef;
可以看到这个类定义都是函数指针,在调用之前必定实例化(借用面向对象来词汇)过。
main -> MX_USB_DEVICE_Init->USBD_RegisterClass->pdev->pClass=pclass
如果是CDC类,那么最终指向的是在usbd_cdc.c中的USBD_CDC类,如果是复合类,那么就需要我们自己定义。
在调用DeInit过程中,又会调用两个void 指针:pclassData,pUserData
其中pClassData是初始化是在初始化各个类的时候,比如
USBD_MSC_Init -> pdev->pClassData = USBD_malloc(sizeof (USBD_MSC_BOT_HandleTypeDef));
USBD_CDC_Init -> pdev->pClassData = USBD_malloc(sizeof (USBD_CDC_HandleTypeDef));
不同的类,指向不同的函数指针。
pUserData是通过一个函数初始化,比如CDC类
main -> USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS);
USBD_Interface_fops_FS定义如下:
typedef struct _USBD_CDC_Itf
{int8_t (* Init) (void);int8_t (* DeInit) (void);int8_t (* Control) (uint8_t, uint8_t * , uint16_t);int8_t (* Receive) (uint8_t *, uint32_t *);}USBD_CDC_ItfTypeDef;
pClassData和pUserData在USBD_HandleTypeDef中是指针形式,所以在调用不同类的时候,改变指针的指向,即可完成不同类的功能。我们复合设备类的设计思想既是如此。
可以总结一下 USBD_HandleTypeDef中几个复杂的指针
USBD_DescriptorsTypeDef *pDesc;USBD_ClassTypeDef *pClass;void *pClassData;void *pUserData;void *pData;
注意点:
#define USBD_malloc malloc
#define USBD_free free
Stack_Size EQU 0x1000
Heap_Size EQU 0x800
#define CDC_IN_EP 0x81 /* EP1 for data IN */
#define CDC_OUT_EP 0x01 /* EP1 for data OUT */
#define CDC_CMD_EP 0x83 /* EP3 for CDC commands */
#define MSC_EPIN_ADDR 0x82
#define MSC_EPOUT_ADDR 0x02
/*** @file usbd_composite.c* @author Weyne* @version V01* @date 2016.10.28* @brief MSC + CDC 复合设备* @note* @attention COYPRIGHT WEYNE*/#include "usbd_composite.h"
#include "usbd_cdc.h"
#include "usbd_msc.h"static USBD_CDC_HandleTypeDef *pCDCData;
static USBD_MSC_BOT_HandleTypeDef *pMSCData;static uint8_t USBD_Composite_Init (USBD_HandleTypeDef *pdev,uint8_t cfgidx);static uint8_t USBD_Composite_DeInit (USBD_HandleTypeDef *pdev,uint8_t cfgidx);static uint8_t USBD_Composite_EP0_RxReady(USBD_HandleTypeDef *pdev);static uint8_t USBD_Composite_Setup (USBD_HandleTypeDef *pdev,USBD_SetupReqTypedef *req);static uint8_t USBD_Composite_DataIn (USBD_HandleTypeDef *pdev,uint8_t epnum);static uint8_t USBD_Composite_DataOut (USBD_HandleTypeDef *pdev,uint8_t epnum);static uint8_t *USBD_Composite_GetFSCfgDesc (uint16_t *length);static uint8_t *USBD_Composite_GetDeviceQualifierDescriptor (uint16_t *length);USBD_ClassTypeDef USBD_COMPOSITE =
{USBD_Composite_Init,USBD_Composite_DeInit,USBD_Composite_Setup,NULL, /*EP0_TxSent*/USBD_Composite_EP0_RxReady,USBD_Composite_DataIn,USBD_Composite_DataOut,NULL,NULL,NULL,NULL,USBD_Composite_GetFSCfgDesc,NULL,USBD_Composite_GetDeviceQualifierDescriptor,
};/* USB composite device Configuration Descriptor */
/* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
__ALIGN_BEGIN uint8_t USBD_Composite_CfgFSDesc[USBD_COMPOSITE_DESC_SIZE] __ALIGN_END =
{0x09, /* bLength: Configuation Descriptor size */USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */WBVAL(USBD_COMPOSITE_DESC_SIZE),USBD_MAX_NUM_INTERFACES , /* bNumInterfaces: */0x01, /* bConfigurationValue: */0x04, /* iConfiguration: */0xC0, /* bmAttributes: */0x96, /* MaxPower 300 mA *//****************************CDC************************************//* Interface Association Descriptor */USBD_IAD_DESC_SIZE, // bLengthUSBD_IAD_DESCRIPTOR_TYPE, // bDescriptorTypeUSBD_CDC_FIRST_INTERFACE, // bFirstInterfaceUSBD_CDC_INTERFACE_NUM, // bInterfaceCount0x02, // bFunctionClass0x02, // bFunctionSubClass0x01, // bInterfaceProtocol0x04, // iFunction/*Interface Descriptor */0x09, /* bLength: Interface Descriptor size */USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface *//* Interface descriptor type */USBD_CDC_CMD_INTERFACE, /* bInterfaceNumber: Number of Interface */0x00, /* bAlternateSetting: Alternate setting */0x01, /* bNumEndpoints: One endpoints used */0x02, /* bInterfaceClass: Communication Interface Class */0x02, /* bInterfaceSubClass: Abstract Control Model */0x01, /* bInterfaceProtocol: Common AT commands */0x01, /* 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: 1 *//*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 */USBD_CDC_CMD_INTERFACE, /* bMasterInterface: Communication class interface */USBD_CDC_DATA_INTERFACE, /* 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),0x01, /* bInterval: *//*Data class interface descriptor*/0x09, /* bLength: Endpoint Descriptor size */USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */USBD_CDC_DATA_INTERFACE, /* bInterfaceNumber: Number of Interface */0x00, /* bAlternateSetting: Alternate setting */0x02, /* bNumEndpoints: Two endpoints used */0x0A, /* bInterfaceClass: CDC */0x02, /* bInterfaceSubClass: */0x00, /* bInterfaceProtocol: */0x01, /* 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),0x01, /* bInterval: ignore for Bulk transfer *//*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),0x01, /* bInterval: ignore for Bulk transfer *//****************************MSC************************************//* Interface Association Descriptor */USBD_IAD_DESC_SIZE, // bLengthUSBD_IAD_DESCRIPTOR_TYPE, // bDescriptorTypeUSBD_MSC_FIRST_INTERFACE, // bFirstInterfaceUSBD_MSC_INTERFACE_NUM, // bInterfaceCount0x08, // bFunctionClass0x06, // bFunctionSubClass0x50, // bInterfaceProtocol0x05,/******************** Mass Storage interface ********************/0x09, /* bLength: Interface Descriptor size */USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */USBD_MSC_INTERFACE, /* bInterfaceNumber: Number of Interface */0x00, /* bAlternateSetting: Alternate setting */0x02, /* bNumEndpoints*/0x08, /* bInterfaceClass: MSC Class */0x06, /* bInterfaceSubClass : SCSI transparent*/0x50, /* nInterfaceProtocol */0x05, /* iInterface: *//******************** Mass Storage Endpoints ********************/0x07, /*Endpoint descriptor length = 7*/0x05, /*Endpoint descriptor type */MSC_EPIN_ADDR, /*Endpoint address (IN, address 1) */0x02, /*Bulk endpoint type */LOBYTE(MSC_MAX_FS_PACKET),HIBYTE(MSC_MAX_FS_PACKET),0x01, /*Polling interval in milliseconds */0x07, /*Endpoint descriptor length = 7 */0x05, /*Endpoint descriptor type */MSC_EPOUT_ADDR, /*Endpoint address (OUT, address 1) */0x02, /*Bulk endpoint type */LOBYTE(MSC_MAX_FS_PACKET),HIBYTE(MSC_MAX_FS_PACKET),0x01, /*Polling interval in milliseconds*/};/* USB Standard Device Descriptor */
__ALIGN_BEGIN uint8_t USBD_Composite_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,
};/*** @brief USBD_Composite_Init* Initialize the Composite interface* @param pdev: device instance* @param cfgidx: Configuration index* @retval status*/
static uint8_t USBD_Composite_Init (USBD_HandleTypeDef *pdev,uint8_t cfgidx)
{uint8_t res = 0;pdev->pUserData = &USBD_CDC_Interface_fops_FS;res += USBD_CDC.Init(pdev,cfgidx);pCDCData = pdev->pClassData;pdev->pUserData = &USBD_Storage_Interface_fops_FS;res += USBD_MSC.Init(pdev,cfgidx);pMSCData = pdev->pClassData;return res;
}/*** @brief USBD_Composite_DeInit* DeInitilaize the Composite configuration* @param pdev: device instance* @param cfgidx: configuration index* @retval status*/
static uint8_t USBD_Composite_DeInit (USBD_HandleTypeDef *pdev,uint8_t cfgidx)
{uint8_t res = 0;pdev->pClassData = pCDCData;pdev->pUserData = &USBD_CDC_Interface_fops_FS;res += USBD_CDC.DeInit(pdev,cfgidx);pdev->pClassData = pMSCData;pdev->pUserData = &USBD_Storage_Interface_fops_FS;res += USBD_MSC.DeInit(pdev,cfgidx);return res;
}static uint8_t USBD_Composite_EP0_RxReady(USBD_HandleTypeDef *pdev)
{return USBD_CDC.EP0_RxReady(pdev);
}/**
* @brief USBD_Composite_Setup
* Handle the Composite requests
* @param pdev: device instance
* @param req: USB request
* @retval status
*/
static uint8_t USBD_Composite_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{switch (req->bmRequest & USB_REQ_RECIPIENT_MASK){case USB_REQ_RECIPIENT_INTERFACE:switch(req->wIndex){case USBD_CDC_DATA_INTERFACE:case USBD_CDC_CMD_INTERFACE:pdev->pClassData = pCDCData;pdev->pUserData = &USBD_CDC_Interface_fops_FS;return(USBD_CDC.Setup(pdev, req));case USBD_MSC_INTERFACE:pdev->pClassData = pMSCData;pdev->pUserData = &USBD_Storage_Interface_fops_FS;return(USBD_MSC.Setup (pdev, req));default:break;}break;case USB_REQ_RECIPIENT_ENDPOINT:switch(req->wIndex){case CDC_IN_EP:case CDC_OUT_EP:case CDC_CMD_EP:pdev->pClassData = pCDCData;pdev->pUserData = &USBD_CDC_Interface_fops_FS;return(USBD_CDC.Setup(pdev, req));case MSC_EPIN_ADDR:case MSC_EPOUT_ADDR:pdev->pClassData = pMSCData;pdev->pUserData = &USBD_Storage_Interface_fops_FS;return(USBD_MSC.Setup (pdev, req));default:break;}break;}return USBD_OK;
}/**
* @brief USBD_Composite_DataIn
* handle data IN Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
uint8_t USBD_Composite_DataIn (USBD_HandleTypeDef *pdev,uint8_t epnum)
{switch(epnum){case CDC_INDATA_NUM:pdev->pClassData = pCDCData;pdev->pUserData = &USBD_CDC_Interface_fops_FS;return(USBD_CDC.DataIn(pdev,epnum));case MSC_INDATA_NUM:pdev->pClassData = pMSCData;pdev->pUserData = &USBD_Storage_Interface_fops_FS;return(USBD_MSC.DataIn(pdev,epnum));default:break;}return USBD_FAIL;
}/**
* @brief USBD_Composite_DataOut
* handle data OUT Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
uint8_t USBD_Composite_DataOut (USBD_HandleTypeDef *pdev,uint8_t epnum)
{switch(epnum){case CDC_OUTDATA_NUM:case CDC_OUTCMD_NUM:pdev->pClassData = pCDCData;pdev->pUserData = &USBD_CDC_Interface_fops_FS;return(USBD_CDC.DataOut(pdev,epnum));case MSC_OUTDATA_NUM:pdev->pClassData = pMSCData;pdev->pUserData = &USBD_Storage_Interface_fops_FS;return(USBD_MSC.DataOut(pdev,epnum));default:break;}return USBD_FAIL;
}/**
* @brief USBD_Composite_GetHSCfgDesc
* return configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t *USBD_Composite_GetFSCfgDesc (uint16_t *length)
{*length = sizeof (USBD_Composite_CfgFSDesc);return USBD_Composite_CfgFSDesc;
}/**
* @brief DeviceQualifierDescriptor
* return Device Qualifier descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t *USBD_Composite_GetDeviceQualifierDescriptor (uint16_t *length)
{*length = sizeof (USBD_Composite_DeviceQualifierDesc);return USBD_Composite_DeviceQualifierDesc;
}/*** @}*//*** @}*//*** @}*//************************ (C) COPYRIGHT WEYNE *****END OF FILE****/
/*** @file usbd_composite.h* @author Weyne* @version V01* @date 2016.10.28* @brief MSC + CDC 复合设备* @note* @attention COYPRIGHT WEYNE*//* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_COMPOSITE_H
#define __USBD_COMPOSITE_H#ifdef __cplusplusextern "C" {
#endif/* Includes ------------------------------------------------------------------*/
#include "usbd_msc.h"
#include "usbd_cdc.h"
#include "usbd_storage_if.h"
#include "usbd_cdc_if.h"#define WBVAL(x) (x & 0xFF),((x >> 8) & 0xFF)
#define DBVAL(x) (x & 0xFF),((x >> 8) & 0xFF),((x >> 16) & 0xFF),((x >> 24) & 0xFF)#define USBD_IAD_DESC_SIZE 0x08
#define USBD_IAD_DESCRIPTOR_TYPE 0x0B#define USBD_CDC_FIRST_INTERFACE 0 /* CDC FirstInterface */
#define USBD_CDC_INTERFACE_NUM 2 /* CDC Interface NUM */#define USBD_CDC_CMD_INTERFACE 0
#define USBD_CDC_DATA_INTERFACE 1#define USBD_MSC_FIRST_INTERFACE 2 /* MSC FirstInterface */
#define USBD_MSC_INTERFACE_NUM 1 /* MSC Interface NUM */#define USBD_MSC_INTERFACE 2#define MSC_INDATA_NUM (MSC_EPIN_ADDR & 0x0F)
#define MSC_OUTDATA_NUM (MSC_EPOUT_ADDR & 0x0F)#define CDC_INDATA_NUM (CDC_IN_EP & 0x0F)
#define CDC_OUTDATA_NUM (CDC_OUT_EP & 0x0F)
#define CDC_OUTCMD_NUM (CDC_CMD_EP & 0x0F)#define USBD_COMPOSITE_DESC_SIZE (9 + 58 + 8 + 32 + 8)extern USBD_ClassTypeDef USBD_COMPOSITE;/*** @}*//*** @}*/#ifdef __cplusplus
}
#endif#endif /* __USBD_MSC_H */
/*** @}*//************************ (C) COPYRIGHT WEYNE *****END OF FILE****/
注意我这里修改了cube原来在usbd_cdc_if中的fops变量名(原来的命名不合理),直接编译会报错,需要修改下。
/* 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_COMPOSITE);// USBD_MSC_RegisterStorage(&hUsbDeviceFS, &USBD_Storage_Interface_fops_FS);USBD_Start(&hUsbDeviceFS);}
#define USBD_MAX_NUM_INTERFACES 3#define USBD_malloc malloc
#define USBD_free free
/*** @brief Initializes the Low Level portion of the Device driver.* @param pdev: Device handle* @retval USBD Status*/
USBD_StatusTypeDef USBD_LL_Init (USBD_HandleTypeDef *pdev)
{/* Init USB_IP *//* Link The driver to the stack */hpcd_USB_FS.pData = pdev;pdev->pData = &hpcd_USB_FS;hpcd_USB_FS.Instance = USB;hpcd_USB_FS.Init.dev_endpoints = 8;hpcd_USB_FS.Init.speed = PCD_SPEED_FULL;hpcd_USB_FS.Init.ep0_mps = DEP0CTL_MPS_8;hpcd_USB_FS.Init.low_power_enable = DISABLE;hpcd_USB_FS.Init.lpm_enable = DISABLE;hpcd_USB_FS.Init.battery_charging_enable = DISABLE;if (HAL_PCD_Init(&hpcd_USB_FS) != HAL_OK){Error_Handler();}HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, 0x18);HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, 0x58);HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_IN_EP , PCD_SNG_BUF, 0x98);HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_OUT_EP , PCD_SNG_BUF, 0xD8);HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , MSC_EPIN_ADDR , PCD_SNG_BUF, 0x118);HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , MSC_EPOUT_ADDR , PCD_SNG_BUF, 0x158);HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_CMD_EP , PCD_SNG_BUF, 0x198);return USBD_OK;
}
修改完成
至此,设备可以枚举成功了,电脑中出现了串口号和U盘。
这里只测试虚拟串口
int main(void)
{/* USER CODE BEGIN 1 */char test[]="testn";/* USER CODE END 1 *//* MCU Configuration----------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* Configure the system clock */SystemClock_Config();/* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();MX_USB_DEVICE_Init();/* USER CODE BEGIN 2 */HAL_Delay(10000);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE */CDC_Transmit_FS((uint8_t*)test,sizeof(test));HAL_Delay(500);/* USER CODE BEGIN 3 */}/* USER CODE END 3 */}
测试串口可以正常收到数据
本文发布于:2024-02-03 08:53:41,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170692161949968.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |