本意是做一個CDC+MSC的複合裝置,就是類似於ST-LINK2的那種裝置,
在平時使用串列埠功能通訊,偶爾可以通過拖拉檔案進行IAP升級,但是在網上
找了好多資料和教學後,卻發現基本都是同一個教學,而且效果都不盡人意,
總會出現一堆奇奇怪怪的效果,但是USB這個東西本身又是一個很複雜的協定
,我又不想去學習,所以就賊心不死,去google了一些資料,但發現按照
他們的流程走一遍還是有問題,大概記錄一下移植過程中遇到的問題。
在你的CDC工程中找到如下四個檔案:
usbd_cdc.c
usbd_cdc.h
usbd_cdc_if.c
usbd_cdc_if.h
拷貝到MSC工程下,在KEIL裡新增標頭檔案路徑。
新建usbd_composite.c和usbd_composite.h檔案。
在usbd_composite.c檔案中新增如下內容。
/**
******************************************************************************
* @file usbd_MC.c
* @author MCD Application Team
* @version V2.4.2
* @date 11-December-2015
* @brief This file provides all the MC core functions.
*
* @verbatim
*
* ===================================================================
* MC Class Description
* ===================================================================
* This module manages the MC class V1.0 following the "Universal
* Serial Bus Mass Storage Class (MC) Bulk-Only Transport (BOT) Version 1.0
* Sep. 31, 1999".
* This driver implements the following aspects of the specification:
* - Bulk-Only Transport protocol
* - Subclass : SCSI transparent command set (ref. SCSI Primary Commands - 3 (SPC-3))
*
* @endverbatim
*
******************************************************************************
* @attention
*
* <h2><center>© COPYRIGHT 2015 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#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"
/** @defgroup MC_CORE_Private_FunctionPrototypes
* @{
*/
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;
/** @defgroup MC_CORE_Private_Variables
* @{
*/
USBD_ClassTypeDef USBD_MC =
{
USBD_MC_Init,
USBD_MC_DeInit,
USBD_MC_Setup,
NULL, /*EP0_TxSent*/
USBD_MC_RxReady, /*EP0_RxReady*/
USBD_MC_DataIn,
USBD_MC_DataOut,
NULL, /*SOF */
NULL,
NULL,
USBD_MC_GetHSCfgDesc,
USBD_MC_GetFSCfgDesc,
USBD_MC_GetOtherSpeedCfgDesc,
USBD_MC_GetDeviceQualifierDescriptor,
};
/* USB Mass storage device Configuration Descriptor */
/* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
uint8_t USBD_MC_CfgDesc[USB_MC_CONFIG_DESC_SIZ] =
{
/*Configuration Descriptor*/
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_MC_CONFIG_DESC_SIZ, /* wTotalLength:no of returned bytes */
0x00,
0x03, /* bNumInterfaces: 3 interface */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor describing the configuration */
0xC0, /* bmAttributes: self powered */
0x32, /* MaxPower 0 mA */
/*---------------------------------------------------------------------------*/
// IAD
0x08, //ÃèÊö·û´óС
0x0B, //IADÃèÊö·ûÀàÐÍ
0x00, // bFirstInterface
0x02, // bInterfaceCount
0x02, // bFunctionClass: CDC Class
0x02, // bFunctionSubClass
0x01, // bFunctionProtocol
0x00, // iFunction
/*---------------------------------------------------------------------------*/
/*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 endpoints 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: 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 */
0x00, /* bMasterInterface: Communication class interface */
0x01, /* bSlaveInterface0: Data Class Interface */
/*Endpoint 2 Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
MC_CDC_CMD_EP, /* bEndpointAddress */
0x03, /* bmAttributes: Interrupt */
LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */
HIBYTE(CDC_CMD_PACKET_SIZE),
0x10, /* 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 */
MC_CDC_OUT_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(MC_MAX_FS_PACKET), /* wMaxPacketSize: */
HIBYTE(MC_MAX_FS_PACKET),
0x00, /* bInterval: ignore for Bulk transfer */
/*Endpoint IN Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
MC_CDC_IN_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(MC_MAX_FS_PACKET), /* wMaxPacketSize: */
HIBYTE(MC_MAX_FS_PACKET),
0x00, /* bInterval: ignore for Bulk transfer */
/*---------------------------------------------------------------------------*/
// IAD
0x08, //ÃèÊö·û´óС
0x0B, //IADÃèÊö·ûÀàÐÍ
0x02, // bFirstInterface
0x01, // bInterfaceCount
0x08, // bFunctionClass: MASS STORAGE Class
0x06, // bFunctionSubClass
0x50, // bFunctionProtocol
0x01, // iFunction
/******************** Mass Storage interface ********************/
0x09, /* bLength: Interface Descriptor size */
0x04, /* bDescriptorType: */
0x02, /* 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 */
MC_MSC_EPIN_ADDR, /*Endpoint address (IN, address 1) */
0x02, /*Bulk endpoint type */
LOBYTE(MC_MAX_FS_PACKET),
HIBYTE(MC_MAX_FS_PACKET),
0x00, /*Polling interval in milliseconds */
0x07, /*Endpoint descriptor length = 7 */
0x05, /*Endpoint descriptor type */
MC_MSC_EPOUT_ADDR, /*Endpoint address (OUT, address 1) */
0x02, /*Bulk endpoint type */
LOBYTE(MC_MAX_FS_PACKET),
HIBYTE(MC_MAX_FS_PACKET),
0x00 /*Polling interval in milliseconds*/
};
/* USB Standard Device Descriptor */
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,
};
/**
* @}
*/
/** @defgroup MC_CORE_Private_Functions
* @{
*/
/**
* @brief USBD_MC_Init
* Initialize the mass storage configuration
* @param pdev: device instance
* @param cfgidx: configuration index
* @retval status
*/
uint8_t USBD_MC_Init (USBD_HandleTypeDef *pdev,
uint8_t cfgidx)
{
{
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);
}
{
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);
}
return USBD_OK;
}
/**
* @brief USBD_MC_DeInit
* DeInitilaize the mass storage configuration
* @param pdev: device instance
* @param cfgidx: configuration index
* @retval status
*/
uint8_t USBD_MC_DeInit (USBD_HandleTypeDef *pdev,
uint8_t cfgidx)
{
return USBD_OK;
}
/**
* @brief USBD_MC_Setup
* Handle the MC specific requests
* @param pdev: device instance
* @param req: USB request
* @retval status
*/
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)
{
/* Class request */
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;
/* Interface & Endpoint request */
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:
/* Flush the FIFO and Clear the stall status */
USBD_LL_FlushEP(pdev, (uint8_t)req->wIndex);
/* Reactivate the EP */
USBD_LL_CloseEP (pdev , (uint8_t)req->wIndex);
if((((uint8_t)req->wIndex) & 0x80) == 0x80)
{
if(pdev->dev_speed == USBD_SPEED_HIGH )
{
/* Open EP IN */
USBD_LL_OpenEP(pdev,
MC_MSC_EPIN_ADDR,
USBD_EP_TYPE_BULK,
MSC_MAX_HS_PACKET);
}
else
{
/* Open EP IN */
USBD_LL_OpenEP(pdev,
MC_MSC_EPIN_ADDR,
USBD_EP_TYPE_BULK,
MSC_MAX_FS_PACKET);
}
}
else
{
if(pdev->dev_speed == USBD_SPEED_HIGH )
{
/* Open EP IN */
USBD_LL_OpenEP(pdev,
MC_MSC_EPOUT_ADDR,
USBD_EP_TYPE_BULK,
MSC_MAX_HS_PACKET);
}
else
{
/* Open EP IN */
USBD_LL_OpenEP(pdev,
MC_MSC_EPOUT_ADDR,
USBD_EP_TYPE_BULK,
MSC_MAX_FS_PACKET);
}
}
/* Handle BOT error */
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;
}
/**
* @brief USBD_MC_DataIn
* handle data IN Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
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;
}
/**
* @brief USBD_MC_DataOut
* handle data OUT Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
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;
}
/**
* @brief USBD_MC_GetHSCfgDesc
* return configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t *USBD_MC_GetHSCfgDesc (uint16_t *length)
{
*length = sizeof (USBD_MC_CfgDesc);
return USBD_MC_CfgDesc;
}
/**
* @brief USBD_MC_GetFSCfgDesc
* return configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
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_CDC_Interface_fops_FS);
pdev->pClassData = &cdc_handle;
}
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
#ifndef __USBD_COMPOSITE_H
#define __USBD_COMPOSITE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#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_MC;
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USBD_MSC_H */
/**
* @}
*/
/************************ (C) COPYRIGHT WEYNE *****END OF FILE****/
#define CDC_IN_EP 0x81U /* EP1 for data IN */
#define CDC_OUT_EP 0x01U /* EP1 for data OUT */
#define CDC_CMD_EP 0x83U /* EP2 for CDC commands */
修改usbd_msc.h檔案內容
#define MSC_EPIN_ADDR 0x82U
#define MSC_EPOUT_ADDR 0x02U
#define USBD_MAX_NUM_INTERFACES 3
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.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( );
}
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
/* Register USB PCD CallBacks */
HAL_PCD_RegisterCallback(&hpcd_USB_FS, HAL_PCD_SOF_CB_ID, PCD_SOFCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_FS, HAL_PCD_SETUPSTAGE_CB_ID, PCD_SetupStageCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_FS, HAL_PCD_RESET_CB_ID, PCD_ResetCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_FS, HAL_PCD_SUSPEND_CB_ID, PCD_SuspendCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_FS, HAL_PCD_RESUME_CB_ID, PCD_ResumeCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_FS, HAL_PCD_CONNECT_CB_ID, PCD_ConnectCallback);
HAL_PCD_RegisterCallback(&hpcd_USB_FS, HAL_PCD_DISCONNECT_CB_ID, PCD_DisconnectCallback);
HAL_PCD_RegisterDataOutStageCallback(&hpcd_USB_FS, PCD_DataOutStageCallback);
HAL_PCD_RegisterDataInStageCallback(&hpcd_USB_FS, PCD_DataInStageCallback);
HAL_PCD_RegisterIsoOutIncpltCallback(&hpcd_USB_FS, PCD_ISOOUTIncompleteCallback);
HAL_PCD_RegisterIsoInIncpltCallback(&hpcd_USB_FS, PCD_ISOINIncompleteCallback);
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
/* USER CODE BEGIN EndPoint_Configuration */
// HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, 0x18);
// HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, 0x58);
// /* USER CODE END EndPoint_Configuration */
// /* USER CODE BEGIN EndPoint_Configuration_MSC */
// HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x81 , PCD_SNG_BUF, 0x98);
// HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x01 , PCD_SNG_BUF, 0xD8);
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);
/* USER CODE END EndPoint_Configuration_MSC */
return USBD_OK;
}
void MX_USB_DEVICE_Init(void)
{
if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK)
{
Error_Handler();
}
if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_MC) != 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();
}
}
#define USBD_SERIALNUMBER_STRING_FS "00000000001A"
__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*/
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*/
};
uint8_t * USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length)
{
UNUSED(speed);
*length = USB_SIZ_STRING_SERIAL;
/* Update the serial number string descriptor with the data from the unique
* ID */
Get_SerialNum();
/* USER CODE BEGIN USBD_FS_SerialStrDescriptor */
USBD_GetString((uint8_t *)USBD_SERIALNUMBER_STRING_FS, USBD_StrDesc, length);
/* USER CODE END USBD_FS_SerialStrDescriptor */
return (uint8_t *) USBD_StrDesc;
}
這裏USBD_FS_SerialStrDescriptor我是修改後才成功的,當然後來成功後還沒來得及驗證不修改該函數是否有效。後續繼續測試。
理論上來說,這個函數只是回傳序列字串描述符,只是對USB列舉階段有影響,對後續的傳輸應該是無任何影響的。
總體來說,所有的32HAL庫的移植步驟大概都分爲下面 下麪幾步,以CDC+MSC舉例。
1. 先把類檔案較少的一個類的檔案移植到類檔案較多的工程中,一般該路徑在
USB_MSC\Middlewares\ST\STM32_USB_Device_Library\Class下。
2. 找到該類的usbd_xxxx_if.c和標頭檔案,一併新增到工程。(上述流程的1-2)
3. 在你想複合的裝置中找到端點號,進行端點號分配。(上述流程中的第7步)
4. 新增一個新的c檔案和標頭檔案,名字隨便。該檔案的主要目的如下
①. 整合你想移植類的一些函數(一般就是找到要整合的類的USBD_XXX_if.c檔案進行合併).
②. 定義一個USBD_ClassTypeDef型別變數,將所有函數名按順序存放到該變數。
③.定義複合裝置的設定描述符和USB標準描述符。
5. 在usbd_conf.c檔案的USBD_LL_Init函數中新增你新增端點的PMA
6. 在usbd_conf.h檔案中修改最大介面數,因爲是複合裝置,具體數量根據你
的實際使用情況來填寫。
7. 修改USBD_device.c檔案中的註冊介面,將原有的變數修改爲你自定義的
USBD_ClassTypeDef型別的變數,註釋掉,USBD_XXX_RegisterXXXX等字樣的函數。
只有第5步是隻涉及到STM32本身的,在32裏面是由一段記憶體專門用於USB數據緩衝的
大概分爲兩個階段的問題
1. 列舉階段
- 列舉失敗
- 只識別一個裝置,另外一個裝置列舉失敗
2. 使用階段
- U盤正常工作,可讀寫,但是CDC只有在開啓串列埠的時候會輸出兩條語句
- 使用U盤讀寫時CDC沒有數據輸出,但在彈出U盤後CDC正常工作
- 使用U盤讀寫後,CDC直接掛掉!!!無論如何都沒有數據
- CDC也沒數據,MSC出現請插入U盤
反正是問題一大堆,然後在網上翻來覆去的找,也沒找到一個好的解決辦法(太菜了,也懶,實在不想去看USB協定,裏面的分包機制 機製和應答機制 機製,最關鍵的是CDC和MSC的通訊機制 機製),最後在國外論壇找到了一個工程,打開了他的工程,然後參照着修修改改,最終才勉強能用,但還是會存在以下問題。
對於問題一對於目前我的需求來說並沒有什麼影響,主要在於問題二。
經過測試,使用不同的串列埠工具最終會進入**CDC_Control_FS**函數的幾
個分支,但具體是通過setup還是EP0_RxReady進入我還沒有測試,後續測試後在
補上。如果知道瞭如何模擬開啓串列埠這一操作,那麼這一問題就好解決了。
說白了還是對CDC和MSC的通訊機制 機製不是很熟,英文的文件看着確實慢。 慢慢看吧,一個人摸索一個陌生的東西實在太難了,還好網上有大量技術人員的部落格,感謝他們的筆記和一些開源的程式碼資料,萬分感謝。