TaterLi's LazyBlog

自言自语,不喜绕路,科学上网,远离天国.

@TaterLi3周前

04/7
10:29
技术控

使用STM32CubeMX编写USB复合设备

其实很简单搞了好久,怪ST呗,既没做到可读性增强,又搞到复杂了.目的先做一个CDC+MSC复合,就像STLink V2-1一样.

首先生成一个CDC工程并测试.

再用同样方法生成MSC,但是不要覆盖当前工程.因为木有分区和很多逻辑没实现,所以借助工具看看.

开始合并了,把CDC内容挪过来.

新建两个文件.

添加文件到Keil.

Keil的Include还要设置.然后编译测试,当然这个时候是不能用的.

修改CDC所用EP.

修改MSC所用EP.

编辑我们的复合头文件.复合用IAD.大概都是写在一起.

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_COMPOSITE_H
#define __USBD_COMPOSITE_H
#ifdef __cplusplus
extern "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 */
/**
* @}
*/
/*****************************END OF FILE****/

然后写对应C文件,分别初始化各种.

#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,               // bLength
USBD_IAD_DESCRIPTOR_TYPE,         // bDescriptorType
USBD_CDC_FIRST_INTERFACE,         // bFirstInterface
USBD_CDC_INTERFACE_NUM,           // bInterfaceCount
0x02,                             // bFunctionClass
0x02,                             // bFunctionSubClass
0x01,                             // bInterfaceProtocol
0x04,                             // 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,                        // bLength
USBD_IAD_DESCRIPTOR_TYPE,                  // bDescriptorType
USBD_MSC_FIRST_INTERFACE,                  // bFirstInterface
USBD_MSC_INTERFACE_NUM,                    // bInterfaceCount
0x08,                                      // bFunctionClass
0x06,                                      // bFunctionSubClass
0x50,                                      // bInterfaceProtocol
0x05,
/********************  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;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/

然后CDC的描述太任性了,改.

不然看文件吗根本不知道是什么玩意.接着修改usb_device.c

修改最大接口数.

因为是CDC 2个 + MSC 1个.然后如果还没有识别,修改Stack Size.

修改为IAD兼容.

复合成功:

程序:

USB 复合

后话:

如果电脑没驱动,请求助官网:http://www.st.com/en/development-tools/stsw-stm32102.html

思考:

如何复合多重HID呢?复合只是为了增加功能,并不能增加带宽.

 

使用STM32CubeMX编写USB复合设备