打印
[STM32F1]

STM32 的 USB Mutidevice CDC+ Mass实现 record

[复制链接]
6100|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
b620126|  楼主 | 2014-1-14 11:11 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近移植了一下 STM32F103 MutiDevice的功能 实现一个 SD读卡器 和 CDC串口同时实现的功能


其实整个过程是融合2部分的代码

USB程序的架构是这样的

HW层  -》 USBEndPoint组 -》 回调函数


HW层两部分的代码完全一样不需要关心

主要过程是配置Endpoint 和 USB 相关的回调函数


USBEndPoint 一共有可配置的 EP 0-7 8个端点


其中EP0 用于传输枚举 及其它控制信息不可以动

其他端点EP 均可以自由配置


CDC 和 Mass占用端点如下

CDC 和Mass ENDP比较
        CDC        Mass Storage
ENDP0
TX/RX        枚举和控制        枚举和控制
ENDP1
TX        CDC
串口输入        Mass数据输入
ENDP2
TX        CDC
中断输入        未使用
ENDP2
RX        未使用        Mass数据输出
ENDP3
RX        CDC
串口输出        未使用

。。。。这个表格真不好用

现在重新分配如下
EP0 : 不动

EP1TX:不动   串口输入

EP2TX:不动   CDC中断

EP3RX:不动   串口输出


EP4TX:Mass  数据输入

EP5RX:Mass  数据输出


确定了这个分配之后,就要用代码实现:

实现需要修改3处:

1.端点描述符和设备描述符
在usbdesc.c中修改
首先修改设备描述符为Muti设备
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
/* USB Standard Device Descriptor */  
const u8 Composite_DeviceDescriptor[] =  
  {  
    0x12,   /* bLength */  
    USB_DEVICE_DESCRIPTOR_TYPE,     /* bDescriptorType */  
    0x00,  
    0x02,   /* bcdUSB = 2.00 */  
    0x00,//0xEF,//0x02,   /* bDeviceClass: CDC */  
    0x00,//0X02,//0x00,   /* bDeviceSubClass */  
    0x00,//0X01,//0x00,   /* bDeviceProtocol */  
    0x40,   /* bMaxPacketSize0 */  
    0x83,  
    0x04,   /* idVendor = 0x0483 */  
    0x41,  
    0xaa,   /* idProduct = 0x7540 */  
    0x00,  
    0x02,   /* bcdDevice = 2.00 */  
    1,              /* Index of string descriptor describing manufacturer */  
    2,              /* Index of string descriptor describing product */  
    3,              /* Index of string descriptor describing the device's serial number */  
    0x01    /* bNumConfigurations */  
  };  
主要修改USB子类 修改为 EF 02 01 或者 00 00 00 似乎都可以

然后修改描述符 这个才是关键
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
#define WBVAL(x) (x & 0xFF),((x >> 8) & 0xFF)  
// Interface numbers  
enum {  
    USB_CDC_CIF_NUM0,  
    USB_CDC_DIF_NUM0,  
    USB_MAS_CIF_NUM0,  
//     USB_MAS_DIF_NUM2,  
      
    USB_NUM_INTERFACES        // number of interfaces  
};  
   
#define USB_CONFIGUARTION_DESC_SIZE             9  
#define USB_IAD_DESC_SIZE                 8  
#define USB_INTERFACE_DESC_SIZE                 9  
#define USB_ENDPOINT_DESC_SIZE                  7  
  
#define CDC_COMMUNICATION_INTERFACE_CLASS       0x02  
#define CDC_COMMUNICATION_INTERFACE_SUBCLASS    0x00  
#define CDC_COMMUNICATION_INTERFACE_PROTOCOL    0x00  
#define CDC_DATA_INTERFACE_CLASS                0x0A  
#define CDC_CS_INTERFACE                        0x24  
#define CDC_HEADER                              0x00  
#define CDC_CALL_MANAGEMENT                     0x01  
#define CDC_ABSTRACT_CONTROL_MANAGEMENT         0x02  
#define CDC_UNION                               0x06  
  
#define USB_ENDPOINT_TYPE_BULK                  0x02  
#define USB_ENDPOINT_TYPE_INTERRUPT             0x03  
  
