×
单片机 > 单片机程序设计 > 详情

STM32 USB 枚举分析

发布时间:2020-06-09 发布时间:
|

芯片:STM32F407VE


编译器:KEIL5



STM32 USB枚举

用到比较重要的寄存器:OTG_HS 主机端口控制和状态寄存器 (OTG_HS_HPRT)


系统复位


等待USB连接,延时100ms

主机对USB设备复位,主机检测到端口使能位置位,与设备建立连接

主机再次对USB设备复位,复位结束,开始枚举过程。

主机拥有8个通道,其中IN占用0通道,OUT占用1通道。打开IN和OUT管道

获取设备描述符,只获取8个字节,为了得到通道0的最大包长度。将状态机调整到HOST_CTRL_XFER。同时备份当前全局状态,便于跳转到HOST_CTRL_XFER恢复状态。


USBH_Get_DevDesc(pdev , phost, 8); -->

USBH_GetDescriptor(); -->

        phost->Control.setup.b.bRequest = USB_REQ_GET_DESCRIPTOR; //发送的请求

      phost->Control.setup.b.wLength.w = length; //数据长度。如果为0,则在[控制传输]中忽略数据阶段

        USBH_CtlReq(); -->

                USBH_SubmitSetupRequest(); -->

                    USBH_HandleControl(); --> 

                        CTRL_SETUP -> CTRL_SETUP_WAIT -> 

                        if (phost->Control.setup.b.wLength.w);

                      then

                            [CTRL_DATA_IN/CTRL_DATA_OUT]

                      else

                            [CTRL_STATUS_IN/CTRL_STATUS_OUT]

                      fi                    


发送SETUP令牌包,等待回复

发送DATA1数据包,等待回复

发送状态,回复从机

流程走完后,获取到当前通道的最大包长度64,因此修改当前通道的最大包长度为64


获取全部设备描述符,长度18字节


typedef struct _DeviceDescriptor

{

uint8_t   bLength;

uint8_t   bDescriptorType;

uint16_t  bcdUSB;        /* USB Specification Number which device complies too */

uint8_t   bDeviceClass;

uint8_t   bDeviceSubClass; 

uint8_t   bDeviceProtocol;

/* If equal to Zero, each interface specifies its own class

code if equal to 0xFF, the class code is vendor specified.

Otherwise field is valid Class Code.*/

uint8_t   bMaxPacketSize;

uint16_t  idVendor;      /* Vendor ID (Assigned by USB Org) */

uint16_t  idProduct;     /* Product ID (Assigned by Manufacturer) */

uint16_t  bcdDevice;     /* Device Release Number */

uint8_t   iManufacturer;  /* Index of Manufacturer String Descriptor */

uint8_t   iProduct;       /* Index of Product String Descriptor */

uint8_t   iSerialNumber;  /* Index of Serial Number String Descriptor */

uint8_t   bNumConfigurations; /* Number of Possible Configurations */

}

USBH_DevDesc_TypeDef;



可以看到第8个字节,正好是bMaxPacketSize最大包大小

而且已经获取到设备的VID、PID

设置地址



#define USBH_DEVICE_ADDRESS                             1


USBH_SetAddress(pdev, phost, USBH_DEVICE_ADDRESS) -->

phost->Control.setup.b.wValue.w = (uint16_t)DeviceAddress;

USBH_CtlReq(pdev, phost, 0 , 0 ); -->

    USBH_HandleControl(); -->


typedef union _USB_Setup

{

uint8_t d8[8];


struct _SetupPkt_Struc

{

  uint8_t           bmRequestType;

  uint8_t           bRequest;

  uint16_t_uint8_t  wValue;

  uint16_t_uint8_t  wIndex;

  uint16_t_uint8_t  wLength;

} b;

} USB_Setup_TypeDef;


SETUP包一共包含8个字节

+ 将设备的地址设置为`1`,`SETUP`包包含设备地址字段

+ 发送`SETUP`令牌包,等待回复

+ 发送状态,回复从机


获取配置描述符



#define USB_CONFIGURATION_DESC_SIZE                        9


USBH_Get_CfgDesc(pdev, phost, USB_CONFIGURATION_DESC_SIZE); -->

