//USBD.h
/*************************************************************************************************************
* 文件名: usbd.h
* 功能: NUC970 USB设备相关驱动
* 作者: cp1300@139.com
* 创建时间: 2020-10-12
* 最后修改时间: 2020-10-12
* 详细:
*************************************************************************************************************/
#ifndef _USB_D_
#define _USB_D_
#include "nuc970_system.h"
#include "typedef.h"
#define USBD_MAX_EP 12 //端点数量
//端点通道定义
typedef enum
{
USBD_EPA = 0, //USB端点A
USBD_EPB = 1,
USBD_EPC = 2,
USBD_EPD = 3,
USBD_EPE = 4,
USBD_EPF = 5,
USBD_EPG = 6,
USBD_EPH = 7,
USBD_EPI = 8,
USBD_EPJ = 9,
USBD_EPK = 10,
USBD_EPL = 11,
USBD_CEP = 12, //保留的控制端点
USBD_INVALID_EP = 0xff, //无效的EP
}USBD_EPx;
//USBD所需全局变量定义==必须4字节对齐
//#pragma pack(4)
EPx读取数据相关信息
//typedef struct
//{
// volatile u16 ReadDataCount; //已经读取的数据数量
// volatile u16 DataBuffSize; //缓冲区大小
// volatile u8 *pReadDataBuff; //读取的数据缓冲区
// volatile bool isNewData; //新数据标志
//}USBD_EP_READ_DATA;
//#pragma pack()
typedef void (*USBD_IRQHandlerType)(u32 Status); //中断服务程序定义
typedef void (*USBD_EPxIRQHandlerType)(USBD_EPx EPx, u32 Status); //数据端口中断服务程序定义
typedef void (*USBD_CLASS_REQ)(void); //类别请求回调处理函数定义
typedef void (*USBD_VENDOR_REQ)(void); //厂商请求回调处理函数定义
//端点类型定义
typedef enum
{
USBD_EP_TYPE_BULK = 1, //块传输
USBD_EP_TYPE_INT = 2, //中断
USBD_EP_TYPE_ISO = 3, //同步
}USBD_EP_TYPE;
//端点方向设置
typedef enum
{
USBD_EP_OUTPUT = 0, //主机输出
USBD_EP_INPUT = 1, //主机输入
}USBD_EP_DIR;
//USB请求定义 USBD_SETUP_TYPE.Request 的值
typedef enum
{
USBD_GET_STATUS = 0x00, //用来返回特定接收者的状态
USBD_CLEAR_FEATURE = 0x01, //用来清除或禁止接收者的某些特性
USBD_SET_FEATURE = 0x03, //用来启用或激活命令接收者的某些特性
USBD_SET_ADDRESS = 0x05, //用来给设备分配地址
USBD_GET_DESCRIPTOR = 0x06, //用于主机获取设备的特定描述符
USBD_SET_DESCRIPTOR = 0x07, //修改设备中有关的描述符,或者增加新的描述符
USBD_GET_CONFIGURATION = 0x08, //用于主机获取设备当前设备的配置值(注同上面的不同)
USBD_SET_CONFIGURATION = 0x09, //用于主机指示设备采用的要求的配置
USBD_GET_INTERFACE = 0x0A, //用于获取当前某个接口描述符编号
USBD_SET_INTERFACE = 0x0B, //用于主机要求设备用某个描述符来描述接口
USBD_SYNC_FRAME = 0x0C, //用于设备设置和报告一个端点的同步帧
}USBD_REQUEST_TYPE;
//USB SETUP请求数据结构体
typedef struct
{
//最高位BIT8:0:数据由主控发送到设备;1:数据由设备发送到主控
//D6-D5位是请求主分类型
//D4-D0位是表求接收这个包的接口
u8 RequestType; //请求类型,
u8 Request; //本描述符的请求类型
u16 Value; //参数
u16 Index; //标示
u16 Length; //下一阶段发送数据的长度
}USBD_SETUP_TYPE;
extern USBD_SETUP_TYPE g_USBD_Setup;
//USB设备描述符集合
typedef struct
{
const u8 *DeveceDescripArray; //设备描述符
const u8 *ConfigDescripArray; //配置描述符
const u8 **StringDescripPoint; //USB字符串描述符指针的指针
const u8 *QualifierDescripArray; //限定描述符
const u8 *OtherConfigDescripArray; //其他速度配置描述符
const u8 **HidReportDescripPoint; //HID报告描述符的指针
const u32 *HidReportSize; //HID报告描述符大小的指针
}USBD_DESCRIPTOR;
//控制端点buff
#define CEP_BUFF_OFFSET 0 //控制端点buff缓冲区偏移
#define CEP_BUFF_SIZE 64 //控制端点缓冲区大小
//USB描述符长度
#define USBD_LEN_DEVICE 18
#define USBD_LEN_QUALIFIER 10
#define USBD_LEN_CONFIG 9
#define USBD_LEN_INTERFACE 9
#define USBD_LEN_ENDPOINT 7
#define USBD_LEN_OTG 5
#define USBD_LEN_HID 9
//USB描述符类型
#define USBD_DESC_DEVICE 0x01 //设备描述符(Device Descriptor)
#define USBD_DESC_CONFIG 0x02 //配置描述符(Configuration Descriptor)
#define USBD_DESC_STRING 0x03 //字符串描述符(String Descriptor)
#define USBD_DESC_INTERFACE 0x04 //接口描述符(Interface Descriptor)
#define USBD_DESC_ENDPOINT 0x05 //端点描述符(EndPont Descriptor)
#define USBD_DESC_QUALIFIER 0x06
#define USBD_DESC_OTHERSPEED 0x07
#define USBD_DESC_IFPOWER 0x08
#define USBD_DESC_OTG 0x09
//USB HID描述符类型
#define USBD_DESC_HID 0x21 //获取HID描述符
#define USBD_DESC_HID_RPT 0x22 //获取HID报告描述符
//USB SETUP主请求类型
#define USBD_REQ_STANDARD 0x00 //标准请求
#define USBD_REQ_CLASS 0x20 //类别请求
#define USBD_REQ_VENDOR 0x40 //厂商请求
//定义的数据存储器类型的请求
#define USBD_BULK_ONLY_MASS_STORAGE_RESET 0xFF
#define USBD_GET_MAX_LUN 0xFE //获取存储器逻辑磁盘数量
//USB功能选择器
#define USBD_FEATURE_ENDPOINT_HALT 0x00
#define USBD_FEATURE_DEVICE_REMOTE_WAKEUP 0x01
#define USBD_FEATURE_TEST_MODE 0x02
/********************* Bit definition of CEPCTL register **********************/
#define USB_CEPCTL_NAKCLR ((uint32_t)0x00000000) //NAK clear
#define USB_CEPCTL_STALL ((uint32_t)0x00000002) //Stall
#define USB_CEPCTL_ZEROLEN ((uint32_t)0x00000004) //Zero length packet
#define USB_CEPCTL_FLUSH ((uint32_t)0x00000008) //CEP flush
/********************* Bit definition of EPxRSPCTL register **********************/
#define USB_EP_RSPCTL_FLUSH ((uint32_t)0x00000001) //Buffer Flush
#define USB_EP_RSPCTL_MODE_AUTO ((uint32_t)0x00000000) //Auto-Validate Mode
#define USB_EP_RSPCTL_MODE_MANUAL ((uint32_t)0x00000002) //Manual-Validate Mode
#define USB_EP_RSPCTL_MODE_FLY ((uint32_t)0x00000004) //Fly Mode
#define USB_EP_RSPCTL_MODE_MASK ((uint32_t)0x00000006) //Mode Mask
#define USB_EP_RSPCTL_TOGGLE ((uint32_t)0x00000008) //Clear Toggle bit
#define USB_EP_RSPCTL_HALT ((uint32_t)0x00000010) //Endpoint halt
#define USB_EP_RSPCTL_ZEROLEN ((uint32_t)0x00000020) //Zero length packet IN
#define USB_EP_RSPCTL_SHORTTXEN ((uint32_t)0x00000040) //Packet end
#define USB_EP_RSPCTL_DISBUF ((uint32_t)0x00000080) //Disable buffer
//USBD GINTSTS GINTEN 总的USB中断状态
#define USBD_GINTSTS_USBIF_Pos (0)
#define USBD_GINTSTS_USBIF_Msk (0x1ul << USBD_GINTSTS_USBIF_Pos) //USB中断状态
#define USBD_GINTSTS_CEPIF_Pos (1)
#define USBD_GINTSTS_CEPIF_Msk (0x1ul << USBD_GINTSTS_CEPIF_Pos) //控制端点中断
#define USBD_GINTSTS_EPAIF_Pos (2)
#define USBD_GINTSTS_EPAIF_Msk (0x1ul << USBD_GINTSTS_EPAIF_Pos) //端点A中断
#define USBD_GINTSTS_EPBIF_Pos (3)
#define USBD_GINTSTS_EPBIF_Msk (0x1ul << USBD_GINTSTS_EPBIF_Pos) //端点B中断
#define USBD_GINTSTS_EPCIF_Pos (4)
#define USBD_GINTSTS_EPCIF_Msk (0x1ul << USBD_GINTSTS_EPCIF_Pos) //端点C中断
#define USBD_GINTSTS_EPDIF_Pos (5)
#define USBD_GINTSTS_EPDIF_Msk (0x1ul << USBD_GINTSTS_EPDIF_Pos) //端点D中断
#define USBD_GINTSTS_EPEIF_Pos (6)
#define USBD_GINTSTS_EPEIF_Msk (0x1ul << USBD_GINTSTS_EPEIF_Pos) //端点E中断
#define USBD_GINTSTS_EPFIF_Pos (7)
#define USBD_GINTSTS_EPFIF_Msk (0x1ul << USBD_GINTSTS_EPFIF_Pos) //端点F中断
#define USBD_GINTSTS_EPGIF_Pos (8)
#define USBD_GINTSTS_EPGIF_Msk (0x1ul << USBD_GINTSTS_EPGIF_Pos) //端点G中断
#define USBD_GINTSTS_EPHIF_Pos (9)
#define USBD_GINTSTS_EPHIF_Msk (0x1ul << USBD_GINTSTS_EPHIF_Pos) //端点H中断
#define USBD_GINTSTS_EPIIF_Pos (10)
#define USBD_GINTSTS_EPIIF_Msk (0x1ul << USBD_GINTSTS_EPIIF_Pos) //端点I中断
#define USBD_GINTSTS_EPJIF_Pos (11)
#define USBD_GINTSTS_EPJIF_Msk (0x1ul << USBD_GINTSTS_EPJIF_Pos) //端点J中断
#define USBD_GINTSTS_EPKIF_Pos (12)
#define USBD_GINTSTS_EPKIF_Msk (0x1ul << USBD_GINTSTS_EPKIF_Pos) //端点K中断
#define USBD_GINTSTS_EPLIF_Pos (13)
#define USBD_GINTSTS_EPLIF_Msk (0x1ul << USBD_GINTSTS_EPLIF_Pos) //端点L中断
//USBD BUSINTSTS BUSINTEN 总线中断状态
#define USBD_BUSINTSTS_SOFIF_Pos (0)
#define USBD_BUSINTSTS_SOFIF_Msk (0x1ul << USBD_BUSINTSTS_SOFIF_Pos) //接收到SOF中断
#define USBD_BUSINTSTS_RSTIF_Pos (1)
#define USBD_BUSINTSTS_RSTIF_Msk (0x1ul << USBD_BUSINTSTS_RSTIF_Pos) //USB端口重置
#define USBD_BUSINTSTS_RESUMEIF_Pos (2)
#define USBD_BUSINTSTS_RESUMEIF_Msk (0x1ul << USBD_BUSINTSTS_RESUMEIF_Pos) //发生设备恢复
#define USBD_BUSINTSTS_SUSPENDIF_Pos (3)
#define USBD_BUSINTSTS_SUSPENDIF_Msk (0x1ul << USBD_BUSINTSTS_SUSPENDIF_Pos) //暂停请求
#define USBD_BUSINTSTS_HISPDIF_Pos (4)
#define USBD_BUSINTSTS_HISPDIF_Msk (0x1ul << USBD_BUSINTSTS_HISPDIF_Pos) //设备已设置为高速
#define USBD_BUSINTSTS_DMADONEIF_Pos (5)
#define USBD_BUSINTSTS_DMADONEIF_Msk (0x1ul << USBD_BUSINTSTS_DMADONEIF_Pos) //DMA完成中断
#define USBD_BUSINTSTS_PHYCLKVLDIF_Pos (6)
#define USBD_BUSINTSTS_PHYCLKVLDIF_Msk (0x1ul << USBD_BUSINTSTS_PHYCLKVLDIF_Pos) //可从收发器获得可用时钟
#define USBD_BUSINTSTS_VBUSDETIF_Pos (8)
#define USBD_BUSINTSTS_VBUSDETIF_Msk (0x1ul << USBD_BUSINTSTS_VBUSDETIF_Pos) //VBUS已插入
//USBD_CEPINTEN CEPINTSTS USBD控制端点中断
#define USBD_CEPINTSTS_SETUPTKIF_Pos (0)
#define USBD_CEPINTSTS_SETUPTKIF_Msk (0x1ul << USBD_CEPINTSTS_SETUPTKIF_Pos) //控制端点SETUP令牌中断
#define USBD_CEPINTSTS_SETUPPKIF_Pos (1)
#define USBD_CEPINTSTS_SETUPPKIF_Msk (0x1ul << USBD_CEPINTSTS_SETUPPKIF_Pos) //控制端点SETUP数据包中断
#define USBD_CEPINTSTS_OUTTKIF_Pos (2)
#define USBD_CEPINTSTS_OUTTKIF_Msk (0x1ul << USBD_CEPINTSTS_OUTTKIF_Pos) //控制端点OUT令牌中断
#define USBD_CEPINTSTS_INTKIF_Pos (3)
#define USBD_CEPINTSTS_INTKIF_Msk (0x1ul << USBD_CEPINTSTS_INTKIF_Pos) //控制端点IN令牌中断
#define USBD_CEPINTSTS_PINGIF_Pos (4)
#define USBD_CEPINTSTS_PINGIF_Msk (0x1ul << USBD_CEPINTSTS_PINGIF_Pos) //控制端点ping令牌中断
#define USBD_CEPINTSTS_TXPKIF_Pos (5)
#define USBD_CEPINTSTS_TXPKIF_Msk (0x1ul << USBD_CEPINTSTS_TXPKIF_Pos) //控制端点数据发送中断
#define USBD_CEPINTSTS_RXPKIF_Pos (6)
#define USBD_CEPINTSTS_RXPKIF_Msk (0x1ul << USBD_CEPINTSTS_RXPKIF_Pos) //控制端点数据接收中断
#define USBD_CEPINTSTS_NAKIF_Pos (7)
#define USBD_CEPINTSTS_NAKIF_Msk (0x1ul << USBD_CEPINTSTS_NAKIF_Pos) //控制端点NAK发送中断
#define USBD_CEPINTSTS_STALLIF_Pos (8)
#define USBD_CEPINTSTS_STALLIF_Msk (0x1ul << USBD_CEPINTSTS_STALLIF_Pos) //控制端点STALL发送中断
#define USBD_CEPINTSTS_ERRIF_Pos (9)
#define USBD_CEPINTSTS_ERRIF_Msk (0x1ul << USBD_CEPINTSTS_ERRIF_Pos) //控制端点USB错误中断
#define USBD_CEPINTSTS_STSDONEIF_Pos (10)
#define USBD_CEPINTSTS_STSDONEIF_Msk (0x1ul << USBD_CEPINTSTS_STSDONEIF_Pos) //控制端点状态完成中断
#define USBD_CEPINTSTS_BUFFULLIF_Pos (11)
#define USBD_CEPINTSTS_BUFFULLIF_Msk (0x1ul << USBD_CEPINTSTS_BUFFULLIF_Pos) //控制端点缓冲区满中断
#define USBD_CEPINTSTS_BUFEMPTYIF_Pos (12)
#define USBD_CEPINTSTS_BUFEMPTYIF_Msk (0x1ul << USBD_CEPINTSTS_BUFEMPTYIF_Pos) //控制端点缓冲区空中断
//USBD_OPER USBD操作命令
#define USBD_OPER_RESUMEEN_Pos (0)
#define USBD_OPER_RESUMEEN_Msk (0x1ul << USBD_OPER_RESUMEEN_Pos) //如果启用了设备远程唤醒,将向主机启动一个恢复序列(发送后自动清除)。
#define USBD_OPER_HISPDEN_Pos (1)
#define USBD_OPER_HISPDEN_Msk (0x1ul << USBD_OPER_HISPDEN_Pos) //USB设备控制器在复位协议期间启动线性调频序列
#define USBD_OPER_CURSPD_Pos (2)
#define USBD_OPER_CURSPD_Msk (0x1ul << USBD_OPER_CURSPD_Pos) //USB设备控制器设置为“高速”
//USBD_CEPCTL USBD控制端点控制
#define USBD_CEPCTL_NAKCLR_Pos (0)
#define USBD_CEPCTL_NAKCLR_Msk (0x1ul << USBD_CEPCTL_NAKCLR_Pos) //置1后,每当设置令牌被设置时,本地CPU可以花费自己的时间来完成其它工作,然后清除此位
#define USBD_CEPCTL_STALLEN_Pos (1)
#define USBD_CEPCTL_STALLEN_Msk (0x1ul << USBD_CEPCTL_STALLEN_Pos) //发送停止握手之后,控制端点响应任何输入或输出令牌
#define USBD_CEPCTL_ZEROLEN_Pos (2)
#define USBD_CEPCTL_ZEROLEN_Msk (0x1ul << USBD_CEPCTL_ZEROLEN_Pos) //USB设备控制器可以在数据阶段将零长度的数据包发送到主机到IN令牌
#define USBD_CEPCTL_FLUSH_Pos (3)
#define USBD_CEPCTL_FLUSH_Msk (0x1ul << USBD_CEPCTL_FLUSH_Pos) //清除数据包缓冲区(此位自动复位)
//USBD_DMACTL DMA控制
#define USBD_DMACTL_EPNUM_Pos (0)
#define USBD_DMACTL_EPNUM_Msk (0xful << USBD_DMACTL_EPNUM_Pos) //DMA端点地址位
#define USBD_DMACTL_DMARD_Pos (4)
#define USBD_DMACTL_DMARD_Msk (0x1ul << USBD_DMACTL_DMARD_Pos) //DMA读写操作
#define USBD_DMACTL_DMAEN_Pos (5)
#define USBD_DMACTL_DMAEN_Msk (0x1ul << USBD_DMACTL_DMAEN_Pos) //启用DMA
#define USBD_DMACTL_SGEN_Pos (6)
#define USBD_DMACTL_SGEN_Msk (0x1ul << USBD_DMACTL_SGEN_Pos) //分散收集功能
#define USBD_DMACTL_DMARST_Pos (7)
#define USBD_DMACTL_DMARST_Msk (0x1ul << USBD_DMACTL_DMARST_Pos) //重置DMA状态机
//USBD_EPxINTSTS EPxINTEN 端点中断状态
#define USBD_EPINTSTS_BUFFULLIF_Pos (0)
#define USBD_EPINTSTS_BUFFULLIF_Msk (0x1ul << USBD_EPINTSTS_BUFFULLIF_Pos) //端点数据包缓冲区已满
#define USBD_EPINTSTS_BUFEMPTYIF_Pos (1)
#define USBD_EPINTSTS_BUFEMPTYIF_Msk (0x1ul << USBD_EPINTSTS_BUFEMPTYIF_Pos) //端点缓冲区为空
#define USBD_EPINTSTS_SHORTTXIF_Pos (2)
#define USBD_EPINTSTS_SHORTTXIF_Msk (0x1ul << USBD_EPINTSTS_SHORTTXIF_Pos) //端点最后一个数据包的长度小于最大数据包大小(EPMPS)
#define USBD_EPINTSTS_TXPKIF_Pos (3)
#define USBD_EPINTSTS_TXPKIF_Msk (0x1ul << USBD_EPINTSTS_TXPKIF_Pos) //端点数据发送完成中断
#define USBD_EPINTSTS_RXPKIF_Pos (4)
#define USBD_EPINTSTS_RXPKIF_Msk (0x1ul << USBD_EPINTSTS_RXPKIF_Pos) //端点从主机接收到数据包
#define USBD_EPINTSTS_OUTTKIF_Pos (5)
#define USBD_EPINTSTS_OUTTKIF_Msk (0x1ul << USBD_EPINTSTS_OUTTKIF_Pos) //端点已从主机收到数据输出令牌。 此位也由PING令牌(仅在高速中)设置
#define USBD_EPINTSTS_INTKIF_Pos (6)
#define USBD_EPINTSTS_INTKIF_Msk (0x1ul << USBD_EPINTSTS_INTKIF_Pos) //端点已从主机收到数据输入令牌
#define USBD_EPINTSTS_PINGIF_Pos (7)
#define USBD_EPINTSTS_PINGIF_Msk (0x1ul << USBD_EPINTSTS_PINGIF_Pos) //端点已从主机收到数据PING令牌
#define USBD_EPINTSTS_NAKIF_Pos (8)
#define USBD_EPINTSTS_NAKIF_Msk (0x1ul << USBD_EPINTSTS_NAKIF_Pos) //端点无法提供最后一个USB IN数据包,并且通过一个NAK确认
#define USBD_EPINTSTS_STALLIF_Pos (9)
#define USBD_EPINTSTS_STALLIF_Msk (0x1ul << USBD_EPINTSTS_STALLIF_Pos) //端点无法接受或提供最后一个USB数据包,因为端点停滞了,并被告知失速
#define USBD_EPINTSTS_NYETIF_Pos (10)
#define USBD_EPINTSTS_NYETIF_Msk (0x1ul << USBD_EPINTSTS_NYETIF_Pos) //端点RAM中的可用空间不足以容纳下一个即将到来的数据包
#define USBD_EPINTSTS_ERRIF_Pos (11)
#define USBD_EPINTSTS_ERRIF_Msk (0x1ul << USBD_EPINTSTS_ERRIF_Pos) //端点发生了错误
#define USBD_EPINTSTS_SHORTRXIF_Pos (12)
#define USBD_EPINTSTS_SHORTRXIF_Msk (0x1ul << USBD_EPINTSTS_SHORTRXIF_Pos) //端点收到的批量输出短数据包(包括零长度数据包)
//USBD_EPxRSPCTL 端点控制
#define USBD_EPRSPCTL_FLUSH_Pos (0)
#define USBD_EPRSPCTL_FLUSH_Msk (0x1ul << USBD_EPRSPCTL_FLUSH_Pos) //端点清除数据缓冲区
#define USBD_EPRSPCTL_MODE_Pos (1)
#define USBD_EPRSPCTL_MODE_Msk (0x3ul << USBD_EPRSPCTL_MODE_Pos) //端点模式控制
#define USBD_EPRSPCTL_TOGGLE_Pos (3)
#define USBD_EPRSPCTL_TOGGLE_Msk (0x1ul << USBD_EPRSPCTL_TOGGLE_Pos) //端点切换,清除端点数据触发位
#define USBD_EPRSPCTL_HALT_Pos (4)
#define USBD_EPRSPCTL_HALT_Msk (0x1ul << USBD_EPRSPCTL_HALT_Pos) //端点停止,发送一个STALL握手作为对主机令牌的响应
#define USBD_EPRSPCTL_ZEROLEN_Pos (5)
#define USBD_EPRSPCTL_ZEROLEN_Msk (0x1ul << USBD_EPRSPCTL_ZEROLEN_Pos) //端点收到IN令牌后,会将零数据包发送到主机
#define USBD_EPRSPCTL_SHORTTXEN_Pos (6)
#define USBD_EPRSPCTL_SHORTTXEN_Msk (0x1ul << USBD_EPRSPCTL_SHORTTXEN_Pos) //端点短数据包传输使能,验证缓冲区中的任何剩余数据
#define USBD_EPRSPCTL_DISBUF_Pos (7)
#define USBD_EPRSPCTL_DISBUF_Msk (0x1ul << USBD_EPRSPCTL_DISBUF_Pos) //端点缓冲区禁用控制,当接收到Bulk-OUT短数据包时,禁用缓冲器
//USBD_EPxCFG 端点配置
#define USBD_EPCFG_EPEN_Pos (0)
#define USBD_EPCFG_EPEN_Msk (0x1ul << USBD_EPCFG_EPEN_Pos) //端点已经启用
#define USBD_EPCFG_EPTYPE_Pos (1)
#define USBD_EPCFG_EPTYPE_Msk (0x3ul << USBD_EPCFG_EPTYPE_Pos) //端点类型
#define USBD_EPCFG_EPDIR_Pos (3)
#define USBD_EPCFG_EPDIR_Msk (0x1ul << USBD_EPCFG_EPDIR_Pos) //端点方向
#define USBD_EPCFG_EPNUM_Pos (4)
#define USBD_EPCFG_EPNUM_Msk (0xful << USBD_EPCFG_EPNUM_Pos) //端点编号,不支持两个端点具有相同的端点号
//USBD_PHYCTL USB PHY控制
#define USBD_PHYCTL_DPPUEN_Pos (8)
#define USBD_PHYCTL_DPPUEN_Msk (0x1ul << USBD_PHYCTL_DPPUEN_Pos) //使能D +上拉电阻
#define USBD_PHYCTL_PHYEN_Pos (9)
#define USBD_PHYCTL_PHYEN_Msk (0x1ul << USBD_PHYCTL_PHYEN_Pos) //USB PHY未挂起
#define USBD_PHYCTL_WKEN_Pos (24)
#define USBD_PHYCTL_WKEN_Msk (0x1ul << USBD_PHYCTL_WKEN_Pos) //唤醒功能已启用
#define USBD_PHYCTL_VBUSDET_Pos (31)
#define USBD_PHYCTL_VBUSDET_Msk (0x1ul << USBD_PHYCTL_VBUSDET_Pos) //检测到VBUS
//相关操作
#define USBD_ENABLE_USB() ((u32)(USBD->PHYCTL |= (USBD_PHYCTL_PHYEN_Msk|USBD_PHYCTL_DPPUEN_Msk))) //使能 USB
#define USBD_DISABLE_USB() ((u32)(USBD->PHYCTL &= ~USBD_PHYCTL_DPPUEN_Msk)) //禁用 USB
#define USBD_ENABLE_PHY() ((u32)(USBD->PHYCTL |= USBD_PHYCTL_PHYEN_Msk)) //使能硬件 PHY
#define USBD_DISABLE_PHY() ((u32)(USBD->PHYCTL &= ~USBD_PHYCTL_PHYEN_Msk)) //禁用硬件 PHY
#define USBD_SET_OPER(x) (USBD->OPER = (x)) //设置OPER操作命令
#define USBD_SET_SE0() ((u32)(USBD->PHYCTL &= ~USBD_PHYCTL_DPPUEN_Msk)) //Enable SE0, 强制USB PHY收发器驱动SE0
#define USBD_CLR_SE0() ((u32)(USBD->PHYCTL |= USBD_PHYCTL_DPPUEN_Msk)) //Disable SE0
#define USBD_SET_ADDR(addr) (USBD->FADDR = (addr)) //设置USB功能地址
#define USBD_GET_ADDR() ((u32)(USBD->FADDR)) //获取USB功能地址
#define USBD_ENABLE_USB_INT(intr) (USBD->GINTEN = (intr)) //设置USB相关中断
#define USBD_ENABLE_BUS_INT(intr) (USBD->BUSINTEN = (intr)) //设置USB总线中断
#define USBD_GET_BUS_INT_FLAG() (USBD->BUSINTSTS) //获取总线中断状态
#define USBD_CLR_BUS_INT_FLAG(flag) (USBD->BUSINTSTS = flag) //清除总线中断状态
#define USBD_ENABLE_CEP_INT(intr) (USBD->CEPINTEN = (intr)) //设置控制端点中断
#define USBD_SET_CEP_INT_BIT(intr) (USBD->CEPINTEN |= (intr)) //设置控制端点中断-只增加
#define USBD_CLEAR_CEP_INT_BIT(intr) (USBD->CEPINTEN &= ~(intr)) //清除控制端点中断-只减少
#define USBD_CLR_CEP_INT_FLAG(flag) (USBD->CEPINTSTS = flag) //清除控制端点中断状态
#define USBD_SET_CEP_STATE(flag) (USBD->CEPCTL = flag) //设置控制端点控制寄存器
#define USBD_START_CEP_IN(size) (USBD->CEPTXCNT = size) //设置控制端点传输数据长度
#define USBD_ENABLE_EP_INT(ep, intr) (USBD->EPx[ep].INTEN = (intr)) //设置端点x的中断
#define USBD_SET_EP_INT_BIT(ep, intr) (USBD->EPx[ep].INTEN |= (intr)) //设置端点x的中断-只增加
#define USBD_CLEAR_EP_INT_BIT(ep, intr) (USBD->EPx[ep].INTEN &= ~(intr)) //清除端点x的中断-只减少
#define USBD_GET_EP_INT_FLAG(ep) (USBD->EPx[ep].INTSTS) //获取端点x的中断状态
#define USBD_CLR_EP_INT_FLAG(ep, flag) (USBD->EPx[ep].INTSTS = (flag)) //清除端点x的中断状态
#define USBD_SET_DMA_LEN(len) (USBD->DMACNT = len) //设置DMA传输长度
#define USBD_SET_DMA_ADDR(addr) (USBD->DMAADDR = addr) //设置DMA传输的地址
#define USBD_SET_DMA_READ(epnum) (USBD->DMACTL = (USBD->DMACTL & ~USBD_DMACTL_EPNUM_Msk) | USBD_DMACTL_DMARD_Msk | epnum) //设置DMA为读取方向
#define USBD_SET_DMA_WRITE(epnum) (USBD->DMACTL = (USBD->DMACTL & ~(USBD_DMACTL_EPNUM_Msk | USBD_DMACTL_DMARD_Msk)) | epnum) //设置DMA为写入方向
#define USBD_ENABLE_DMA() (USBD->DMACTL |= USBD_DMACTL_DMAEN_Msk) //使能DMA传输
#define USBD_IS_ATTACHED() ((u32)(USBD->PHYCTL & USBD_PHYCTL_VBUSDET_Msk)) //检查USB连接状态
#define USBD_WriteEPx_DataByte(ep, data) (*((vu8*)(&(USBD->EPx[ep].DAT))) = (data)) //写入BYTE数据到端点x数据发送寄存器
#define USBD_ReadEPx_DataByte(ep) (*((vu8*)(&(USBD->EPx[ep].DAT)))) //从端点x数据接收寄存器读取BYTE数据
#define Maximum(a,b) (a)>(b) ? (a) : (b)
#define Minimum(a,b) (a)<(b) ? (a) : (b)
//USBD需要使用到的内存拷贝
__inline void USBD_MemCopy(uint8_t *u8Dst, uint8_t *u8Src, int32_t i32Size)
{
while (i32Size--) *u8Dst++ = *u8Src++;
}
//获取指定EP的最大数据包大小
__inline u16 USBD_GetEpMaxPacketSize(USBD_EPx EPx)
{
if(EPx > USBD_EPL) return 0;
return USBD->EPx[EPx].MPS & 0x7FF;
}
//获取指定EP的缓冲区数据大小
__inline u16 USBD_GetEpDataCount(USBD_EPx EPx)
{
if(EPx > USBD_EPL) return 0;
return USBD->EPx[EPx].DATCNT & 0xffff;
}
//EP配置
typedef struct
{
u32 InitId; //端点是否初始化了-不要在外部修改
USBD_EPx EPx; //EP端点-不要在外部修改
u32 EnableIntBit; //使能的中断
u8 EpNum; //EP端点编号-不要在外部修改
u16 EpBuffOffset; //EP端点缓冲区位置(USBD缓冲区)
u16 EpBuffSzie; //EP端点缓冲区大小(USBD缓冲区)
u16 EpUSB20_MaxPackSize; //USB2.0对应的最大数据包大小
u16 EpMaxPackSzie; //EP端点最大数据包大小-实际数据包大小,如果是USB1.1则固定为64字节,否则等于EpUSB20_MaxPackSize
USBD_EP_TYPE EpType; //EP端点类型
USBD_EP_DIR EpDir; //EP端点方向
USBD_EPxIRQHandlerType EpIRQHandlerCallBack;//EP端点中断回调函数
}USBD_EP_CONFIG;
//初始化USBD
void USBD_Init(void);
void USBD_InterfaceConfig(USBD_IRQHandlerType pBusIRQCallBack, USBD_IRQHandlerType pCEpIRQCallBack, USBD_CLASS_REQ pClassReqCallBack,
USBD_VENDOR_REQ pVendorReqCallBack, const USBD_DESCRIPTOR *pDescData);//USBD所需接口配置
void USBD_Start(void); //USBD启动
bool USBD_GetIdleEp(USBD_EPx *pEPx); //获取一个空闲的EP通道
void USBD_ResetDMA(void); //复位DMA
USBD_EP_CONFIG *USBD_GetEpConfigPointer(USBD_EPx EPx); //获取一个端点的配置指针,可以对端点进行配置
void USBD_SetEpConfigData(USBD_EPx EPx,USBD_EP_TYPE EpType, USBD_EP_DIR EpDir, u32 EnableIntBit, u16 EpBuffOffset, u16 EpBuffSzie, u16 EpMaxPackSzie,
USBD_EPxIRQHandlerType pCallBack);//设置一数据个端点的配置数据
void USBD_PrepareCtrlIn(u8 *pDataBuff, u8 DataLen); //控制端点准备响应控制命令(将数据写入缓冲区,准备等待控制端口IN令牌到来后发送到主机)
bool USBD_CtrlIn(void); //控制端点发送数据给主机(必须在控制端点IN令牌有效时调用)
bool USBD_BulkOut(USBD_EPx EPx, u8 *pDataBuff, u32 Len); //接收来自Bulk OUT的数据
bool USBD_BulkIn(USBD_EPx EPx, u8 *pDataBuff, u32 Len); //写入数据到Bulk IN
bool USBD_ReadBulkOutPackData(USBD_EPx EPx, u8 *pData, u16 EpBuffSize);//读取一整包来自OUT的数据(需要等待缓冲区满)
u16 USBD_GetEpBuffSize(USBD_EPx EPx); //获取端点缓冲区大小(从硬件配置中获取)
void USBD_SetEpBuffAddr(USBD_EPx EPx, u32 u32Base, u32 u32Len); //设置端点缓冲区地址
void USBD_EpConfig(USBD_EPx EPx, u8 EpNum, USBD_EP_TYPE EpType, USBD_EP_DIR EpDir); //端点配置
void USBD_SetEpStall(USBD_EPx EPx); //将USB端点停止状态设置为指定的端点ID。 端点将自动响应STALL令牌
void USBD_ClearEpStall(USBD_EPx EPx); //清除USB端点停止状态
u32 USBD_GetEpStall(USBD_EPx EPx); //获取指定端点ID的USB端点停顿状态
void USBD_SwReset(void); //软复位
u16 USBD_ReadEPxOutData(USBD_EPx EPx, u8 *pData); //从EPx的OUT缓冲区中读取数据
void USBD_ClearStall(u8 EpNum); //清除指定编号端点的停止状态,端点将返回ACK / NAK令牌
u32 USBD_GetStall(u8 EpNum); //获取指定端点号的停止状态
#endif //_USB_D_
|