WinUSB与MSC复合设备--最佳搭配!

本文中采用stm32f103核心板,自带USB FS接口,板载了Flash W25Q16,将该Flash配置为MSC的存储区,最终实现的效果为:将设备插入电脑,可以识别到WinUSB免驱设备,高速通信,同时也能识别出一个大容量存储区域,方便存放一些设备相关的资料、文档等,非常实用!

本文的方法是在WinUSB工程的基础上增加MSC功能。

首先准备好一个WinUSB工程,配置方法见之前的文章:

https://blog.csdn.net/bingwueyi/article/details/121622001

在准备WinUSB工程的时候,将SPI也配置好,后期增加MSC的时候就不用再去设置SPI相关功能,省去一些麻烦。

1 工程配置

1、通过CubeMX生成一个MSC的工程,设置如下:

2、将下图中框出的几个文件及其头文件拷贝到WinUSB工程中的对应目录中

3、将Flash的操作文件W25QXX.c和复合设备文件usbd_composite.c也放到工程目录中,并且将上述文件添加到Keil工程目录,添加完后的工程目录如下:

Keil工程配置中添加相关路径

Flash操作函数参见:STM32CubeMX系列教程11:串行外设接口SPI(二) - STM32CubeMX系列教程 微雪课堂

头文件中将引用改为

#include "main.h"

同时增加如下定义:

#define SPI_FLASH_REBUILD           1    // 1:使能格式化串行Flash,0:禁用格式化串行Flash

#define SPI_FLASH_SECTOR_SIZE    4096    // 串行Flash扇区大小

#define SPI_FLASH_START_SECTOR   256    // 串行Flash文件系统FatFS偏移量

#define SPI_FLASH_SECTOR_COUNT   256    // 串行Flash文件系统FatFS占用扇区个数 

extern  SPI_HandleTypeDef hspi1;   // 添加SPI定义 

usbd_composite.c,usbd_composite.h基于这篇文章修改:https://www.bbsmax.com/A/kjdwBXA5Np/

修改后的文件如下

//usbd_composite.c


/**

 * @file        usbd_composite.c

 * @author      Weyne

 * @version     V01

 * @date        2023.09.10

 * @brief       MSC + WinUSB 复合设备

 * @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);



//-----------------ADD GUOXUAN-----------------

extern uint8_t* USBD_WinUSBOSStrDescriptor(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,

           //-----------------ADD GUOXUAN----------------

  USBD_WinUSBOSStrDescriptor,

//--------------------------------------------

};

/* 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: */

  0x00,   /* 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

  0x02,                             // iFunction ??

  /*Interface Descriptor */



  /* Data class interface descriptor */

  0x09,                                       /* bLength: Endpoint Descriptor size */

  USB_DESC_TYPE_INTERFACE,                    /* bDescriptorType: */

  0x00,                                       /* bInterfaceNumber: Number of Interface */

  0x00,                                       /* bAlternateSetting: Alternate setting */

  0x02,                                       /* bNumEndpoints: Two endpoints used */

  0xFF,                                       /* 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 */





 /****************************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_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_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:

                     pdev->pClassData = pCDCData;

                     pdev->pUserData =  &USBD_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_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_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_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****/

//usbd_composite.h

/**

 * @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 __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       1          /* winusb Interface NUM */

#define USBD_CDC_DATA_INTERFACE      0

#define USBD_MSC_FIRST_INTERFACE     1          /* MSC FirstInterface */

#define USBD_MSC_INTERFACE_NUM       1          /* MSC Interface NUM */

#define USBD_MSC_INTERFACE           1

#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    (71)

extern USBD_ClassTypeDef    USBD_COMPOSITE;

/**

  * @}

  */

/**

  * @}

  */

#ifdef __cplusplus

}

#endif

#endif  /* __USBD_MSC_H */

/**

  * @}

  */

/************************ (C) COPYRIGHT WEYNE *****END OF FILE****/

2 修改工程文件

2.1 修改usbd_storage_if.c

1、添加Flash操作函数头文件

#include "W25QXX.h"

2、根据Flash容量修改block数量,例如此处我用的时2MB的Flash,Flash需要划分一部分空间存文件系统信息,此处Block大小为4K,数量为256,总容量为1M,修改如下

#define STORAGE_LUN_NBR                  1

#define STORAGE_BLK_NBR                  256

#define STORAGE_BLK_SIZ                  0x1000

3、在STORAGE_Init_FS中加入Flash初始化函数BSP_W25Qx_Init(),在初始化中可以执行唤醒、读写使能、三四字节模式切换等操作。

