内容:
Part 1:stm32的USB库结构 Part 2:USB枚举、描述符及请求 Part 3:USB模块相关改动的详细说明
Part 1:stm32的USB库结构
1、 usb库的结构
1.1 USB库分为两个层次:
A) USB库内核层:管理使用USB IP硬件和USB标准协议的直接传输。
包括以下文件:
B) 应用接口层:
1.2 USB库内核模块介绍 1.2.1 usb_type.h
定义USB库中使用的主要类型,这个文件独立于stm32固件库的数据类型定义文件stdint.h,保证USB库的独立性。
1.2.2 usb_regs(.c,.h) 此模块实现了硬件的抽象层,定义了访问USB寄存器的基本函数
1.2.3 usb_int(.c,.h)
处理传输中断服务程序,实现USB协议事件和库内核之间的连接。
主要有两个函数void CTR_LP(void)和void CTR_HP(void),前一个是数据传输完成处理的核心处理部分。 1.2.4 usb_core(.c,.h) USB库的内核,实现USB 2.0规范中的功能。
覆盖了和ENDP0有关的变准请求处理以及为列举,并且利用结构体
User_Standard_Requests实现了标准请求和用户实现之间的动态接口。内核中使用的各种数据和函数结构如下:
A、 内核将设备级的信息存储在结构为DEVICE类型的设备表结构中,定义为:
typedef struct _DEVICE
{
uint8_t Total_Endpoint; /* Number of endpoints that are used */ uint8_t Total_Configuration;/* Number of configuration available */ } DEVICE;
包括了使用的总端点数和总的配置数,其赋值操作在usb_prop.c中实现。
B、 内核将主机发送的用于实现usb设备的设置包保存在类型为DEVICE_INFOR的设备
信息结构中,定义为:
typedef struct _DEVICE_INFO {
uint8_t USBbmRequestType; /* bmRequestType */ uint8_t USBbRequest; /* bRequest */ uint16_t_uint8_t USBwValues; /* wValue */ uint16_t_uint8_t USBwIndexs; /* wIndex */ uint16_t_uint8_t USBwLengths; /* wLength */
uint8_t ControlState; /* of type CONTROL_STATE */ uint8_t Current_Feature;
uint8_t Current_Configuration; /* Selected configuration */
uint8_t Current_Interface; /* Selected interface of current configuration */
uint8_t Current_AlternateSetting;/* Selected Alternate Setting of current interface*/
ENDPOINT_INFO Ctrl_Info; }DEVICE_INFO
为了实现对结构中某些字段的访问(以16位或8位的格式),定义了一个共用体uint16_t_uint8_t,其定义为:
typedef union
{
uint16_t w; struct BW {
uint8_t bb1; uint8_t bb0; } bw;
} uint16_t_uint8_t
DEVICE_INFO结构体中需要关心的字段: -USBbmRequestType是设置包中的bmRequestType副本,说明设置包的请求属性。 - USBbRequest是设置包中bRequest的副本,指设置包的请求号。
- USBwValues是设置包中wValues的副本,对应不同的请求,有着不同的作用,它
是uint16_t_uint8_t的结构。其成员通过宏进行了定义: #define USBwValue USBwValues.w
#define USBwValue0 USBwValues.bw.bb0 #define USBwValue1 USBwValues.bw.bb1
因此通过这个宏就可以访问整个word,或其中的某个byte。
- USBwIndexs和USBwValues的定义和访问方式一样,作用是接口和端点的索引好,分别对应USB接口描述符中的bInterfaceNumber值和端点描述符中的bEndpointAddress值。
- USBwLengths和USBwValues的定义和访问方式一样,它的值代表着设备返回数据
包的长度
C、内核在必要时将控制权交给用户,用户处理过程以结构体DEVICE_PROP类型给出,
定义为:
typedef struct _DEVICE_PROP
{
void (*Init)(void); void (*Reset)(void);
void (*Process_Status_IN)(void); void (*Process_Status_OUT)(void);
RESULT (*Class_Data_Setup)(uint8_t RequestNo); RESULT (*Class_NoData_Setup)(uint8_t RequestNo);
RESULT (*Class_Get_Interface_Setting)(uint8_t Interface, uint8_t
AlternateSetting);
uint8_t* (*GetDeviceDescriptor)(uint16_t Length); uint8_t* (*GetConfigDescriptor)(uint16_t Length); uint8_t* (*GetStringDescriptor)(uint16_t Length); uint8_t* RxEP_buffer; uint8_t MaxPacketSize; }DEVICE_PROP
D、用户标准需求结构是用户代码与标准请求管理之间的接口,属于 USER_STARDARD_REQUESTS类型。
必须在usb_prop中实现以上的几种结构。
1.2.5 usb_mem(.c,.h) 负责拷贝数据,从用户内存区到USB模块内存区(PMA)或者从USB模块内存区(PMA)到用户内存区
1.2.6 Usb_sil(.h,.c): 主要对以下两个函数(这两个函数定义在usb_mem.c中)进行封装 A)UserToPMABufferCopy() B)PMAToUserBufferCopy()
1)对UserToPMABufferCopy()进行封装的函数:
uint32_t USB_SIL_Write(uint8_t bEpAddr, uint8_t* pBufferPointer, uint32_t wBufferSize) Parameter:bEpAddr:端点地址,例如EP1_IN、EP1_OUT、EP2_IN、EP2_OUT等。
pBufferPointer:需要发送的数据数组指针。 wBufferSize:要发送的数据数组大小。
Function:通过指定的端点将需要的数据数组从下位机发送到上位机,上位机再使用软件读出来。
2)对PMAToUserBufferCopy()进行封装的函数:
uint32_t USB_SIL_Read(uint8_t bEpAddr, uint8_t* pBufferPointer)
Parameter:bEpAddr:端点地址,例如EP1_IN、EP1_OUT、EP2_IN、EP2_OUT等。 pBufferPointer:接收上位机数据的数据数组指针。 Function:在指定的端点接收上位机发送到下位机的数据,存到pBufferPointer指定的数组中
注意:在stm32工程中没有引用USB_SIL_Read,而是使用未封装的PMAToUserBufferCopy(),在usb_istr.c中引用来接收数据,函数为PMAToUserBufferCopy(Receive_Buffer,
ENDP2_RXADDR,50),作用是接收上位机数据到Receive_Buffer[50]中,上位机发送数据时datasize必须为50,无用的位可以写为0发送。
1.3 USB库应用接口层 1.3.1 usb_istr(.c)
Usb_istr.c提供了一个函数USB_istr()处理所有的USB宏单元中断。
函数void (*pEpInt_IN[7])(void)引用了所有EP*_IN(1-7)的回调函数,函数void
(*pEpInt_OUT[7])(void)引用了所有EP*_out(1-7)的回调函数,如果需要调用相应的回调函数,则应该在usb_config.h中将对应的函数无效声明注释掉如//#define EP2_OUT_Callback NOP_Process,再添加函数的具体内容。
注:在工程中,HID双向通信定义使用端点1发送数据,端点2接收数据,其中端点2接收数据需要用回调函数接收,所以在usb_config.h中将//#define EP2_OUT_Callback NOP_Process注释掉,并且在usb_istr.c中添加了EP2_OUT_Callback的定义: void EP2_OUT_Callback(void) {
PMAToUserBufferCopy(Receive_Buffer, ENDP2_RXADDR,50); SetEPRxStatus(ENDP2, EP_RX_VALID); Usb_ReceivePro(); }
函数的第一句作用是将端点2接收的数据存入大小为50bytes的Receive_Buffer中。 第二句作用是使能端点2的数据接收,第三句是引用自己定义的函数,这个函数用来处理接收到的数据。
1.3.2 usb_conf(.h)
Usb_conf.h定义了BTABLE和PMA中的所有端点地址
注:EP_NUM指需要用到的端点数量。 以下这一段宏定义定义了端点发送或接收缓冲区的大小,
都定义为了64bytes
#define BTABLE_ADDRESS (0x00) //这个是基地址 /* EP0 */
/* rx/tx buffer base address */
#define ENDP0_RXADDR (0x18) #define ENDP0_TXADDR (0x58)
/* EP1 */
/* tx buffer base address */
#define ENDP1_TXADDR (0x100) #define ENDP2_RXADDR (0x140)
下面这一段是回调函数的无效宏定义,相当于一个mask,需要相应的回调函数,则注释掉那一句。
#define EP1_IN_Callback NOP_Process
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库stm32 USB模块的HID设备开发在线全文阅读。
相关推荐: