| //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_
 
 
 
 |