int8_t STORAGE_Init_FS(uint8_t lun)

{

  /* USER CODE BEGIN 2 */

BSP_W25Qx_Init();

  return (USBD_OK);

  /* USER CODE END 2 */

}

4、在读写函数中分别加入对Flash的操作

int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)

{

  /* USER CODE BEGIN 6 */

blk_addr+=SPI_FLASH_START_SECTOR;        

BSP_W25Qx_Read(buf, blk_addr*SPI_FLASH_SECTOR_SIZE, blk_len*SPI_FLASH_SECTOR_SIZE);



  return (USBD_OK);

  /* USER CODE END 6 */

}





int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)

{

  /* USER CODE BEGIN 7 */

uint32_t write_addr;

blk_addr+=SPI_FLASH_START_SECTOR;

write_addr = blk_addr*SPI_FLASH_SECTOR_SIZE;   

BSP_W25Qx_Erase_Block(write_addr);

BSP_W25Qx_Write((uint8_t *)buf,write_addr,blk_len*SPI_FLASH_SECTOR_SIZE);

  return (USBD_OK);

  /* USER CODE END 7 */

}

2.2 修改usbd_msc.h

查看MSC_EPIN_ADDR的值为0x81,与WinUSB的端点重复了,此处将MSC的端点改为0x83和0x03:

#define MSC_EPIN_ADDR                0x83U

#define MSC_EPOUT_ADDR               0x03U

2.3 修改usb_device.c

1、添加复合设备头文件引用

#include "usbd_composite.h"

2、将初始化函数中的设备注册修改注册为复合设备

void MX_USB_DEVICE_Init(void)

{

  /* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */



  /* USER CODE END USB_DEVICE_Init_PreTreatment */



  /* Init Device Library, add supported class and start the library. */

  if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK)

  {

    Error_Handler();

  }

 

  USBD_RegisterClass(&hUsbDeviceFS, &USBD_COMPOSITE);

//  if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC) != USBD_OK)

//  {

//    Error_Handler();

//  }

//  if (USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS) != USBD_OK)

//  {

//    Error_Handler();

//  }

  if (USBD_Start(&hUsbDeviceFS) != USBD_OK)

  {

    Error_Handler();

  }



  /* USER CODE BEGIN USB_DEVICE_Init_PostTreatment */



  /* USER CODE END USB_DEVICE_Init_PostTreatment */

}

2.4 修改usbd_conf.c

1、添加msc的头文件引用

#include "usbd_msc.h"

2、在USBD_LL_Init函数中增加MSC的内存区间定义

USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)

{

  /* Init USB Ip. */

uint32_t addr = 0x20;

  /* 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, addr); addr = addr + 0x40;

  HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, addr); addr = addr + 0x40;

  HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , MSC_EPIN_ADDR , PCD_SNG_BUF, addr); addr = addr + 0x40;

  HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , MSC_EPOUT_ADDR , PCD_SNG_BUF, addr); addr = addr + 0x40;

  HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_IN_EP , PCD_SNG_BUF, addr); addr = addr + 0x40;

  HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_OUT_EP , PCD_SNG_BUF, addr); addr = addr + 0x40;

  HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_CMD_EP   , PCD_SNG_BUF, addr); addr = addr + 0x40;

 

  /* USER CODE END EndPoint_Configuration_MSC */

  return USBD_OK;

}

3、修改USBD_static_malloc函数,增加MSC的存储空间:

void *USBD_static_malloc(uint32_t size)

{

static uint32_t mem2[(sizeof(USBD_MSC_BOT_HandleTypeDef)/4)+1];/* On 32-bit boundary */

static uint32_t mem[(sizeof(USBD_CDC_HandleTypeDef)/4)+1];/* */



if(size == sizeof(USBD_MSC_BOT_HandleTypeDef))

           return mem2;

else return mem;

}

2.5 修改usbd_conf.h

1、将USBD_MAX_NUM_INTERFACES定义为2个接口:

#define USBD_MAX_NUM_INTERFACES     2

2、添加MSC_MEDIA_PACKET定义:

#define MSC_MEDIA_PACKET     4096

3 测试

完成上述修改(建议随意修改一个PID VID),编译-->下载-->插入电脑,将会枚举出一个usb复合设备,并且识别到一个WinUSB设备和一个大容量存储设备:

查看识别到的U盘,容量与2.1章节第2小节设置的一致,打开U盘创建文件、导入、导出等功能一切正常。

使用WinUSB通用调试软件,可以识别到刚插入的设备,并且通信正常,此处WinUSB为回环模式,收到数据原包回复。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值