基于cubemx H750 的 MSC与CDC复合设备
参考:STM32F7USB复合设备cube-MSC与CDC复合设备
首先得保证MSC作为单独设备时,可以在PC被正确识别。
USB为 USB_OTG_FS
-
RCC使用外部高速时钟 -
先生成一个CDC工程下面配置图。 -
USB_OTG_FS如图 -
USB_Device如图箭头其他默认 -
修改堆栈大小: 按需求设置,HeapSize 应大于 4k -
同样生成一个新的MSC工程不可覆盖原本的工程,MSC配置入下: -
生成后把CDC工程下Src文件夹里的usbd_cdc_if.c与Inc下的usbd_cdc_if.h复制到MSC工程下Src与Inc文件夹里面,MSC工程下Src文件夹下新建usbd_composite.c与Inc下新建usbd_composite.h
8. 把CDC工程\Middlewares\ST\STM32_USB_Device_Library\Class目录下的CDC文件夹复制到MSC工程下见图
-
添加CDC路径 -
在工程中添加usbd_cdc.c usbd_cdc_if.c usbd_composite.c见图 -
usbd_conf.h 把USBD_MAX_NUM_INTERFACES值 1修改为3
#define USBD_MAX_NUM_INTERFACES 3U
- usbd_cdc.h 修改CDC_IN_EP CDC_OUT_EP CDC_CMD_EP
#define CDC_IN_EP 0x83
#define CDC_OUT_EP 0x03
#define CDC_CMD_EP 0x82
- usbd_conf.c USBD_LL_Init中新增
USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
{
if (pdev->id == DEVICE_FS) {
hpcd_USB_OTG_FS.pData = pdev;
pdev->pData = &hpcd_USB_OTG_FS;
hpcd_USB_OTG_FS.Instance = USB_OTG_FS;
hpcd_USB_OTG_FS.Init.dev_endpoints = 9;
hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL;
hpcd_USB_OTG_FS.Init.dma_enable = DISABLE;
hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
hpcd_USB_OTG_FS.Init.Sof_enable = DISABLE;
hpcd_USB_OTG_FS.Init.low_power_enable = DISABLE;
hpcd_USB_OTG_FS.Init.lpm_enable = DISABLE;
hpcd_USB_OTG_FS.Init.battery_charging_enable = DISABLE;
hpcd_USB_OTG_FS.Init.vbus_sensing_enable = DISABLE;
hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = DISABLE;
if (HAL_PCD_Init(&hpcd_USB_OTG_FS) != HAL_OK)
{
Error_Handler( );
}
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SOF_CB_ID, PCD_SOFCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SETUPSTAGE_CB_ID, PCD_SetupStageCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_RESET_CB_ID, PCD_ResetCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_SUSPEND_CB_ID, PCD_SuspendCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_RESUME_CB_ID, PCD_ResumeCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_CONNECT_CB_ID, PCD_ConnectCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_OTG_FS, HAL_PCD_DISCONNECT_CB_ID, PCD_DisconnectCallback);
HAL_PCD_RegisterDataOutStageCallback(&hpcd_USB_OTG_FS, PCD_DataOutStageCallback);
HAL_PCD_RegisterDataInStageCallback(&hpcd_USB_OTG_FS, PCD_DataInStageCallback);
HAL_PCD_RegisterIsoOutIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOOUTIncompleteCallback);
HAL_PCD_RegisterIsoInIncpltCallback(&hpcd_USB_OTG_FS, PCD_ISOINIncompleteCallback);
#endif
HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 0x80);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 0x40);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x80);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x40);
HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 3, 0x40);
}
return USBD_OK;
}
- usb_device.c 修改MX_USB_DEVICE_Init与SER CODE BEGIN Includes中新增usbd_composite.h
#include "usbd_composite.h"
void MX_USB_DEVICE_Init(void)
{
#if 0
if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK)
{
Error_Handler();
}
if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_MSC) != USBD_OK)
{
Error_Handler();
}
if (USBD_MSC_RegisterStorage(&hUsbDeviceFS, &USBD_Storage_Interface_fops_FS) != USBD_OK)
{
Error_Handler();
}
if (USBD_Start(&hUsbDeviceFS) != USBD_OK)
{
Error_Handler();
}
#endif
if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK)
{
Error_Handler();
}
if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_COMPOSITE) != USBD_OK)
{
Error_Handler();
}
if (USBD_Start(&hUsbDeviceFS) != USBD_OK)
{
Error_Handler();
}
HAL_PWREx_EnableUSBVoltageDetector();
}
15.在usbd_composite.h中新增代码
#ifndef __USBD_COMPOSITE_H
#define __USBD_COMPOSITE_H
#include "usbd_ioreq.h"
#include "usbd_cdc.h"
#include "usbd_msc.h"
#define MC_MAX_FS_PACKET 0x40
#define USB_MC_CONFIG_DESC_SIZ 106
#define MC_MSC_EPIN_ADDR MSC_EPIN_ADDR
#define MC_MSC_EPOUT_ADDR MSC_EPOUT_ADDR
#define MC_CDC_IN_EP CDC_IN_EP
#define MC_CDC_OUT_EP CDC_OUT_EP
#define MC_CDC_CMD_EP CDC_CMD_EP
extern USBD_ClassTypeDef USBD_COMPOSITE;
#endif
16.在usbd_composite.c中新增代码
#include "usbd_composite.h"
#include "usbd_def.h"
#include "usbd_msc.h"
#include "usbd_cdc.h"
#include "usbd_storage_if.h"
#include "usbd_cdc_if.h"
USBD_CDC_HandleTypeDef *pCDCData;
USBD_MSC_BOT_HandleTypeDef *pMSCData;
uint8_t USBD_MC_Init (USBD_HandleTypeDef *pdev,
uint8_t cfgidx);
uint8_t USBD_MC_DeInit (USBD_HandleTypeDef *pdev,
uint8_t cfgidx);
uint8_t USBD_MC_Setup (USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req);
uint8_t USBD_MC_DataIn (USBD_HandleTypeDef *pdev,
uint8_t epnum);
uint8_t USBD_MC_DataOut (USBD_HandleTypeDef *pdev,
uint8_t epnum);
uint8_t *USBD_MC_GetHSCfgDesc (uint16_t *length);
uint8_t *USBD_MC_GetFSCfgDesc (uint16_t *length);
uint8_t *USBD_MC_GetOtherSpeedCfgDesc (uint16_t *length);
uint8_t *USBD_MC_GetDeviceQualifierDescriptor (uint16_t *length);
static uint8_t USBD_MC_RxReady (USBD_HandleTypeDef *pdev);
static void MC_Switch_MSC(USBD_HandleTypeDef *pdev);
static void MC_Switch_CDC(USBD_HandleTypeDef *pdev);
extern USBD_HandleTypeDef hUsbDeviceFS;
USBD_ClassTypeDef USBD_COMPOSITE =
{
USBD_MC_Init,
USBD_MC_DeInit,
USBD_MC_Setup,
NULL,
USBD_MC_RxReady,
USBD_MC_DataIn,
USBD_MC_DataOut,
NULL,
NULL,
NULL,
USBD_MC_GetHSCfgDesc,
USBD_MC_GetFSCfgDesc,
USBD_MC_GetOtherSpeedCfgDesc,
USBD_MC_GetDeviceQualifierDescriptor,
};
uint8_t USBD_MC_CfgDesc[USB_MC_CONFIG_DESC_SIZ] =
{
0x09,
USB_DESC_TYPE_CONFIGURATION,
USB_MC_CONFIG_DESC_SIZ,
0x00,
0x03,
0x01,
0x00,
0xC0,
0x32,
0x08,
0x0B,
0x00,
0x02,
0x02,
0x02,
0x01,
0x00,
0x09,
USB_DESC_TYPE_INTERFACE,
0x00,
0x00,
0x01,
0x02,
0x02,
0x01,
0x00,
0x05,
0x24,
0x00,
0x10,
0x01,
0x05,
0x24,
0x01,
0x00,
0x01,
0x04,
0x24,
0x02,
0x02,
0x05,
0x24,
0x06,
0x00,
0x01,
0x07,
USB_DESC_TYPE_ENDPOINT,
MC_CDC_CMD_EP,
0x03,
LOBYTE(CDC_CMD_PACKET_SIZE),
HIBYTE(CDC_CMD_PACKET_SIZE),
0x10,
0x09,
USB_DESC_TYPE_INTERFACE,
0x01,
0x00,
0x02,
0x0A,
0x00,
0x00,
0x00,
0x07,
USB_DESC_TYPE_ENDPOINT,
MC_CDC_OUT_EP,
0x02,
LOBYTE(MC_MAX_FS_PACKET),
HIBYTE(MC_MAX_FS_PACKET),
0x00,
0x07,
USB_DESC_TYPE_ENDPOINT,
MC_CDC_IN_EP,
0x02,
LOBYTE(MC_MAX_FS_PACKET),
HIBYTE(MC_MAX_FS_PACKET),
0x00,
0x08,
0x0B,
0x02,
0x01,
0x08,
0x06,
0x50,
0x01,
0x09,
0x04,
0x02,
0x00,
0x02,
0x08,
0x06,
0x50,
0x05,
0x07,
0x05,
MC_MSC_EPIN_ADDR,
0x02,
LOBYTE(MC_MAX_FS_PACKET),
HIBYTE(MC_MAX_FS_PACKET),
0x00,
0x07,
0x05,
MC_MSC_EPOUT_ADDR,
0x02,
LOBYTE(MC_MAX_FS_PACKET),
HIBYTE(MC_MAX_FS_PACKET),
0x00
};
uint8_t USBD_MC_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] =
{
USB_LEN_DEV_QUALIFIER_DESC,
USB_DESC_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
MC_MAX_FS_PACKET,
0x01,
0x00,
};
uint8_t USBD_MC_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
uint8_t ret = 0U;
USBD_CDC_HandleTypeDef * hcdc;
MC_Switch_CDC(pdev);
USBD_LL_OpenEP(pdev,
MC_CDC_IN_EP,
USBD_EP_TYPE_BULK,
MC_MAX_FS_PACKET);
USBD_LL_OpenEP(pdev,
MC_CDC_OUT_EP,
USBD_EP_TYPE_BULK,
MC_MAX_FS_PACKET);
USBD_LL_OpenEP(pdev,
MC_CDC_CMD_EP,
USBD_EP_TYPE_INTR,
CDC_CMD_PACKET_SIZE);
hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData;
((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Init();
hcdc->TxState =0;
hcdc->RxState =0;
USBD_LL_PrepareReceive(pdev,
MC_CDC_OUT_EP,
hcdc->RxBuffer,
MC_MAX_FS_PACKET);
pCDCData = pdev->pClassData;
MC_Switch_MSC(pdev);
USBD_LL_OpenEP(pdev,
MC_MSC_EPOUT_ADDR,
USBD_EP_TYPE_BULK,
MC_MAX_FS_PACKET);
USBD_LL_OpenEP(pdev,
MC_MSC_EPIN_ADDR,
USBD_EP_TYPE_BULK,
MC_MAX_FS_PACKET);
MSC_BOT_Init(pdev);
pMSCData = pdev->pClassData;
if(pdev->pClassData == NULL)
{
ret = USBD_FAIL;
}
return ret;
}
uint8_t USBD_MC_DeInit (USBD_HandleTypeDef *pdev,
uint8_t cfgidx)
{
return USBD_OK;
}
uint8_t USBD_MC_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
if(req->wIndex == 0x0002)
{
MC_Switch_MSC(pdev);
USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef*) pdev->pClassData;
switch (req->bmRequest & USB_REQ_TYPE_MASK)
{
case USB_REQ_TYPE_CLASS :
switch (req->bRequest)
{
case BOT_GET_MAX_LUN :
if((req->wValue == 0) &&
(req->wLength == 1) &&
((req->bmRequest & 0x80) == 0x80))
{
hmsc->max_lun = ((USBD_StorageTypeDef *)pdev->pUserData)->GetMaxLun();
USBD_CtlSendData (pdev,
(uint8_t *)&hmsc->max_lun,
1);
}
else
{
USBD_CtlError(pdev , req);
return USBD_FAIL;
}
break;
case BOT_RESET :
if((req->wValue == 0) &&
(req->wLength == 0) &&
((req->bmRequest & 0x80) != 0x80))
{
MSC_BOT_Reset(pdev);
}
else
{
USBD_CtlError(pdev , req);
return USBD_FAIL;
}
break;
default:
USBD_CtlError(pdev , req);
return USBD_FAIL;
}
break;
case USB_REQ_TYPE_STANDARD:
switch (req->bRequest)
{
case USB_REQ_GET_INTERFACE :
USBD_CtlSendData (pdev,
(uint8_t *)&hmsc->interface,
1);
break;
case USB_REQ_SET_INTERFACE :
hmsc->interface = (uint8_t)(req->wValue);
break;
case USB_REQ_CLEAR_FEATURE:
USBD_LL_FlushEP(pdev, (uint8_t)req->wIndex);
USBD_LL_CloseEP (pdev , (uint8_t)req->wIndex);
if((((uint8_t)req->wIndex) & 0x80) == 0x80)
{
if(pdev->dev_speed == USBD_SPEED_HIGH )
{
USBD_LL_OpenEP(pdev,
MC_MSC_EPIN_ADDR,
USBD_EP_TYPE_BULK,
MSC_MAX_HS_PACKET);
}
else
{
USBD_LL_OpenEP(pdev,
MC_MSC_EPIN_ADDR,
USBD_EP_TYPE_BULK,
MSC_MAX_FS_PACKET);
}
}
else
{
if(pdev->dev_speed == USBD_SPEED_HIGH )
{
USBD_LL_OpenEP(pdev,
MC_MSC_EPOUT_ADDR,
USBD_EP_TYPE_BULK,
MSC_MAX_HS_PACKET);
}
else
{
USBD_LL_OpenEP(pdev,
MC_MSC_EPOUT_ADDR,
USBD_EP_TYPE_BULK,
MSC_MAX_FS_PACKET);
}
}
MSC_BOT_CplClrFeature(pdev, (uint8_t)req->wIndex);
break;
}
break;
default:
break;
}
}
else
{
MC_Switch_CDC(pdev);
static uint8_t ifalt = 0;
USBD_CDC_HandleTypeDef * hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassData;
switch (req->bmRequest & USB_REQ_TYPE_MASK)
{
case USB_REQ_TYPE_CLASS :
if (req->wLength)
{
if (req->bmRequest & 0x80)
{
((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Control(req->bRequest,
(uint8_t *)hcdc->data,
req->wLength);
USBD_CtlSendData (pdev,
(uint8_t *)hcdc->data,
req->wLength);
}
else
{
hcdc->CmdOpCode = req->bRequest;
hcdc->CmdLength = req->wLength;
USBD_CtlPrepareRx (pdev,
(uint8_t *)hcdc->data,
req->wLength);
}
}
else
{
((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Control(req->bRequest,
(uint8_t*)req,
0);
}
break;
case USB_REQ_TYPE_STANDARD:
switch (req->bRequest)
{
case USB_REQ_GET_INTERFACE :
USBD_CtlSendData (pdev,
&ifalt,
1);
break;
case USB_REQ_SET_INTERFACE :
break;
}
default:
break;
}
}
return USBD_OK;
}
uint8_t USBD_MC_DataIn (USBD_HandleTypeDef *pdev,
uint8_t epnum)
{
if(epnum == (MC_MSC_EPIN_ADDR & 0x7f))
{
MC_Switch_MSC(pdev);
MSC_BOT_DataIn(pdev , epnum);
}
else if(epnum == (MC_CDC_IN_EP & 0x7f))
{
USBD_CDC_HandleTypeDef *hcdc;
MC_Switch_CDC(pdev);
hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData;
hcdc->TxState = 0;
}
return USBD_OK;
}
uint8_t USBD_MC_DataOut (USBD_HandleTypeDef *pdev,
uint8_t epnum)
{
if(epnum == MC_MSC_EPOUT_ADDR)
{
MC_Switch_MSC(pdev);
MSC_BOT_DataOut(pdev , epnum);
}
else if(epnum == MC_CDC_OUT_EP)
{
USBD_CDC_HandleTypeDef *hcdc;
MC_Switch_CDC(pdev);
hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData;
hcdc->RxLength = USBD_LL_GetRxDataSize (pdev, epnum);
((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Receive(hcdc->RxBuffer, &hcdc->RxLength);
}
return USBD_OK;
}
uint8_t *USBD_MC_GetHSCfgDesc (uint16_t *length)
{
*length = sizeof (USBD_MC_CfgDesc);
return USBD_MC_CfgDesc;
}
uint8_t *USBD_MC_GetFSCfgDesc (uint16_t *length)
{
*length = sizeof (USBD_MC_CfgDesc);
return USBD_MC_CfgDesc;
}
uint8_t *USBD_MC_GetOtherSpeedCfgDesc (uint16_t *length)
{
*length = sizeof (USBD_MC_CfgDesc);
return USBD_MC_CfgDesc;
}
uint8_t *USBD_MC_GetDeviceQualifierDescriptor (uint16_t *length)
{
*length = sizeof (USBD_MC_DeviceQualifierDesc);
return USBD_MC_DeviceQualifierDesc;
}
static uint8_t USBD_MC_RxReady (USBD_HandleTypeDef *pdev)
{
USBD_CDC_HandleTypeDef *hcdc;
MC_Switch_CDC(pdev);
hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData;
if((pdev->pUserData != NULL) && (hcdc->CmdOpCode != 0xFF))
{
((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Control(hcdc->CmdOpCode,
(uint8_t *)hcdc->data,
hcdc->CmdLength);
hcdc->CmdOpCode = 0xFF;
}
return USBD_OK;
}
static void MC_Switch_MSC(USBD_HandleTypeDef *pdev)
{
static USBD_MSC_BOT_HandleTypeDef msc_handle;
USBD_MSC_RegisterStorage(pdev, &USBD_Storage_Interface_fops_FS);
pdev->pClassData = &msc_handle;
}
static void MC_Switch_CDC(USBD_HandleTypeDef *pdev)
{
static USBD_CDC_HandleTypeDef cdc_handle;
USBD_CDC_RegisterInterface(pdev, &USBD_Interface_fops_FS);
pdev->pClassData = &cdc_handle;
}
通过以上修改后电脑电脑端显示USB复合设备MSC+CDC
17.在usbd_cdc_if.c CDC_Receive_FS /* USER CODE BEGIN 6 */ 增加发送测试
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
CDC_Transmit_FS(UserRxBufferFS, *Len);
return (USBD_OK);
}
|