const u8 Composite_ConfigDescriptor[] =  
  {  
    /*Configuation Descriptor*/  
    USB_CONFIGUARTION_DESC_SIZE,   /* bLength: Configuation Descriptor size */  
    USB_CONFIGURATION_DESCRIPTOR_TYPE,      /* bDescriptorType: Configuration */  
    //Composite_SIZ_CONFIG_DESC,       /* wTotalLength:no of returned bytes */  
    //0x00,  
    WBVAL(                             /* wTotalLength */  
      Composite_SIZ_CONFIG_DESC  
    ),  
    USB_NUM_INTERFACES,   /* bNumInterfaces: 2 interface */  
    0x01,   /* bConfigurationValue: Configuration value */  
    0x00,   /* iConfiguration: Index of string descriptor describing the configuration */  
    0xC0,   /* bmAttributes: self powered */  
    0x32,   /* MaxPower 0 mA */  
        
    USB_IAD_DESC_SIZE,   
    USB_IAD_DESCRIPTOR_TYPE,  
    USB_CDC_CIF_NUM0,                       /* bFirstInterface */  
    0x02,                                   /* bInterfaceCount */         
    CDC_COMMUNICATION_INTERFACE_CLASS,      /* bFunctionClass */         
    CDC_COMMUNICATION_INTERFACE_SUBCLASS,   /* bFunctionSubClass */      
    CDC_COMMUNICATION_INTERFACE_PROTOCOL,   /* bFunctionProcotol */      
    0x00,                                   /* iInterface */        
// //CDC      
    /*Interface Descriptor*/  
    USB_INTERFACE_DESC_SIZE,   /* bLength: Interface Descriptor size */  
    USB_INTERFACE_DESCRIPTOR_TYPE,  /* bDescriptorType: Interface */  
    /* Interface descriptor type */  
    USB_CDC_CIF_NUM0,   /* 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 Managment Functional Descriptor*/  
    0x05,   /* bFunctionLength */  
    0x24,   /* bDescriptorType: CS_INTERFACE */  
    0x01,   /* bDescriptorSubtype: Call Management Func Desc */  
    0x00,   /* bmCapabilities: D0+D1 */  
    USB_CDC_DIF_NUM0,   /* 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 */  
    USB_CDC_CIF_NUM0,   /* bMasterInterface: Communication class interface */  
    USB_CDC_DIF_NUM0,   /* bSlaveInterface0: Data Class Interface */  
    /*Endpoint 2 Descriptor*/  
    USB_ENDPOINT_DESC_SIZE,   /* bLength: Endpoint Descriptor size */  
    USB_ENDPOINT_DESCRIPTOR_TYPE,   /* bDescriptorType: Endpoint */  
    0x82,   /* bEndpointAddress: (IN2) */  
    USB_ENDPOINT_TYPE_INTERRUPT,   /* bmAttributes: Interrupt */  
    WBVAL(Composite_INT_SIZE),      /* wMaxPacketSize: */  
    0xFF,   /* bInterval: */  
    /*Data class interface descriptor*/  
    USB_INTERFACE_DESC_SIZE,   /* bLength: Endpoint Descriptor size */  
    USB_INTERFACE_DESCRIPTOR_TYPE,  /* bDescriptorType: */  
    USB_CDC_DIF_NUM0,   /* bInterfaceNumber: Number of Interface */  
    0x00,   /* bAlternateSetting: Alternate setting */  
    0x02,   /* bNumEndpoints: Two endpoints used */  
    CDC_DATA_INTERFACE_CLASS,   /* bInterfaceClass: CDC */  
    0x00,   /* bInterfaceSubClass: */  
    0x00,   /* bInterfaceProtocol: */  
    0x00,   /* iInterface: */  
    /*Endpoint 3 Descriptor*/  
    USB_ENDPOINT_DESC_SIZE,   /* bLength: Endpoint Descriptor size */  
    USB_ENDPOINT_DESCRIPTOR_TYPE,   /* bDescriptorType: Endpoint */  
    0x03,   /* bEndpointAddress: (OUT3) */  
    USB_ENDPOINT_TYPE_BULK,   /* bmAttributes: Bulk */  
    WBVAL(Composite_DATA_SIZE),             /* wMaxPacketSize: */  
    0x00,   /* bInterval: ignore for Bulk transfer */  
    /*Endpoint 1 Descriptor*/  
    USB_ENDPOINT_DESC_SIZE,   /* bLength: Endpoint Descriptor size */  
    USB_ENDPOINT_DESCRIPTOR_TYPE,   /* bDescriptorType: Endpoint */  
    0x81,   /* bEndpointAddress: (IN1) */  
    USB_ENDPOINT_TYPE_BULK,   /* bmAttributes: Bulk */  
    WBVAL(Composite_DATA_SIZE),             /* wMaxPacketSize: */  
    0x00,    /* bInterval */  
/******************** Descriptor of Mass Storage interface ********************/  
    /* 09 */  
    0x09,   /* bLength: Interface Descriptor size */  
    0x04,   /* bDescriptorType: */  
    /*      Interface descriptor type */  
    USB_MAS_CIF_NUM0,   /* bInterfaceNumber: Number of Interface */  
    0x00,   /* bAlternateSetting: Alternate setting */  
    0x02,   /* bNumEndpoints*/  
    0x08,   /* bInterfaceClass: MASS STORAGE Class */  
    0x06,   /* bInterfaceSubClass : SCSI transparent*/  
    0x50,   /* nInterfaceProtocol */  
    1,          /* iInterface: */  
    /* 18 */  
    0x07,   /*Endpoint descriptor length = 7*/  
    0x05,   /*Endpoint descriptor type */  
    0x84,//0x82,   /*Endpoint address (IN, address 2) */  
    0x02,   /*Bulk endpoint type */  
    0x40,   /*Maximum packet size (64 bytes) */  
    0x00,  
    0x00,   /*Polling interval in milliseconds */  
    /* 25 */  
    0x07,   /*Endpoint descriptor length = 7 */  
    0x05,   /*Endpoint descriptor type */  
    0x05,//0x02,   /*Endpoint address (OUT, address 2) */  
    0x02,   /*Bulk endpoint type */  
    0x40,   /*Maximum packet size (64 bytes) */  
    0x00,  
    0x00     /*Polling interval in milliseconds*/  
    /*32*/      
  };  
CDC实现最好添加一个 IAD的头 不过测试似乎不加也没关系

