diff --git a/components/esp32s2/ld/esp32s2.peripherals.ld b/components/esp32s2/ld/esp32s2.peripherals.ld index 04e48f9b62..512d840f8e 100644 --- a/components/esp32s2/ld/esp32s2.peripherals.ld +++ b/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 ); diff --git a/components/hal/esp32s2/include/hal/usbh_ll.h b/components/hal/esp32s2/include/hal/usbh_ll.h new file mode 100644 index 0000000000..0d080e5964 --- /dev/null +++ b/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 +#include +#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 diff --git a/components/hal/include/hal/usb_types.h b/components/hal/include/hal/usb_types.h new file mode 100644 index 0000000000..ef93fed6b2 --- /dev/null +++ b/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 + +#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 diff --git a/components/soc/esp32s2/include/soc/usbh_struct.h b/components/soc/esp32s2/include/soc/usbh_struct.h new file mode 100644 index 0000000000..ace84d7fa9 --- /dev/null +++ b/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 + +/* ---------------------------- 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