原创 基于STM32的USB程序开发笔记(四)

2008-11-21 14:38 7295 11 15 分类: MCU/ 嵌入式
第四篇:USB设备的枚举(上)

USB设备能否工作,枚举步骤,用“乡村爱情”里的话说,“必须的!”,网上也有很多资料,圈圈就提供了一份详细的枚举过程,但对STM32是怎么响应的没有说明,一会详细道来,先上圈圈的提供的那个枚举图示,希望圈圈支持,如果不妥,请与我联系,谢谢。
我将此转换成了PDF文件,方便查看:
USB枚举过程图解.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;
  }
}

下篇将介绍上述的各个请求函数如何响应主机。朋友们请多支持啊,这是我第一次较为系统的介绍一个知识点,错误在所难免,网上的USB开发资料不是很齐全,我的目标就是努力抽点时间将USB上、下位机程序开发资料公布出来,作为给想学USB的朋友一个辅助指导,请给我点信心,多支持啊!!!
PARTNER CONTENT

文章评论4条评论)

登录后参与讨论

用户239228 2010-6-15 21:21

支持。。。。。。。。

用户1572896 2009-1-15 10:44

支持!!!

用户159039 2008-11-25 10:32

小顶一个

用户125281 2008-11-23 22:12

支持你!!
相关推荐阅读
用户1206224 2010-11-22 08:05
基于STM32的智能交通信号机
基于STM32的智能交通信号机,有兴趣探讨的朋友可以跟我联系...
用户1206224 2010-03-26 21:30
STM32 USB 源代码及笔记下载 修复贴
今年比较忙,很少来空间,看到大家的留言,故发布此STM32 USB 源代码及笔记下载修复贴STM32 USB固件以及上位机驱动、应用程序源程序:笔记:...
用户1206224 2010-03-26 21:28
STM32 SD卡FATFS移植
最近试玩了STM32用SPI方式操作SD卡,这样就涉及到文件系统,搜索到几种支持FAT16/32的文件,综合考虑,最后选择了完全开源、免费的FATFS,版本是R0.07e,该版本支持长文件名:Wind...
用户1206224 2009-06-02 08:53
基于STM32的USB程序开发笔记(一)
第一篇:需要准备的一些资料1:STM32的参考手册,这对于设备底层USB的硬件配置以及事件驱动机制的了解尤为重要,你需要了解各个寄存器的功能以及如何操作,比如CNTR、ISTR、EPnR、DADDR等...
用户1206224 2009-06-02 08:51
STM32的16路ADC的USB高速采集
STM32的16路ADC的USB高速采集前提:本例基于STM32F103VBT6平台功能说明:16路AD转换并将结果通过USB发送至PC,PC端驱动为定制编写,并附带一款测试软件。附件说明:1:STM...
用户1206224 2009-03-28 09:50
第二版STM32F103ZET6最小系统板实物照片
第二版STM32F103ZET6最小系统板实物照片,PCB工艺不是好,手工焊接后也很脏。第二版硬件上没有问题,各项都调试通过,但综合多种因素,该套小板原则上不会制作并对外,但还是非常感谢大家这段时间对...
EE直播间
更多
我要评论
4
11
关闭 站长推荐上一条 /3 下一条