8、STM32HAL_USB_DEVICE库数据结构

目录

1、重要的状态类型

1.1、USBD_StatusTypeDef

2.1、 EP0 Statue

2、设备内核结构体

3、USB驱动结构体(*pData)

4、类方法结构体USBD_ClassTypeDef(*pClass)

5、类特有的数据结构(*pClassData)

6、类的用户方法结构体(*pUserData)

7、综述




以CDC类举例,首先看一张图(原谅这张图吧,实在是不想画visio了,能看懂就行).

其中USBD_DescriptorsTypeDef因为只涉及到枚举过程中的设备描述符和字符串描述符,也没什么特别需要注意的,一般情况下,是不会修改它的,所以也就没写.

1、重要的状态类型

1.1、USBD_StatusTypeDef

几乎所有库函数都会返回类型为 USBD_StatusTypeDef 的状态,应用应该始终检查返回的状态。定义如下.

typedef enum
{
  USBD_OK   = 0U,
  USBD_BUSY,
  USBD_FAIL,
} USBD_StatusTypeDef;

2.1、 EP0 Statue

定义了EP0端点的几个状态.保存在USBD_HandleTypeDef的ep0_state变量中.如下

/*  EP0 State */
#define USBD_EP0_IDLE                                   0x00U
#define USBD_EP0_SETUP                                  0x01U
#define USBD_EP0_DATA_IN                                0x02U
#define USBD_EP0_DATA_OUT                               0x03U
#define USBD_EP0_STATUS_IN                              0x04U
#define USBD_EP0_STATUS_OUT                             0x05U
#define USBD_EP0_STALL                                  0x06U

 

2、设备内核结构体

在DEVICE库里面,最主要的数据结构是USBD_HandleTypeDef,它将USB传输中的数据抽象到该数据结构内.该结构体包含所有变量和结构体,用以实时保存与设备、控制传输状态机以及端点的状态相关的所有信息.USB内核层所有的操作都围绕着该数据结构展开.

下面列出了其中比较重要的成员变量,未列出的基本未使用或者很少使用.

成员变量描述
dev_config枚举过程的最后会有一个SET_CONFIG的通用标准请求,该变量保存该请求内设置的配置值.
ep_in[16]STM32全系列最多由16个端点,可以全部作为单向端点,为了兼容所以定义了16个端点.该变量保存了端点的最大包长,发送/接收数据总长度,剩余发送/接收总长度,是否被使用,端点状态等属性.
ep_out[16]同上
ep0_stateEP0端点的状态,它控制着内核的状态机
dev_state设备库里只支持连接、配置和上电  其余的统统认为时默认状态
dev_address保存主机位设备分配的地址
request标准请求存放
*pDesc指向设备描述符,字符串描述符的管理接口结构体
*pClass指向USB Device Class的操作接口,一般存放在USBD_XXX.C(XXX代表类名)文件.
*pClassData指向USB Device Class的数据接口,初始化时候动态内存分配的,一般存放在USBD_XXX.H(XXX代表类名)文件
*pUserData指向用户自己实现的应用层的函数集合,一般存放在USBD_XXX_IF.C文件
*pData指向底层硬件驱动结构体,根据硬件平台也不一样.

3、USB驱动结构体(*pData)

硬件相关的结构体PCD_HandleTypeDef,根据具体的硬件平台不一样,可能略有变化.

成员变量描述
*Instance USB_IP Peripheral Registers base address
Initcubemx配置页面的参数
USB_Address主机为设备分配的USB地址
IN_ep[8]

F1系列只有8个双向端点,所以定义为8.

存放着端点的端点号,方向,类型,缓存地址等等很多东西.

OUT_ep[8]同上
Setup[12]标准请求的数据,硬件接受完就存放到这了.
*pData指向了设备内核结构体.
没有使用,各个阶段的回调函数,如有需要可打开宏后,自行实现.

4、类方法结构体USBD_ClassTypeDef(*pClass)

USB协议栈将所有USB类都抽象成一个数据结构:USBD_ClassTypeDef,其定义如下所示:

typedef struct _Device_cb
{
  uint8_t (*Init)(struct _USBD_HandleTypeDef *pdev, uint8_t cfgidx);
  uint8_t (*DeInit)(struct _USBD_HandleTypeDef *pdev, uint8_t cfgidx);
  /* Control Endpoints*/
  uint8_t (*Setup)(struct _USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef  *req);
  uint8_t (*EP0_TxSent)(struct _USBD_HandleTypeDef *pdev);
  uint8_t (*EP0_RxReady)(struct _USBD_HandleTypeDef *pdev);
  /* Class Specific Endpoints*/
  uint8_t (*DataIn)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
  uint8_t (*DataOut)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
  uint8_t (*SOF)(struct _USBD_HandleTypeDef *pdev);
  uint8_t (*IsoINIncomplete)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);
  uint8_t (*IsoOUTIncomplete)(struct _USBD_HandleTypeDef *pdev, uint8_t epnum);

  uint8_t  *(*GetHSConfigDescriptor)(uint16_t *length);
  uint8_t  *(*GetFSConfigDescriptor)(uint16_t *length);
  uint8_t  *(*GetOtherSpeedConfigDescriptor)(uint16_t *length);
  uint8_t  *(*GetDeviceQualifierDescriptor)(uint16_t *length);
