基于STM32的USB程序开发笔记(四)——USB设备的枚举(上)

USB设备能否工作,枚举步骤,用“乡村爱情”里的话说,“必须的!”,网上也有很多资料,圈圈就提供了一份详细的枚举过程,但对STM32是怎么响应的没有说明,一会详细道来,先上圈圈的提供的那个枚举图示,希望圈圈支持,如果不妥,请与我联系,谢谢。 
我将此转换成了PDF文件,方便查看。
首先说明一个变量,定义在usb_core.c中: 
volatile DEVICE_INFO vsDeviceInfo; 
看意思就知道他的作用了,DEVICE_INFO是个结构,定义在usb_type.h中: 
// ***************************************************************************** 
// DEVICE_INFO 
// ***************************************************************************** 
typedef struct _DEVICE_INFO 

  unsigned char bDeviceAddress; 

  unsigned char bCurrentFeature; 
  unsigned char bCurrentConfiguration; 
  unsigned char bCurrentInterface; 
  unsigned char bCurrentAlternateSetting; 

  WORD_2BYTE    uStatusInfo; 

  DEVICE_STATE  eDeviceState; 
  RESUME_STATE  eResumeState; 
  CONTROL_STATE eControlState; 

  SETUP_DATA    SetupData; 

  TRANSFER_INFO TransInfo; 

DEVICE_INFO, 
*PDEVICE_INFO; 

在枚举过程中,就是如何处理好SETUP事件,如果STM32 USB接收到正确的SETUP事件,将响应函数CTR_SETUP0(),SETUP事件是特殊的OUT事件,数据方向 Host->Device,SETUP事件数据长度固定为8,数据定义在DEVICE_INFO.SetupData,其数据结构是(定义在 usb_type.h中): 
typedef struct _SETUP_DATA 

  unsigned char bmRequestType;            // request type 
  unsigned char bRequest;                 // request code 

  WORD_2BYTE wValue; 
  WORD_2BYTE wIndex; 
  WORD_2BYTE wLength; 

SETUP_DATA, 
*PSETUP_DATA; 

WORD_2BYTE是定义的一个共用体: 
typedef union _WORD_2BYTE 

  unsigned short w; 
  struct 
  { 
    unsigned char LSB; 
    unsigned char MSB; 
  }b; 

WORD_2BYTE; 

为什么将SETUP数据结构中的wValue,wIndex,wLength如此定义? 
1:USB协议中所有数据传输都是依照低位在先的原则 
2:高地位字节可能功能复用 
这样在后续的程序编写中就变得十分方便,ST提供的USB固件方法同样如此,但这方面的处理让人有些摸不着头脑,详情可参阅。至于具体的SETUP数据结构含义如何,还是要具备基本知识:了解USB协议 

CTR_SETUP0() 函数将SETUP数据提取出来,SETUP数据结构有0长度和非0长度的数据结构,详细参阅USB2.0官方协议第9章。在这将两种区别开来分别执行 SETUP0_NoData()和SETUP0_Data()函数,并返回结果,根据返回结果再响应USB主机 
// ***************************************************************************** 
// Function Name  : CTR_SETUP0 
// Description    : 
// Input          : 
// Output         : 
// Return         : 
// ***************************************************************************** 
void CTR_SETUP0(void) 

  RESULT eResult; 

  BufferCopy_PMAToUser( (unsigned char *)&vsDeviceInfo.SetupData, 
                        GetBuffDescTable_RXAddr(ENDP0), 
                        GetBuffDescTable_RXCount(ENDP0)); 

  if(vsDeviceInfo.SetupData.wLength.w == 0) 
  { 
    eResult = SETUP0_NoData(); 
  } 
  else 
  { 
    eResult = SETUP0_Data(); 
  } 

  switch(eResult) 
  { 
  case RESULT_SUCCESS: 

    break; 

  case RESULT_LASTDATA: 

    break; 

  case RESULT_ERROR: 
  case RESULT_UNSUPPORT: 
    SetEPR_RXStatus(ENDP0, EP_RX_VALID); 
    SetEPR_TXStatus(ENDP0, EP_TX_STALL); 
    break; 
  } 


SETUP0_Data() 和SETUP0_NoData()函数支持的所有USB请求类型只有罗列的这些,有多少种组合都定义在USB协议中,程序根据请求代码,再去执行对应函数,这样做的目的就是让程序结构明了。其中注释为"// done"的部分表明此部分功能已完成。对于未完成部分,希望大家在交流中完善。 

// ***************************************************************************** 
// Routine Groups: SETUP_Data 
// ***************************************************************************** 
RESULT SETUP0_Data(void) 

  // SetupData.bRequest: request code 
  switch(vsDeviceInfo.SetupData.bRequest) 
  { 
  case SR_GET_STATUS:         return SR_GetStatus();                  // done 
  case SR_GET_DESCRIPTOR:     return SR_GetDescriptor();              // done 
  case SR_SET_DESCRIPTOR:     return SR_SetDescriptor();              // unsupport 
  case SR_GET_CONFIGURATION:  return SR_GetConfiguration();           // done 
  case SR_GET_INTERFACE:      return SR_GetInterface();               // unsupport 
  case SR_SYNCH_FRAME:        return SR_SynchFrame();                 // unsupport 

  default: return RESULT_UNSUPPORT; 
  } 


// ***************************************************************************** 
// Routine Groups: SETUP_NoData 
// ***************************************************************************** 
RESULT SETUP0_NoData(void) 

  // SetupData.bRequest: request code 
  switch(vsDeviceInfo.SetupData.bRequest) 
  { 
  case SR_CLEAR_FEATURE:      return SR_ClearFeature();        // unsupport 
  case SR_SET_FEATURE:        return SR_SetFeature();          // unsupport 
  case SR_SET_ADDRESS:        return SR_SetAddress();          // done 
  case SR_SET_CONFIGURATION:  return SR_SetConfiguration();    // done 
  case SR_SET_INTERFACE:      return SR_SetInterface();        // unsupport 

  default: return RESULT_UNSUPPORT; 
  } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值