修改主要是这些部分
1.修改 USB类型 同时增加 IAD头
2.重新分配一下Interface,可以用枚举类型方式实现
CDC 需要 2个 Mass需要一个
3.设置好Interface的 ENDPoint
4.重新设置一下 这个描述符的长度


这时运行 就可以看到描述的设备了 不过可能出现感叹号
沙发
b620126|  楼主 | 2014-1-14 11:12 | 只看该作者
本帖最后由 b620126 于 2014-1-15 10:19 编辑

2014-01-14 STEP1 修改描述符        http://blog.csdn.net/chentyjpm/article/details/18256357
2014-01-15 STEP2 修改ENDP0   5L  http://blog.csdn.net/chentyjpm/article/details/18302813

使用特权

评论回复
板凳
beyond696| | 2014-1-14 12:03 | 只看该作者
我刚刚完成个STM32F105实现USB转双串口的功能,串口用DMA发送接收数据,测试了下,感觉还不错!

使用特权

评论回复
地板
b620126|  楼主 | 2014-1-14 13:46 | 只看该作者
beyond696 发表于 2014-1-14 12:03
我刚刚完成个STM32F105实现USB转双串口的功能,串口用DMA发送接收数据,测试了下,感觉还不错! ...

Dual CDC 好像需要IAD 其实理论上 3个串口也可以的~

使用特权

评论回复
5
b620126|  楼主 | 2014-1-15 10:17 | 只看该作者
为了去掉感叹号需要实现每个端点的功能
首先是 ENDP0 控制端点

这个端点 的功能在 USBprop.c里面
主要是一大把函数指针
这是CDC下的
DEVICE_PROP Device_Property =
  {
    Virtual_Com_Port_init,
    Virtual_Com_Port_Reset,
    Virtual_Com_Port_Status_In,
    Virtual_Com_Port_Status_Out,
    Virtual_Com_Port_Data_Setup,
    Virtual_Com_Port_NoData_Setup,
    Virtual_Com_Port_Get_Interface_Setting,
    Virtual_Com_Port_GetDeviceDescriptor,
    Virtual_Com_Port_GetConfigDescriptor,
    Virtual_Com_Port_GetStringDescriptor,
    0,
    0x40 /*MAX PACKET SIZE*/
  };
这是MassStroage下的
DEVICE_PROP Device_Property =
  {
    MASS_init,
    MASS_Reset,
    MASS_Status_In,
    MASS_Status_Out,
    MASS_Data_Setup,
    MASS_NoData_Setup,
    MASS_Get_Interface_Setting,
    MASS_GetDeviceDescriptor,
    MASS_GetConfigDescriptor,
    MASS_GetStringDescriptor,
    0,
    0x40 /*MAX PACKET SIZE*/
  };

可以看到这一部分都是一样的 我们修改时改个名字即可
DEVICE_PROP Device_Property =
  {
    Composite_init,
    Composite_Reset,
    Composite_Status_In,
    Composite_Status_Out,
    Composite_Data_Setup,
    Composite_NoData_Setup,
    Composite_Get_Interface_Setting,
    Composite_GetDeviceDescriptor,
    Composite_GetConfigDescriptor,
    Composite_GetStringDescriptor,
    0,
    0x40 /*MAX PACKET SIZE*/
  };

下一个函数指针组也是一样的,改个名字就好了
CDC
USER_STANDARD_REQUESTS User_Standard_Requests =
  {
    Virtual_Com_Port_GetConfiguration,
    Virtual_Com_Port_SetConfiguration,
    Virtual_Com_Port_GetInterface,
    Virtual_Com_Port_SetInterface,
    Virtual_Com_Port_GetStatus,
    Virtual_Com_Port_ClearFeature,
    Virtual_Com_Port_SetEndPointFeature,
    Virtual_Com_Port_SetDeviceFeature,
    Virtual_Com_Port_SetDeviceAddress
  };
MassStroage
USER_STANDARD_REQUESTS User_Standard_Requests =
  {
    Mass_Storage_GetConfiguration,
    Mass_Storage_SetConfiguration,
    Mass_Storage_GetInterface,
    Mass_Storage_SetInterface,
    Mass_Storage_GetStatus,
    Mass_Storage_ClearFeature,
    Mass_Storage_SetEndPointFeature,
    Mass_Storage_SetDeviceFeature,
    Mass_Storage_SetDeviceAddress
  };
如下
USER_STANDARD_REQUESTS User_Standard_Requests =
  {
    Composite_GetConfiguration,
    Composite_SetConfiguration,
    Composite_GetInterface,
    Composite_SetInterface,
    Composite_GetStatus,
    Composite_ClearFeature,
    Composite_SetEndPointFeature,
    Composite_SetDeviceFeature,
    Composite_SetDeviceAddress
  };