USBH_GetDescriptor(); -->

        USBH_ParseCfgDesc();


typedef struct _ConfigurationDescriptor

{

uint8_t   bLength;

uint8_t   bDescriptorType;

uint16_t  wTotalLength;        /* Total Length of Data Returned */

uint8_t   bNumInterfaces;       /* Number of Interfaces */

uint8_t   bConfigurationValue;  /* Value to use as an argument to select this configuration*/

uint8_t   iConfiguration;       /*Index of String Descriptor Describing this configuration */

uint8_t   bmAttributes;         /* D7 Bus Powered , D6 Self Powered, D5 Remote Wakeup , D4..0 Reserved (0)*/

uint8_t   bMaxPower;            /*Maximum Power Consumption */

}

USBH_CfgDesc_TypeDef;


这9个字节为第一次获取配置描述符时,从机返回的数据。主要获取wTotalLength的值。实测wTotalLength=32

获取配置描述符集合


/* get FULL config descriptor (config, interface, endpoints) */

USBH_Get_CfgDesc(pdev, phost, phost->device_prop.Cfg_Desc.wTotalLength); -->

USBH_GetDescriptor(); -->

        USBH_ParseCfgDesc();


获取到的数据存储在数组中,数据结构如下:


typedef  struct  _DescHeader 

{

 uint8_t  bLength;       

 uint8_t  bDescriptorType;

USBH_DescHeader_t;


描述符类型bDescriptorType列表:


/* Table 9-5. Descriptor Types of USB Specifications */


#define  USB_DESC_TYPE_DEVICE                              1



#define  USB_DESC_TYPE_CONFIGURATION                       2



#define  USB_DESC_TYPE_STRING                              3



#define  USB_DESC_TYPE_INTERFACE                           4



#define  USB_DESC_TYPE_ENDPOINT                            5



#define  USB_DESC_TYPE_DEVICE_QUALIFIER                    6



#define  USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION           7



#define  USB_DESC_TYPE_INTERFACE_POWER                     8



#define  USB_DESC_TYPE_HID                                 0x21



#define  USB_DESC_TYPE_HID_REPORT                          0x22



解析数据:


解析接口描述符

typedef struct _InterfaceDescriptor

{

 uint8_t bLength;

 uint8_t bDescriptorType;

 uint8_t bInterfaceNumber;

 uint8_t bAlternateSetting;    /* Value used to select alternative setting */

 uint8_t bNumEndpoints;        /* Number of Endpoints used for this interface */

 uint8_t bInterfaceClass;      /* Class Code (Assigned by USB Org) */

 uint8_t bInterfaceSubClass;   /* Subclass Code (Assigned by USB Org) */

 uint8_t bInterfaceProtocol;   /* Protocol Code */

 uint8_t iInterface;           /* Index of String Descriptor Describing this interface */


}

USBH_InterfaceDesc_TypeDef;


获取到bNumEndpoints端点个数为2。


然后解析端点描述符

typedef struct _EndpointDescriptor

{

 uint8_t   bLength;

 uint8_t   bDescriptorType;

 uint8_t   bEndpointAddress;   /* indicates what endpoint this descriptor is describing */

 uint8_t   bmAttributes;       /* specifies the transfer type. */

 uint16_t  wMaxPacketSize;    /* Maximum Packet Size this endpoint is capable of sending or receiving */  

 uint8_t   bInterval;          /* is used to specify the polling interval of certain transfers. */

}

USBH_EpDesc_TypeDef;

1

2

3

4

5

6

7

8

9

10

通知用户,此时通过接口描述符可以知道设备是哪一种类:



#define MSC_CLASS                             0x08 /* MSC */



#define HID_CLASS                             0x03 /* HID */




#define USB_AUDIO                             0x01 /* Audio */



#define USB_CDCC                              0x02  /* Communications and CDC Control */



#define USB_HID                               0x03  /* HID (Human Interface Device) */



#define USB_PRINTER                           0x07  /* Printer */



#define USB_MSC                               0x08  /* Mass Storage */



#define USB_HUB


关键字:STM32  USB  枚举分析 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
STM32单片机的复用端口初始化的步骤及方法