#if (USBD_SUPPORT_USER_STRING_DESC == 1U)
  uint8_t  *(*GetUsrStrDescriptor)(struct _USBD_HandleTypeDef *pdev, uint8_t index,  uint16_t *length);
#endif

} USBD_ClassTypeDef;

 

   ST目前官方提供的USB设备类的DEMO程序并没有囊括所有USB类,因此,若用户需要实现这些官方提供DEMO之外的USB类时,则用户需要根据自己的需要来定制化自己的USB类。

这个结构体是一个抽象类,定义了一些虚拟函数,比如初始化,反初始化,类请求指令处理函数,端点0发送完成,端点0接收处理,数据发送完成,数据接收处理,SOF中断处理,同步传输发送未完成,同步传输接收未完成处理等等;用户在实现自己具体的USB类的时候需要将它实例化,USBD_ClassTypeDef结构体是USBD内核提供给外部定义一个USB设备类的窗口,而USB类文件(如usbd_cdc.c)实际就是实现这个结构体具体实例化的过程。最后通过USBD_HandleTypeDefpClass进行链接.

在ST提供的CDC的DEMO如下.

USBD_ClassTypeDef  USBD_CDC =
{
  USBD_CDC_Init,
  USBD_CDC_DeInit,
  USBD_CDC_Setup,
  NULL,                 /* EP0_TxSent, */
  USBD_CDC_EP0_RxReady,
  USBD_CDC_DataIn,
  USBD_CDC_DataOut,
  NULL,
  NULL,
  NULL,
  USBD_CDC_GetHSCfgDesc,
  USBD_CDC_GetFSCfgDesc,
  USBD_CDC_GetOtherSpeedCfgDesc,
  USBD_CDC_GetDeviceQualifierDescriptor,
};

这些成员函数都在USBD_CDC.C文件中实现,除此之外,还有对上层应用提供的接口,比如让内核调用CDC类方法的接口,CDC类的发送等API.

/**/

uint8_t  USBD_CDC_SetTxBuffer(USBD_HandleTypeDef   *pdev,
                              uint8_t  *pbuff,
                              uint16_t length);

uint8_t  USBD_CDC_SetRxBuffer(USBD_HandleTypeDef   *pdev,
                              uint8_t  *pbuff);

/*--------------------------------对上层应用提供的接口API----------------------------------*/
uint8_t  USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev);

uint8_t  USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev);

uint8_t  USBD_CDC_RegisterInterface(USBD_HandleTypeDef   *pdev,
                                    USBD_CDC_ItfTypeDef *fops);

5、类特有的数据结构(*pClassData)

依旧以CDC类举例,因为CDC是通信类,所以数据结构中少不了的会有发送接收缓冲区的地址,长度等信息,官方提供的demo中定义的结构体如下所示.

typedef struct
{
  uint32_t data[CDC_DATA_HS_MAX_PACKET_SIZE / 4U];   //USB的CDC类标准请求全部在该数组存放
  uint8_t  CmdOpCode;                                //CDC类的bRequest值
  uint8_t  CmdLength;                                //该次请求指令的数据长度
  uint8_t  *RxBuffer;
  uint8_t  *TxBuffer;
  uint32_t RxLength;
  uint32_t TxLength;

  __IO uint32_t TxState;
  __IO uint32_t RxState;
}
USBD_CDC_HandleTypeDef;

 需要注意的是该结构体的初始化实在USBD_ClassTypeDef的初始化里面,在官方提供的DEMO里面使用的是一个假的动态内存分配,如下所示.

void *USBD_static_malloc(uint32_t size)
{
  static uint32_t mem[(sizeof(USBD_CDC_HandleTypeDef)/4)+1];/* On 32-bit boundary */
  return mem;
}
/** Alias for memory allocation. */
#define USBD_malloc         (uint32_t *)USBD_static_malloc

/** Alias for memory release. */
#define USBD_free           USBD_static_free


static uint8_t  USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
/*省略代码*/
  pdev->pClassData = USBD_malloc(sizeof(USBD_CDC_HandleTypeDef));
/*省略代码*/
}

6、类的用户方法结构体(*pUserData)

依旧以CDC类为例子,在USBD_CDC_IF.H文件中提供了如下结构体

typedef struct _USBD_CDC_Itf
{
  int8_t (* Init)(void);
  int8_t (* DeInit)(void);
  int8_t (* Control)(uint8_t cmd, uint8_t *pbuf, uint16_t length);
  int8_t (* Receive)(uint8_t *Buf, uint32_t *Len);

} USBD_CDC_ItfTypeDef;

该类结构体存在的意义就是为了让USBD_CDC类与应从层代码完全分离,类似USBD内核与USBD_CDC类完全分离一般.

7、综述

综上,基本上重要的结构体已经说完了,最终的关系如下所示.

备注: 做好的表格提交的时候飞了???  还要重新写,心态炸了啊

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值