可以看到这些函数指针都是一样的,但是CDC和Mass的函数实现不同,我们需要把它们和到一起。
首先去看usbprop.h
可以看到
#define Virtual_Com_Port_GetConfiguration          NOP_Process
//#define Virtual_Com_Port_SetConfiguration          NOP_Process
#define Virtual_Com_Port_GetInterface              NOP_Process
#define Virtual_Com_Port_SetInterface              NOP_Process
#define Virtual_Com_Port_GetStatus                 NOP_Process
#define Virtual_Com_Port_ClearFeature              NOP_Process
#define Virtual_Com_Port_SetEndPointFeature        NOP_Process
#define Virtual_Com_Port_SetDeviceFeature          NOP_Process
//#define Virtual_Com_Port_SetDeviceAddress          NOP_Process
CDC只要2和函数 其他都为nop
#define Mass_Storage_GetConfiguration          NOP_Process
/* #define Mass_Storage_SetConfiguration          NOP_Process*/
#define Mass_Storage_GetInterface              NOP_Process
#define Mass_Storage_SetInterface              NOP_Process
#define Mass_Storage_GetStatus                 NOP_Process
/* #define Mass_Storage_ClearFeature              NOP_Process*/
#define Mass_Storage_SetEndPointFeature        NOP_Process
#define Mass_Storage_SetDeviceFeature          NOP_Process
/*#define Mass_Storage_SetDeviceAddress          NOP_Process*/
Mass则实现了3个,其中2个重合
我们先修改注释掉这3个nop
#define Composite_GetConfiguration          NOP_Process
//#define Composite_SetConfiguration          NOP_Process
#define Composite_GetInterface              NOP_Process
#define Composite_SetInterface              NOP_Process
#define Composite_GetStatus                 NOP_Process
//#define Composite_ClearFeature              NOP_Process
#define Composite_SetEndPointFeature        NOP_Process
#define Composite_SetDeviceFeature          NOP_Process
//#define Composite_SetDeviceAddress          NOP_Process

然后去看这些函数,主要是看这些函数都做了什么
CDC中
/*******************************************************************************
* Function Name  : Virtual_Com_Port_SetConfiguration.
* Description    : Update the device state to configured.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void Virtual_Com_Port_SetConfiguration(void)
{
  DEVICE_INFO *pInfo = &Device_Info;

  if (pInfo->Current_Configuration != 0)
  {
    /* Device configured */
    bDeviceState = CONFIGURED;
  }
}

/*******************************************************************************
* Function Name  : Virtual_Com_Port_SetConfiguration.
* Description    : Update the device state to addressed.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void Virtual_Com_Port_SetDeviceAddress (void)
{
  bDeviceState = ADDRESSED;
}

Mass
/*******************************************************************************
* Function Name  : Mass_Storage_SetConfiguration
* Description    : Handle the SetConfiguration request.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void Mass_Storage_SetConfiguration(void)
{
  if (pInformation->Current_Configuration != 0)
  {
    /* Device configured */
    bDeviceState = CONFIGURED;
   
    ClearDTOG_TX(ENDP1);
    ClearDTOG_RX(ENDP2);

    Bot_State = BOT_IDLE; /* set the Bot state machine to the IDLE state */
  }
}

/*******************************************************************************
* Function Name  : Mass_Storage_ClearFeature
* Description    : Handle the ClearFeature request.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void Mass_Storage_ClearFeature(void)
{
  /* when the host send a CBW with invalid signature or invalid length the two
     Endpoints (IN & OUT) shall stall until receiving a Mass Storage Reset     */
  if (CBW.dSignature != BOT_CBW_SIGNATURE)
    Bot_Abort(BOTH_DIR);
}

/*******************************************************************************
* Function Name  : Mass_Storage_SetConfiguration.
* Description    : Update the device state to addressed.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void Mass_Storage_SetDeviceAddress (void)
{
  bDeviceState = ADDRESSED;
}

可以看到 CDC做的Mass都做了,所以直接用Mass的修改下名字即可
/*******************************************************************************
* Function Name  : Composite_SetConfiguration.
* Description    : Udpade the device state to configured.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void Composite_SetConfiguration(void)
{
  DEVICE_INFO *pInfo = &Device_Info;

  if (pInfo->Current_Configuration != 0)
  {
    /* Device configured */
    bDeviceState = CONFIGURED;
    ClearDTOG_TX(ENDP4);
    ClearDTOG_RX(ENDP5);
    Bot_State = BOT_IDLE; /* set the Bot state machine to the IDLE state */
  }
}

/*******************************************************************************
* Function Name  : Composite_SetConfiguration.
* Description    : Udpade the device state to addressed.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void Composite_SetDeviceAddress (void)
{
  bDeviceState = ADDRESSED;
}

void Composite_ClearFeature (void)
{
    if (CBW.dSignature != BOT_CBW_SIGNATURE)
    Bot_Abort(BOTH_DIR);
}

下面需要一个一个看init Reset这些函数的实现并且融合
这里以Reset看
/*******************************************************************************
* Function Name  : Virtual_Com_Port_Reset
* Description    : Virtual_Com_Port Mouse reset routine
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void Virtual_Com_Port_Reset(void)
{
  /* Set Virtual_Com_Port DEVICE as not configured */
  pInformation->Current_Configuration = 0;

  /* Current Feature initialization */
  pInformation->Current_Feature = Virtual_Com_Port_ConfigDescriptor[7];

  /* Set Virtual_Com_Port DEVICE with the default Interface*/
  pInformation->Current_Interface = 0;

  SetBTABLE(BTABLE_ADDRESS);

  /* Initialize Endpoint 0 */
  SetEPType(ENDP0, EP_CONTROL);
  SetEPTxStatus(ENDP0, EP_TX_STALL);
  SetEPRxAddr(ENDP0, ENDP0_RXADDR);
  SetEPTxAddr(ENDP0, ENDP0_TXADDR);
  Clear_Status_Out(ENDP0);
  SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);
  SetEPRxValid(ENDP0);

  /* Initialize Endpoint 1 */
  SetEPType(ENDP1, EP_BULK);
  SetEPTxAddr(ENDP1, ENDP1_TXADDR);
  SetEPTxStatus(ENDP1, EP_TX_NAK);
  SetEPRxStatus(ENDP1, EP_RX_DIS);

  /* Initialize Endpoint 2 */
  SetEPType(ENDP2, EP_INTERRUPT);
  SetEPTxAddr(ENDP2, ENDP2_TXADDR);
  SetEPRxStatus(ENDP2, EP_RX_DIS);
  SetEPTxStatus(ENDP2, EP_TX_NAK);

  /* Initialize Endpoint 3 */
  SetEPType(ENDP3, EP_BULK);
  SetEPRxAddr(ENDP3, ENDP3_RXADDR);
  SetEPRxCount(ENDP3, VIRTUAL_COM_PORT_DATA_SIZE);
  SetEPRxStatus(ENDP3, EP_RX_VALID);
  SetEPTxStatus(ENDP3, EP_TX_DIS);

  /* Set this device to response on default address */
  SetDeviceAddress(0);
  
  bDeviceState = ATTACHED;
}

