ソースを参照

Merge branch 'feature/usb_host_ll' into 'master'

USB Host struct, LL Layer, and types

See merge request espressif/esp-idf!11669
Ivan Grokhotkov 5 年 前
コミット
fb7fbdb299

+ 1 - 0
components/esp32s2/ld/esp32s2.peripherals.ld

@@ -28,4 +28,5 @@ PROVIDE ( TWAI = 0x3f42B000 );
 PROVIDE ( APB_SARADC = 0x3f440000 );
 PROVIDE ( DEDIC_GPIO = 0x3f4cf000 );
 PROVIDE ( USB0     = 0x60080000 );
+PROVIDE ( USBH     = 0x60080000 );
 PROVIDE ( USB_WRAP = 0x3f439000 );

+ 886 - 0
components/hal/esp32s2/include/hal/usbh_ll.h

@@ -0,0 +1,886 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "soc/usbh_struct.h"
+#include "soc/usb_wrap_struct.h"
+#include "hal/usb_types.h"
+
+/* -----------------------------------------------------------------------------
+------------------------------- Global Registers -------------------------------
+----------------------------------------------------------------------------- */
+
+/*
+ * Interrupt bit masks of the GINTSTS and GINTMSK registers
+ */
+#define USB_LL_INTR_CORE_WKUPINT        (1 << 31)
+#define USB_LL_INTR_CORE_SESSREQINT     (1 << 30)
+#define USB_LL_INTR_CORE_DISCONNINT     (1 << 29)
+#define USB_LL_INTR_CORE_CONIDSTSCHNG   (1 << 28)
+#define USB_LL_INTR_CORE_PTXFEMP        (1 << 26)
+#define USB_LL_INTR_CORE_HCHINT         (1 << 25)
+#define USB_LL_INTR_CORE_PRTINT         (1 << 24)
+#define USB_LL_INTR_CORE_RESETDET       (1 << 23)
+#define USB_LL_INTR_CORE_FETSUSP        (1 << 22)
+#define USB_LL_INTR_CORE_INCOMPIP       (1 << 21)
+#define USB_LL_INTR_CORE_INCOMPISOIN    (1 << 20)
+#define USB_LL_INTR_CORE_OEPINT         (1 << 19)
+#define USB_LL_INTR_CORE_IEPINT         (1 << 18)
+#define USB_LL_INTR_CORE_EPMIS          (1 << 17)
+#define USB_LL_INTR_CORE_EOPF           (1 << 15)
+#define USB_LL_INTR_CORE_ISOOUTDROP     (1 << 14)
+#define USB_LL_INTR_CORE_ENUMDONE       (1 << 13)
+#define USB_LL_INTR_CORE_USBRST         (1 << 12)
+#define USB_LL_INTR_CORE_USBSUSP        (1 << 11)
+#define USB_LL_INTR_CORE_ERLYSUSP       (1 << 10)
+#define USB_LL_INTR_CORE_GOUTNAKEFF     (1 << 7)
+#define USB_LL_INTR_CORE_GINNAKEFF      (1 << 6)
+#define USB_LL_INTR_CORE_NPTXFEMP       (1 << 5)
+#define USB_LL_INTR_CORE_RXFLVL         (1 << 4)
+#define USB_LL_INTR_CORE_SOF            (1 << 3)
+#define USB_LL_INTR_CORE_OTGINT         (1 << 2)
+#define USB_LL_INTR_CORE_MODEMIS        (1 << 1)
+#define USB_LL_INTR_CORE_CURMOD         (1 << 0)
+
+/*
+ * Bit mask of interrupt generating bits of the the HPRT register. These bits
+ * are ORd into the USB_LL_INTR_CORE_PRTINT interrupt.
+ *
+ * Note: Some fields of the HPRT are W1C (write 1 clear), this we cannot do a
+ * simple read and write-back to clear the HPRT interrupt bits. Instead we need
+ * a W1C mask the non-interrupt related bits
+ */
+#define USBH_LL_HPRT_W1C_MSK                (0x2E)
+#define USBH_LL_HPRT_ENA_MSK                (0x04)
+#define USBH_LL_INTR_HPRT_PRTOVRCURRCHNG    (1 << 5)
+#define USBH_LL_INTR_HPRT_PRTENCHNG         (1 << 3)
+#define USBH_LL_INTR_HPRT_PRTCONNDET        (1 << 1)
+
+/*
+ * Bit mask of channel interrupts (HCINTi and HCINTMSKi registers)
+ *
+ * Note: Under Scatter/Gather DMA mode, only the following interrupts can be unmasked
+ * - DESC_LS_ROLL
+ * - XCS_XACT_ERR (always unmasked)
+ * - BNAINTR
+ * - CHHLTD
+ * - XFERCOMPL
+ * The remaining interrupt bits will still be set (when the corresponding event occurs)
+ * but will not generate an interrupt. Therefore we must proxy through the
+ * USBH_LL_INTR_CHAN_CHHLTD interrupt to check the other interrupt bits.
+ */
+#define USBH_LL_INTR_CHAN_DESC_LS_ROLL      (1 << 13)
+#define USBH_LL_INTR_CHAN_XCS_XACT_ERR      (1 << 12)
+#define USBH_LL_INTR_CHAN_BNAINTR           (1 << 11)
+#define USBH_LL_INTR_CHAN_DATATGLERR        (1 << 10)
+#define USBH_LL_INTR_CHAN_FRMOVRUN          (1 << 9)
+#define USBH_LL_INTR_CHAN_BBLEER            (1 << 8)
+#define USBH_LL_INTR_CHAN_XACTERR           (1 << 7)
+#define USBH_LL_INTR_CHAN_NYET              (1 << 6)
+#define USBH_LL_INTR_CHAN_ACK               (1 << 5)
+#define USBH_LL_INTR_CHAN_NAK               (1 << 4)
+#define USBH_LL_INTR_CHAN_STALL             (1 << 3)
+#define USBH_LL_INTR_CHAN_AHBERR            (1 << 2)
+#define USBH_LL_INTR_CHAN_CHHLTD            (1 << 1)
+#define USBH_LL_INTR_CHAN_XFERCOMPL         (1 << 0)
+
+/*
+ * QTD (Queue Transfer Descriptor) structure used in Scatter/Gather DMA mode.
+ * Each QTD describes one transfer. Scatter gather mode will automatically split
+ * a transfer into multiple MPS packets. Each QTD is 64bits in size
+ *
+ * Note: The status information part of the QTD is interpreted differently depending
+ * on IN or OUT, and ISO or non-ISO
+ */
+typedef struct {
+    union {
+        struct {
+            uint32_t xfer_size: 17;
+            uint32_t aqtd_offset: 6;
+            uint32_t aqtd_valid: 1;
+            uint32_t reserved_24: 1;
+            uint32_t intr_cplt: 1;
+            uint32_t eol: 1;
+            uint32_t reserved_27: 1;
+            uint32_t rx_status: 2;
+            uint32_t reserved_30: 1;
+            uint32_t active: 1;
+        } in_non_iso;
+        struct {
+            uint32_t xfer_size: 12;
+            uint32_t reserved_12_24: 13;
+            uint32_t intr_cplt: 1;
+            uint32_t reserved_26_27: 2;
+            uint32_t rx_status: 2;
+            uint32_t reserved_30: 1;
+            uint32_t active: 1;
+        } in_iso;
+        struct {
+            uint32_t xfer_size: 17;
+            uint32_t reserved_17_23: 7;
+            uint32_t is_setup: 1;
+            uint32_t intr_cplt: 1;
+            uint32_t eol: 1;
+            uint32_t reserved_27: 1;
+            uint32_t tx_status: 2;
+            uint32_t reserved_30: 1;
+            uint32_t active: 1;
+        } out_non_iso;
+        struct {
+            uint32_t xfer_size: 12;
+            uint32_t reserved_12_24: 13;
+            uint32_t intr_cplt: 1;
+            uint32_t eol: 1;
+            uint32_t reserved_27: 1;
+            uint32_t tx_status: 2;
+            uint32_t reserved_30: 1;
+            uint32_t active: 1;
+        } out_iso;
+        uint32_t buffer_status_val;
+    };
+    void *buffer;
+} usbh_ll_dma_qtd_t;
+
+/*
+ * Enumeration of different possible lengths of the periodic frame list
+ */
+typedef enum {
+    USBH_LL_FRAME_LIST_LEN_8 = 0,
+    USBH_LL_FRAME_LIST_LEN_16,
+    USBH_LL_FRAME_LIST_LEN_32,
+    USBH_LL_FRAME_LIST_LEN_64,
+} usbh_ll_frame_list_len_t;
+
+/* -----------------------------------------------------------------------------
+------------------------------ USB Wrap Registers ------------------------------
+----------------------------------------------------------------------------- */
+
+/**
+ * @brief Configures the internal PHY to operate as HOST
+ *
+ * @param hw Start address of the USB Wrap registers
+ */
+static inline void usbh_ll_internal_phy_conf(usb_wrap_dev_t *hw)
+{
+    //Enable internal PHY
+    hw->otg_conf.pad_enable = 1;
+    hw->otg_conf.phy_sel = 0;
+    //Set pulldowns on D+ and D-
+    hw->otg_conf.pad_pull_override = 1;
+    hw->otg_conf.dp_pulldown = 1;
+    hw->otg_conf.dm_pulldown = 1;
+}
+
+/* -----------------------------------------------------------------------------
+------------------------------- Global Registers -------------------------------
+----------------------------------------------------------------------------- */
+
+// --------------------------- GAHBCFG Register --------------------------------
+
+static inline void usb_ll_en_dma_mode(usbh_dev_t *hw)
+{
+    hw->gahbcfg_reg.dmaen = 1;
+}
+
+static inline void usb_ll_en_slave_mode(usbh_dev_t *hw)
+{
+    hw->gahbcfg_reg.dmaen = 0;
+}
+
+static inline void usb_ll_set_hbstlen(usbh_dev_t *hw, uint32_t burst_len)
+{
+    hw->gahbcfg_reg.hbstlen = burst_len;
+}
+
+static inline void usb_ll_en_global_intr(usbh_dev_t *hw)
+{
+    hw->gahbcfg_reg.glbllntrmsk = 1;
+}
+
+static inline void usb_ll_dis_global_intr(usbh_dev_t *hw)
+{
+    hw->gahbcfg_reg.glbllntrmsk = 0;
+}
+
+// --------------------------- GUSBCFG Register --------------------------------
+
+static inline void usb_ll_set_host_mode(usbh_dev_t *hw)
+{
+    hw->gusbcfg_reg.forcehstmode = 1;
+}
+
+static inline void usb_ll_dis_hnp_cap(usbh_dev_t *hw)
+{
+    hw->gusbcfg_reg.hnpcap = 0;
+}
+
+static inline void usb_ll_dis_srp_cap(usbh_dev_t *hw)
+{
+    hw->gusbcfg_reg.srpcap = 0;
+}
+
+// --------------------------- GRSTCTL Register --------------------------------
+
+static inline bool usb_ll_check_ahb_idle(usbh_dev_t *hw)
+{
+    return hw->grstctl_reg.ahbidle;
+}
+
+static inline bool usb_ll_check_dma_req_in_progress(usbh_dev_t *hw)
+{
+    return hw->grstctl_reg.dmareq;
+}
+
+static inline void usb_ll_flush_tx_fifo(usbh_dev_t *hw, uint32_t chan_num)
+{
+    usb_grstctl_reg_t grstctl;
+    grstctl.val = hw->grstctl_reg.val;
+    grstctl.txfnum = chan_num;      //Set channel number to flush
+    grstctl.txfflsh = 1;            //Flush that channel's TX FIFO
+    hw->grstctl_reg.val = grstctl.val;
+}
+
+static inline void usb_ll_flush_rx_fifo(usbh_dev_t *hw)
+{
+    hw->grstctl_reg.rxfflsh = 1;
+}
+
+static inline void usb_ll_reset_frame_counter(usbh_dev_t *hw)
+{
+    hw->grstctl_reg.frmcntrrst = 1;
+}
+
+// --------------------------- GINTSTS Register --------------------------------
+
+/**
+ * @brief Reads and clears the global interrupt register
+ *
+ * @param hw
+ * @return uint32_t
+ */
+static inline uint32_t usb_ll_intr_read_and_clear(usbh_dev_t *hw)
+{
+    usb_gintsts_reg_t gintsts;
+    gintsts.val = hw->gintsts_reg.val;
+    hw->gintsts_reg.val = gintsts.val;  //Write back to clear
+    return gintsts.val;
+}
+
+// --------------------------- GINTMSK Register --------------------------------
+
+static inline void usb_ll_en_intrs(usbh_dev_t *hw, uint32_t intr_mask)
+{
+    hw->gintmsk_reg.val |= intr_mask;
+}
+
+static inline void usb_ll_dis_intrs(usbh_dev_t *hw, uint32_t intr_mask)
+{
+    hw->gintmsk_reg.val &= ~intr_mask;
+}
+
+// --------------------------- GRXFSIZ Register --------------------------------
+
+static inline void usb_ll_set_rx_fifo_size(usbh_dev_t *hw, uint32_t size)
+{
+    //Set size in words
+    hw->grxfsiz_reg.rxfdep = size;
+}
+
+// -------------------------- GNPTXFSIZ Register -------------------------------
+
+static inline void usb_ll_set_nptx_fifo_size(usbh_dev_t *hw, uint32_t addr, uint32_t size)
+{
+    usb_gnptxfsiz_reg_t gnptxfsiz;
+    gnptxfsiz.val = hw->gnptxfsiz_reg.val;
+    gnptxfsiz.nptxfstaddr = addr;
+    gnptxfsiz.nptxfdep = size;
+    hw->gnptxfsiz_reg.val = gnptxfsiz.val;
+}
+
+static inline uint32_t usb_ll_get_controller_core_id(usbh_dev_t *hw)
+{
+    return hw->gsnpsid_reg.val;
+}
+
+/**
+ * @brief Get the hardware configuration regiters of the DWC_OTG controller
+ *
+ * The hardware configuraiton regitsers are read only and indicate the various
+ * features of the DWC_OTG core.
+ *
+ * @param hw Start address of the DWC_OTG registers
+ * @param[out] ghwcfg1 Hardware configuration registesr 1
+ * @param[out] ghwcfg2 Hardware configuration registesr 2
+ * @param[out] ghwcfg3 Hardware configuration registesr 3
+ * @param[out] ghwcfg4 Hardware configuration registesr 4
+ */
+static inline void usb_ll_get_hardware_config(usbh_dev_t *hw, uint32_t *ghwcfg1, uint32_t *ghwcfg2, uint32_t *ghwcfg3, uint32_t *ghwcfg4)
+{
+    *ghwcfg1 = hw->ghwcfg1_reg.val;
+    *ghwcfg2 = hw->ghwcfg2_reg.val;
+    *ghwcfg3 = hw->ghwcfg3_reg.val;
+    *ghwcfg4 = hw->ghwcfg4_reg.val;
+}
+
+// --------------------------- HPTXFSIZ Register -------------------------------
+
+static inline void usbh_ll_set_ptx_fifo_size(usbh_dev_t *hw, uint32_t addr, uint32_t size)
+{
+    usb_hptxfsiz_reg_t hptxfsiz;
+    hptxfsiz.val = hw->hptxfsiz_reg.val;
+    hptxfsiz.ptxfstaddr = addr;
+    hptxfsiz.ptxfsize = size;
+    hw->hptxfsiz_reg.val = hptxfsiz.val;
+}
+
+/* -----------------------------------------------------------------------------
+-------------------------------- Host Registers --------------------------------
+----------------------------------------------------------------------------- */
+
+// ----------------------------- HCFG Register ---------------------------------
+
+static inline void usbh_ll_hcfg_en_perio_sched(usbh_dev_t *hw)
+{
+    hw->hcfg_reg.perschedena = 1;
+}
+
+static inline void usbh_ll_hcfg_dis_perio_sched(usbh_dev_t *hw)
+{
+    hw->hcfg_reg.perschedena = 0;
+}
+
+/**
+ * Sets the length of the frame list
+ *
+ * @param num_entires Number of entires in the frame list
+ */
+static inline void usbh_ll_hcfg_set_num_frame_list_entries(usbh_dev_t *hw, usbh_ll_frame_list_len_t num_entries)
+{
+    hw->hcfg_reg.frlisten = num_entries;
+}
+
+static inline void usbh_ll_hcfg_en_scatt_gatt_dma(usbh_dev_t *hw)
+{
+    hw->hcfg_reg.descdma = 1;
+}
+
+static inline void usbh_ll_hcfg_set_fsls_supp_only(usbh_dev_t *hw)
+{
+    hw->hcfg_reg.fslssupp = 1;
+}
+
+static inline void usbh_ll_hcfg_set_fsls_pclk_sel(usbh_dev_t *hw)
+{
+    hw->hcfg_reg.fslspclksel = 1;
+}
+
+/**
+ * @brief Sets some default values to HCFG to operate in Host mode wiht scatter/gather DMA
+ *
+ * @param hw
+ */
+static inline void usbh_ll_hcfg_set_defaults(usbh_dev_t *hw)
+{
+    hw->hcfg_reg.descdma = 1;   //Enable scatt/gatt
+    hw->hcfg_reg.fslssupp = 1;  //FS/LS supp only
+    hw->hcfg_reg.fslspclksel = 1;   //48MHz PHY clock
+    hw->hcfg_reg.perschedena = 0;   //Disable perio sched
+}
+
+// ----------------------------- HFIR Register ---------------------------------
+
+static inline void usbh_ll_hfir_set_defaults(usbh_dev_t *hw)
+{
+    usb_hfir_reg_t hfir;
+    hfir.val = hw->hfir_reg.val;
+    hfir.hfirrldctrl = 0;       //Disable dynamic loading
+    hfir.frint = 48000;         //Set frame interval to 48000 cycles of 48KHz clock (1ms)
+    hw->hfir_reg.val = hfir.val;
+}
+
+// ----------------------------- HFNUM Register --------------------------------
+
+static inline uint32_t usbh_ll_get_frm_time_rem(usbh_dev_t *hw)
+{
+    return hw->hfnum_reg.frrem;
+}
+
+static inline uint32_t usbh_ll_get_frm_num(usbh_dev_t *hw)
+{
+    return hw->hfnum_reg.frnum;
+}
+
+// ---------------------------- HPTXSTS Register -------------------------------
+
+static inline uint32_t usbh_ll_get_p_tx_queue_top(usbh_dev_t *hw)
+{
+    return hw->hptxsts_reg.ptxqtop;
+}
+
+static inline uint32_t usbh_ll_get_p_tx_queue_space_avail(usbh_dev_t *hw)
+{
+    return hw->hptxsts_reg.ptxqspcavail;
+}
+
+static inline uint32_t usbh_ll_get_p_tx_fifo_space_avail(usbh_dev_t *hw)
+{
+    return hw->hptxsts_reg.ptxfspcavail;
+}
+
+// ----------------------------- HAINT Register --------------------------------
+
+static inline uint32_t usbh_ll_get_chan_intrs_msk(usbh_dev_t *hw)
+{
+    return hw->haint_reg.haint;
+}
+
+// --------------------------- HAINTMSK Register -------------------------------
+
+static inline void usbh_ll_haintmsk_en_chan_intr(usbh_dev_t *hw, uint32_t mask)
+{
+    hw->haintmsk_reg.val |= mask;
+}
+
+static inline void usbh_ll_haintmsk_dis_chan_intr(usbh_dev_t *hw, uint32_t mask)
+{
+    hw->haintmsk_reg.val &= ~mask;
+}
+
+// --------------------------- HFLBAddr Register -------------------------------
+
+static inline void usbh_ll_set_frame_list_base_addr(usbh_dev_t *hw, uint32_t addr)
+{
+    hw->hflbaddr_reg.hflbaddr = addr;
+}
+
+static inline uint32_t usbh_ll_get_frame_list_base_addr(usbh_dev_t *hw)
+{
+    return hw->hflbaddr_reg.hflbaddr;
+}
+
+// ----------------------------- HPRT Register ---------------------------------
+
+static inline usb_speed_t usbh_ll_hprt_get_speed(usbh_dev_t *hw)
+{
+    int prtspd = hw->hprt_reg.prtspd;
+    if (prtspd == 1) {
+        return USB_SPEED_FULL;
+    } else {
+        return USB_SPEED_LOW;
+    }
+}
+
+static inline uint32_t usbh_ll_hprt_get_test_ctl(usbh_dev_t *hw)
+{
+    return hw->hprt_reg.prttstctl;
+}
+static inline void usbh_ll_hprt_set_test_ctl(usbh_dev_t *hw, uint32_t test_mode)
+{
+    usb_hprt_reg_t hprt;
+    hprt.val = hw->hprt_reg.val;
+    hprt.prttstctl = test_mode;
+    hw->hprt_reg.val = hprt.val & (~USBH_LL_HPRT_W1C_MSK);
+}
+
+static inline void usbh_ll_hprt_en_pwr(usbh_dev_t *hw)
+{
+    usb_hprt_reg_t hprt;
+    hprt.val = hw->hprt_reg.val;
+    hprt.prtpwr = 1;
+    hw->hprt_reg.val = hprt.val & (~USBH_LL_HPRT_W1C_MSK);
+}
+
+static inline void usbh_ll_hprt_dis_pwr(usbh_dev_t *hw)
+{
+    usb_hprt_reg_t hprt;
+    hprt.val = hw->hprt_reg.val;
+    hprt.prtpwr = 0;
+    hw->hprt_reg.val = hprt.val & (~USBH_LL_HPRT_W1C_MSK);
+}
+
+static inline uint32_t usbh_ll_hprt_get_pwr_line_status(usbh_dev_t *hw)
+{
+    return hw->hprt_reg.prtlnsts;
+}
+
+static inline void usbh_ll_hprt_set_port_reset(usbh_dev_t *hw, bool reset)
+{
+    usb_hprt_reg_t hprt;
+    hprt.val = hw->hprt_reg.val;
+    hprt.prtrst = reset;
+    hw->hprt_reg.val = hprt.val & (~USBH_LL_HPRT_W1C_MSK);
+}
+
+static inline bool usbh_ll_hprt_get_port_reset(usbh_dev_t *hw)
+{
+    return hw->hprt_reg.prtrst;
+}
+
+static inline void usbh_ll_hprt_set_port_suspend(usbh_dev_t *hw)
+{
+    usb_hprt_reg_t hprt;
+    hprt.val = hw->hprt_reg.val;
+    hprt.prtsusp = 1;
+    hw->hprt_reg.val = hprt.val & (~USBH_LL_HPRT_W1C_MSK);
+}
+
+static inline bool usbh_ll_hprt_get_port_suspend(usbh_dev_t *hw)
+{
+    return hw->hprt_reg.prtsusp;
+}
+
+static inline void usbh_ll_hprt_set_port_resume(usbh_dev_t *hw)
+{
+    usb_hprt_reg_t hprt;
+    hprt.val = hw->hprt_reg.val;
+    hprt.prtres = 1;
+    hw->hprt_reg.val = hprt.val & (~USBH_LL_HPRT_W1C_MSK);
+}
+
+static inline void usbh_ll_hprt_clr_port_resume(usbh_dev_t *hw)
+{
+    usb_hprt_reg_t hprt;
+    hprt.val = hw->hprt_reg.val;
+    hprt.prtres = 0;
+    hw->hprt_reg.val = hprt.val & (~USBH_LL_HPRT_W1C_MSK);
+}
+
+static inline bool usbh_ll_hprt_get_port_resume(usbh_dev_t *hw)
+{
+    return hw->hprt_reg.prtres;
+}
+static inline bool usbh_ll_hprt_get_port_overcur(usbh_dev_t *hw)
+{
+    return hw->hprt_reg.prtovrcurract;
+}
+
+static inline bool usbh_ll_hprt_get_port_en(usbh_dev_t *hw)
+{
+    return hw->hprt_reg.prtena;
+}
+
+static inline void usbh_ll_hprt_port_dis(usbh_dev_t *hw)
+{
+    usb_hprt_reg_t hprt;
+    hprt.val = hw->hprt_reg.val;
+    hprt.prtena = 1;        //W1C to disable
+    //we want to W1C ENA but not W1C the interrupt bits
+    hw->hprt_reg.val = hprt.val & ((~USBH_LL_HPRT_W1C_MSK) | USBH_LL_HPRT_ENA_MSK);
+}
+
+static inline bool usbh_ll_hprt_get_conn_status(usbh_dev_t *hw)
+{
+    return hw->hprt_reg.prtconnsts;
+}
+
+static inline uint32_t usbh_ll_hprt_intr_read_and_clear(usbh_dev_t *hw)
+{
+    usb_hprt_reg_t hprt;
+    hprt.val = hw->hprt_reg.val;
+    //We want to W1C the interrupt bits but not that ENA
+    hw->hprt_reg.val = hprt.val & (~USBH_LL_HPRT_ENA_MSK);
+    //Return only the interrupt bits
+    return (hprt.val & (USBH_LL_HPRT_W1C_MSK & ~(USBH_LL_HPRT_ENA_MSK)));
+}
+
+//Per Channel registers
+
+// --------------------------- HCCHARi Register --------------------------------
+
+static inline void usbh_ll_chan_start(volatile usb_host_chan_regs_t *chan)
+{
+    chan->hcchar_reg.chena = 1;
+}
+
+static inline bool usbh_ll_chan_is_active(volatile usb_host_chan_regs_t *chan)
+{
+    return chan->hcchar_reg.chena;
+}
+
+static inline void usbh_ll_chan_halt(volatile usb_host_chan_regs_t *chan)
+{
+    chan->hcchar_reg.chdis = 1;
+}
+
+static inline void usbh_ll_chan_xfer_odd_frame(volatile usb_host_chan_regs_t *chan)
+{
+    chan->hcchar_reg.oddfrm = 1;
+}
+
+static inline void usbh_ll_chan_xfer_even_frame(volatile usb_host_chan_regs_t *chan)
+{
+    chan->hcchar_reg.oddfrm = 0;
+}
+
+static inline void usbh_ll_chan_set_dev_addr(volatile usb_host_chan_regs_t *chan, uint32_t addr)
+{
+    chan->hcchar_reg.devaddr = addr;
+}
+
+static inline void usbh_ll_chan_set_ep_type(volatile usb_host_chan_regs_t *chan, usb_xfer_type_t type)
+{
+    switch (type) {
+        case USB_XFER_TYPE_CTRL:
+            chan->hcchar_reg.eptype = 0x0;
+            break;
+        case USB_XFER_TYPE_ISOCHRONOUS:
+            chan->hcchar_reg.eptype = 0x1;
+            break;
+        case USB_XFER_TYPE_BULK:
+            chan->hcchar_reg.eptype = 0x2;
+            break;
+        case USB_XFER_TYPE_INTR:
+            chan->hcchar_reg.eptype = 0x3;
+            break;
+        default:
+            ;
+    }
+}
+
+static inline void usbh_ll_chan_set_ls(volatile usb_host_chan_regs_t *chan)
+{
+    chan->hcchar_reg.lspddev = 1;
+}
+
+static inline void usbh_ll_chan_set_dir(volatile usb_host_chan_regs_t *chan, bool is_in)
+{
+    chan->hcchar_reg.epdir = is_in;
+}
+
+static inline void usbh_ll_chan_set_ep_num(volatile usb_host_chan_regs_t *chan, uint32_t num)
+{
+    chan->hcchar_reg.epnum = num;
+}
+
+static inline void usbh_ll_chan_set_mps(volatile usb_host_chan_regs_t *chan, uint32_t mps)
+{
+    chan->hcchar_reg.mps = mps;
+}
+
+static inline void usbh_ll_chan_hcchar_init(volatile usb_host_chan_regs_t *chan, int dev_addr, int ep_num, int mps, usb_xfer_type_t type, bool is_in)
+{
+    //Sets all persistent fields of the channel over its lifetime
+    usbh_ll_chan_set_dev_addr(chan, dev_addr);
+    usbh_ll_chan_set_ep_type(chan, type);
+    usbh_ll_chan_set_dir(chan, is_in);
+    usbh_ll_chan_set_ep_num(chan, ep_num);
+    usbh_ll_chan_set_mps(chan, mps);
+}
+
+// ---------------------------- HCINTi Register --------------------------------
+
+static inline uint32_t usbh_ll_chan_intr_read_and_clear(volatile usb_host_chan_regs_t *chan)
+{
+    usb_hcint_reg_t hcint;
+    hcint.val = chan->hcint_reg.val;
+    chan->hcint_reg.val = hcint.val;
+    return hcint.val;
+}
+
+// --------------------------- HCINTMSKi Register ------------------------------
+
+static inline void usbh_ll_chan_set_intr_mask(volatile usb_host_chan_regs_t *chan, uint32_t mask)
+{
+    chan->hcintmsk_reg.val = mask;
+}
+
+// ---------------------- HCTSIZi and HCDMAi Registers -------------------------
+
+static inline void usbh_ll_chan_set_pid(volatile usb_host_chan_regs_t *chan, uint32_t data_pid)
+{
+    if (data_pid == 0) {
+        chan->hctsiz_reg.pid = 0;
+    } else {
+        chan->hctsiz_reg.pid = 2;
+    }
+}
+
+static inline void usbh_ll_chan_set_dma_addr_non_iso(volatile usb_host_chan_regs_t *chan,
+                                                    void *dmaaddr,
+                                                    uint32_t qtd_idx)
+{
+    //Set HCDMAi
+    chan->hcdma_reg.val = 0;
+    chan->hcdma_reg.non_iso.dmaaddr = (((uint32_t)dmaaddr) >> 9) & 0x7FFFFF;  //MSB of 512 byte aligned address
+    chan->hcdma_reg.non_iso.ctd = qtd_idx;
+}
+
+static inline void usbh_ll_chan_set_dma_addr_iso(volatile usb_host_chan_regs_t *chan,
+                                                void *dmaaddr,
+                                                uint32_t ntd,
+                                                uint32_t pktcnt,
+                                                uint32_t ctd)
+{
+    int n;
+    if (ntd == 2) {
+        n = 4;
+    } else if (ntd == 4) {
+        n = 5;
+    } else if (ntd == 8) {
+        n = 6;
+    } else if (ntd == 16) {
+        n = 7;
+    } else if (ntd == 32) {
+        n = 8;
+    } else {    //ntd == 64
+        n = 9;
+    }
+    //Set HCTSIZi
+    chan->hctsiz_reg.ntd = ntd -1;
+    chan->hctsiz_reg.sched_info = 0xFF;     //Always set to 0xFF for FS
+    //Set HCDMAi
+    chan->hcdma_reg.iso.dmaaddr_ctd = (((uint32_t)dmaaddr) & 0x1FF) << (n-3);   //ctd is set to 0
+}
+
+static inline int usbh_ll_chan_get_ctd(usb_host_chan_regs_t *chan)
+{
+    return chan->hcdma_reg.non_iso.ctd;
+}
+
+static inline void usbh_ll_chan_hctsiz_init(volatile usb_host_chan_regs_t *chan, int qtd_list_len)
+{
+    //HCTSIZi
+    chan->hctsiz_reg.dopng = 0;     //Don't do ping
+    chan->hctsiz_reg.pid = 0;       //Reset PID to Data0
+    chan->hctsiz_reg.ntd = qtd_list_len - 1;    //Set the length of the descriptor list
+    chan->hctsiz_reg.sched_info = 0xFF; //Schedinfo is always 0xFF for fullspeed. Not used in Bulk/Ctrl channels
+}
+
+// ---------------------------- HCDMABi Register -------------------------------
+
+static inline void *usbh_ll_chan_get_cur_buff_addr(volatile usb_host_chan_regs_t *chan)
+{
+    return (void *)chan->hcdmab_reg.hcdmab;
+}
+
+/* -----------------------------------------------------------------------------
+---------------------------- Scatter/Gather DMA QTDs ---------------------------
+----------------------------------------------------------------------------- */
+
+// ---------------------------- Helper Functions -------------------------------
+
+/**
+ * @brief Get the base address of a channel's register based on the channel's index
+ *
+ * @param dev Start address of the DWC_OTG registers
+ * @param chan_idx The channel's index
+ * @return usb_host_chan_regs_t* Pointer to channel's registers
+ */
+static inline usb_host_chan_regs_t *usbh_ll_get_chan_regs(usbh_dev_t *dev, int chan_idx)
+{
+    return &dev->host_chans[chan_idx];
+}
+
+// ------------------------------ QTD related ----------------------------------
+
+#define USBH_LL_QTD_STATUS_SUCCESS      0x0     //If QTD was processed, it indicates the data was transmitted/received successfully
+#define USBH_LL_QTD_STATUS_PKTERR       0x1     //Data trasnmitted/received with errors (CRC/Timeout/Stuff/False EOP/Excessive NAK).
+//Note: 0x2 is reserved
+#define USBH_LL_QTD_STATUS_BUFFER       0x3     //AHB error occurred.
+#define USBH_LL_QTD_STATUS_NOT_EXECUTED 0x4     //QTD as never processed
+
+/**
+ * @brief Set a QTD for a non isochronous IN transfer
+ *
+ * @param qtd Pointer to the QTD
+ * @param data_buff Pointer to buffer containing the data to transfer
+ * @param xfer_len Number of bytes in transfer. Setting 0 will do a zero length IN transfer.
+ *                 Non zero length must be mulitple of the endpoint's MPS.
+ * @param halt_on_cplt Generate a channel halted interrupt on completion of QTD
+ */
+static inline void usbh_ll_set_qtd_in(usbh_ll_dma_qtd_t *qtd, void *data_buff, int xfer_len, bool halt_on_cplt)
+{
+    qtd->buffer = data_buff;        //Set pointer to data buffer
+    qtd->buffer_status_val = 0;     //Reset all flags to zero
+    qtd->in_non_iso.xfer_size = xfer_len;
+    if (halt_on_cplt) {
+        qtd->in_non_iso.intr_cplt = 1;  //Used to indicate successful completion
+        qtd->in_non_iso.eol = 1;        //Used to halt the channel at this qtd
+    }
+    qtd->in_non_iso.active = 1;
+}
+
+/**
+ * @brief Set a QTD for a non isochronous OUT transfer
+ *
+ * @param qtd Poitner to the QTD
+ * @param data_buff Pointer to buffer containing the data to transfer
+ * @param xfer_len Number of bytes to transfer. Setting 0 will do a zero length transfer.
+ *                 For ctrl setup packets, this should be set to 8.
+ * @param halt_on_cplt Generate a channel halted interrupt on completion of QTD.
+ * @param is_setup Indicates whether this is a control transfer setup packet or a normal OUT Data transfer.
+ *                 (As per the USB protocol, setup packets cannot be STALLd or NAKd by the device)
+ */
+static inline void usbh_ll_set_qtd_out(usbh_ll_dma_qtd_t *qtd, void *data_buff, int xfer_len, bool halt_on_cplt, bool is_setup)
+{
+    qtd->buffer = data_buff;        //Set pointer to data buffer
+    qtd->buffer_status_val = 0;     //Reset all flags to zero
+    qtd->out_non_iso.xfer_size = xfer_len;
+    if (is_setup) {
+        qtd->out_non_iso.is_setup = 1;
+    }
+    if (halt_on_cplt) {
+        qtd->out_non_iso.intr_cplt = 1;  //Used to indicate successful completion
+        qtd->out_non_iso.eol = 1;        //Used to halt the channel at this qtd
+    }
+    qtd->out_non_iso.active = 1;
+}
+
+/**
+ * @brief Set a QTD as NULL
+ *
+ * This sets the QTD to a value of 0. This is only useful when you need to insert
+ * blank QTDs into a list of QTDs
+ *
+ * @param qtd Pointer to the QTD
+ */
+static inline void usbh_ll_set_qtd_null(usbh_ll_dma_qtd_t *qtd)
+{
+    qtd->buffer = NULL;
+    qtd->buffer_status_val = 0;     //Disable qtd by clearing it to zero. Used by interrupt/isoc as an unscheudled frame
+}
+
+/**
+ * @brief Get the status of a QTD
+ *
+ * When a channel get's halted, call this to check whether each QTD was executed successfully
+ *
+ * @param qtd Poitner to the QTD
+ * @param[out] rem_len Number of bytes ramining in the QTD
+ * @param[out] status Status of the QTD
+ */
+static inline void usbh_ll_get_qtd_status(usbh_ll_dma_qtd_t *qtd, int *rem_len, int *status)
+{
+    //Status is the same regardless of IN or OUT
+    if (qtd->in_non_iso.active) {
+        //QTD was never processed
+        *status = USBH_LL_QTD_STATUS_NOT_EXECUTED;
+    } else {
+        *status = qtd->in_non_iso.rx_status;
+    }
+    *rem_len = qtd->in_non_iso.xfer_size;
+    //Clear the QTD just for safety
+    qtd->buffer_status_val = 0;
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 394 - 0
components/hal/include/hal/usb_types.h

@@ -0,0 +1,394 @@
+// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+
+#define USB_CTRL_REQ_ATTR       __attribute__((packed))
+#define USB_DESC_ATTR           __attribute__((packed))
+
+/* -----------------------------------------------------------------------------
+------------------------------ USB Protocol Enums ------------------------------
+----------------------------------------------------------------------------- */
+
+/**
+ * @brief Enumeration of USB PHY type
+ */
+typedef enum {
+    USB_PHY_INTERNAL = 0,       /**< Use the chip's internal USB PHY */
+    USB_PHY_EXTERNAL,           /**< Use an external USB PHY */
+} usb_phy_t;
+
+/**
+ * @brief The type of USB transfer
+ *
+ * @note The enum values need to match the bmAttributes field of an EP descriptor
+ */
+typedef enum {
+    USB_XFER_TYPE_CTRL = 0,
+    USB_XFER_TYPE_ISOCHRONOUS,
+    USB_XFER_TYPE_BULK,
+    USB_XFER_TYPE_INTR,
+} usb_xfer_type_t;
+
+/**
+ * @brief USB Standard Speeds
+ */
+typedef enum {
+    USB_SPEED_LOW = 0,          /**< USB Low Speed (1.5 Mbit/s) */
+    USB_SPEED_FULL,             /**< USB Full Speed (12 Mbit/s) */
+} usb_speed_t;
+
+/* -----------------------------------------------------------------------------
+-------------------------------- Control Request -------------------------------
+----------------------------------------------------------------------------- */
+
+/**
+ * @brief Size of a USB control transfer setup packet in bytes
+ */
+#define USB_CTRL_REQ_SIZE       8
+
+/**
+ * @brief Structure representing a USB control transfer setup packet
+ */
+typedef union {
+    struct {
+        uint8_t bRequestType;
+        uint8_t bRequest;
+        uint16_t wValue;
+        uint16_t wIndex;
+        uint16_t wLength;
+    } USB_CTRL_REQ_ATTR;
+    uint8_t val[USB_CTRL_REQ_SIZE];
+} usb_ctrl_req_t;
+_Static_assert(sizeof(usb_ctrl_req_t) == USB_CTRL_REQ_SIZE, "Size of usb_ctrl_req_t incorrect");
+
+/**
+ * @brief Bit masks pertaining to the bRequestType field of a setup packet
+ */
+#define USB_B_REQUEST_TYPE_DIR_OUT          (0X00 << 7)
+#define USB_B_REQUEST_TYPE_DIR_IN           (0x01 << 7)
+#define USB_B_REQUEST_TYPE_TYPE_STANDARD    (0x00 << 5)
+#define USB_B_REQUEST_TYPE_TYPE_CLASS       (0x01 << 5)
+#define USB_B_REQUEST_TYPE_TYPE_VENDOR      (0x02 << 5)
+#define USB_B_REQUEST_TYPE_TYPE_RESERVED    (0x03 << 5)
+#define USB_B_REQUEST_TYPE_TYPE_MASK        (0x03 << 5)
+#define USB_B_REQUEST_TYPE_RECIP_DEVICE     (0x00 << 0)
+#define USB_B_REQUEST_TYPE_RECIP_INTERFACE  (0x01 << 0)
+#define USB_B_REQUEST_TYPE_RECIP_ENDPOINT   (0x02 << 0)
+#define USB_B_REQUEST_TYPE_RECIP_OTHER      (0x03 << 0)
+#define USB_B_REQUEST_TYPE_RECIP_MASK       (0x1f << 0)
+
+/**
+ * @brief Bit masks pertaining to the bRequest field of a setup packet
+ */
+#define USB_B_REQUEST_GET_STATUS            0x00
+#define USB_B_REQUEST_CLEAR_FEATURE         0x01
+#define USB_B_REQUEST_SET_FEATURE           0x03
+#define USB_B_REQUEST_SET_ADDRESS           0x05
+#define USB_B_REQUEST_GET_DESCRIPTOR        0x06
+#define USB_B_REQUEST_SET_DESCRIPTOR        0x07
+#define USB_B_REQUEST_GET_CONFIGURATION     0x08
+#define USB_B_REQUEST_SET_CONFIGURATION     0x09
+#define USB_B_REQUEST_GET_INTERFACE         0x0A
+#define USB_B_REQUEST_SET_INTERFACE         0x0B
+#define USB_B_REQUEST_SYNCH_FRAME           0x0C
+
+/**
+ * @brief Bit masks pertaining to the wValue field of a setup packet
+ */
+#define USB_W_VALUE_DT_DEVICE               0x01
+#define USB_W_VALUE_DT_CONFIG               0x02
+#define USB_W_VALUE_DT_STRING               0x03
+#define USB_W_VALUE_DT_INTERFACE            0x04
+#define USB_W_VALUE_DT_ENDPOINT             0x05
+#define USB_W_VALUE_DT_DEVICE_QUALIFIER     0x06
+#define USB_W_VALUE_DT_OTHER_SPEED_CONFIG   0x07
+#define USB_W_VALUE_DT_INTERFACE_POWER      0x08
+
+/**
+ * @brief Initializer for a SET_ADDRESS request
+ *
+ * Sets the address of a connected device
+ */
+#define USB_CTRL_REQ_INIT_SET_ADDR(ctrl_req_ptr, addr) ({  \
+    (ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_OUT | USB_B_REQUEST_TYPE_TYPE_STANDARD |USB_B_REQUEST_TYPE_RECIP_DEVICE;   \
+    (ctrl_req_ptr)->bRequest = USB_B_REQUEST_SET_ADDRESS;  \
+    (ctrl_req_ptr)->wValue = (addr);   \
+    (ctrl_req_ptr)->wIndex = 0;    \
+    (ctrl_req_ptr)->wLength = 0;   \
+})
+
+/**
+ * @brief Initializer for a request to get a device's device descriptor
+ */
+#define USB_CTRL_REQ_INIT_GET_DEVC_DESC(ctrl_req_ptr) ({ \
+    (ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_IN | USB_B_REQUEST_TYPE_TYPE_STANDARD | USB_B_REQUEST_TYPE_RECIP_DEVICE;   \
+    (ctrl_req_ptr)->bRequest = USB_B_REQUEST_GET_DESCRIPTOR;   \
+    (ctrl_req_ptr)->wValue = (USB_W_VALUE_DT_DEVICE << 8); \
+    (ctrl_req_ptr)->wIndex = 0;    \
+    (ctrl_req_ptr)->wLength = 18;  \
+})
+
+/**
+ * @brief Initializer for a request to get a device's current configuration number
+ */
+#define USB_CTRL_REQ_INIT_GET_CONFIG(ctrl_req_ptr) ({  \
+    (ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_IN | USB_B_REQUEST_TYPE_TYPE_STANDARD | USB_B_REQUEST_TYPE_RECIP_DEVICE;   \
+    (ctrl_req_ptr)->bRequest = USB_B_REQUEST_GET_CONFIGURATION;    \
+    (ctrl_req_ptr)->wValue = 0;    \
+    (ctrl_req_ptr)->wIndex = 0;    \
+    (ctrl_req_ptr)->wLength = 1;   \
+})
+
+/**
+ * @brief Initializer for a request to get one of the device's current configuration descriptor
+ *
+ * - desc_index indicates the configuration's index number
+ * - Number of bytes of the configuration descriptor to get
+ */
+#define USB_CTRL_REQ_INIT_GET_CFG_DESC(ctrl_req_ptr, desc_index, desc_len) ({  \
+    (ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_IN | USB_B_REQUEST_TYPE_TYPE_STANDARD | USB_B_REQUEST_TYPE_RECIP_DEVICE;   \
+    (ctrl_req_ptr)->bRequest = USB_B_REQUEST_GET_DESCRIPTOR;   \
+    (ctrl_req_ptr)->wValue = (USB_W_VALUE_DT_CONFIG << 8) | ((desc_index) & 0xFF); \
+    (ctrl_req_ptr)->wIndex = 0;    \
+    (ctrl_req_ptr)->wLength = (desc_len);  \
+})
+
+/**
+ * @brief Initializer for a request to set a device's current configuration number
+ */
+#define USB_CTRL_REQ_INIT_SET_CONFIG(ctrl_req_ptr, config_num) ({  \
+    (ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_OUT | USB_B_REQUEST_TYPE_TYPE_STANDARD | USB_B_REQUEST_TYPE_RECIP_DEVICE;   \
+    (ctrl_req_ptr)->bRequest = USB_B_REQUEST_SET_CONFIGURATION;    \
+    (ctrl_req_ptr)->wValue = (config_num); \
+    (ctrl_req_ptr)->wIndex = 0;    \
+    (ctrl_req_ptr)->wLength = 0;   \
+})
+
+/* -----------------------------------------------------------------------------
+---------------------------------- Descriptors ---------------------------------
+----------------------------------------------------------------------------- */
+
+// -------------------------- Device Descriptor --------------------------------
+
+/**
+ * @brief Size of a USB device descriptor in bytes
+ */
+#define USB_DESC_DEV_SIZE       18
+
+/**
+ * @brief Structure representing a USB device descriptor
+ */
+typedef union {
+    struct {
+        uint8_t bLength;
+        uint8_t bDescriptorType;
+        uint16_t bcdUSB;
+        uint8_t bDeviceClass;
+        uint8_t bDeviceSubClass;
+        uint8_t bDeviceProtocol;
+        uint8_t bMaxPacketSize0;
+        uint16_t idVendor;
+        uint16_t idProduct;
+        uint16_t bcdDevice;
+        uint8_t iManufacturer;
+        uint8_t iProduct;
+        uint8_t iSerialNumber;
+        uint8_t bNumConfigurations;
+    } USB_DESC_ATTR;
+    uint8_t val[USB_DESC_DEV_SIZE];
+} usb_desc_devc_t;
+_Static_assert(sizeof(usb_desc_devc_t) == USB_DESC_DEV_SIZE, "Size of usb_desc_devc_t incorrect");
+
+/**
+ * @brief Possible base class values of the bDeviceClass field of a USB device descriptor
+ */
+#define USB_CLASS_PER_INTERFACE             0x00
+#define USB_CLASS_AUDIO                     0x01
+#define USB_CLASS_COMM                      0x02
+#define USB_CLASS_HID                       0x03
+#define USB_CLASS_PHYSICAL                  0x05
+#define USB_CLASS_STILL_IMAGE               0x06
+#define USB_CLASS_PRINTER                   0x07
+#define USB_CLASS_MASS_STORAGE              0x08
+#define USB_CLASS_HUB                       0x09
+#define USB_CLASS_CDC_DATA                  0x0a
+#define USB_CLASS_CSCID                     0x0b
+#define USB_CLASS_CONTENT_SEC               0x0d
+#define USB_CLASS_VIDEO                     0x0e
+#define USB_CLASS_WIRELESS_CONTROLLER       0xe0
+#define USB_CLASS_PERSONAL_HEALTHCARE       0x0f
+#define USB_CLASS_AUDIO_VIDEO               0x10
+#define USB_CLASS_BILLBOARD                 0x11
+#define USB_CLASS_USB_TYPE_C_BRIDGE         0x12
+#define USB_CLASS_MISC                      0xef
+#define USB_CLASS_APP_SPEC                  0xfe
+#define USB_CLASS_VENDOR_SPEC               0xff
+
+/**
+ * @brief Vendor specific subclass code
+ */
+#define USB_SUBCLASS_VENDOR_SPEC            0xff
+
+// ----------------------- Configuration Descriptor ----------------------------
+
+/**
+ * @brief Size of a short USB configuration descriptor in bytes
+ *
+ * @note The size of a full USB configuration includes all the interface and endpoint
+ *       descriptors of that configuration.
+ */
+#define USB_DESC_CFG_SIZE       9
+
+/**
+ * @brief Structure representing a short USB configuration descriptor
+ *
+ * @note The full USB configuration includes all the interface and endpoint
+ *       descriptors of that configuration.
+ */
+typedef union {
+    struct {
+        uint8_t bLength;
+        uint8_t bDescriptorType;
+        uint16_t wTotalLength;
+        uint8_t bNumInterfaces;
+        uint8_t bConfigurationValue;
+        uint8_t iConfiguration;
+        uint8_t bmAttributes;
+        uint8_t bMaxPower;
+    } USB_DESC_ATTR;
+    uint8_t val[USB_DESC_CFG_SIZE];
+} usb_desc_cfg_t;
+_Static_assert(sizeof(usb_desc_cfg_t) == USB_DESC_CFG_SIZE, "Size of usb_desc_cfg_t incorrect");
+
+/**
+ * @brief Bit masks pertaining to the bmAttributes field of a configuration descriptor
+ */
+#define USB_BM_ATTRIBUTES_ONE               (1 << 7)    //Must be set
+#define USB_BM_ATTRIBUTES_SELFPOWER         (1 << 6)    //Self powered
+#define USB_BM_ATTRIBUTES_WAKEUP            (1 << 5)    //Can wakeup
+#define USB_BM_ATTRIBUTES_BATTERY           (1 << 4)    //Battery powered
+
+// ------------------------- Interface Descriptor ------------------------------
+
+/**
+ * @brief Size of a USB interface descriptor in bytes
+ */
+#define USB_DESC_INTF_SIZE      9
+
+/**
+ * @brief Structure representing a USB interface descriptor
+ */
+typedef union {
+    struct {
+        uint8_t bLength;
+        uint8_t bDescriptorType;
+        uint8_t bInterfaceNumber;
+        uint8_t bAlternateSetting;
+        uint8_t bNumEndpoints;
+        uint8_t bInterfaceClass;
+        uint8_t bInterfaceSubClass;
+        uint8_t bInterfaceProtocol;
+        uint8_t iInterface;
+    } USB_DESC_ATTR;
+    uint8_t val[USB_DESC_INTF_SIZE];
+} usb_desc_intf_t;
+_Static_assert(sizeof(usb_desc_intf_t) == USB_DESC_INTF_SIZE, "Size of usb_desc_intf_t incorrect");
+
+// ------------------------- Endpoint Descriptor -------------------------------
+
+/**
+ * @brief Size of a USB endpoint descriptor in bytes
+ */
+#define USB_DESC_EP_SIZE        7
+
+/**
+ * @brief Structure representing a USB endp;oint descriptor
+ */
+typedef union {
+    struct {
+        uint8_t bLength;
+        uint8_t bDescriptorType;
+        uint8_t bEndpointAddress;
+        uint8_t bmAttributes;
+        uint16_t wMaxPacketSize;
+        uint8_t bInterval;
+    } USB_DESC_ATTR;
+    uint8_t val[USB_DESC_EP_SIZE];
+} usb_desc_ep_t;
+_Static_assert(sizeof(usb_desc_ep_t) == USB_DESC_EP_SIZE, "Size of usb_desc_ep_t incorrect");
+
+/**
+ * @brief Bit masks pertaining to the bEndpointAddress field of an endpoint descriptor
+ */
+#define USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK              0x0f
+#define USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK              0x80
+
+/**
+ * @brief Bit masks pertaining to the bmAttributes field of an endpoint descriptor
+ */
+#define USB_BM_ATTRIBUTES_XFERTYPE_MASK                 0x03
+#define USB_BM_ATTRIBUTES_XFER_CONTROL                  (0 << 0)
+#define USB_BM_ATTRIBUTES_XFER_ISOC                     (1 << 0)
+#define USB_BM_ATTRIBUTES_XFER_BULK                     (2 << 0)
+#define USB_BM_ATTRIBUTES_XFER_INT                      (3 << 0)
+#define USB_BM_ATTRIBUTES_SYNCTYPE_MASK                 0x0C    /* in bmAttributes */
+#define USB_BM_ATTRIBUTES_SYNC_NONE                     (0 << 2)
+#define USB_BM_ATTRIBUTES_SYNC_ASYNC                    (1 << 2)
+#define USB_BM_ATTRIBUTES_SYNC_ADAPTIVE                 (2 << 2)
+#define USB_BM_ATTRIBUTES_SYNC_SYNC                     (3 << 2)
+#define USB_BM_ATTRIBUTES_USAGETYPE_MASK                0x30
+#define USB_BM_ATTRIBUTES_USAGE_DATA                    (0 << 4)
+#define USB_BM_ATTRIBUTES_USAGE_FEEDBACK                (1 << 4)
+#define USB_BM_ATTRIBUTES_USAGE_IMPLICIT_FB             (2 << 4)
+
+/**
+ * @brief Macro helpers to get information about an endpoint from its descriptor
+ */
+#define USB_DESC_EP_GET_XFERTYPE(desc_ptr) ((usb_xfer_type_t) ((desc_ptr)->bmAttributes & USB_BM_ATTRIBUTES_XFERTYPE_MASK))
+#define USB_DESC_EP_GET_EP_NUM(desc_ptr) ((desc_ptr)->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK)
+#define USB_DESC_EP_GET_EP_DIR(desc_ptr) (((desc_ptr)->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK) ? 1 : 0)
+#define USB_DESC_EP_GET_MPS(desc_ptr) ((desc_ptr)->wMaxPacketSize & 0x7FF)
+
+
+// --------------------------- String Descriptor -------------------------------
+
+/**
+ * @brief Size of a short USB string descriptor in bytes
+ */
+#define USB_DESC_STR_SIZE       4
+
+/**
+ * @brief Structure representing a USB string descriptor
+ */
+typedef union {
+    struct {
+        uint8_t bLength;
+        uint8_t bDescriptorType;
+        uint16_t wData[1];        /* UTF-16LE encoded */
+    } USB_DESC_ATTR;
+    uint8_t val[USB_DESC_STR_SIZE];
+} usb_desc_str_t;
+_Static_assert(sizeof(usb_desc_str_t) == USB_DESC_STR_SIZE, "Size of usb_desc_str_t incorrect");
+
+#ifdef __cplusplus
+}
+#endif

