USB学习笔记(4)STM32关于USB库的解读
为了方便在STM32上实现USB功能,本文对USB库的文件进行解读。
USB-FS_Device peripheral interface(外围接口)
1. usb_regs(.h/.c)
此模块实现硬件抽象层,提供访问USB外围寄存器的基本功能。
- 通用寄存器函数
| 寄存器 | 偏移量 | 功能 | 说明 |
|---|---|---|---|
| CNTR | 0x40 | void SetCNTR(uint16_t wValue) | 设置USB控制寄存器 |
uint16_t GetCNTR(void) | 获取USB控制寄存器值 | ||
| ISTR | 0x44 | void SetISTR(uint16_t wValue) | 设置USB中断状态寄存器 |
uint16_t GetISTR(void) | 获取USB中断状态寄存器 | ||
| FNR | 0x48 | uint16_t GetFNR(void) | 获取USB帧编号寄存器 |
| DADDR | 0x4C | void SetDADDR(uint16_t wValue) | 设置USB设备地址寄存器 |
uint16_t GetDADDR(void) | 获取USB设备地址寄存器值 | ||
| BTABLE | 0x50 | void SetBTABLE(uint16_t wValue) | 设置USB分组缓冲区描述表地址寄存器 |
uint16_t GetBTABLE(void) | 获取USB分组缓冲区描述表地址寄存器值 |
- 端点寄存器函数
Endpoint set/get value:获取或者设置端点寄存器的值
void SetENDPOINT(uint8_t bEpNum,uint16_t wRegValue)
uint16_t GetENDPOINT(uint8_t bEpNum)
Endpoint TYPE field:获取或者设置端点类型
#define EP_BULK (0x0000) // 批量端点
#define EP_CONTROL (0x0200) // 控制端点
#define EP_ISOCHRNOUS (0x0400) // 同步端点
#define EP_INTERRUPT (0x0600) // 中断端点
void SetEPType (uint8_t bEpNum, uint16_t wtype)
uint16_t GetEPType (uint8_t bEpNum)
Endpoint STATUS field:获取或者设置端点发送或者接受状态
#define EP_TX_DIS (0x0000) // 端点忽略所有的发送请求
#define EP_TX_STALL (0x0010) // 端点以STALL分组响应所有的发送请求
#define EP_TX_NAK (0x0020) // 端点以NAK分组响应所有发送请求
#define EP_TX_VALID (0x0030) // 端点可以用于发送
#define EP_RX_DIS (0x0000) // 端点忽略所有的接受请求
#define EP_RX_STALL (0x1000) // 端点以STALL分组响应所有的接受请求
#define EP_RX_NAK (0x2000) // 端点以NAK分组响应所有接受请求
#define EP_RX_VALID (0x3000) // 端点可以用于接受
void SetEPTxStatus(uint8_t bEpNum,uint16_t wState)
void SetEPRxStatus(uint8_t bEpNum,uint16_t wState)
uint16_t GetEPTxStatus(uint8_t bEpNum)
uint16_t GetEPRxStatus(uint8_t bEpNum)
Endpoint KIND field:设置端点特殊类型位,需要和TYPE位搭配使用
| EP_TYPE | EP_KIND意义 |
|---|---|
| BULK | DBL_BUF,双缓冲端点 |
| CONTROL | STATUS_OUT |
| IOS | 未使用 |
| INTERRUPT | 未使用 |
void SetEP_KIND(uint8_t bEpNum)
void ClearEP_KIND(uint8_t bEpNum)
void Set_Status_Out(uint8_t bEpNum)
void Clear_Status_Out(uint8_t bEpNum)
void SetEPDoubleBuff(uint8_t bEpNum)
void ClearEPDoubleBuff(uint8_t bEpNum)
//正确接受/发送标志位
void ClearEP_CTR_RX(uint8_t bEpNum)
void ClearEP_CTR_TX(uint8_t bEpNum)
Data Toggle Rx/Tx fields:数据包类型翻转
void ToggleDTOG_RX(uint8_t bEpNum)
void ToggleDTOG_TX(uint8_t bEpNum)
Address field:设置/获取端点地址,在使能端点前,需要给端点设置地址
void SetEPAddress(uint8_t bEpNum,uint8_t bAddr)
uint8_t GetEPAddress(uint8_t bEpNum)
- 缓冲区描述表函数:这些函数用于设置或获取端点的接收和发送缓冲区地址和大小。
Tx/Rx buffer address fields
void SetEPTxAddr(uint8_t bEpNum,uint16_t wAddr);
void SetEPRxAddr(uint8_t bEpNum,uint16_t wAddr);
uint16_t GetEPTxAddr(uint8_t bEpNum);
uint16_t GetEPRxAddr(uint8_t bEpNum);
Tx/Rx buffer counter fields
void SetEPTxCount(uint8_t bEpNum,uint16_t wCount);
void SetEPRxCount(uint8_t bEpNum,uint16_t wCount);
uint16_t GetEPTxCount(uint8_t bEpNum);
uint16_t GetEPRxCount(uint8_t bEpNum);
- 双缓冲区端点函数:为了获得大量或等时模式下的高数据传输吞吐量,必须对双缓冲模式进行编程。在这种操作模式下,端点寄存器和缓冲区描述的某些字段有不同的含义。
通过设置EP-KIND位,可以将编程为在批量模式下工作的端点设置为双缓冲。
void SetEPDoubleBuff(uint8_t bEpNum);
在双缓冲模式下,端点变为单向,并应用未使用方向的缓冲区作为第二个缓冲区来处理。
从应用程序中释放正在使用的缓冲区,
void FreeUserBuffer(uint8_t bEpNum, uint8_t bDir);
地址和计数器必须以不同的方式处理。Rx和TX地址和计数器单元变成Buffer0和Buffer1单元。
Double buffer addresses
void SetEPDblBuffAddr(uint8_t bEpNum,uint16_t wBuf0Addr,uint16_t wBuf1Addr);
void SetEPDblBuf0Addr(uint8_t bEpNum,uint16_t wBuf0Addr);
void SetEPDblBuf1Addr(uint8_t bEpNum,uint16_t wBuf1Addr);
uint16_t GetEPDblBuf0Addr(uint8_t bEpNum);
uint16_t GetEPDblBuf1Addr(uint8_t bEpNum);
Double buffer counters
void SetEPDblBuffCount(uint8_t bEpNum, uint8_t bDir, uint16_t wCount);
void SetEPDblBuf0Count(uint8_t bEpNum, uint8_t bDir, uint16_t wCount);
void SetEPDblBuf1Count(uint8_t bEpNum, uint8_t bDir, uint16_t wCount);
uint16_t GetEPDblBuf0Count(uint8_t bEpNum);
uint16_t GetEPDblBuf1Count(uint8_t bEpNum);
Double buffer STATUS
STALL状态由下面的函数控制,其他状态用之前单模式下的函数控制。
void SetDouBleBuffEPStall(uint8_t bEpNum,uint8_t bDir)
2. usb_int(.h/.c)
此模块处理正确的传输中断服务例程;它提供USB设备协议事件和库之间的链接。
CTR_LP(): 低优先级中断:由函数CTR_LP()管理,用于控制,中断和批量(在简单的缓冲模式下)。CTR_HP(): 高优先级中断:由函数CTR_HP()管理,用于像等时和批量(双缓冲模式)这样更快的传输模式)。
3. usb_mem(.h/.c)
此模块将用户缓冲区数据复制到PMA缓冲区(USB设备与主机通讯使用的数据缓冲区),反之亦然
void UserToPMABufferCopy(uint8_t *pbUsrBuf,uint16_t wPMABufAddr, uint16_t
wNBytes);
void PMAToUserBufferCopy(uint8_t *pbUsrBuf,uint16_t wPMABufAddr, uint16_t
wNBytes);
USB-FS-Device_Driver medium layer(中间层模块)
1. usb_init(.h/.c)
此模块设置将在库中使用的初始化例程和全局变量
2. usb_core(.h/.c)
此模块是库的"内核"。它实现了USB2.0规范第9章中描述的所有功能。
可用的子程序包括与控制端点(ENDP0)相关的USB标准请求的处理,提供了完成枚举阶段序列所需的代码。
实现状态机是为了处理设置事务的不同阶段。
该USB内核模块还使用结构User_Standard_Requests实现标准请求和用户实现之间的动态接口。
USB内核就会向用户程序发送特定类的请求和一些总线事件。用户处理程序在Device_Property结构中给出。
Device table structure:
DEVICEtypedef struct _DEVICE { uint8_t Total_Endpoint; //USB应用程序使用的端点数 uint8_t Total_Configuration; //USB应用程序的配置数量 } DEVICE;Device information structure:
DEVICE_INFO
由于该结构在库中的任何地方都使用,因此定义了一个全局变量pInformation,以便于访问Device_Info表,它是指向DEVICE_INFO结构的指针。pInformation = &Device_Info.
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; //控制过程所处的状态:CONTROL_STATE
uint8_t Current_Feature; //当前设备特性。它受到SET_FEATURE和CLEAR_FEATURE请求的影响并由GET_STATUS请求检索。用户代码不使用此字段。
uint8_t Current_Configuration; //当前配置状态。它分别由SET_CONFIGURATION和GET_CONFIGURATION请求设置和检索
uint8_t Current_Interface; //当前接口
uint8_t Current_AlternateSetting; //当前工作配置和接口选择的替代设置。它由SET_INTERFACE和GET_INTERFACE请求设置和检索
ENDPOINT_INFO Ctrl_Info; //端点等待发送的字符串信息
}DEVICE_INFO;
typedef struct _ENDPOINT_INFO
{
uint16_t Usb_wLength; //字符串长度
uint16_t Usb_wOffset; //字符串发送的偏移量
uint16_t PacketSize; //包的大小
uint8_t *(*CopyData)(uint16_t Length);
}ENDPOINT_INFO; /*端点等待发送的字符串信息*/
Device property structure:
DEVICE_PROPtypedef 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); void* RxEP_buffer; /* This field is not used in current library version. It is kept only for compatibility with previous versions */ uint8_t MaxPacketSize; } DEVICE_PROP;User standard request structure:
USER_STANDARD_REQUESTS标准请求中的用户代码typedef struct _USER_STANDARD_REQUESTS { void(*User_GetConfiguration)(void); void(*User_SetConfiguration)(void); void(*User_GetInterface)(void); void(*User_SetInterface)(void); void(*User_GetStatus)(void); void(*User_ClearFeature)(void); void(*User_SetEndPointFeature)(void); void(*User_SetDeviceFeature)(void); void(*User_SetDeviceAddress)(void); } USER_STANDARD_REQUESTS;
3. usb_sil(.h/.c)
此模块为USB_FS_Device外围设备实现了额外的抽象层。它提供了访问读写操作端点的简单函数
void USB_SIL_Write(uint32_t EPNum, uint8_t* pBufferPointer, uint32_t
wBufferSize);
uint32_t USB_SIL_Read(uint32_t EPNum, uint8_t* pBufferPointer);
4. usb_type.h/usb_def.h
此模块提供了库中使用的主要类型和USB定义。
5. platform_config.h
此模块负责为每个eval板提供特定的配置。 此文件应复制到应用程序文件夹,然后由用户在该文件夹中配置。
Application interface(应用程序接口)
应用程序接口的模块作为模板提供,它们必须由应用程序开发人员为每个应用程序量身定做
1. usb_conf.h/usb_endp.c
此模块自定义USB端点,以及端点回调函数等信息
2. usb_desc(.h/.c)
此模块应该包含与应用程序相关的所有USB描述符。用户必须根据应用程序、程序和类设置这些描述符
3. usb_prop(.h/.c)
此模块用于实现USB核心使用的Device_Property、Device_Table和USER_STANDARD_REQUEST结构。
Device_Property:
void Init(void):USB外设的初始化程序。在应用程序开始时调用一次来管理初始化过程void Reset(void):USB外设的复位程序。当设备从总线接收到重置信号时,就会调用它。用户程序应在此过程中设置端点功能。void Process_Status_IN(void):回调过程,它是在阶段中的状态完成时调用的。用户程序可以通过这个回调来控制执行与类和应用程序相关的进程。void Process_Status_OUT(void):回调过程,当状态退出阶段完成时调用它。与Process_Status_IN一样,用户程序可以在状态退出阶段之后执行操作RESULT (see note below) *(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):获取字符串描述符。uint16_t MaxPacketSize:设备默认控制端点的最大数据包大小。
RESULT 返回结果:
typedef enum _RESULT {
USB_SUCCESS = 0, /* 请求过程成功 */
USB_ERROR, /* 请求过程错误 */
USB_UNSUPPORT, /* 请求不支持 */
USB_NOT_READY /* 请求过程还没结束,端点将以NAK满足进一步的请求 */
} RESULT;
USER_STANDARD_REQUEST:
void (*User_GetConfiguration)(void): 获取配置描述符的标准请求void (*User_SetConfiguration)(void): 设置配置描述符的标准请求void (*User_GetInterface)(void): 获取接口描述符的标准请求void (*User_SetInterface)(void): 设置接口描述符的标准请求void (*User_GetStatus)(void): 获取接口描述符的标准请求void (*User_ClearFeature)(void): 在收到Clear Feature Standard请求后调用。void (*User_SetEndPointFeature)(void): 在收到设置的Feature Standard请求后调用(仅针对端点接收方)。
Standard request (only for endpoint recipient).void (*User_SetDeviceFeature)(void): 在收到设置的特性标准请求后调用(仅用于设备接收方)。void (*User_SetDeviceAddress)(void): 在收到设置的地址标准请求后调用。
4. usb_istr.c
此模块提供了一个名为USB_Istr()的函数,它处理所有USB中断
5. usb_pwr(.h/.c)
此模块管理USB设备的电源管理
| 函数 | 说明 |
|---|---|
| RESULT Power_on(void) | 关闭 |
| RESULT Power_off(void) | 打开 |
| void Suspend(void) | 挂起 |
| void Resume(RESUME_STATE eResumeSetVal) | 唤醒 |