/*******************************************************************************
* Function Name  : MASS_Reset
* Description    : Mass Storage reset routine.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void MASS_Reset()
{
  /* Set the device as not configured */
  Device_Info.Current_Configuration = 0;

  /* Current Feature initialization */
  pInformation->Current_Feature = MASS_ConfigDescriptor[7];

  SetBTABLE(BTABLE_ADDRESS);

  /* Initialize Endpoint 0 */
  SetEPType(ENDP0, EP_CONTROL);
  SetEPTxStatus(ENDP0, EP_TX_NAK);
  SetEPRxAddr(ENDP0, ENDP0_RXADDR);
  SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);
  SetEPTxAddr(ENDP0, ENDP0_TXADDR);
  Clear_Status_Out(ENDP0);
  SetEPRxValid(ENDP0);

  /* Initialize Endpoint 1 */
  SetEPType(ENDP1, EP_BULK);
  SetEPTxAddr(ENDP1, ENDP1_TXADDR);
  SetEPTxStatus(ENDP1, EP_TX_NAK);
  SetEPRxStatus(ENDP1, EP_RX_DIS);

  /* Initialize Endpoint 2 */
  SetEPType(ENDP2, EP_BULK);
  SetEPRxAddr(ENDP2, ENDP2_RXADDR);
  SetEPRxCount(ENDP2, Device_Property.MaxPacketSize);
  SetEPRxStatus(ENDP2, EP_RX_VALID);
  SetEPTxStatus(ENDP2, EP_TX_DIS);


  SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);
  SetEPRxValid(ENDP0);

  /* Set the device to response on default address */
  SetDeviceAddress(0);

  bDeviceState = ATTACHED;

  CBW.dSignature = BOT_CBW_SIGNATURE;
  Bot_State = BOT_IDLE;

  USB_NotConfigured_LED();
}
我们看到这个两个函数实现由较大的差异
这个函数的功能可以看到是实现可USBEP的初始化,这里我们要按照实际情况写
把Mass的ENDP1,ENDP2 改换为我们配置的 ENDP4 ENDP5 然后叠加到CDC的配置上去,结果就成了这样
/*******************************************************************************
* Function Name  : Composite_Reset
* Description    : Composite Mouse reset routine
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void Composite_Reset(void)
{
  /* Set Composite DEVICE as not configured */
  pInformation->Current_Configuration = 0;

  /* Current Feature initialization */
  pInformation->Current_Feature = Composite_ConfigDescriptor[7];

  /* Set Composite DEVICE with the default Interface*/
  pInformation->Current_Interface = 0;
  SetBTABLE(BTABLE_ADDRESS);

  /* Initialize Endpoint 0 */
  SetEPType(ENDP0, EP_CONTROL);
  SetEPTxStatus(ENDP0, EP_TX_STALL);
  SetEPRxAddr(ENDP0, ENDP0_RXADDR);
  SetEPTxAddr(ENDP0, ENDP0_TXADDR);
  Clear_Status_Out(ENDP0);
  SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);
  SetEPRxValid(ENDP0);

  /* Initialize Endpoint 1 */
  SetEPType(ENDP1, EP_BULK);
  SetEPTxAddr(ENDP1, ENDP1_TXADDR);
  SetEPTxStatus(ENDP1, EP_TX_NAK);
  SetEPRxStatus(ENDP1, EP_RX_DIS);

  /* Initialize Endpoint 2 */
  SetEPType(ENDP2, EP_INTERRUPT);
  SetEPTxAddr(ENDP2, ENDP2_TXADDR);
  SetEPRxStatus(ENDP2, EP_RX_DIS);
  SetEPTxStatus(ENDP2, EP_TX_NAK);

  /* Initialize Endpoint 3 */
  SetEPType(ENDP3, EP_BULK);
  SetEPRxAddr(ENDP3, ENDP3_RXADDR);
  SetEPRxCount(ENDP3, Composite_DATA_SIZE);
  SetEPRxStatus(ENDP3, EP_RX_VALID);
  SetEPTxStatus(ENDP3, EP_TX_DIS);