+ 1163 - 0
components/soc/esp32s2/include/soc/usbh_struct.h

@@ -0,0 +1,1163 @@
+// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+/* ---------------------------- Register Types ------------------------------ */
+
+typedef union {
+    struct {
+        uint32_t sesreqscs: 1;
+        uint32_t sesreq: 1;
+        uint32_t vbvalidoven: 1;
+        uint32_t vbvalidovval: 1;
+        uint32_t avalidoven: 1;
+        uint32_t avalidovval: 1;
+        uint32_t bvalidoven: 1;
+        uint32_t bvalidovval: 1;
+        uint32_t hstnegscs: 1;
+        uint32_t hnpreq: 1;
+        uint32_t hstsethnpen: 1;
+        uint32_t devhnpen: 1;
+        uint32_t ehen: 1;
+        uint32_t reserved2: 2;
+        uint32_t dbncefltrbypass: 1;
+        uint32_t conidsts: 1;
+        uint32_t dbnctime: 1;
+        uint32_t asesvld: 1;
+        uint32_t bsesvld: 1;
+        uint32_t otgver: 1;
+        uint32_t curmod: 1;
+        uint32_t reserved10: 10;
+    };
+    uint32_t val;
+} usb_gotgctl_reg_t;
+
+typedef union {
+    struct {
+        uint32_t reserved2: 2;
+        uint32_t sesenddet: 1;
+        uint32_t reserved5: 5;
+        uint32_t sesreqsucstschng: 1;
+        uint32_t hstnegsucstschng: 1;
+        uint32_t reserved7: 7;
+        uint32_t hstnegdet: 1;
+        uint32_t adevtoutchg: 1;
+        uint32_t dbncedone: 1;
+        uint32_t reserved12: 12;
+    };
+    uint32_t val;
+} usb_gotgint_reg_t;
+
+typedef union {
+        struct {
+        uint32_t glbllntrmsk: 1;
+        uint32_t hbstlen: 4;
+        uint32_t dmaen: 1;
+        uint32_t reserved1: 1;
+        uint32_t nptxfemplvl: 1;
+        uint32_t ptxfemplvl: 1;
+        uint32_t reserved12: 12;
+        uint32_t remmemsupp: 1;
+        uint32_t notialldmawrit: 1;
+        uint32_t ahbsingle: 1;
+        uint32_t invdescendianess: 1;
+        uint32_t reserved7: 7;
+    };
+    uint32_t val;
+    //Checked
+} usb_gahbcfg_reg_t;
+
+typedef union {
+    struct {
+        uint32_t toutcal: 3;
+        uint32_t phyif: 1;
+        uint32_t reserved1a: 1;
+        uint32_t fsintf: 1;
+        uint32_t physel: 1;
+        uint32_t reserved1b: 1;
+        uint32_t srpcap: 1;
+        uint32_t hnpcap: 1;
+        uint32_t usbtrdtim: 4;
+        uint32_t reserved8: 8;
+        uint32_t termseldlpulse: 1;
+        uint32_t reserved5: 5;
+        uint32_t txenddelay: 1;
+        uint32_t forcehstmode: 1;
+        uint32_t forcedevmode: 1;
+        uint32_t corrupttxpkt: 1;
+    };
+    uint32_t val;
+} usb_gusbcfg_reg_t;
+
+typedef union {
+    struct {
+        uint32_t csftrst: 1;
+        uint32_t piufssftrst: 1;
+        uint32_t frmcntrrst: 1;
+        uint32_t reserved1: 1;
+        uint32_t rxfflsh: 1;
+        uint32_t txfflsh: 1;
+        uint32_t txfnum: 5;
+        uint32_t reserved19: 19;
+        uint32_t dmareq: 1;
+        uint32_t ahbidle: 1;
+    };
+    uint32_t val;
+} usb_grstctl_reg_t;
+
+typedef union {
+    struct {
+        uint32_t curmod_int: 1;
+        uint32_t modemis: 1;
+        uint32_t otgint: 1;
+        uint32_t sof: 1;
+        uint32_t rxflvi: 1;
+        uint32_t nptxfemp: 1;
+        uint32_t ginnakeff: 1;
+        uint32_t goutnakeff: 1;
+        uint32_t reserved2: 2;
+        uint32_t erlysusp: 1;
+        uint32_t usbsusp: 1;
+        uint32_t usbrst: 1;
+        uint32_t enumdone: 1;
+        uint32_t isooutdrop: 1;
+        uint32_t eopf: 1;
+        uint32_t reserved1a: 1;
+        uint32_t epmis: 1;
+        uint32_t iepint: 1;
+        uint32_t oepint: 1;
+        uint32_t incompisoin: 1;
+        uint32_t incompip: 1;
+        uint32_t fetsusp: 1;
+        uint32_t resetdet: 1;
+        uint32_t prtlnt: 1;
+        uint32_t hchlnt: 1;
+        uint32_t ptxfemp: 1;
+        uint32_t reserved1b: 1;
+        uint32_t conidstschng: 1;
+        uint32_t disconnint: 1;
+        uint32_t sessreqint: 1;
+        uint32_t wkupint: 1;
+    };
+    uint32_t val;
+} usb_gintsts_reg_t;
+
+typedef union {
+    struct {
+        uint32_t reserved1a: 1;
+        uint32_t modemismsk: 1;
+        uint32_t otgintmsk: 1;
+        uint32_t sofmsk: 1;
+        uint32_t rxflvimsk: 1;
+        uint32_t nptxfempmsk: 1;
+        uint32_t ginnakeffmsk: 1;
+        uint32_t goutnackeffmsk: 1;
+        uint32_t reserved2: 2;
+        uint32_t erlysuspmsk: 1;
+        uint32_t usbsuspmsk: 1;
+        uint32_t usbrstmsk: 1;
+        uint32_t enumdonemsk: 1;
+        uint32_t isooutdropmsk: 1;
+        uint32_t eopfmsk: 1;
+        uint32_t reserved1b: 1;
+        uint32_t epmismsk: 1;
+        uint32_t iepintmsk: 1;
+        uint32_t oepintmsk: 1;
+        uint32_t incompisoinmsk: 1;
+        uint32_t incompipmsk: 1;
+        uint32_t fetsuspmsk: 1;
+        uint32_t resetdetmsk: 1;
+        uint32_t prtlntmsk: 1;
+        uint32_t hchintmsk: 1;
+        uint32_t ptxfempmsk: 1;
+        uint32_t reserved1c: 1;
+        uint32_t conidstschngmsk: 1;
+        uint32_t disconnintmsk: 1;
+        uint32_t sessreqintmsk: 1;
+        uint32_t wkupintmsk: 1;
+    };
+    uint32_t val;
+} usb_gintmsk_reg_t;
+
+typedef union {
+    struct {
+        uint32_t g_chnum: 4;
+        uint32_t g_bcnt: 11;
+        uint32_t g_dpid: 2;
+        uint32_t g_pktsts: 4;
+        uint32_t g_fn: 4;
+        uint32_t reserved7: 7;
+    };
+    uint32_t val;
+} usb_grxstsr_reg_t;
+
+typedef union {
+    struct {
+        uint32_t chnum: 4;
+        uint32_t bcnt: 11;
+        uint32_t dpid: 2;
+        uint32_t pktsts: 4;
+        uint32_t fn: 4;
+        uint32_t reserved7: 7;
+    };
+    uint32_t val;
+} usb_grxstsp_reg_t;
+
+typedef union {
+    struct {
+        uint32_t rxfdep: 16;
+        uint32_t reserved16: 16;
+    };
+    uint32_t val;
+} usb_grxfsiz_reg_t;
+
+typedef union {
+    struct {
+        uint32_t nptxfstaddr: 16;
+        uint32_t nptxfdep: 16;
+    };
+    uint32_t val;
+} usb_gnptxfsiz_reg_t;
+
+typedef union {
+    struct {
+        uint32_t nptxfspcavail: 16;
+        uint32_t nptxqspcavail: 4;
+        uint32_t reserved4: 4;
+        uint32_t nptxqtop: 7;
+        uint32_t reserved1: 1;
+    };
+    uint32_t val;
+} usb_gnptxsts_reg_t;
+
+typedef union {
+    struct {
+        uint32_t synopsysid;
+    };
+    uint32_t val;
+} usb_gsnpsid_reg_t;
+
+typedef union {
+    struct {
+        uint32_t epdir;
+    };
+    uint32_t val;
+} usb_ghwcfg1_reg_t;
+
+typedef union {
+    struct {
+        uint32_t otgmode: 3;
+        uint32_t otgarch: 2;
+        uint32_t singpnt: 1;
+        uint32_t hsphytype: 2;
+        uint32_t fsphytype: 2;
+        uint32_t numdeveps: 4;
+        uint32_t numhstchnl: 4;
+        uint32_t periosupport: 1;
+        uint32_t dynfifosizing: 1;
+        uint32_t multiprocintrpt: 1;
+        uint32_t reserved1a: 1;
+        uint32_t nptxqdepth: 2;
+        uint32_t ptxqdepth: 2;
+        uint32_t tknqdepth: 5;
+        uint32_t reserved1b: 1;
+    };
+    uint32_t val;
+} usb_ghwcfg2_reg_t;
+
+typedef union {
+    struct {
+        uint32_t xfersizewidth: 4;
+        uint32_t pktsizewidth: 3;
+        uint32_t otgen: 1;
+        uint32_t i2cintsel: 1;
+        uint32_t vndctlsupt: 1;
+        uint32_t optfeature: 1;
+        uint32_t rsttype: 1;
+        uint32_t adpsupport: 1;
+        uint32_t hsicmode: 1;
+        uint32_t bcsupport: 1;
+        uint32_t lpmmode: 1;
+        uint32_t dfifodepth: 16;
+    };
+    uint32_t val;
+} usb_ghwcfg3_reg_t;
+
+typedef union {
+    struct {
+        uint32_t g_numdevperioeps: 4;
+        uint32_t g_partialpwrdn: 1;
+        uint32_t g_ahbfreq: 1;
+        uint32_t g_hibernation: 1;
+        uint32_t g_extendedhibernation: 1;
+        uint32_t reserved4: 4;
+        uint32_t g_acgsupt: 1;
+        uint32_t g_enhancedlpmsupt: 1;
+        uint32_t g_phydatawidth: 2;
+        uint32_t g_numctleps: 4;
+        uint32_t g_iddqfltr: 1;
+        uint32_t g_vbusvalidfltr: 1;
+        uint32_t g_avalidfltr: 1;
+        uint32_t g_bvalidfltr: 1;
+        uint32_t g_sessendfltr: 1;
+        uint32_t g_dedfifomode: 1;
+        uint32_t g_ineps: 4;
+        uint32_t g_descdmaenabled: 1;
+        uint32_t g_descdma: 1;
+    };
+    uint32_t val;
+} usb_ghwcfg4_reg_t;
+
+typedef union {
+    struct {
+        uint32_t gdfifocfg: 16;
+        uint32_t epinfobaseaddr: 16;
+
+    };
+    uint32_t val;
+} usb_gdfifocfg_reg_t;
+
+typedef union {
+    struct {
+        uint32_t ptxfstaddr: 16;
+        uint32_t ptxfsize: 16;
+    };
+    uint32_t val;
+} usb_hptxfsiz_reg_t;
+
+typedef union {
+    struct {
+        uint32_t inepitxfstaddr: 16;
+        uint32_t inep1txfdep: 16;
+    };
+    uint32_t val;
+} usb_dieptxfi_reg_t;
+
+typedef union {
+    struct {
+        uint32_t fslspclksel: 2;
+        uint32_t fslssupp: 1;
+        uint32_t reserved4a: 4;
+        uint32_t ena32khzs: 1;
+        uint32_t resvalid: 8;
+        uint32_t reserved1: 1;
+        uint32_t reserved6: 6;
+        uint32_t descdma: 1;
+        uint32_t frlisten: 2;
+        uint32_t perschedena: 1;
+        uint32_t reserved4b: 4;
+        uint32_t modechtimen: 1;
+    };
+    uint32_t val;
+} usb_hcfg_reg_t;
+
+typedef union {
+    struct {
+        uint32_t frint: 16;
+        uint32_t hfirrldctrl: 1;
+        uint32_t reserved15: 15;
+    };
+    uint32_t val;
+} usb_hfir_reg_t;
+
+typedef union {
+    struct {
+        uint32_t frnum: 14;
+        uint32_t reserved: 2;
+        uint32_t frrem: 16;
+    };
+    uint32_t val;
+} usb_hfnum_reg_t;
+
+typedef union {
+    struct {
+        uint32_t ptxfspcavail: 16;
+        uint32_t ptxqspcavail: 5;
+        uint32_t reserved: 3;
+        uint32_t ptxqtop: 8;
+    };
+    uint32_t val;
+} usb_hptxsts_reg_t;
+
+typedef union {
+    struct {
+        uint32_t haint: 8;
+        uint32_t reserved24: 24;
+    };
+    uint32_t val;
+} usb_haint_reg_t;
+
+typedef union {
+    struct {
+        uint32_t haintmsk: 8;
+        uint32_t reserved24: 24;
+    };
+    uint32_t val;
+} usb_haintmsk_reg_t;
+
+typedef union {
+    struct {
+        uint32_t hflbaddr;
+    };
+    uint32_t val;
+} usb_hflbaddr_reg_t;
+
+typedef union {
+    struct {
+        uint32_t prtconnsts: 1;
+        uint32_t prtconndet: 1;
+        uint32_t prtena: 1;
+        uint32_t prtenchng: 1;
+        uint32_t prtovrcurract: 1;
+        uint32_t prtovrcurrchng: 1;
+        uint32_t prtres: 1;
+        uint32_t prtsusp: 1;
+        uint32_t prtrst: 1;
+        uint32_t reserved1: 1;
+        uint32_t prtlnsts: 2;
+        uint32_t prtpwr: 1;
+        uint32_t prttstctl: 4;
+        uint32_t prtspd: 2;
+        uint32_t reserved13: 13;
+    };
+    uint32_t val;
+} usb_hprt_reg_t;
+
+typedef union {
+    struct {
+        uint32_t mps: 11;
+        uint32_t epnum: 4;
+        uint32_t epdir: 1;
+        uint32_t reserved: 1;
+        uint32_t lspddev: 1;
+        uint32_t eptype: 2;
+        uint32_t ec: 2;
+        uint32_t devaddr: 7;
+        uint32_t oddfrm: 1;
+        uint32_t chdis: 1;
+        uint32_t chena: 1;
+    };
+    uint32_t val;
+    //Checked with changes
+} usb_hcchar_reg_t;
+
+typedef union {
+    struct {
+        uint32_t xfercompl: 1;
+        uint32_t chhltd: 1;
+        uint32_t ahberr: 1;
+        uint32_t stall: 1;
+        uint32_t nack: 1;
+        uint32_t ack: 1;
+        uint32_t nyet: 1;
+        uint32_t xacterr: 1;
+        uint32_t bblerr: 1;
+        uint32_t frmovrun: 1;
+        uint32_t datatglerr: 1;
+        uint32_t bnaintr: 1;
+        uint32_t xcs_xact_err: 1;
+        uint32_t desc_lst_rollintr: 1;
+        uint32_t reserved18: 18;
+    };
+    uint32_t val;
+    //Checked
+} usb_hcint_reg_t;
+
+typedef union {
+    struct {
+        uint32_t xfercomplmsk: 1;
+        uint32_t chhltdmsk: 1;
+        uint32_t ahberrmsk: 1;
+        uint32_t stallmsk: 1;
+        uint32_t nakmsk: 1;
+        uint32_t ackmsk: 1;
+        uint32_t nyetmsk: 1;
+        uint32_t xacterrmsk: 1;
+        uint32_t bblerrmsk: 1;
+        uint32_t frmovrunmsk: 1;
+        uint32_t datatglerrmsk: 1;
+        uint32_t bnaintrmsk: 1;
+        uint32_t reserved1: 1;
+        uint32_t desc_lst_rollintrmsk: 1;
+        uint32_t reserved18: 18;
+    };
+    uint32_t val;
+    //Checked
+} usb_hcintmsk_reg_t;
+
+typedef union {
+    struct {
+        uint32_t sched_info: 8;
+        uint32_t ntd: 8;
+        uint32_t reserved3: 3;
+        uint32_t reserved10: 10;
+        uint32_t pid: 2;
+        uint32_t dopng: 1;
+    };
+    uint32_t val;
+    //Checked
+} usb_hctsiz_reg_t;
+
+typedef union {
+    struct {
+        uint32_t reserved3: 3;
+        uint32_t ctd: 6;
+        uint32_t dmaaddr: 23;
+    } non_iso;
+    struct {
+        uint32_t reserved3: 3;
+        uint32_t dmaaddr_ctd: 29;
+    } iso;
+    uint32_t val;
+    //Checked
+} usb_hcdma_reg_t;
+
+typedef union {
+    struct {
+        uint32_t hcdmab;
+    };
+    uint32_t val;
+} usb_hcdmab_reg_t;
+
+typedef union {
+    struct {
+        uint32_t reserved2a: 2;
+        uint32_t nzstsouthshk: 1;
+        uint32_t reserved1: 1;
+        uint32_t devaddr: 7;
+        uint32_t perfrlint: 2;
+        uint32_t endevoutnak: 1;
+        uint32_t xcvrdly: 1;
+        uint32_t erraticintmsk: 1;
+        uint32_t reserved2b: 2;
+        uint32_t epmiscnt: 5;
+        uint32_t descdma: 1;
+        uint32_t perschintvl: 2;
+        uint32_t resvalid: 6;
+    };
+    uint32_t val;
+} usb_dcfg_reg_t;
+
+typedef union {
+    struct {
+        uint32_t rmtwkupsig: 1;
+        uint32_t sftdiscon: 1;
+        uint32_t gnpinnaksts: 1;
+        uint32_t goutnaksts: 1;
+        uint32_t tstctl: 3;
+        uint32_t sgnpinnak: 1;
+        uint32_t cgnpinnak: 1;
+        uint32_t sgoutnak: 1;
+        uint32_t cgoutnak: 1;
+        uint32_t pwronprgdone: 1;
+        uint32_t reserved1: 1;
+        uint32_t gmc: 2;
+        uint32_t ignrfrmnum: 1;
+        uint32_t nakonbble: 1;
+        uint32_t encountonbna: 1;
+        uint32_t deepsleepbeslreject: 1;
+        uint32_t reserved3: 13;
+    };
+    uint32_t val;
+} usb_dctl_reg_t;
+
+typedef union {
+    struct {
+        uint32_t suspsts: 1;
+        uint32_t enumspd: 2;
+        uint32_t errticerr: 1;
+        uint32_t reserved4: 4;
+        uint32_t soffn: 14;
+        uint32_t devlnsts: 2;
+        uint32_t reserved8: 8;
+    };
+    uint32_t val;
+} usb_dsts_reg_t;
+
+typedef union {
+    struct {
+        uint32_t di_xfercomplmsk: 1;
+        uint32_t di_epdisbldmsk: 1;
+        uint32_t di_ahbermsk: 1;
+        uint32_t timeoutmsk: 1;
+        uint32_t intkntxfempmsk: 1;
+        uint32_t intknepmismsk: 1;
+        uint32_t inepnakeffmsk: 1;
+        uint32_t reserved1: 1;
+        uint32_t txfifoundrnmsk: 1;
+        uint32_t bnainintrmsk: 1;
+        uint32_t reserved3: 3;
+        uint32_t di_nakmsk: 1;
+        uint32_t reserved18: 18;
+    };
+    uint32_t val;
+} usb_diepmsk_reg_t;
+
+typedef union {
+    struct {
+        uint32_t xfercomplmsk: 1;
+        uint32_t epdisbldmsk: 1;
+        uint32_t ahbermsk: 1;
+        uint32_t setupmsk: 1;
+        uint32_t outtknepdismsk: 1;
+        uint32_t stsphsercvdmsk: 1;
+        uint32_t back2backsetup: 1;
+        uint32_t reserved1: 1;
+        uint32_t outpkterrmsk: 1;
+        uint32_t bnaoutintrmsk: 1;
+        uint32_t reserved2: 2;
+        uint32_t bbleerrmsk: 1;
+        uint32_t nakmsk: 1;
+        uint32_t nyetmsk: 1;
+        uint32_t reserved17: 17;
+    };
+    uint32_t val;
+} usb_doepmsk_reg_t;
+
+typedef union {
+    struct {
+        uint32_t inepint0: 1;
+        uint32_t inepint1: 1;
+        uint32_t inepint2: 1;
+        uint32_t inepint3: 1;
+        uint32_t inepint4: 1;
+        uint32_t inepint5: 1;
+        uint32_t inepint6: 1;
+        uint32_t reserved9a: 9;
+        uint32_t outepint0: 1;
+        uint32_t outepint1: 1;
+        uint32_t outepint2: 1;
+        uint32_t outepint3: 1;
+        uint32_t outepint4: 1;
+        uint32_t outepint5: 1;
+        uint32_t outepint6: 1;
+        uint32_t reserved9b: 9;
+    };
+    uint32_t val;
+} usb_daint_reg_t;
+
+typedef union {
+    struct {
+        uint32_t inepmsk0: 1;
+        uint32_t inepmsk1: 1;
+        uint32_t inepmsk2: 1;
+        uint32_t inepmsk3: 1;
+        uint32_t inepmsk4: 1;
+        uint32_t inepmsk5: 1;
+        uint32_t inepmsk6: 1;
+        uint32_t reserved9a: 9;
+        uint32_t outepmsk0: 1;
+        uint32_t outepmsk1: 1;
+        uint32_t outepmsk2: 1;
+        uint32_t outepmsk3: 1;
+        uint32_t outepmsk4: 1;
+        uint32_t outepmsk5: 1;
+        uint32_t outepmsk6: 1;
+        uint32_t reserved9b: 9;
+    };
+    uint32_t val;
+} usb_daintmsk_reg_t;
+
+typedef union {
+    struct {
+        uint32_t dvbusdis: 16;
+        uint32_t reserved16: 16;
+    };
+    uint32_t val;
+} usb_dvbusdis_reg_t;
+
+typedef union {
+    struct {
+        uint32_t dvbuspulse: 12;
+        uint32_t reserved20: 20;
+    };
+    uint32_t val;
+} usb_dvbuspulse_reg_t;
+
+typedef union {
+    struct {
+        uint32_t nonisothren: 1;
+        uint32_t isothren: 1;
+        uint32_t txthrlen: 9;
+        uint32_t ahbthrratio: 2;
+        uint32_t reserved3: 3;
+        uint32_t rxthren: 1;
+        uint32_t rxthrlen: 9;
+        uint32_t reserved1: 1;
+        uint32_t arbprken: 1;
+        uint32_t reserved4: 4;
+    };
+    uint32_t val;
+} usb_dthrctl_reg_t;
+
+typedef union {
+    struct {
+        uint32_t ineptxfernpmsk: 16;
+        uint32_t reserved16: 16;
+    };
+    uint32_t val;
+} usb_diepempmsk_reg_t;
+
+typedef union {
+    struct {
+        uint32_t mps0: 2;
+        uint32_t reserved9: 9;
+        uint32_t reserved4: 4;
+        uint32_t usbactep0: 1;
+        uint32_t reserved1a: 1;
+        uint32_t naksts0: 1;
+        uint32_t eptype0: 2;
+        uint32_t reserved1b: 1;
+        uint32_t stall0: 1;
+        uint32_t txfnum0: 4;
+        uint32_t cnak0: 1;
+        uint32_t snak0: 1;
+        uint32_t reserved2: 2;
+        uint32_t epdis0: 1;
+        uint32_t epena0: 1;
+    };
+    uint32_t val;
+} usb_diepctl0_reg_t;
+
+typedef union {
+    struct {
+        uint32_t xfercompl0: 1;
+        uint32_t epdisbld0: 1;
+        uint32_t ahberr0: 1;
+        uint32_t timeout0: 1;
+        uint32_t intkntxfemp0: 1;
+        uint32_t intknepmis0: 1;
+        uint32_t inepnakeff0: 1;
+        uint32_t txfemp0: 1;
+        uint32_t txfifoundrn0: 1;
+        uint32_t bnaintr0: 1;
+        uint32_t reserved1: 1;
+        uint32_t pktdrpsts0: 1;
+        uint32_t bbleerr0: 1;
+        uint32_t nakintrpt0: 1;
+        uint32_t nyetintrpt0: 1;
+        uint32_t reserved17: 17;
+    };
+    uint32_t val;
+} usb_diepint0_reg_t;
+
+typedef union {
+    struct {
+        uint32_t xfersize0: 7;
+        uint32_t reserved12: 12;
+        uint32_t pktcnt0: 2;
+        uint32_t reserved11: 11;
+    };
+    uint32_t val;
+} usb_dieptsiz0_reg_t;
+
+typedef union {
+    struct {
+        uint32_t dmaaddr0;
+    };
+    uint32_t val;
+} usb_diepdma0_reg_t;
+
+typedef union {
+    struct {
+        uint32_t ineptxfspcavail0: 16;
+        uint32_t reserved16: 16;
+    };
+    uint32_t val;
+} usb_dtxfsts0_reg_t;
+
+typedef union {
+    struct {
+        uint32_t dmabufferaddr0;
+    };
+    uint32_t val;
+} usb_diepdmab0_reg_t;
+
+typedef union {
+    struct {
+        uint32_t mps: 2;
+        uint32_t reserved9: 9;
+        uint32_t reserved4: 4;
+        uint32_t usbactep: 1;
+        uint32_t reserved1a: 1;
+        uint32_t naksts: 1;
+        uint32_t eptype: 2;
+        uint32_t reserved1b: 1;
+        uint32_t stall: 1;
+        uint32_t txfnum: 4;
+        uint32_t cnak: 1;
+        uint32_t snak: 1;
+        uint32_t setd0pid: 1;
+        uint32_t setd1pid: 1;
+        uint32_t epdis: 1;
+        uint32_t epena: 1;
+    };
+    uint32_t val;
+} usb_diepctl_reg_t;
+
+typedef union {
+    struct {
+        uint32_t xfercompl: 1;
+        uint32_t epdisbld: 1;
+        uint32_t ahberr: 1;
+        uint32_t timeout: 1;
+        uint32_t intkntxfemp: 1;
+        uint32_t intknepmis: 1;
+        uint32_t inepnakeff: 1;
+        uint32_t txfemp: 1;
+        uint32_t txfifoundrn: 1;
+        uint32_t bnaintr: 1;
+        uint32_t reserved1: 1;
+        uint32_t pktdrpsts: 1;
+        uint32_t bbleerr: 1;
+        uint32_t nakintrpt: 1;
+        uint32_t nyetintrpt: 1;
+        uint32_t reserved16: 16;
+    };
+    uint32_t val;
+} usb_diepint_reg_t;
+
+typedef union {
+    struct {
+        uint32_t xfersize: 7;
+        uint32_t reserved12: 12;
+        uint32_t pktcnt: 2;
+        uint32_t reserved11: 11;
+    };
+    uint32_t val;
+} usb_dieptsiz_reg_t;
+
+typedef union {
+    struct {
+        uint32_t dmaddr1;
+    };
+    uint32_t val;
+} usb_diepdma_reg_t;
+
+typedef union {
+    struct {
+        uint32_t ineptxfspcavail: 16;
+        uint32_t reserved16: 16;
+    };
+    uint32_t val;
+} usb_dtxfsts_reg_t;
+
+typedef union {
+    struct {
+        uint32_t dmabufferaddr1;
+    };
+    uint32_t val;
+} usb_diepdmab_reg_t;
+
+typedef union {
+    struct {
+        uint32_t mps0: 2;
+        uint32_t reserved13: 13;
+        uint32_t usbactep0: 1;
+        uint32_t reserved1: 1;
+        uint32_t naksts0: 1;
+        uint32_t eptype0: 2;
+        uint32_t snp0: 1;
+        uint32_t stall0: 1;
+        uint32_t reserved4: 4;
+        uint32_t cnak0: 1;
+        uint32_t snak0: 1;
+        uint32_t reserved2: 2;
+        uint32_t epdis0: 1;
+        uint32_t epena0: 1;
+    };
+    uint32_t val;
+} usb_doepctl0_reg_t;
+
+typedef union {
+    struct {
+        uint32_t xfercompl0: 1;
+        uint32_t epdisbld0: 1;
+        uint32_t ahberr0: 1;
+        uint32_t setup0: 1;
+        uint32_t outtknepdis0: 1;
+        uint32_t stsphsercvd0: 1;
+        uint32_t back2backsetup0: 1;
+        uint32_t reserved1a: 1;
+        uint32_t outpkterr0: 1;
+        uint32_t bnaintr0: 1;
+        uint32_t reserved1b: 1;
+        uint32_t pktdrpsts0: 1;
+        uint32_t bbleerr0: 1;
+        uint32_t nakintrpt0: 1;
+        uint32_t nyepintrpt0: 1;
+        uint32_t stuppktrcvd0: 1;
+        uint32_t reserved16: 16;
+    };
+    uint32_t val;
+} usb_doepint0_reg_t;
+
+typedef union {
+    struct {
+        uint32_t xfersize0: 7;
+        uint32_t reserved12: 12;
+        uint32_t pktcnt0: 1;
+        uint32_t reserved9: 9;
+        uint32_t supcnt0: 2;
+        uint32_t reserved1: 1;
+    };
+    uint32_t val;
+} usb_doeptsiz0_reg_t;
+
+typedef union {
+    struct {
+        uint32_t dmaaddr0;
+    };
+    uint32_t val;
+} usb_doepdma0_reg_t;
+
+typedef union {
+    struct {
+        uint32_t dmabufferaddr0;
+    };
+    uint32_t val;
+} usb_doepdmab0_reg_t;
+
+typedef union {
+    struct {
+        uint32_t mps: 11;
+        uint32_t reserved4a: 4;
+        uint32_t usbactep: 1;
+        uint32_t reserved1: 1;
+        uint32_t naksts: 1;
+        uint32_t eptype: 2;
+        uint32_t snp: 1;
+        uint32_t stall: 1;
+        uint32_t reserved4b: 4;
+        uint32_t cnak: 1;
+        uint32_t snak: 1;
+        uint32_t setd0pid: 1;
+        uint32_t setd1pid: 1;
+        uint32_t epdis: 1;
+        uint32_t epena: 1;
+    };
+    uint32_t val;
+} usb_doepctl_reg_t;
+
+typedef union {
+    struct {
+        uint32_t xfercompl: 1;
+        uint32_t epdisbld: 1;
+        uint32_t ahberr: 1;
+        uint32_t setup: 1;
+        uint32_t outtknepdis: 1;
+        uint32_t stsphsercvd: 1;
+        uint32_t back2backsetup: 1;
+        uint32_t reserved1a: 1;
+        uint32_t outpkterr: 1;
+        uint32_t bnaintr: 1;
+        uint32_t reserved1b: 1;
+        uint32_t pktdrpsts: 1;
+        uint32_t bbleerr: 1;
+        uint32_t nakintrpt: 1;
+        uint32_t nyepintrpt: 1;
+        uint32_t stuppktrcvd: 1;
+        uint32_t reserved16: 16;
+    };
+    uint32_t val;
+} usb_doepint_reg_t;
+
+typedef union {
+    struct {
+        uint32_t xfersize: 7;
+        uint32_t reserved12: 12;
+        uint32_t pktcnt: 1;
+        uint32_t reserved9: 9;
+        uint32_t supcnt: 2;
+        uint32_t reserved1: 1;
+    };
+    uint32_t val;
+} usb_doeptsiz_reg_t;
+
+typedef union {
+    struct {
+        uint32_t dmaaddr;
+    };
+    uint32_t val;
+} usb_doepdma_reg_t;
+
+typedef union {
+    struct {
+        uint32_t dmabufferaddr;
+    };
+    uint32_t val;
+} usb_doepdmab_reg_t;
+
+typedef union {
+    struct {
+        uint32_t stoppclk: 1;
+        uint32_t gatehclk: 1;
+        uint32_t pwrclmp: 1;
+        uint32_t rstpdwnmodule: 1;
+        uint32_t reserved2: 2;
+        uint32_t physleep: 1;
+        uint32_t l1suspended: 1;
+        uint32_t resetaftersusp: 1;
+        uint32_t reserved23: 23;
+    };
+    uint32_t val;
+} usb_pcgcctl_reg_t;
+
+/* --------------------------- Register Groups ------------------------------ */
+
+typedef struct {
+    volatile usb_hcchar_reg_t hcchar_reg;    //0x00
+    uint32_t reserved_0x04_0x08[1]; //0x04
+    volatile usb_hcint_reg_t hcint_reg;      //0x08
+    volatile usb_hcintmsk_reg_t hcintmsk_reg;    //0x0c
+    volatile usb_hctsiz_reg_t hctsiz_reg;    //0x10
+    volatile usb_hcdma_reg_t hcdma_reg;      //0x14
+    uint32_t reserved_0x14_0x14[1]; //0x18*
+    volatile usb_hcdmab_reg_t hcdmab_reg;    //0x1c
+} usb_host_chan_regs_t;
+
+typedef struct {
+    volatile usb_diepctl_reg_t diepctl_reg;  //0x00
+    uint32_t reserved_0x04_0x08[1]; //0x04
+    volatile usb_diepint_reg_t diepint_reg;  //0x08
+    uint32_t reserved_0x0c_0x10[1]; //0x0c
+    volatile usb_dieptsiz_reg_t dieptsiz_reg;    //0x010
+    volatile usb_diepdma_reg_t diepdma_reg;  //0x14
+    volatile usb_dtxfsts_reg_t dtxfsts_reg;  //0x18
+    volatile usb_diepdmab_reg_t diepdmab_reg;    //0x1c
+} usb_in_ep_regs_t;
+
+typedef struct {
+    volatile usb_doepctl_reg_t doepctl_reg;  //0x00
+    uint32_t reserved_0x04_0x08[1]; //0x04
+    volatile usb_doepint_reg_t doepint_reg;  //0x08
+    uint32_t reserved_0x0c_0x10[1]; //0x0c
+    volatile usb_doeptsiz_reg_t doeptsiz_reg;    //0x10
+    volatile usb_doepdma_reg_t doepdma_reg;  //0x14
+    uint32_t reserved_0x18_0x1c[1]; //0x18
+    volatile usb_doepdmab_reg_t doepdmab_reg;    //0x1c
+} usb_out_ep_regs_t;
+
+/* --------------------------- Register Layout ------------------------------ */
+
+typedef struct {
+    //Global Registers
+    volatile usb_gotgctl_reg_t gotgctl_reg;             //0x0000
+    volatile usb_gotgint_reg_t gotgint_reg;             //0x0004
+    volatile usb_gahbcfg_reg_t gahbcfg_reg;             //0x0008
+    volatile usb_gusbcfg_reg_t gusbcfg_reg;             //0x000c
+    volatile usb_grstctl_reg_t grstctl_reg;             //0x0010
+    volatile usb_gintsts_reg_t gintsts_reg;             //0x0014
+    volatile usb_gintmsk_reg_t gintmsk_reg;             //0x0018
+    volatile usb_grxstsr_reg_t grxstsr_reg;             //0x001c
+    volatile usb_grxstsp_reg_t grxstsp_reg;             //0x0020
+    volatile usb_grxfsiz_reg_t grxfsiz_reg;             //0x0024
+    volatile usb_gnptxfsiz_reg_t gnptxfsiz_reg;         //0x0028
+    volatile usb_gnptxsts_reg_t gnptxsts_reg;           //0x002c
+    uint32_t reserved_0x0030_0x0040[4];                 //0x0030 to 0x0040
+    volatile usb_gsnpsid_reg_t gsnpsid_reg;             //0x0040
+    volatile usb_ghwcfg1_reg_t ghwcfg1_reg;             //0x0044
+    volatile usb_ghwcfg2_reg_t ghwcfg2_reg;             //0x0048
+    volatile usb_ghwcfg3_reg_t ghwcfg3_reg;             //0x004c
+    volatile usb_ghwcfg4_reg_t ghwcfg4_reg;             //0x0050
+    uint32_t reserved_0x0054_0x005c[2];                 //0x0054 to 0x005c
+
+    //FIFO Configurations
+    volatile usb_gdfifocfg_reg_t gdfifocfg_reg;         //0x005c
+    uint32_t reserved_0x0060_0x0100[40];                //0x0060 to 0x0100
+    volatile usb_hptxfsiz_reg_t hptxfsiz_reg;           //0x0100
+    volatile usb_dieptxfi_reg_t dieptxfi_regs[4];       //0x0104 to 0x0114
+    usb_dieptxfi_reg_t reserved_0x0114_0x0140[11];      //0x0114 to 0x0140
+    uint32_t reserved_0x140_0x400[176];                 //0x0140 to 0x0400
+
+    //Host Mode Registers
+    volatile usb_hcfg_reg_t hcfg_reg;                   //0x0400
+    volatile usb_hfir_reg_t hfir_reg;                   //0x0404
+    volatile usb_hfnum_reg_t hfnum_reg;                 //0x0408
+    uint32_t reserved_0x40c_0x410[1];                   //0x040c to 0x0410
+    volatile usb_hptxsts_reg_t hptxsts_reg;             //0x0410
+    volatile usb_haint_reg_t haint_reg;                 //0x0414
+    volatile usb_haintmsk_reg_t haintmsk_reg;           //0x0418
+    volatile usb_hflbaddr_reg_t hflbaddr_reg;           //0x041c
+    uint32_t reserved_0x420_0x440[8];                   //0x0420 to 0x0440
+    volatile usb_hprt_reg_t hprt_reg;                   //0x0440
+    uint32_t reserved_0x0444_0x0500[47];                //0x0444 to 0x0500
+    usb_host_chan_regs_t host_chans[8];                 //0x0500 to 0x0600
+    usb_host_chan_regs_t reserved_0x0600_0x0700[8];     //0x0600 to 0x0700
+    uint32_t reserved_0x0700_0x0800[64];                //0x0700 to 0x0800
+    volatile usb_dcfg_reg_t dcfg_reg;                   //0x0800
+    volatile usb_dctl_reg_t dctl_reg;                   //0x0804
+    volatile usb_dsts_reg_t dsts_reg;                   //0x0808
+    uint32_t reserved_0x080c_0x0810[1];                 //0x080c to 0x0810
+
+    //Device Mode Registers
+    volatile usb_diepmsk_reg_t diepmsk_reg;             //0x810
+    volatile usb_doepmsk_reg_t doepmsk_reg;             //0x0814
+    volatile usb_daint_reg_t daint_reg;                 //0x0818
+    volatile usb_daintmsk_reg_t daintmsk_reg;           //0x081c
+    uint32_t reserved_0x0820_0x0828[2];                 //0x0820 to 0x0828
+    volatile usb_dvbusdis_reg_t dvbusdis_reg;           //0x0828
+    volatile usb_dvbuspulse_reg_t dvbuspulse_reg;       //0x082c
+    volatile usb_dthrctl_reg_t dthrctl_reg;             //0x0830
+    volatile usb_diepempmsk_reg_t diepempmsk_reg;       //0x0834
+    uint32_t reserved_0x0838_0x0900[50];                //0x0838 to 0x0900
+
+    //Deivce: IN EP0 reigsters
+    volatile usb_diepctl0_reg_t diepctl0_reg;           //0x0900
+    uint32_t reserved_0x0904_0x0908[1];                 //0x0904 to 0x0908
+    volatile usb_diepint0_reg_t diepint0_reg;           //0x0908
+    uint32_t reserved_0x090c_0x0910[1];                 //0x090c to 0x0910
+    volatile usb_dieptsiz0_reg_t dieptsiz0_reg;         //0x0910
+    volatile usb_diepdma0_reg_t diepdma0_reg;           //0x0914
+    volatile usb_dtxfsts0_reg_t dtxfsts0_reg;           //0x0918
+    volatile usb_diepdmab0_reg_t diepdmab0_reg;         //0x091c
+
+    //Deivce: IN EP registers
+    usb_in_ep_regs_t in_eps[6];                         //0x0920 to 0x09e0
+    usb_in_ep_regs_t reserved_0x09e0_0x0b00[9];         //0x09e0 to 0x0b00
+
+    //Device: OUT EP0 reigsters
+    volatile usb_doepctl0_reg_t doepctl0_reg;           //0x0b00
+    uint32_t reserved_0x0b04_0x0b08[1];                 //0x0b04 to 0x0b08
+    volatile usb_doepint0_reg_t doepint0_reg;           //0b0b08
+    uint32_t reserved_0x0b0c_0x0b10[1];                 //0x0b0c to 0x0b10
+    volatile usb_doeptsiz0_reg_t doeptsiz0_reg;         //0x0b10
+    volatile usb_doepdma0_reg_t doepdma0_reg;           //0x0b14
+    uint32_t reserved_0x0b18_0x0b1c[1];                 //0x0b18 to 0x0b1c
+    volatile usb_doepdmab0_reg_t doepdmab0_reg;         //0x0b1c
+
+    //Deivce: OUT EP registers
+    usb_out_ep_regs_t out_eps[6];                       //0xb1c
+    usb_out_ep_regs_t reserved_0x0be0_0x0d00[9];        //0x0be0 to 0x0d00
+    uint32_t reserved_0x0d00_0x0e00[64];                //0x0d00 to 0x0e00
+    volatile usb_pcgcctl_reg_t pcgcctl_reg;             //0x0e00
+    uint32_t reserved_0x0e04_0x0e08[1];                 //0x0d00 to 0x0e00
+} usbh_dev_t;
+
+
+_Static_assert(sizeof(usbh_dev_t) == 0xe08, "USB new struct should be 0xe08 large");
+
+extern usbh_dev_t USBH;
+
+
+#ifdef __cplusplus
+}
+#endif