芯片: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
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』