/* Initialize Endpoint 2 IN */
  SetEPType(ENDP4, EP_BULK);
  SetEPTxCount(ENDP4, 64);
  SetEPTxAddr(ENDP4, ENDP4_TXADDR);
  SetEPTxStatus(ENDP4, EP_TX_NAK);
  SetEPRxStatus(ENDP4, EP_RX_DIS);

  /* Initialize Endpoint 2 OUT */
  SetEPType(ENDP5, EP_BULK);
  SetEPRxAddr(ENDP5, ENDP5_RXADDR);
  SetEPRxCount(ENDP5, 64);
  SetEPRxStatus(ENDP5, EP_RX_VALID);
  SetEPTxStatus(ENDP5, EP_TX_DIS);
  
  /* Set this device to response on default address */
  SetDeviceAddress(0);
  CBW.dSignature = BOT_CBW_SIGNATURE;
  Bot_State = BOT_IDLE;


  bDeviceState = ATTACHED;
}


使用特权

评论回复
6
b620126|  楼主 | 2014-1-15 10:17 | 只看该作者
其他函数也是根据实际情况进行修改
最终修改结果如下
uspprop.c
/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
* File Name          : usb_prop.c
* Author             : MCD Application Team
* Version            : V2.2.0
* Date               : 06/13/2008
* Description        : All processing related to Virtual Com Port Demo
********************************************************************************
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*******************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "usb_lib.h"
#include "usb_conf.h"
#include "usb_prop.h"
#include "usb_desc.h"
#include "usb_pwr.h"
#include "hw_config.h"
#include "usb_bot.h"
#include "memory.h"
#include "mass_mal.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
u8 Request = 0;

extern unsigned char Bot_State;
extern Bulk_Only_CBW CBW;
unsigned int Max_Lun = 0;

LINE_CODING linecoding =
  {
    115200, /* baud rate*/
    0x00,   /* stop bits-1*/
    0x00,   /* parity - none*/
    0x08    /* no. of bits 8*/
  };

/* -------------------------------------------------------------------------- */
/*  Structures initializations */
/* -------------------------------------------------------------------------- */

DEVICE Device_Table =
  {
    EP_NUM,
    1
  };

DEVICE_PROP Device_Property =
  {
    Composite_init,
    Composite_Reset,
    Composite_Status_In,
    Composite_Status_Out,
    Composite_Data_Setup,
    Composite_NoData_Setup,
    Composite_Get_Interface_Setting,
    Composite_GetDeviceDescriptor,
    Composite_GetConfigDescriptor,
    Composite_GetStringDescriptor,
    0,
    0x40 /*MAX PACKET SIZE*/
  };

USER_STANDARD_REQUESTS User_Standard_Requests =
  {
    Composite_GetConfiguration,
    Composite_SetConfiguration,
    Composite_GetInterface,
    Composite_SetInterface,
    Composite_GetStatus,
    Composite_ClearFeature,
    Composite_SetEndPointFeature,
    Composite_SetDeviceFeature,
    Composite_SetDeviceAddress
  };

ONE_DESCRIPTOR Device_Descriptor =
  {
    (u8*)Composite_DeviceDescriptor,
    Composite_SIZ_DEVICE_DESC
  };

ONE_DESCRIPTOR Config_Descriptor =
  {
    (u8*)Composite_ConfigDescriptor,
    Composite_SIZ_CONFIG_DESC
  };

ONE_DESCRIPTOR String_Descriptor[4] =
  {
    {(u8*)Composite_StringLangID, Composite_SIZ_STRING_LANGID},
    {(u8*)Composite_StringVendor, Composite_SIZ_STRING_VENDOR},
    {(u8*)Composite_StringProduct, Composite_SIZ_STRING_PRODUCT},
    {(u8*)Composite_StringSerial, Composite_SIZ_STRING_SERIAL}
  };

/* Extern variables ----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Extern function prototypes ------------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************
* Function Name  : Get_Max_Lun
* Description    : Handle the Get Max Lun request.
* Input          : unsigned short Length.
* Output         : None.
* Return         : None.
*******************************************************************************/
unsigned char *Get_Max_Lun(unsigned short Length)
{
  if (Length == 0)
  {
    pInformation->Ctrl_Info.Usb_wLength = LUN_DATA_LENGTH;
    return 0;
  }
  else
  {
    return((unsigned char*)(&Max_Lun));
  }
}
/*******************************************************************************
* Function Name  : Composite_init.
* Description    : Virtual COM Port Mouse init routine.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void Composite_init(void)
{

  /* Update the serial number string descriptor with the data from the unique
  ID*/
  Get_SerialNum();

  pInformation->Current_Configuration = 0;

  /* Connect the device */
  PowerOn();
   
  USB_SIL_Init();  
//   /* USB interrupts initialization */
//   /* clear pending interrupts */
//   _SetISTR(0);

//   
//   wInterrupt_Mask = IMR_MSK;
//   /* set interrupts mask */
//   _SetCNTR(wInterrupt_Mask);

//   /* configure the USART 1 to the default settings */
//   //USART_Config_Default();

  bDeviceState = UNCONNECTED;
}

/*******************************************************************************
* Function Name  : Composite_Reset
* Description    : Composite Mouse reset routine
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void Composite_Reset(void)
{
  /* Set Composite DEVICE as not configured */
  pInformation->Current_Configuration = 0;

  /* Current Feature initialization */
  pInformation->Current_Feature = Composite_ConfigDescriptor[7];

  /* Set Composite DEVICE with the default Interface*/
  pInformation->Current_Interface = 0;
  SetBTABLE(BTABLE_ADDRESS);

  /* Initialize Endpoint 0 */
  SetEPType(ENDP0, EP_CONTROL);
  SetEPTxStatus(ENDP0, EP_TX_STALL);
  SetEPRxAddr(ENDP0, ENDP0_RXADDR);
  SetEPTxAddr(ENDP0, ENDP0_TXADDR);
  Clear_Status_Out(ENDP0);
  SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);
  SetEPRxValid(ENDP0);

  /* Initialize Endpoint 1 */
  SetEPType(ENDP1, EP_BULK);
  SetEPTxAddr(ENDP1, ENDP1_TXADDR);
  SetEPTxStatus(ENDP1, EP_TX_NAK);
  SetEPRxStatus(ENDP1, EP_RX_DIS);

  /* Initialize Endpoint 2 */
  SetEPType(ENDP2, EP_INTERRUPT);
  SetEPTxAddr(ENDP2, ENDP2_TXADDR);
  SetEPRxStatus(ENDP2, EP_RX_DIS);
  SetEPTxStatus(ENDP2, EP_TX_NAK);

  /* Initialize Endpoint 3 */
  SetEPType(ENDP3, EP_BULK);
  SetEPRxAddr(ENDP3, ENDP3_RXADDR);
  SetEPRxCount(ENDP3, Composite_DATA_SIZE);
  SetEPRxStatus(ENDP3, EP_RX_VALID);
  SetEPTxStatus(ENDP3, EP_TX_DIS);

/* Initialize Endpoint 2 IN */
  SetEPType(ENDP4, EP_BULK);
  SetEPTxCount(ENDP4, 64);
  SetEPTxAddr(ENDP4, ENDP4_TXADDR);
  SetEPTxStatus(ENDP4, EP_TX_NAK);
  SetEPRxStatus(ENDP4, EP_RX_DIS);

  /* Initialize Endpoint 2 OUT */
  SetEPType(ENDP5, EP_BULK);
  SetEPRxAddr(ENDP5, ENDP5_RXADDR);
  SetEPRxCount(ENDP5, 64);
  SetEPRxStatus(ENDP5, EP_RX_VALID);
  SetEPTxStatus(ENDP5, EP_TX_DIS);
  
  /* Set this device to response on default address */
  SetDeviceAddress(0);
  CBW.dSignature = BOT_CBW_SIGNATURE;
  Bot_State = BOT_IDLE;


  bDeviceState = ATTACHED;
}

/*******************************************************************************
* Function Name  : Composite_SetConfiguration.
* Description    : Udpade the device state to configured.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void Composite_SetConfiguration(void)
{
  DEVICE_INFO *pInfo = &Device_Info;

  if (pInfo->Current_Configuration != 0)
  {
    /* Device configured */
    bDeviceState = CONFIGURED;
    ClearDTOG_TX(ENDP4);
    ClearDTOG_RX(ENDP5);
    Bot_State = BOT_IDLE; /* set the Bot state machine to the IDLE state */
  }
}

/*******************************************************************************
* Function Name  : Composite_SetConfiguration.
* Description    : Udpade the device state to addressed.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void Composite_SetDeviceAddress (void)
{
  bDeviceState = ADDRESSED;
}

/*******************************************************************************
* Function Name  : Composite_Status_In.
* Description    : Virtual COM Port Status In Routine.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void Composite_Status_In(void)
{
  if (Request == SET_LINE_CODING)
  {
    USART_Config();
    Request = 0;
  }
}

/*******************************************************************************
* Function Name  : Composite_Status_Out
* Description    : Virtual COM Port Status OUT Routine.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void Composite_Status_Out(void)
{}

/*******************************************************************************
* Function Name  : Composite_Data_Setup
* Description    : handle the data class specific requests
* Input          : Request Nb.
* Output         : None.
* Return         : USB_UNSUPPORT or USB_SUCCESS.
*******************************************************************************/
RESULT Composite_Data_Setup(u8 RequestNo)
{
  u8    *(*CopyRoutine)(u16);
  
  if (pInformation->USBwIndex != 0)
    return USB_UNSUPPORT;  
  
  CopyRoutine = NULL;

  if (RequestNo == GET_LINE_CODING)
  {
    if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
    {
      CopyRoutine = Composite_GetLineCoding;
    }
  }
  else if (RequestNo == SET_LINE_CODING)
  {
    if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
    {
      CopyRoutine = Composite_SetLineCoding;
    }
    Request = SET_LINE_CODING;
  }

   
  if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
      && (RequestNo == GET_MAX_LUN) && (pInformation->USBwValue == 0)
      && (pInformation->USBwIndex == 0) && (pInformation->USBwLength == 0x01))
  {
    CopyRoutine = Get_Max_Lun;
  }
  else
  {
    return USB_UNSUPPORT;
  }

  if (CopyRoutine == NULL)
  {
    return USB_UNSUPPORT;
  }

  pInformation->Ctrl_Info.CopyData = CopyRoutine;
  pInformation->Ctrl_Info.Usb_wOffset = 0;
  (*CopyRoutine)(0);
  return USB_SUCCESS;
}

/*******************************************************************************
* Function Name  : Composite_NoData_Setup.
* Description    : handle the no data class specific requests.
* Input          : Request Nb.
* Output         : None.
* Return         : USB_UNSUPPORT or USB_SUCCESS.
*******************************************************************************/
RESULT Composite_NoData_Setup(u8 RequestNo)
{
    if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
      && (RequestNo == MASS_STORAGE_RESET) && (pInformation->USBwValue == 0)
      && (pInformation->USBwIndex == 0) && (pInformation->USBwLength == 0x00))
    {
    /* Initialize Endpoint 1 */
    ClearDTOG_TX(ENDP4);

    /* Initialize Endpoint 2 */
    ClearDTOG_RX(ENDP5);

    /*initialize the CBW signature to enable the clear feature*/
    CBW.dSignature = BOT_CBW_SIGNATURE;
    Bot_State = BOT_IDLE;

    return USB_SUCCESS;
    }
  if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
  {
    if (RequestNo == SET_COMM_FEATURE)
    {
      return USB_SUCCESS;
    }
    else if (RequestNo == SET_CONTROL_LINE_STATE)
    {
      return USB_SUCCESS;
    }
  }

  return USB_UNSUPPORT;
}

/*******************************************************************************
* Function Name  : MASS_Get_Interface_Setting
* Description    : Test the interface and the alternate setting according to the
*                  supported one.
* Input          : uint8_t Interface, uint8_t AlternateSetting.
* Output         : None.
* Return         : RESULT.
*******************************************************************************/
RESULT Composite_Get_Interface_Setting(u8 Interface, u8 AlternateSetting)
{
  if (AlternateSetting > 0)
  {
    return USB_UNSUPPORT;/* in this application we don't have AlternateSetting*/
  }
  else if (Interface > 2)
  {
    return USB_UNSUPPORT;/*in this application we have only 1 interfaces*/
  }
  return USB_SUCCESS;
}

/*******************************************************************************
* Function Name  : Composite_GetDeviceDescriptor.
* Description    : Gets the device descriptor.
* Input          : Length.
* Output         : None.
* Return         : The address of the device descriptor.
*******************************************************************************/
u8 *Composite_GetDeviceDescriptor(u16 Length)
{
  return Standard_GetDescriptorData(Length, &Device_Descriptor);
}

/*******************************************************************************
* Function Name  : Composite_GetConfigDescriptor.
* Description    : get the configuration descriptor.
* Input          : Length.
* Output         : None.
* Return         : The address of the configuration descriptor.
*******************************************************************************/
u8 *Composite_GetConfigDescriptor(u16 Length)
{
  return Standard_GetDescriptorData(Length, &Config_Descriptor);
}

/*******************************************************************************
* Function Name  : Composite_GetStringDescriptor
* Description    : Gets the string descriptors according to the needed index
* Input          : Length.
* Output         : None.
* Return         : The address of the string descriptors.
*******************************************************************************/
u8 *Composite_GetStringDescriptor(u16 Length)
{
  u8 wValue0 = pInformation->USBwValue0;
  if (wValue0 > 4)
  {
    return NULL;
  }
  else
  {
    return Standard_GetDescriptorData(Length, &String_Descriptor[wValue0]);
  }
}

/*******************************************************************************
* Function Name  : Composite_GetLineCoding.
* Description    : send the linecoding structure to the PC host.
* Input          : Length.
* Output         : None.
* Return         : Inecoding structure base address.
*******************************************************************************/
u8 *Composite_GetLineCoding(u16 Length)
{
  if (Length == 0)
  {
    pInformation->Ctrl_Info.Usb_wLength = sizeof(linecoding);
    return NULL;
  }
  return(u8 *)&linecoding;
}

/*******************************************************************************
* Function Name  : Composite_SetLineCoding.
* Description    : Set the linecoding structure fields.
* Input          : Length.
* Output         : None.
* Return         : Linecoding structure base address.
*******************************************************************************/
u8 *Composite_SetLineCoding(u16 Length)
{
  if (Length == 0)
  {
    pInformation->Ctrl_Info.Usb_wLength = sizeof(linecoding);
    return NULL;
  }
  return(u8 *)&linecoding;
}

void Composite_ClearFeature (void)
{
    if (CBW.dSignature != BOT_CBW_SIGNATURE)
    Bot_Abort(BOTH_DIR);
}
/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/

使用特权

评论回复
7
beyond696| | 2014-1-20 15:52 | 只看该作者
b620126 发表于 2014-1-14 13:46
Dual CDC 好像需要IAD 其实理论上 3个串口也可以的~

STM32的端点数有限,所以最多只能两个

使用特权

评论回复
8
未曾走远| | 2015-9-23 21:36 | 只看该作者
好东西,能把修改过的.c直接发出来就更好了

使用特权

评论回复
9
ljjdkl99| | 2016-6-22 18:43 | 只看该作者
楼主你好,不知你用的单片机具体型号是什么,我的是STM32f103vet6,HID模式OK,CDC模式插上后连无法识别的USB提示都没有,我的QQ是1036980828,希望看到后可以给我回复,谢谢了,么么哒!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

93

主题

179

帖子

3

粉丝