summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/class/audio/audio.h29
-rw-r--r--src/class/audio/audio_device.c398
-rwxr-xr-xsrc/class/bth/bth_device.c4
-rw-r--r--src/class/cdc/cdc.h17
-rw-r--r--src/class/cdc/cdc_device.c10
-rw-r--r--src/class/cdc/cdc_host.c66
-rw-r--r--src/class/cdc/cdc_host.h10
-rw-r--r--src/class/cdc/cdc_rndis_host.c10
-rw-r--r--src/class/dfu/dfu.h47
-rw-r--r--src/class/dfu/dfu_device.c706
-rw-r--r--src/class/dfu/dfu_device.h62
-rw-r--r--src/class/dfu/dfu_rt_device.c6
-rw-r--r--src/class/hid/hid.h4
-rw-r--r--src/class/hid/hid_device.c29
-rw-r--r--src/class/hid/hid_device.h24
-rw-r--r--src/class/hid/hid_host.c169
-rw-r--r--src/class/hid/hid_host.h49
-rw-r--r--src/class/midi/midi_device.c43
-rw-r--r--src/class/msc/msc_device.c573
-rw-r--r--src/class/msc/msc_device.h2
-rw-r--r--src/class/msc/msc_host.c14
-rw-r--r--src/class/msc/msc_host.h20
-rw-r--r--src/class/vendor/vendor_device.c9
-rw-r--r--src/class/vendor/vendor_device.h15
-rw-r--r--src/class/vendor/vendor_host.c4
-rw-r--r--src/common/tusb_common.h60
-rw-r--r--src/common/tusb_compiler.h67
-rw-r--r--src/common/tusb_fifo.c6
-rw-r--r--src/common/tusb_fifo.h4
-rw-r--r--src/common/tusb_types.h26
-rw-r--r--src/common/tusb_verify.h2
-rw-r--r--src/device/dcd.h21
-rw-r--r--src/device/dcd_attr.h164
-rw-r--r--src/device/usbd.c322
-rw-r--r--src/device/usbd.h83
-rw-r--r--src/device/usbd_control.c1
-rw-r--r--src/device/usbd_pvt.h4
-rw-r--r--src/host/hcd.h21
-rw-r--r--src/host/hcd_attr.h105
-rw-r--r--src/host/hub.c66
-rw-r--r--src/host/hub.h10
-rw-r--r--src/host/usbh.c743
-rw-r--r--src/host/usbh.h19
-rw-r--r--src/host/usbh_classdriver.h6
-rw-r--r--src/host/usbh_control.c15
-rw-r--r--src/host/usbh_hcd.h106
-rw-r--r--src/portable/dialog/da146xx/dcd_da146xx.c46
-rw-r--r--src/portable/ehci/ehci.c109
-rw-r--r--src/portable/ehci/ehci.h9
-rw-r--r--src/portable/ehci/ehci_api.h (renamed from src/portable/ehci/hcd_ehci.h)14
-rw-r--r--src/portable/espressif/esp32sx/dcd_esp32sx.c116
-rw-r--r--src/portable/microchip/samd/dcd_samd.c12
-rw-r--r--src/portable/microchip/samg/dcd_samg.c6
-rw-r--r--src/portable/microchip/samx7x/common_usb_regs.h2108
-rw-r--r--src/portable/microchip/samx7x/dcd_samx7x.c768
-rw-r--r--src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c6
-rw-r--r--src/portable/nordic/nrf5x/dcd_nrf5x.c239
-rw-r--r--src/portable/nuvoton/nuc120/dcd_nuc120.c19
-rw-r--r--src/portable/nuvoton/nuc121/dcd_nuc121.c85
-rw-r--r--src/portable/nuvoton/nuc505/dcd_nuc505.c6
-rw-r--r--src/portable/nxp/khci/dcd_khci.c244
-rw-r--r--src/portable/nxp/lpc17_40/dcd_lpc17_40.c6
-rw-r--r--src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c6
-rw-r--r--src/portable/nxp/transdimension/common_transdimension.h2
-rw-r--r--src/portable/nxp/transdimension/dcd_transdimension.c370
-rw-r--r--src/portable/nxp/transdimension/hcd_transdimension.c26
-rw-r--r--src/portable/ohci/ohci.c11
-rw-r--r--src/portable/ohci/ohci.h2
-rw-r--r--src/portable/raspberrypi/rp2040/dcd_rp2040.c425
-rw-r--r--src/portable/raspberrypi/rp2040/hcd_rp2040.c251
-rw-r--r--src/portable/raspberrypi/rp2040/rp2040_usb.c388
-rw-r--r--src/portable/raspberrypi/rp2040/rp2040_usb.h90
-rw-r--r--src/portable/renesas/usba/dcd_usba.c499
-rw-r--r--src/portable/silabs/efm32/dcd_efm32.c6
-rw-r--r--src/portable/sony/cxd56/dcd_cxd56.c6
-rw-r--r--src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c27
-rw-r--r--src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h4
-rw-r--r--src/portable/st/synopsys/dcd_synopsys.c140
-rw-r--r--src/portable/st/synopsys/synopsys_common.h1465
-rw-r--r--src/portable/template/dcd_template.c5
-rw-r--r--src/portable/ti/msp430x5xx/dcd_msp430x5xx.c6
-rw-r--r--src/portable/valentyusb/eptri/dcd_eptri.c6
-rw-r--r--src/tusb.c93
-rw-r--r--src/tusb.h2
-rw-r--r--src/tusb_option.h62
85 files changed, 8867 insertions, 2989 deletions
diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h
index 936f09104..f99061eae 100644
--- a/src/class/audio/audio.h
+++ b/src/class/audio/audio.h
@@ -489,7 +489,7 @@ typedef enum
AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2),
AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3),
AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4),
- AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x100000000,
+ AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x80000000,
} audio_data_format_type_I_t;
/// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification
@@ -823,6 +823,33 @@ typedef struct TU_ATTR_PACKED
uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field.
} audio_desc_cs_as_iso_data_ep_t;
+// 5.2.2 Control Request Layout
+typedef struct TU_ATTR_PACKED
+{
+ union
+ {
+ struct TU_ATTR_PACKED
+ {
+ uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t.
+ uint8_t type : 2; ///< Request type tusb_request_type_t.
+ uint8_t direction : 1; ///< Direction type. tusb_dir_t
+ } bmRequestType_bit;
+
+ uint8_t bmRequestType;
+ };
+
+ uint8_t bRequest; ///< Request type audio_cs_req_t
+ uint8_t bChannelNumber;
+ uint8_t bControlSelector;
+ union
+ {
+ uint8_t bInterface;
+ uint8_t bEndpoint;
+ };
+ uint8_t bEntityID;
+ uint16_t wLength;
+} audio_control_request_t;
+
//// 5.2.3 Control Request Parameter Block Layout
// 5.2.3.1 1-byte Control CUR Parameter Block
diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c
index 8e4420ed0..ff4e312a7 100644
--- a/src/class/audio/audio_device.c
+++ b/src/class/audio/audio_device.c
@@ -86,7 +86,11 @@
CFG_TUSB_MCU == OPT_MCU_STM32F4 || \
CFG_TUSB_MCU == OPT_MCU_STM32F7 || \
CFG_TUSB_MCU == OPT_MCU_STM32H7 || \
- (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS))
+ (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) || \
+ CFG_TUSB_MCU == OPT_MCU_RX63X || \
+ CFG_TUSB_MCU == OPT_MCU_RX65X || \
+ CFG_TUSB_MCU == OPT_MCU_RX72N || \
+ CFG_TUSB_MCU == OPT_MCU_GD32VF103
#define USE_LINEAR_BUFFER 0
#else
#define USE_LINEAR_BUFFER 1
@@ -102,19 +106,19 @@
// EP IN software buffers and mutexes
#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING
#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0
-CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ];
#if CFG_FIFO_MUTEX
osal_mutex_def_t ep_in_ff_mutex_wr_1; // No need for read mutex as only USB driver reads from FIFO
#endif
#endif // CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0
-CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ];
#if CFG_FIFO_MUTEX
osal_mutex_def_t ep_in_ff_mutex_wr_2; // No need for read mutex as only USB driver reads from FIFO
#endif
#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0
-CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ];
#if CFG_FIFO_MUTEX
osal_mutex_def_t ep_in_ff_mutex_wr_3; // No need for read mutex as only USB driver reads from FIFO
#endif
@@ -126,32 +130,32 @@ osal_mutex_def_t ep_in_ff_mutex_wr_3;
// - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into
#if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING)
#if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0
-CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX];
#endif
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0
-CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX];
#endif
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0
-CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX];
#endif
#endif // CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING)
// EP OUT software buffers and mutexes
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING
#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0
-CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ];
#if CFG_FIFO_MUTEX
osal_mutex_def_t ep_out_ff_mutex_rd_1; // No need for write mutex as only USB driver writes into FIFO
#endif
#endif // CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0
-CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ];
#if CFG_FIFO_MUTEX
osal_mutex_def_t ep_out_ff_mutex_rd_2; // No need for write mutex as only USB driver writes into FIFO
#endif
#endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0
-CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ];
#if CFG_FIFO_MUTEX
osal_mutex_def_t ep_out_ff_mutex_rd_3; // No need for write mutex as only USB driver writes into FIFO
#endif
@@ -163,52 +167,52 @@ osal_mutex_def_t ep_out_ff_mutex_rd_3;
// - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING)
#if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0
-CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX];
#endif
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0
-CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX];
#endif
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0
-CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX];
#endif
#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING)
// Control buffers
-CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ];
#if CFG_TUD_AUDIO > 1
-CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ];
#endif
#if CFG_TUD_AUDIO > 2
-CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ];
#endif
// Active alternate setting of interfaces
-CFG_TUSB_MEM_ALIGN uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT];
+uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT];
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0
-CFG_TUSB_MEM_ALIGN uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT];
+uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT];
#endif
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0
-CFG_TUSB_MEM_ALIGN uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT];
+uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT];
#endif
// Software encoding/decoding support FIFOs
#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING
#if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0
-CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ];
tu_fifo_t tx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO];
#if CFG_FIFO_MUTEX
osal_mutex_def_t tx_supp_ff_mutex_wr_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO
#endif
#endif
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0
-CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ];
tu_fifo_t tx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO];
#if CFG_FIFO_MUTEX
osal_mutex_def_t tx_supp_ff_mutex_wr_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO
#endif
#endif
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0
-CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ];
tu_fifo_t tx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO];
#if CFG_FIFO_MUTEX
osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO
@@ -218,21 +222,21 @@ osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO];
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING
#if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0
-CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ];
tu_fifo_t rx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO];
#if CFG_FIFO_MUTEX
osal_mutex_def_t rx_supp_ff_mutex_rd_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO
#endif
#endif
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0
-CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ];
tu_fifo_t rx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO];
#if CFG_FIFO_MUTEX
osal_mutex_def_t rx_supp_ff_mutex_rd_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO
#endif
#endif
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0
-CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ];
tu_fifo_t rx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO];
#if CFG_FIFO_MUTEX
osal_mutex_def_t rx_supp_ff_mutex_rd_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO
@@ -294,7 +298,7 @@ typedef struct
// Audio control interrupt buffer - no FIFO - 6 Bytes according to UAC 2 specification (p. 74)
#if CFG_TUD_AUDIO_INT_CTR_EPSIZE_IN
- CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE];
+ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ep_int_ctr_buf[CFG_TUD_AUDIO_INT_CTR_EP_IN_SW_BUFFER_SIZE];
#endif
// Decoding parameters - parameters are set when alternate AS interface is set by host
@@ -393,12 +397,12 @@ static uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio);
#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING
static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * p_desc, uint8_t const * p_desc_end, uint8_t const as_itf);
-#endif
static inline uint8_t tu_desc_subtype(void const* desc)
{
return ((uint8_t const*) desc)[2];
}
+#endif
bool tud_audio_n_mounted(uint8_t func_id)
{
@@ -643,7 +647,6 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u
// Determine amount of samples
uint8_t const n_ff_used = audio->n_ff_used_rx;
- uint16_t const nBytesToCopy = audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx;
uint16_t const nBytesPerFFToRead = n_bytes_received / n_ff_used;
uint8_t cnt_ff;
@@ -662,14 +665,14 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u
info.len_lin = tu_min16(nBytesPerFFToRead, info.len_lin);
src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx];
dst_end = info.ptr_lin + info.len_lin;
- src = audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_lin, dst_end, src, n_ff_used);
+ src = audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sampe_rx, info.ptr_lin, dst_end, src, n_ff_used);
// Handle wrapped part of FIFO
info.len_wrap = tu_min16(nBytesPerFFToRead - info.len_lin, info.len_wrap);
if (info.len_wrap != 0)
{
dst_end = info.ptr_wrap + info.len_wrap;
- audiod_interleaved_copy_bytes_fast_decode(nBytesToCopy, info.ptr_wrap, dst_end, src, n_ff_used);
+ audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sampe_rx, info.ptr_wrap, dst_end, src, n_ff_used);
}
tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], info.len_lin + info.len_wrap);
}
@@ -885,7 +888,7 @@ range [-1, +1)
* */
// Helper function
-static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, void * src, uint8_t * src_end, uint8_t * dst, uint8_t const n_ff_used)
+static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, uint8_t * src, uint8_t * src_end, uint8_t * dst, uint8_t const n_ff_used)
{
// Optimize for fast half word copies
typedef struct{
@@ -900,15 +903,15 @@ static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const
switch (nBytesToCopy)
{
case 1:
- while((uint8_t *)src < src_end)
+ while(src < src_end)
{
- *dst = *(uint8_t *)src++;
+ *dst = *src++;
dst += n_ff_used;
}
break;
case 2:
- while((uint8_t *)src < src_end)
+ while(src < src_end)
{
*(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src;
src += 2;
@@ -917,23 +920,23 @@ static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const
break;
case 3:
- while((uint8_t *)src < src_end)
+ while(src < src_end)
{
// memcpy(dst, src, 3);
// src = (uint8_t *)src + 3;
// dst += 3 * n_ff_used;
// TODO: Is there a faster way to copy 3 bytes?
- *dst++ = *(uint8_t *)src++;
- *dst++ = *(uint8_t *)src++;
- *dst++ = *(uint8_t *)src++;
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst++ = *src++;
dst += 3 * (n_ff_used - 1);
}
break;
case 4:
- while((uint8_t *)src < src_end)
+ while(src < src_end)
{
*(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src;
src += 4;
@@ -993,8 +996,8 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi
if (info.len_lin != 0)
{
info.len_lin = tu_min16(nBytesPerFFToSend, info.len_lin); // Limit up to desired length
- src_end = info.ptr_lin + info.len_lin;
- dst = audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_lin, src_end, dst, n_ff_used);
+ src_end = (uint8_t *)info.ptr_lin + info.len_lin;
+ dst = audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sampe_tx, info.ptr_lin, src_end, dst, n_ff_used);
// Limit up to desired length
info.len_wrap = tu_min16(nBytesPerFFToSend - info.len_lin, info.len_wrap);
@@ -1002,8 +1005,8 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi
// Handle wrapped part of FIFO
if (info.len_wrap != 0)
{
- src_end = info.ptr_wrap + info.len_wrap;
- audiod_interleaved_copy_bytes_fast_encode(nBytesToCopy, info.ptr_wrap, src_end, dst, n_ff_used);
+ src_end = (uint8_t *)info.ptr_wrap + info.len_wrap;
+ audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sampe_tx, info.ptr_wrap, src_end, dst, n_ff_used);
}
tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], info.len_lin + info.len_wrap);
@@ -1481,18 +1484,20 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
audio->ep_in_as_intf_num = 0;
usbd_edpt_close(rhport, audio->ep_in);
- // Invoke callback - can be used to stop data sampling
- if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request));
-
- audio->ep_in = 0; // Necessary?
-
- // Clear support FIFOs if used
-#if CFG_TUD_AUDIO_ENABLE_ENCODING
+ // Clear FIFOs, since data is no longer valid
+#if !CFG_TUD_AUDIO_ENABLE_ENCODING
+ tu_fifo_clear(&audio->ep_in_ff);
+#else
for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++)
{
tu_fifo_clear(&audio->tx_supp_ff[cnt]);
}
#endif
+
+ // Invoke callback - can be used to stop data sampling
+ if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request));
+
+ audio->ep_in = 0; // Necessary?
}
#endif
@@ -1502,16 +1507,22 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
{
audio->ep_out_as_intf_num = 0;
usbd_edpt_close(rhport, audio->ep_out);
- audio->ep_out = 0; // Necessary?
- // Clear support FIFOs if used
-#if CFG_TUD_AUDIO_ENABLE_DECODING
+ // Clear FIFOs, since data is no longer valid
+#if !CFG_TUD_AUDIO_ENABLE_DECODING
+ tu_fifo_clear(&audio->ep_out_ff);
+#else
for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++)
{
tu_fifo_clear(&audio->rx_supp_ff[cnt]);
}
#endif
+ // Invoke callback - can be used to stop data sampling
+ if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request));
+
+ audio->ep_out = 0; // Necessary?
+
// Close corresponding feedback EP
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
usbd_edpt_close(rhport, audio->ep_fb);
@@ -1605,9 +1616,17 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
TU_ASSERT( audio->n_ff_used_rx <= audio->n_rx_supp_ff );
#endif
#endif
+
+#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
+ // In case of asynchronous EP, call Cb after ep_fb is set
+ if (!(((tusb_desc_endpoint_t const *) p_desc)->bmAttributes.sync == 0x01 && audio->ep_fb == 0))
+ {
+ if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request));
+ }
+#else
// Invoke callback
if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request));
-
+#endif
// Prepare for incoming data
#if USE_LINEAR_BUFFER_RX
TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false);
@@ -1621,8 +1640,11 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
{
audio->ep_fb = ep_addr;
- // Invoke callback
- if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request));
+ // Invoke callback after ep_out is set
+ if (audio->ep_out != 0)
+ {
+ if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request));
+ }
}
#endif
#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT
@@ -1658,64 +1680,65 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const
switch (p_request->bmRequestType_bit.recipient)
{
- case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label
-
- uint8_t itf = TU_U16_LOW(p_request->wIndex);
- uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
-
- if (entityID != 0)
+ case TUSB_REQ_RCPT_INTERFACE:
{
- if (tud_audio_set_req_entity_cb)
+ uint8_t itf = TU_U16_LOW(p_request->wIndex);
+ uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
+
+ if (entityID != 0)
{
- // Check if entity is present and get corresponding driver index
- TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id));
+ if (tud_audio_set_req_entity_cb)
+ {
+ // Check if entity is present and get corresponding driver index
+ TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id));
- // Invoke callback
- return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf);
+ // Invoke callback
+ return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf);
+ }
+ else
+ {
+ TU_LOG2(" No entity set request callback available!\r\n");
+ return false; // In case no callback function is present or request can not be conducted we stall it
+ }
}
else
{
- TU_LOG2(" No entity set request callback available!\r\n");
- return false; // In case no callback function is present or request can not be conducted we stall it
+ if (tud_audio_set_req_itf_cb)
+ {
+ // Find index of audio driver structure and verify interface really exists
+ TU_VERIFY(audiod_verify_itf_exists(itf, &func_id));
+
+ // Invoke callback
+ return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf);
+ }
+ else
+ {
+ TU_LOG2(" No interface set request callback available!\r\n");
+ return false; // In case no callback function is present or request can not be conducted we stall it
+ }
}
}
- else
+ break;
+
+ case TUSB_REQ_RCPT_ENDPOINT:
{
- if (tud_audio_set_req_itf_cb)
+ uint8_t ep = TU_U16_LOW(p_request->wIndex);
+
+ if (tud_audio_set_req_ep_cb)
{
- // Find index of audio driver structure and verify interface really exists
- TU_VERIFY(audiod_verify_itf_exists(itf, &func_id));
+ // Check if entity is present and get corresponding driver index
+ TU_VERIFY(audiod_verify_ep_exists(ep, &func_id));
// Invoke callback
- return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf);
+ return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf);
}
else
{
- TU_LOG2(" No interface set request callback available!\r\n");
- return false; // In case no callback function is present or request can not be conducted we stall it
+ TU_LOG2(" No EP set request callback available!\r\n");
+ return false; // In case no callback function is present or request can not be conducted we stall it
}
}
-
break;
-
- case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label
-
- uint8_t ep = TU_U16_LOW(p_request->wIndex);
-
- if (tud_audio_set_req_ep_cb)
- {
- // Check if entity is present and get corresponding driver index
- TU_VERIFY(audiod_verify_ep_exists(ep, &func_id));
-
- // Invoke callback
- return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf);
- }
- else
- {
- TU_LOG2(" No EP set request callback available!\r\n");
- return false; // In case no callback function is present or request can not be conducted we stall it
- }
-
// Unknown/Unsupported recipient
default: TU_BREAKPOINT(); return false;
}
@@ -1754,73 +1777,75 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const
// Conduct checks which depend on the recipient
switch (p_request->bmRequestType_bit.recipient)
{
- case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label
-
- uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
-
- // Verify if entity is present
- if (entityID != 0)
+ case TUSB_REQ_RCPT_INTERFACE:
{
- // Find index of audio driver structure and verify entity really exists
- TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id));
+ uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
- // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests
- if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN)
+ // Verify if entity is present
+ if (entityID != 0)
{
- if (tud_audio_get_req_entity_cb)
+ // Find index of audio driver structure and verify entity really exists
+ TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id));
+
+ // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests
+ if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN)
{
- return tud_audio_get_req_entity_cb(rhport, p_request);
+ if (tud_audio_get_req_entity_cb)
+ {
+ return tud_audio_get_req_entity_cb(rhport, p_request);
+ }
+ else
+ {
+ TU_LOG2(" No entity get request callback available!\r\n");
+ return false; // Stall
+ }
}
- else
+ }
+ else
+ {
+ // Find index of audio driver structure and verify interface really exists
+ TU_VERIFY(audiod_verify_itf_exists(itf, &func_id));
+
+ // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests
+ if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN)
{
- TU_LOG2(" No entity get request callback available!\r\n");
- return false; // Stall
+ if (tud_audio_get_req_itf_cb)
+ {
+ return tud_audio_get_req_itf_cb(rhport, p_request);
+ }
+ else
+ {
+ TU_LOG2(" No interface get request callback available!\r\n");
+ return false; // Stall
+ }
}
}
}
- else
+ break;
+
+ case TUSB_REQ_RCPT_ENDPOINT:
{
- // Find index of audio driver structure and verify interface really exists
- TU_VERIFY(audiod_verify_itf_exists(itf, &func_id));
+ uint8_t ep = TU_U16_LOW(p_request->wIndex);
+
+ // Find index of audio driver structure and verify EP really exists
+ TU_VERIFY(audiod_verify_ep_exists(ep, &func_id));
// In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests
if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN)
{
- if (tud_audio_get_req_itf_cb)
+ if (tud_audio_get_req_ep_cb)
{
- return tud_audio_get_req_itf_cb(rhport, p_request);
+ return tud_audio_get_req_ep_cb(rhport, p_request);
}
else
{
- TU_LOG2(" No interface get request callback available!\r\n");
- return false; // Stall
+ TU_LOG2(" No EP get request callback available!\r\n");
+ return false; // Stall
}
}
}
break;
- case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label
-
- uint8_t ep = TU_U16_LOW(p_request->wIndex);
-
- // Find index of audio driver structure and verify EP really exists
- TU_VERIFY(audiod_verify_ep_exists(ep, &func_id));
-
- // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests
- if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN)
- {
- if (tud_audio_get_req_ep_cb)
- {
- return tud_audio_get_req_ep_cb(rhport, p_request);
- }
- else
- {
- TU_LOG2(" No EP get request callback available!\r\n");
- return false; // Stall
- }
- }
- break;
-
// Unknown/Unsupported recipient
default: TU_LOG2(" Unsupported recipient: %d\r\n", p_request->bmRequestType_bit.recipient); TU_BREAKPOINT(); return false;
}
@@ -1913,8 +1938,12 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3
{
if (tud_audio_fb_done_cb) TU_VERIFY(tud_audio_fb_done_cb(rhport));
- // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent
- return audiod_fb_send(rhport, &_audiod_fct[func_id]);
+ // Schedule a transmit with the new value if EP is not busy
+ if (!usbd_edpt_busy(rhport, _audiod_fct[func_id].ep_fb))
+ {
+ // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent
+ return audiod_fb_send(rhport, &_audiod_fct[func_id]);
+ }
}
#endif
#endif
@@ -1935,29 +1964,31 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req
// Conduct checks which depend on the recipient
switch (p_request->bmRequestType_bit.recipient)
{
- case TUSB_REQ_RCPT_INTERFACE: ; // The semicolon is there to enable a declaration right after the label
-
- uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
-
- // Verify if entity is present
- if (entityID != 0)
- {
- // Find index of audio driver structure and verify entity really exists
- TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id));
- }
- else
+ case TUSB_REQ_RCPT_INTERFACE:
{
- // Find index of audio driver structure and verify interface really exists
- TU_VERIFY(audiod_verify_itf_exists(itf, &func_id));
+ uint8_t entityID = TU_U16_HIGH(p_request->wIndex);
+
+ // Verify if entity is present
+ if (entityID != 0)
+ {
+ // Find index of audio driver structure and verify entity really exists
+ TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id));
+ }
+ else
+ {
+ // Find index of audio driver structure and verify interface really exists
+ TU_VERIFY(audiod_verify_itf_exists(itf, &func_id));
+ }
}
break;
- case TUSB_REQ_RCPT_ENDPOINT: ; // The semicolon is there to enable a declaration right after the label
-
- uint8_t ep = TU_U16_LOW(p_request->wIndex);
+ case TUSB_REQ_RCPT_ENDPOINT:
+ {
+ uint8_t ep = TU_U16_LOW(p_request->wIndex);
- // Find index of audio driver structure and verify EP really exists
- TU_VERIFY(audiod_verify_ep_exists(ep, &func_id));
+ // Find index of audio driver structure and verify EP really exists
+ TU_VERIFY(audiod_verify_ep_exists(ep, &func_id));
+ }
break;
// Unknown/Unsupported recipient
@@ -1992,15 +2023,17 @@ static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio
while (p_desc < p_desc_end)
{
// We assume the number of alternate settings is increasing thus we return the index of alternate setting zero!
- if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf)
+ if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == 0)
{
- *idxItf = tmp;
- *pp_desc_int = p_desc;
- return true;
+ if (((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf)
+ {
+ *idxItf = tmp;
+ *pp_desc_int = p_desc;
+ return true;
+ }
+ // Increase index, bytes read, and pointer
+ tmp++;
}
-
- // Increase index, bytes read, and pointer
- tmp++;
p_desc = tu_desc_next(p_desc);
}
}
@@ -2137,10 +2170,10 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const *
if (as_itf == audio->ep_in_as_intf_num)
{
audio->n_channels_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bNrChannels;
- audio->format_type_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType;
+ audio->format_type_tx = (audio_format_type_t)(((audio_desc_cs_as_interface_t const * )p_desc)->bFormatType);
#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING
- audio->format_type_I_tx = ((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats;
+ audio->format_type_I_tx = (audio_data_format_type_I_t)(((audio_desc_cs_as_interface_t const * )p_desc)->bmFormats);
#endif
}
#endif
@@ -2202,22 +2235,19 @@ bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback)
TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL);
// Format the feedback value
- if (_audiod_fct[func_id].rhport == 0)
- {
- uint8_t * fb = (uint8_t *) &_audiod_fct[func_id].fb_val;
+#if !TUD_OPT_HIGH_SPEED
+ uint8_t * fb = (uint8_t *) &_audiod_fct[func_id].fb_val;
- // For FS format is 10.14
- *(fb++) = (feedback >> 2) & 0xFF;
- *(fb++) = (feedback >> 10) & 0xFF;
- *(fb++) = (feedback >> 18) & 0xFF;
- // 4th byte is needed to work correctly with MS Windows
- *fb = 0;
- }
- else
- {
- // For HS format is 16.16 as originally demanded
- _audiod_fct[func_id].fb_val = feedback;
- }
+ // For FS format is 10.14
+ *(fb++) = (feedback >> 2) & 0xFF;
+ *(fb++) = (feedback >> 10) & 0xFF;
+ *(fb++) = (feedback >> 18) & 0xFF;
+ // 4th byte is needed to work correctly with MS Windows
+ *fb = 0;
+#else
+ // For HS format is 16.16 as originally demanded
+ _audiod_fct[func_id].fb_val = feedback;
+#endif
// Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value
if (!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_fb))
diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c
index 1d27ae7c5..b73f829cc 100755
--- a/src/class/bth/bth_device.c
+++ b/src/class/bth/bth_device.c
@@ -214,14 +214,14 @@ bool btd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t c
}
else return false;
- return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, request->wLength);
+ return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, sizeof(_btd_itf.hci_cmd));
}
else if ( stage == CONTROL_STAGE_DATA )
{
// Handle class request only
TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
- if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, request->wLength);
+ if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, tu_min16(request->wLength, sizeof(_btd_itf.hci_cmd)));
}
return true;
diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h
index f59bf0f1a..5df47f70b 100644
--- a/src/class/cdc/cdc.h
+++ b/src/class/cdc/cdc.h
@@ -215,6 +215,10 @@ typedef enum
// Class Specific Functional Descriptor (Communication Interface)
//--------------------------------------------------------------------+
+// Start of all packed definitions for compiler without per-type packed
+TU_ATTR_PACKED_BEGIN
+TU_ATTR_BIT_FIELD_ORDER_BEGIN
+
/// Header Functional Descriptor (Communication Interface)
typedef struct TU_ATTR_PACKED
{
@@ -235,7 +239,7 @@ typedef struct TU_ATTR_PACKED
}cdc_desc_func_union_t;
#define cdc_desc_func_union_n_t(no_slave)\
- struct TU_ATTR_PACKED { \
+ struct TU_ATTR_PACKED { \
uint8_t bLength ;\
uint8_t bDescriptorType ;\
uint8_t bDescriptorSubType ;\
@@ -254,7 +258,7 @@ typedef struct TU_ATTR_PACKED
}cdc_desc_func_country_selection_t;
#define cdc_desc_func_country_selection_n_t(no_country) \
- struct TU_ATTR_PACKED {\
+ struct TU_ATTR_PACKED { \
uint8_t bLength ;\
uint8_t bDescriptorType ;\
uint8_t bDescriptorSubType ;\
@@ -283,7 +287,6 @@ typedef struct TU_ATTR_PACKED
uint8_t bDataInterface;
}cdc_desc_func_call_management_t;
-
typedef struct TU_ATTR_PACKED
{
uint8_t support_comm_request : 1; ///< Device supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature.
@@ -295,8 +298,8 @@ typedef struct TU_ATTR_PACKED
TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler");
-/// \brief Abstract Control Management Functional Descriptor
-/// \details This functional descriptor describes the commands supported by by the Communications Class interface with SubClass code of \ref CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL
+/// Abstract Control Management Functional Descriptor
+/// This functional descriptor describes the commands supported by by the Communications Class interface with SubClass code of \ref CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL
typedef struct TU_ATTR_PACKED
{
uint8_t bLength ; ///< Size of this descriptor in bytes.
@@ -367,6 +370,7 @@ typedef struct TU_ATTR_PACKED
} bmCapabilities;
}cdc_desc_func_telephone_call_state_reporting_capabilities_t;
+// TODO remove
static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc)
{
return p_desc[2];
@@ -394,7 +398,8 @@ typedef struct TU_ATTR_PACKED
TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct");
-/** @} */
+TU_ATTR_PACKED_END // End of all packed definitions
+TU_ATTR_BIT_FIELD_ORDER_END
#ifdef __cplusplus
}
diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c
index cac811c45..e622bd616 100644
--- a/src/class/cdc/cdc_device.c
+++ b/src/class/cdc/cdc_device.c
@@ -273,9 +273,6 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass &&
CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0);
- // Note: 0xFF can be used with RNDIS
- TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA), 0);
-
// Find available interface
cdcd_interface_t * p_cdc = NULL;
for(uint8_t cdc_id=0; cdc_id<CFG_TUD_CDC; cdc_id++)
@@ -303,10 +300,11 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) )
{
- // notification endpoint if any
- TU_ASSERT( usbd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc), 0 );
+ // notification endpoint
+ tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc;
- p_cdc->ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress;
+ TU_ASSERT( usbd_edpt_open(rhport, desc_ep), 0 );
+ p_cdc->ep_notif = desc_ep->bEndpointAddress;
drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c
index 33f1a8ad3..e7eaf4d05 100644
--- a/src/class/cdc/cdc_host.c
+++ b/src/class/cdc/cdc_host.c
@@ -51,7 +51,7 @@ typedef struct {
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-static cdch_data_t cdch_data[CFG_TUSB_HOST_DEVICE_MAX];
+static cdch_data_t cdch_data[CFG_TUH_DEVICE_MAX];
static inline cdch_data_t* get_itf(uint8_t dev_addr)
{
@@ -146,32 +146,30 @@ bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_co
//--------------------------------------------------------------------+
void cdch_init(void)
{
- tu_memclr(cdch_data, sizeof(cdch_data_t)*CFG_TUSB_HOST_DEVICE_MAX);
+ tu_memclr(cdch_data, sizeof(cdch_data));
}
-bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length)
+bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len)
{
- // Only support ACM
- TU_VERIFY( CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass);
+ (void) max_len;
- // Only support AT commands, no protocol and vendor specific commands.
- TU_VERIFY(tu_within(CDC_COMM_PROTOCOL_NONE, itf_desc->bInterfaceProtocol, CDC_COMM_PROTOCOL_ATCOMMAND_CDMA) ||
- 0xff == itf_desc->bInterfaceProtocol);
+ // Only support ACM subclass
+ // Protocol 0xFF can be RNDIS device for windows XP
+ TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass &&
+ CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass &&
+ 0xFF != itf_desc->bInterfaceProtocol);
- uint8_t const * p_desc;
- cdch_data_t * p_cdc;
-
- p_desc = tu_desc_next(itf_desc);
- p_cdc = get_itf(dev_addr);
+ cdch_data_t * p_cdc = get_itf(dev_addr);
- p_cdc->itf_num = itf_desc->bInterfaceNumber;
- p_cdc->itf_protocol = itf_desc->bInterfaceProtocol; // TODO 0xff is consider as rndis candidate, other is virtual Com
+ p_cdc->itf_num = itf_desc->bInterfaceNumber;
+ p_cdc->itf_protocol = itf_desc->bInterfaceProtocol;
//------------- Communication Interface -------------//
- (*p_length) = sizeof(tusb_desc_interface_t);
+ uint16_t drv_len = tu_desc_len(itf_desc);
+ uint8_t const * p_desc = tu_desc_next(itf_desc);
// Communication Functional Descriptors
- while( TUSB_DESC_CS_INTERFACE == p_desc[DESC_OFFSET_TYPE] )
+ while( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len )
{
if ( CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc) )
{
@@ -179,47 +177,47 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it
p_cdc->acm_capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities;
}
- (*p_length) += p_desc[DESC_OFFSET_LEN];
+ drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
}
- if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE])
+ if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) )
{
// notification endpoint
- tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) p_desc;
+ tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc;
- TU_ASSERT( usbh_edpt_open(rhport, dev_addr, ep_desc) );
- p_cdc->ep_notif = ep_desc->bEndpointAddress;
+ TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) );
+ p_cdc->ep_notif = desc_ep->bEndpointAddress;
- (*p_length) += p_desc[DESC_OFFSET_LEN];
+ drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
}
//------------- Data Interface (if any) -------------//
- if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) &&
+ if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) &&
(TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) )
{
- (*p_length) += p_desc[DESC_OFFSET_LEN];
+ // next to endpoint descriptor
+ drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
// data endpoints expected to be in pairs
for(uint32_t i=0; i<2; i++)
{
- tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *) p_desc;
- TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType);
- TU_ASSERT(TUSB_XFER_BULK == ep_desc->bmAttributes.xfer);
+ tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc;
+ TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer);
- TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc));
+ TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep));
- if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN )
+ if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN )
{
- p_cdc->ep_in = ep_desc->bEndpointAddress;
+ p_cdc->ep_in = desc_ep->bEndpointAddress;
}else
{
- p_cdc->ep_out = ep_desc->bEndpointAddress;
+ p_cdc->ep_out = desc_ep->bEndpointAddress;
}
- (*p_length) += p_desc[DESC_OFFSET_LEN];
+ drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next( p_desc );
}
}
@@ -242,6 +240,8 @@ bool cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32
void cdch_close(uint8_t dev_addr)
{
+ TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, );
+
cdch_data_t * p_cdc = get_itf(dev_addr);
tu_memclr(p_cdc, sizeof(cdch_data_t));
}
diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h
index 6ff392709..0d435138b 100644
--- a/src/class/cdc/cdc_host.h
+++ b/src/class/cdc/cdc_host.h
@@ -121,11 +121,11 @@ void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_i
//--------------------------------------------------------------------+
// Internal Class Driver API
//--------------------------------------------------------------------+
-void cdch_init(void);
-bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length);
-bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num);
-bool cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
-void cdch_close(uint8_t dev_addr);
+void cdch_init (void);
+bool cdch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len);
+bool cdch_set_config (uint8_t dev_addr, uint8_t itf_num);
+bool cdch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
+void cdch_close (uint8_t dev_addr);
#ifdef __cplusplus
}
diff --git a/src/class/cdc/cdc_rndis_host.c b/src/class/cdc/cdc_rndis_host.c
index 42b9993bc..cc4ffd1cf 100644
--- a/src/class/cdc/cdc_rndis_host.c
+++ b/src/class/cdc/cdc_rndis_host.c
@@ -40,10 +40,10 @@
//--------------------------------------------------------------------+
#define RNDIS_MSG_PAYLOAD_MAX (1024*4)
-CFG_TUSB_MEM_SECTION static uint8_t msg_notification[CFG_TUSB_HOST_DEVICE_MAX][8];
+CFG_TUSB_MEM_SECTION static uint8_t msg_notification[CFG_TUH_DEVICE_MAX][8];
CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t msg_payload[RNDIS_MSG_PAYLOAD_MAX];
-static rndish_data_t rndish_data[CFG_TUSB_HOST_DEVICE_MAX];
+static rndish_data_t rndish_data[CFG_TUH_DEVICE_MAX];
// TODO Microsoft requires message length for any get command must be at least 4096 bytes
@@ -88,7 +88,7 @@ static tusb_error_t rndis_body_subtask(void)
OSAL_SUBTASK_BEGIN
- for (relative_addr = 0; relative_addr < CFG_TUSB_HOST_DEVICE_MAX; relative_addr++)
+ for (relative_addr = 0; relative_addr < CFG_TUH_DEVICE_MAX; relative_addr++)
{
}
@@ -103,12 +103,12 @@ static tusb_error_t rndis_body_subtask(void)
//--------------------------------------------------------------------+
void rndish_init(void)
{
- tu_memclr(rndish_data, sizeof(rndish_data_t)*CFG_TUSB_HOST_DEVICE_MAX);
+ tu_memclr(rndish_data, sizeof(rndish_data_t)*CFG_TUH_DEVICE_MAX);
//------------- Task creation -------------//
//------------- semaphore creation for notificaiton pipe -------------//
- for(uint8_t i=0; i<CFG_TUSB_HOST_DEVICE_MAX; i++)
+ for(uint8_t i=0; i<CFG_TUH_DEVICE_MAX; i++)
{
rndish_data[i].sem_notification_hdl = osal_semaphore_create( OSAL_SEM_REF(rndish_data[i].semaphore_notification) );
}
diff --git a/src/class/dfu/dfu.h b/src/class/dfu/dfu.h
index 18de3bf99..114c827b8 100644
--- a/src/class/dfu/dfu.h
+++ b/src/class/dfu/dfu.h
@@ -36,6 +36,7 @@
//--------------------------------------------------------------------+
// Common Definitions
//--------------------------------------------------------------------+
+
// DFU Protocol
typedef enum
{
@@ -77,28 +78,28 @@ typedef enum {
// DFU Status
typedef enum {
- DFU_STATUS_OK = 0x00,
- DFU_STATUS_ERRTARGET = 0x01,
- DFU_STATUS_ERRFILE = 0x02,
- DFU_STATUS_ERRWRITE = 0x03,
- DFU_STATUS_ERRERASE = 0x04,
- DFU_STATUS_ERRCHECK_ERASED = 0x05,
- DFU_STATUS_ERRPROG = 0x06,
- DFU_STATUS_ERRVERIFY = 0x07,
- DFU_STATUS_ERRADDRESS = 0x08,
- DFU_STATUS_ERRNOTDONE = 0x09,
- DFU_STATUS_ERRFIRMWARE = 0x0A,
- DFU_STATUS_ERRVENDOR = 0x0B,
- DFU_STATUS_ERRUSBR = 0x0C,
- DFU_STATUS_ERRPOR = 0x0D,
- DFU_STATUS_ERRUNKNOWN = 0x0E,
- DFU_STATUS_ERRSTALLEDPKT = 0x0F,
-} dfu_device_status_t;
+ DFU_STATUS_OK = 0x00,
+ DFU_STATUS_ERR_TARGET = 0x01,
+ DFU_STATUS_ERR_FILE = 0x02,
+ DFU_STATUS_ERR_WRITE = 0x03,
+ DFU_STATUS_ERR_ERASE = 0x04,
+ DFU_STATUS_ERR_CHECK_ERASED = 0x05,
+ DFU_STATUS_ERR_PROG = 0x06,
+ DFU_STATUS_ERR_VERIFY = 0x07,
+ DFU_STATUS_ERR_ADDRESS = 0x08,
+ DFU_STATUS_ERR_NOTDONE = 0x09,
+ DFU_STATUS_ERR_FIRMWARE = 0x0A,
+ DFU_STATUS_ERR_VENDOR = 0x0B,
+ DFU_STATUS_ERR_USBR = 0x0C,
+ DFU_STATUS_ERR_POR = 0x0D,
+ DFU_STATUS_ERR_UNKNOWN = 0x0E,
+ DFU_STATUS_ERR_STALLEDPKT = 0x0F,
+} dfu_status_t;
-#define DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK (1 << 0)
-#define DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK (1 << 1)
-#define DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK (1 << 2)
-#define DFU_FUNC_ATTR_WILL_DETACH_BITMASK (1 << 3)
+#define DFU_ATTR_CAN_DOWNLOAD (1u << 0)
+#define DFU_ATTR_CAN_UPLOAD (1u << 1)
+#define DFU_ATTR_MANIFESTATION_TOLERANT (1u << 2)
+#define DFU_ATTR_WILL_DETACH (1u << 3)
// DFU Status Request Payload
typedef struct TU_ATTR_PACKED
@@ -107,9 +108,9 @@ typedef struct TU_ATTR_PACKED
uint8_t bwPollTimeout[3];
uint8_t bState;
uint8_t iString;
-} dfu_status_req_payload_t;
+} dfu_status_response_t;
-TU_VERIFY_STATIC( sizeof(dfu_status_req_payload_t) == 6, "size is not correct");
+TU_VERIFY_STATIC( sizeof(dfu_status_response_t) == 6, "size is not correct");
#ifdef __cplusplus
}
diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c
index 81045ff7b..28abf6e83 100644
--- a/src/class/dfu/dfu_device.c
+++ b/src/class/dfu/dfu_device.c
@@ -26,7 +26,7 @@
#include "tusb_option.h"
-#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_MODE)
+#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU)
#include "device/usbd.h"
#include "device/usbd_pvt.h"
@@ -40,24 +40,34 @@
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-typedef struct TU_ATTR_PACKED
+typedef struct
{
- dfu_device_status_t status;
- dfu_state_t state;
- uint8_t attrs;
- bool blk_transfer_in_proc;
- CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_TRANSFER_BUFFER_SIZE];
+ uint8_t attrs;
+ uint8_t alt;
+
+ dfu_state_t state;
+ dfu_status_t status;
+
+ bool flashing_in_progress;
+ uint16_t block;
+ uint16_t length;
+
+ CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_XFER_BUFSIZE];
} dfu_state_ctx_t;
// Only a single dfu state is allowed
-CFG_TUSB_MEM_SECTION static dfu_state_ctx_t _dfu_state_ctx;
+CFG_TUSB_MEM_SECTION static dfu_state_ctx_t _dfu_ctx;
+static void reset_state(void)
+{
+ _dfu_ctx.state = DFU_IDLE;
+ _dfu_ctx.status = DFU_STATUS_OK;
+ _dfu_ctx.flashing_in_progress = false;
+}
-static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request);
-static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request);
-static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength);
-static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request);
-static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request);
+static bool reply_getstatus(uint8_t rhport, tusb_control_request_t const * request, dfu_state_t state, dfu_status_t status, uint32_t timeout);
+static bool process_download_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
+static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
//--------------------------------------------------------------------+
// Debug
@@ -66,13 +76,13 @@ static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * req
static tu_lookup_entry_t const _dfu_request_lookup[] =
{
- { .key = DFU_REQUEST_DETACH , .data = "DETACH" },
- { .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" },
- { .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" },
+ { .key = DFU_REQUEST_DETACH , .data = "DETACH" },
+ { .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" },
+ { .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" },
{ .key = DFU_REQUEST_GETSTATUS , .data = "GETSTATUS" },
{ .key = DFU_REQUEST_CLRSTATUS , .data = "CLRSTATUS" },
- { .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" },
- { .key = DFU_REQUEST_ABORT , .data = "ABORT" },
+ { .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" },
+ { .key = DFU_REQUEST_ABORT , .data = "ABORT" },
};
static tu_lookup_table_t const _dfu_request_table =
@@ -83,17 +93,17 @@ static tu_lookup_table_t const _dfu_request_table =
static tu_lookup_entry_t const _dfu_state_lookup[] =
{
- { .key = APP_IDLE , .data = "APP_IDLE" },
- { .key = APP_DETACH , .data = "APP_DETACH" },
- { .key = DFU_IDLE , .data = "DFU_IDLE" },
- { .key = DFU_DNLOAD_SYNC , .data = "DFU_DNLOAD_SYNC" },
- { .key = DFU_DNBUSY , .data = "DFU_DNBUSY" },
- { .key = DFU_DNLOAD_IDLE , .data = "DFU_DNLOAD_IDLE" },
- { .key = DFU_MANIFEST_SYNC , .data = "DFU_MANIFEST_SYNC" },
- { .key = DFU_MANIFEST , .data = "DFU_MANIFEST" },
- { .key = DFU_MANIFEST_WAIT_RESET , .data = "DFU_MANIFEST_WAIT_RESET" },
- { .key = DFU_UPLOAD_IDLE , .data = "DFU_UPLOAD_IDLE" },
- { .key = DFU_ERROR , .data = "DFU_ERROR" },
+ { .key = APP_IDLE , .data = "APP_IDLE" },
+ { .key = APP_DETACH , .data = "APP_DETACH" },
+ { .key = DFU_IDLE , .data = "IDLE" },
+ { .key = DFU_DNLOAD_SYNC , .data = "DNLOAD_SYNC" },
+ { .key = DFU_DNBUSY , .data = "DNBUSY" },
+ { .key = DFU_DNLOAD_IDLE , .data = "DNLOAD_IDLE" },
+ { .key = DFU_MANIFEST_SYNC , .data = "MANIFEST_SYNC" },
+ { .key = DFU_MANIFEST , .data = "MANIFEST" },
+ { .key = DFU_MANIFEST_WAIT_RESET , .data = "MANIFEST_WAIT_RESET" },
+ { .key = DFU_UPLOAD_IDLE , .data = "UPLOAD_IDLE" },
+ { .key = DFU_ERROR , .data = "ERROR" },
};
static tu_lookup_table_t const _dfu_state_table =
@@ -104,22 +114,22 @@ static tu_lookup_table_t const _dfu_state_table =
static tu_lookup_entry_t const _dfu_status_lookup[] =
{
- { .key = DFU_STATUS_OK , .data = "OK" },
- { .key = DFU_STATUS_ERRTARGET , .data = "errTARGET" },
- { .key = DFU_STATUS_ERRFILE , .data = "errFILE" },
- { .key = DFU_STATUS_ERRWRITE , .data = "errWRITE" },
- { .key = DFU_STATUS_ERRERASE , .data = "errERASE" },
- { .key = DFU_STATUS_ERRCHECK_ERASED , .data = "errCHECK_ERASED" },
- { .key = DFU_STATUS_ERRPROG , .data = "errPROG" },
- { .key = DFU_STATUS_ERRVERIFY , .data = "errVERIFY" },
- { .key = DFU_STATUS_ERRADDRESS , .data = "errADDRESS" },
- { .key = DFU_STATUS_ERRNOTDONE , .data = "errNOTDONE" },
- { .key = DFU_STATUS_ERRFIRMWARE , .data = "errFIRMWARE" },
- { .key = DFU_STATUS_ERRVENDOR , .data = "errVENDOR" },
- { .key = DFU_STATUS_ERRUSBR , .data = "errUSBR" },
- { .key = DFU_STATUS_ERRPOR , .data = "errPOR" },
- { .key = DFU_STATUS_ERRUNKNOWN , .data = "errUNKNOWN" },
- { .key = DFU_STATUS_ERRSTALLEDPKT , .data = "errSTALLEDPKT" },
+ { .key = DFU_STATUS_OK , .data = "OK" },
+ { .key = DFU_STATUS_ERR_TARGET , .data = "errTARGET" },
+ { .key = DFU_STATUS_ERR_FILE , .data = "errFILE" },
+ { .key = DFU_STATUS_ERR_WRITE , .data = "errWRITE" },
+ { .key = DFU_STATUS_ERR_ERASE , .data = "errERASE" },
+ { .key = DFU_STATUS_ERR_CHECK_ERASED , .data = "errCHECK_ERASED" },
+ { .key = DFU_STATUS_ERR_PROG , .data = "errPROG" },
+ { .key = DFU_STATUS_ERR_VERIFY , .data = "errVERIFY" },
+ { .key = DFU_STATUS_ERR_ADDRESS , .data = "errADDRESS" },
+ { .key = DFU_STATUS_ERR_NOTDONE , .data = "errNOTDONE" },
+ { .key = DFU_STATUS_ERR_FIRMWARE , .data = "errFIRMWARE" },
+ { .key = DFU_STATUS_ERR_VENDOR , .data = "errVENDOR" },
+ { .key = DFU_STATUS_ERR_USBR , .data = "errUSBR" },
+ { .key = DFU_STATUS_ERR_POR , .data = "errPOR" },
+ { .key = DFU_STATUS_ERR_UNKNOWN , .data = "errUNKNOWN" },
+ { .key = DFU_STATUS_ERR_STALLEDPKT , .data = "errSTALLEDPKT" },
};
static tu_lookup_table_t const _dfu_status_table =
@@ -130,57 +140,59 @@ static tu_lookup_table_t const _dfu_status_table =
#endif
-#define dfu_debug_print_context() \
-{ \
- TU_LOG2(" DFU at State: %s\r\n Status: %s\r\n", \
- tu_lookup_find(&_dfu_state_table, _dfu_state_ctx.state), \
- tu_lookup_find(&_dfu_status_table, _dfu_state_ctx.status) ); \
-}
-
//--------------------------------------------------------------------+
// USBD Driver API
//--------------------------------------------------------------------+
-void dfu_moded_init(void)
+void dfu_moded_reset(uint8_t rhport)
{
- _dfu_state_ctx.state = DFU_IDLE;
- _dfu_state_ctx.status = DFU_STATUS_OK;
- _dfu_state_ctx.attrs = 0;
- _dfu_state_ctx.blk_transfer_in_proc = false;
+ (void) rhport;
+
+ _dfu_ctx.attrs = 0;
+ _dfu_ctx.alt = 0;
- dfu_debug_print_context();
+ reset_state();
}
-void dfu_moded_reset(uint8_t rhport)
+void dfu_moded_init(void)
{
- (void) rhport;
-
- _dfu_state_ctx.state = DFU_IDLE;
- _dfu_state_ctx.status = DFU_STATUS_OK;
- _dfu_state_ctx.blk_transfer_in_proc = false;
- dfu_debug_print_context();
+ dfu_moded_reset(0);
}
uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len)
{
(void) rhport;
- (void) max_len;
-
- // Ensure this is DFU Mode
- TU_VERIFY((itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS) &&
- (itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU), 0);
- uint8_t const * p_desc = tu_desc_next( itf_desc );
- uint16_t drv_len = sizeof(tusb_desc_interface_t);
+ //------------- Interface (with Alt) descriptor -------------//
+ uint8_t const itf_num = itf_desc->bInterfaceNumber;
+ uint8_t alt_count = 0;
- if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) )
+ uint16_t drv_len = 0;
+ while(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU)
{
- tusb_desc_dfu_functional_t const *dfu_desc = (tusb_desc_dfu_functional_t const *)p_desc;
- _dfu_state_ctx.attrs = (uint8_t)dfu_desc->bAttributes;
+ TU_ASSERT(max_len > drv_len, 0);
+
+ // Alternate must have the same interface number
+ TU_ASSERT(itf_desc->bInterfaceNumber == itf_num, 0);
- drv_len += tu_desc_len(p_desc);
- p_desc = tu_desc_next(p_desc);
+ // Alt should increase by one every time
+ TU_ASSERT(itf_desc->bAlternateSetting == alt_count, 0);
+ alt_count++;
+
+ drv_len += tu_desc_len(itf_desc);
+ itf_desc = (tusb_desc_interface_t const *) tu_desc_next(itf_desc);
}
+ //------------- DFU Functional descriptor -------------//
+ tusb_desc_dfu_functional_t const *func_desc = (tusb_desc_dfu_functional_t const *) itf_desc;
+ TU_ASSERT(tu_desc_type(func_desc) == TUSB_DESC_FUNCTIONAL, 0);
+ drv_len += sizeof(tusb_desc_dfu_functional_t);
+
+ _dfu_ctx.attrs = func_desc->bAttributes;
+
+ // CFG_TUD_DFU_XFER_BUFSIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR
+ uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16((uint8_t*) func_desc + offsetof(tusb_desc_dfu_functional_t, wTransferSize)) );
+ TU_ASSERT(transfer_size <= CFG_TUD_DFU_XFER_BUFSIZE, drv_len);
+
return drv_len;
}
@@ -189,432 +201,258 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc,
// return false to stall control endpoint (e.g unsupported request)
bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
{
- // nothing to do with DATA stage
- if ( stage == CONTROL_STAGE_DATA ) return true;
-
TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE);
- if(stage == CONTROL_STAGE_SETUP)
- {
- // dfu-util will try to claim the interface with SET_INTERFACE request before sending DFU request
- if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type &&
- TUSB_REQ_SET_INTERFACE == request->bRequest )
- {
- tud_control_status(rhport, request);
- return true;
- }
- }
-
- // Handle class request only from here
- TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
+ TU_LOG2(" DFU State : %s, Status: %s\r\n", tu_lookup_find(&_dfu_state_table, _dfu_ctx.state), tu_lookup_find(&_dfu_status_table, _dfu_ctx.status));
- switch (request->bRequest)
+ if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD )
{
- case DFU_REQUEST_DNLOAD:
- {
- if ( (stage == CONTROL_STAGE_ACK)
- && ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0)
- && (_dfu_state_ctx.state == DFU_DNLOAD_SYNC))
- {
- dfu_req_dnload_reply(rhport, request);
- return true;
- }
- } // fallthrough
- case DFU_REQUEST_DETACH:
- case DFU_REQUEST_UPLOAD:
- case DFU_REQUEST_GETSTATUS:
- case DFU_REQUEST_CLRSTATUS:
- case DFU_REQUEST_GETSTATE:
- case DFU_REQUEST_ABORT:
+ // Standard request include GET/SET_INTERFACE
+ switch ( request->bRequest )
{
- if(stage == CONTROL_STAGE_SETUP)
- {
- return dfu_state_machine(rhport, request);
- }
- }
- break;
+ case TUSB_REQ_SET_INTERFACE:
+ if ( stage == CONTROL_STAGE_SETUP )
+ {
+ // Switch Alt interface and reset state machine
+ _dfu_ctx.alt = (uint8_t) request->wValue;
+ reset_state();
+ return tud_control_status(rhport, request);
+ }
+ break;
- default:
- {
- TU_LOG2(" DFU Nonstandard Request: %u\r\n", request->bRequest);
- return false; // stall unsupported request
+ case TUSB_REQ_GET_INTERFACE:
+ if(stage == CONTROL_STAGE_SETUP)
+ {
+ return tud_control_xfer(rhport, request, &_dfu_ctx.alt, 1);
+ }
+ break;
+
+ // unsupported request
+ default: return false;
}
- break;
}
-
- return true;
-}
-
-static uint16_t dfu_req_upload(uint8_t rhport, tusb_control_request_t const * request, uint16_t block_num, uint16_t wLength)
-{
- TU_VERIFY( wLength <= CFG_TUD_DFU_TRANSFER_BUFFER_SIZE);
- uint16_t retval = tud_dfu_req_upload_data_cb(block_num, (uint8_t *)_dfu_state_ctx.transfer_buf, wLength);
- tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, retval);
- return retval;
-}
-
-static void dfu_req_getstatus_reply(uint8_t rhport, tusb_control_request_t const * request)
-{
- dfu_status_req_payload_t resp;
-
- resp.bStatus = _dfu_state_ctx.status;
- memset((uint8_t *)&resp.bwPollTimeout, 0x00, 3);
- resp.bState = _dfu_state_ctx.state;
- resp.iString = 0;
-
- tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t));
-}
-
-static void dfu_req_getstate_reply(uint8_t rhport, tusb_control_request_t const * request)
-{
- tud_control_xfer(rhport, request, &_dfu_state_ctx.state, 1);
-}
-
-static void dfu_req_dnload_setup(uint8_t rhport, tusb_control_request_t const * request)
-{
- // TODO: add "zero" copy mode so the buffer we read into can be provided by the user
- // if they wish, there still will be the internal control buffer copy to this buffer
- // but this mode would provide zero copy from the class driver to the application
-
- // setup for data phase
- tud_control_xfer(rhport, request, _dfu_state_ctx.transfer_buf, request->wLength);
-}
-
-static void dfu_req_dnload_reply(uint8_t rhport, tusb_control_request_t const * request)
-{
- (void) rhport;
- tud_dfu_req_dnload_data_cb(request->wValue, (uint8_t *)_dfu_state_ctx.transfer_buf, request->wLength);
- _dfu_state_ctx.blk_transfer_in_proc = false;
-}
-
-void tud_dfu_dnload_complete(void)
-{
- if (_dfu_state_ctx.state == DFU_DNBUSY)
- {
- _dfu_state_ctx.state = DFU_DNLOAD_SYNC;
- } else if (_dfu_state_ctx.state == DFU_MANIFEST)
+ else if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS )
{
- _dfu_state_ctx.state = ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) != 0)
- ? DFU_MANIFEST_WAIT_RESET : DFU_MANIFEST_SYNC;
- }
-}
-
-static bool dfu_state_machine(uint8_t rhport, tusb_control_request_t const * request)
-{
- TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest));
- TU_LOG2(" DFU State Machine: %s\r\n", tu_lookup_find(&_dfu_state_table, _dfu_state_ctx.state));
+ TU_LOG2(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest));
- switch (_dfu_state_ctx.state)
- {
- case DFU_IDLE:
+ // Class request
+ switch ( request->bRequest )
{
- switch (request->bRequest)
- {
- case DFU_REQUEST_DNLOAD:
+ case DFU_REQUEST_DETACH:
+ if ( stage == CONTROL_STAGE_SETUP )
{
- if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0)
- && (request->wLength > 0) )
- {
- _dfu_state_ctx.state = DFU_DNLOAD_SYNC;
- _dfu_state_ctx.blk_transfer_in_proc = true;
- dfu_req_dnload_setup(rhport, request);
- } else {
- _dfu_state_ctx.state = DFU_ERROR;
- }
+ tud_control_status(rhport, request);
}
- break;
-
- case DFU_REQUEST_UPLOAD:
+ else if ( stage == CONTROL_STAGE_ACK )
{
- if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_UPLOAD_BITMASK) != 0) )
- {
- _dfu_state_ctx.state = DFU_UPLOAD_IDLE;
- dfu_req_upload(rhport, request, request->wValue, request->wLength);
- } else {
- _dfu_state_ctx.state = DFU_ERROR;
- }
+ if ( tud_dfu_detach_cb ) tud_dfu_detach_cb();
}
- break;
+ break;
- case DFU_REQUEST_GETSTATUS:
+ case DFU_REQUEST_CLRSTATUS:
+ if ( stage == CONTROL_STAGE_SETUP )
{
- dfu_req_getstatus_reply(rhport, request);
+ reset_state();
+ tud_control_status(rhport, request);
}
- break;
+ break;
- case DFU_REQUEST_GETSTATE:
+ case DFU_REQUEST_GETSTATE:
+ if ( stage == CONTROL_STAGE_SETUP )
{
- dfu_req_getstate_reply(rhport, request);
+ tud_control_xfer(rhport, request, &_dfu_ctx.state, 1);
}
- break;
+ break;
- case DFU_REQUEST_ABORT:
+ case DFU_REQUEST_ABORT:
+ if ( stage == CONTROL_STAGE_SETUP )
{
- ; // do nothing, but don't stall so continue on
+ reset_state();
+ tud_control_status(rhport, request);
}
- break;
-
- default:
+ else if ( stage == CONTROL_STAGE_ACK )
{
- _dfu_state_ctx.state = DFU_ERROR;
- return false; // stall on all other requests
+ if ( tud_dfu_abort_cb ) tud_dfu_abort_cb(_dfu_ctx.alt);
}
- break;
- }
- }
- break;
+ break;
- case DFU_DNLOAD_SYNC:
- {
- switch (request->bRequest)
- {
- case DFU_REQUEST_GETSTATUS:
+ case DFU_REQUEST_UPLOAD:
+ if ( stage == CONTROL_STAGE_SETUP )
{
- if ( _dfu_state_ctx.blk_transfer_in_proc )
- {
- _dfu_state_ctx.state = DFU_DNBUSY;
- dfu_req_getstatus_reply(rhport, request);
- } else {
- _dfu_state_ctx.state = DFU_DNLOAD_IDLE;
- dfu_req_getstatus_reply(rhport, request);
- }
- }
- break;
+ TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_UPLOAD);
+ TU_VERIFY(tud_dfu_upload_cb);
+ TU_VERIFY(request->wLength <= CFG_TUD_DFU_XFER_BUFSIZE);
- case DFU_REQUEST_GETSTATE:
- {
- dfu_req_getstate_reply(rhport, request);
- }
- break;
+ uint16_t const xfer_len = tud_dfu_upload_cb(_dfu_ctx.alt, request->wValue, _dfu_ctx.transfer_buf, request->wLength);
- default:
- {
- _dfu_state_ctx.state = DFU_ERROR;
- return false; // stall on all other requests
+ return tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, xfer_len);
}
- break;
- }
- }
- break;
+ break;
- case DFU_DNBUSY:
- {
- switch (request->bRequest)
- {
- default:
+ case DFU_REQUEST_DNLOAD:
+ if ( stage == CONTROL_STAGE_SETUP )
{
- _dfu_state_ctx.state = DFU_ERROR;
- return false; // stall on all other requests
- }
- break;
- }
- }
- break;
+ TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_DOWNLOAD);
+ TU_VERIFY(_dfu_ctx.state == DFU_IDLE || _dfu_ctx.state == DFU_DNLOAD_IDLE);
+ TU_VERIFY(request->wLength <= CFG_TUD_DFU_XFER_BUFSIZE);
- case DFU_DNLOAD_IDLE:
- {
- switch (request->bRequest)
- {
- case DFU_REQUEST_DNLOAD:
- {
- if( ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_CAN_DOWNLOAD_BITMASK) != 0)
- && (request->wLength > 0) )
- {
- _dfu_state_ctx.state = DFU_DNLOAD_SYNC;
- _dfu_state_ctx.blk_transfer_in_proc = true;
- dfu_req_dnload_setup(rhport, request);
- } else {
- if ( tud_dfu_device_data_done_check_cb() )
- {
- _dfu_state_ctx.state = DFU_MANIFEST_SYNC;
- tud_control_status(rhport, request);
- } else {
- _dfu_state_ctx.state = DFU_ERROR;
- return false; // stall
- }
- }
- }
- break;
+ // set to true for both download and manifest
+ _dfu_ctx.flashing_in_progress = true;
- case DFU_REQUEST_GETSTATUS:
+ // save block and length for flashing
+ _dfu_ctx.block = request->wValue;
+ _dfu_ctx.length = request->wLength;
+
+ if ( request->wLength )
{
- dfu_req_getstatus_reply(rhport, request);
+ // Download with payload -> transition to DOWNLOAD SYNC
+ _dfu_ctx.state = DFU_DNLOAD_SYNC;
+ return tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, request->wLength);
}
- break;
-
- case DFU_REQUEST_GETSTATE:
+ else
{
- dfu_req_getstate_reply(rhport, request);
+ // Download is complete -> transition to MANIFEST SYNC
+ _dfu_ctx.state = DFU_MANIFEST_SYNC;
+ return tud_control_status(rhport, request);
}
+ }
+ break;
+
+ case DFU_REQUEST_GETSTATUS:
+ switch ( _dfu_ctx.state )
+ {
+ case DFU_DNLOAD_SYNC:
+ return process_download_get_status(rhport, stage, request);
break;
- case DFU_REQUEST_ABORT:
- {
- if ( tud_dfu_abort_cb )
- {
- tud_dfu_abort_cb();
- }
- _dfu_state_ctx.state = DFU_IDLE;
- }
+ case DFU_MANIFEST_SYNC:
+ return process_manifest_get_status(rhport, stage, request);
break;
default:
- {
- _dfu_state_ctx.state = DFU_ERROR;
- return false; // stall on all other requests
- }
+ if ( stage == CONTROL_STAGE_SETUP ) return reply_getstatus(rhport, request, _dfu_ctx.state, _dfu_ctx.status, 0);
break;
}
+ break;
+
+ default: return false; // stall unsupported request
}
- break;
+ }else
+ {
+ return false; // unsupported request
+ }
- case DFU_MANIFEST_SYNC:
- {
- switch (request->bRequest)
- {
- case DFU_REQUEST_GETSTATUS:
- {
- if ((_dfu_state_ctx.attrs & DFU_FUNC_ATTR_MANIFESTATION_TOLERANT_BITMASK) != 0)
- {
- _dfu_state_ctx.state = DFU_MANIFEST;
- dfu_req_getstatus_reply(rhport, request);
- } else {
- if ( tud_dfu_firmware_valid_check_cb() )
- {
- _dfu_state_ctx.state = DFU_IDLE;
- }
- dfu_req_getstatus_reply(rhport, request);
- }
- }
- break;
+ return true;
+}
- case DFU_REQUEST_GETSTATE:
- {
- dfu_req_getstate_reply(rhport, request);
- }
- break;
+void tud_dfu_finish_flashing(uint8_t status)
+{
+ _dfu_ctx.flashing_in_progress = false;
- default:
- {
- _dfu_state_ctx.state = DFU_ERROR;
- return false; // stall on all other requests
- }
- break;
- }
+ if ( status == DFU_STATUS_OK )
+ {
+ if (_dfu_ctx.state == DFU_DNBUSY)
+ {
+ _dfu_ctx.state = DFU_DNLOAD_SYNC;
}
- break;
-
- case DFU_MANIFEST:
+ else if (_dfu_ctx.state == DFU_MANIFEST)
{
- switch (request->bRequest)
- {
- default:
- {
- return false; // stall on all other requests
- }
- break;
- }
+ _dfu_ctx.state = (_dfu_ctx.attrs & DFU_ATTR_MANIFESTATION_TOLERANT)
+ ? DFU_MANIFEST_SYNC : DFU_MANIFEST_WAIT_RESET;
}
- break;
+ }
+ else
+ {
+ // failed while flashing, move to dfuError
+ _dfu_ctx.state = DFU_ERROR;
+ _dfu_ctx.status = (dfu_status_t)status;
+ }
+}
+
+static bool process_download_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
+{
+ if ( stage == CONTROL_STAGE_SETUP )
+ {
+ // only transition to next state on CONTROL_STAGE_ACK
+ dfu_state_t next_state;
+ uint32_t timeout;
- case DFU_MANIFEST_WAIT_RESET:
+ if ( _dfu_ctx.flashing_in_progress )
{
- // technically we should never even get here, but we will handle it just in case
- TU_LOG2(" DFU was in DFU_MANIFEST_WAIT_RESET and got unexpected request: %u\r\n", request->bRequest);
- switch (request->bRequest)
- {
- default:
- {
- return false; // stall on all other requests
- }
- break;
- }
+ next_state = DFU_DNBUSY;
+ timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, (uint8_t) next_state);
}
- break;
-
- case DFU_UPLOAD_IDLE:
+ else
{
- switch (request->bRequest)
- {
- case DFU_REQUEST_UPLOAD:
- {
- if (dfu_req_upload(rhport, request, request->wValue, request->wLength) != request->wLength)
- {
- _dfu_state_ctx.state = DFU_IDLE;
- }
- }
- break;
-
- case DFU_REQUEST_GETSTATUS:
- {
- dfu_req_getstatus_reply(rhport, request);
- }
- break;
-
- case DFU_REQUEST_GETSTATE:
- {
- dfu_req_getstate_reply(rhport, request);
- }
- break;
-
- case DFU_REQUEST_ABORT:
- {
- if (tud_dfu_abort_cb)
- {
- tud_dfu_abort_cb();
- }
- _dfu_state_ctx.state = DFU_IDLE;
- }
- break;
-
- default:
- {
- return false; // stall on all other requests
- }
- break;
- }
+ next_state = DFU_DNLOAD_IDLE;
+ timeout = 0;
}
- break;
- case DFU_ERROR:
+ return reply_getstatus(rhport, request, next_state, _dfu_ctx.status, timeout);
+ }
+ else if ( stage == CONTROL_STAGE_ACK )
+ {
+ if ( _dfu_ctx.flashing_in_progress )
{
- switch (request->bRequest)
- {
- case DFU_REQUEST_GETSTATUS:
- {
- dfu_req_getstatus_reply(rhport, request);
- }
- break;
+ _dfu_ctx.state = DFU_DNBUSY;
+ tud_dfu_download_cb(_dfu_ctx.alt, _dfu_ctx.block, _dfu_ctx.transfer_buf, _dfu_ctx.length);
+ }else
+ {
+ _dfu_ctx.state = DFU_DNLOAD_IDLE;
+ }
+ }
- case DFU_REQUEST_CLRSTATUS:
- {
- _dfu_state_ctx.state = DFU_IDLE;
- }
- break;
+ return true;
+}
- case DFU_REQUEST_GETSTATE:
- {
- dfu_req_getstate_reply(rhport, request);
- }
- break;
+static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
+{
+ if ( stage == CONTROL_STAGE_SETUP )
+ {
+ // only transition to next state on CONTROL_STAGE_ACK
+ dfu_state_t next_state;
+ uint32_t timeout;
- default:
- {
- return false; // stall on all other requests
- }
- break;
- }
+ if ( _dfu_ctx.flashing_in_progress )
+ {
+ next_state = DFU_MANIFEST;
+ timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, next_state);
+ }
+ else
+ {
+ next_state = DFU_IDLE;
+ timeout = 0;
}
- break;
- default:
- _dfu_state_ctx.state = DFU_ERROR;
- TU_LOG2(" DFU ERROR: Unexpected state\r\nStalling control pipe\r\n");
- return false; // Unexpected state, stall and change to error
+ return reply_getstatus(rhport, request, next_state, _dfu_ctx.status, timeout);
+ }
+ else if ( stage == CONTROL_STAGE_ACK )
+ {
+ if ( _dfu_ctx.flashing_in_progress )
+ {
+ _dfu_ctx.state = DFU_MANIFEST;
+ tud_dfu_manifest_cb(_dfu_ctx.alt);
+ }
+ else
+ {
+ _dfu_ctx.state = DFU_IDLE;
+ }
}
return true;
}
+static bool reply_getstatus(uint8_t rhport, tusb_control_request_t const * request, dfu_state_t state, dfu_status_t status, uint32_t timeout)
+{
+ dfu_status_response_t resp;
+ resp.bStatus = (uint8_t) status;
+ resp.bwPollTimeout[0] = TU_U32_BYTE0(timeout);
+ resp.bwPollTimeout[1] = TU_U32_BYTE1(timeout);
+ resp.bwPollTimeout[2] = TU_U32_BYTE2(timeout);
+ resp.bState = (uint8_t) state;
+ resp.iString = 0;
+
+ return tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_response_t));
+}
#endif
diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h
index 9a09a46b1..fecf8596f 100644
--- a/src/class/dfu/dfu_device.h
+++ b/src/class/dfu/dfu_device.h
@@ -33,38 +33,54 @@
extern "C" {
#endif
+//--------------------------------------------------------------------+
+// Class Driver Default Configure & Validation
+//--------------------------------------------------------------------+
+
+#if !defined(CFG_TUD_DFU_XFER_BUFSIZE)
+ #error "CFG_TUD_DFU_XFER_BUFSIZE must be defined, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR"
+#endif
+
+//--------------------------------------------------------------------+
+// Application API
+//--------------------------------------------------------------------+
+
+// Must be called when the application is done with flashing started by
+// tud_dfu_download_cb() and tud_dfu_manifest_cb().
+// status is DFU_STATUS_OK if successful, any other error status will cause state to enter dfuError
+void tud_dfu_finish_flashing(uint8_t status);
//--------------------------------------------------------------------+
// Application Callback API (weak is optional)
//--------------------------------------------------------------------+
-// Invoked during DFU_MANIFEST_SYNC get status request to check if firmware
-// is valid
-bool tud_dfu_firmware_valid_check_cb(void);
-// Invoked when a DFU_DNLOAD request is received
-// This callback takes the wBlockNum chunk of length length and provides it
-// to the application at the data pointer. This data is only valid for this
-// call, so the app must use it not or copy it.
-void tud_dfu_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length);
+// Note: alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc.
-// Must be called when the application is done using the last block of data
-// provided by tud_dfu_req_dnload_data_cb
-void tud_dfu_dnload_complete(void);
+// Invoked right before tud_dfu_download_cb() (state=DFU_DNBUSY) or tud_dfu_manifest_cb() (state=DFU_MANIFEST)
+// Application return timeout in milliseconds (bwPollTimeout) for the next download/manifest operation.
+// During this period, USB host won't try to communicate with us.
+uint32_t tud_dfu_get_timeout_cb(uint8_t alt, uint8_t state);
-// Invoked during the last DFU_DNLOAD request, signifying that the host believes
-// it is done transmitting data.
-// Return true if the application agrees there is no more data
-// Return false if the device disagrees, which will stall the pipe, and the Host
-// should initiate a recovery procedure
-bool tud_dfu_device_data_done_check_cb(void);
+// Invoked when received DFU_DNLOAD (wLength>0) following by DFU_GETSTATUS (state=DFU_DNBUSY) requests
+// This callback could be returned before flashing op is complete (async).
+// Once finished flashing, application must call tud_dfu_finish_flashing()
+void tud_dfu_download_cb (uint8_t alt, uint16_t block_num, uint8_t const *data, uint16_t length);
-// Invoked when the Host has terminated a download or upload transfer
-TU_ATTR_WEAK void tud_dfu_abort_cb(void);
+// Invoked when download process is complete, received DFU_DNLOAD (wLength=0) following by DFU_GETSTATUS (state=Manifest)
+// Application can do checksum, or actual flashing if buffered entire image previously.
+// Once finished flashing, application must call tud_dfu_finish_flashing()
+void tud_dfu_manifest_cb(uint8_t alt);
-// Invoked when a DFU_UPLOAD request is received
-// This callback must populate data with up to length bytes
-// Return the number of bytes to write
-uint16_t tud_dfu_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length);
+// Invoked when received DFU_UPLOAD request
+// Application must populate data with up to length bytes and
+// Return the number of written bytes
+TU_ATTR_WEAK uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length);
+
+// Invoked when a DFU_DETACH request is received
+TU_ATTR_WEAK void tud_dfu_detach_cb(void);
+
+// Invoked when the Host has terminated a download or upload transfer
+TU_ATTR_WEAK void tud_dfu_abort_cb(uint8_t alt);
//--------------------------------------------------------------------+
// Internal Class Driver API
diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c
index 07e6f30f3..afee2aa1f 100644
--- a/src/class/dfu/dfu_rt_device.c
+++ b/src/class/dfu/dfu_rt_device.c
@@ -108,10 +108,10 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request
case DFU_REQUEST_GETSTATUS:
{
TU_LOG2(" DFU RT Request: GETSTATUS\r\n");
- dfu_status_req_payload_t resp;
+ dfu_status_response_t resp;
// Status = OK, Poll timeout is ignored during RT, State = APP_IDLE, IString = 0
- memset(&resp, 0x00, sizeof(dfu_status_req_payload_t));
- tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_req_payload_t));
+ memset(&resp, 0x00, sizeof(dfu_status_response_t));
+ tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_response_t));
}
break;
diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h
index ec14c9c7c..9265a2ede 100644
--- a/src/class/hid/hid.h
+++ b/src/class/hid/hid.h
@@ -871,10 +871,10 @@ enum
{0, 0 }, /* 0x07 */ \
{0, HID_KEY_BACKSPACE }, /* 0x08 Backspace */ \
{0, HID_KEY_TAB }, /* 0x09 Tab */ \
- {0, HID_KEY_RETURN }, /* 0x0A Line Feed */ \
+ {0, HID_KEY_ENTER }, /* 0x0A Line Feed */ \
{0, 0 }, /* 0x0B */ \
{0, 0 }, /* 0x0C */ \
- {0, HID_KEY_RETURN }, /* 0x0D CR */ \
+ {0, HID_KEY_ENTER }, /* 0x0D CR */ \
{0, 0 }, /* 0x0E */ \
{0, 0 }, /* 0x0F */ \
{0, 0 }, /* 0x10 */ \
diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c
index e44f282c4..2ee80750a 100644
--- a/src/class/hid/hid_device.c
+++ b/src/class/hid/hid_device.c
@@ -121,6 +121,7 @@ bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modi
hid_keyboard_report_t report;
report.modifier = modifier;
+ report.reserved = 0;
if ( keycode )
{
@@ -280,7 +281,21 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t
uint8_t const report_type = tu_u16_high(request->wValue);
uint8_t const report_id = tu_u16_low(request->wValue);
- uint16_t xferlen = tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength);
+ uint8_t* report_buf = p_hid->epin_buf;
+ uint16_t req_len = request->wLength;
+
+ uint16_t xferlen = 0;
+
+ // If host request a specific Report ID, add ID to as 1 byte of response
+ if ( (report_id != HID_REPORT_TYPE_INVALID) && (req_len > 1) )
+ {
+ *report_buf++ = report_id;
+ req_len--;
+
+ xferlen++;
+ }
+
+ xferlen += tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, req_len);
TU_ASSERT( xferlen > 0 );
tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen);
@@ -298,7 +313,17 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t
uint8_t const report_type = tu_u16_high(request->wValue);
uint8_t const report_id = tu_u16_low(request->wValue);
- tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epout_buf, request->wLength);
+ uint8_t const* report_buf = p_hid->epout_buf;
+ uint16_t report_len = request->wLength;
+
+ // If host request a specific Report ID, extract report ID in buffer before invoking callback
+ if ( (report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == report_buf[0]) )
+ {
+ report_buf++;
+ report_len--;
+ }
+
+ tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, report_len);
}
break;
diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h
index e2c950dd1..7f67fa9cf 100644
--- a/src/class/hid/hid_device.h
+++ b/src/class/hid/hid_device.h
@@ -195,16 +195,7 @@ static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y
HID_REPORT_COUNT ( 1 ) ,\
HID_REPORT_SIZE ( 8 ) ,\
HID_INPUT ( HID_CONSTANT ) ,\
- /* 6-byte Keycodes */ \
- HID_USAGE_PAGE ( HID_USAGE_PAGE_KEYBOARD ) ,\
- HID_USAGE_MIN ( 0 ) ,\
- HID_USAGE_MAX_N ( 255, 2 ) ,\
- HID_LOGICAL_MIN ( 0 ) ,\
- HID_LOGICAL_MAX_N( 255, 2 ) ,\
- HID_REPORT_COUNT ( 6 ) ,\
- HID_REPORT_SIZE ( 8 ) ,\
- HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\
- /* 5-bit LED Indicator Kana | Compose | ScrollLock | CapsLock | NumLock */ \
+ /* Output 5-bit LED Indicator Kana | Compose | ScrollLock | CapsLock | NumLock */ \
HID_USAGE_PAGE ( HID_USAGE_PAGE_LED ) ,\
HID_USAGE_MIN ( 1 ) ,\
HID_USAGE_MAX ( 5 ) ,\
@@ -215,6 +206,15 @@ static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y
HID_REPORT_COUNT ( 1 ) ,\
HID_REPORT_SIZE ( 3 ) ,\
HID_OUTPUT ( HID_CONSTANT ) ,\
+ /* 6-byte Keycodes */ \
+ HID_USAGE_PAGE ( HID_USAGE_PAGE_KEYBOARD ) ,\
+ HID_USAGE_MIN ( 0 ) ,\
+ HID_USAGE_MAX_N ( 255, 2 ) ,\
+ HID_LOGICAL_MIN ( 0 ) ,\
+ HID_LOGICAL_MAX_N( 255, 2 ) ,\
+ HID_REPORT_COUNT ( 6 ) ,\
+ HID_REPORT_SIZE ( 8 ) ,\
+ HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ) ,\
HID_COLLECTION_END \
// Mouse Report Descriptor Template
@@ -364,14 +364,14 @@ static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y
/* Input */ \
HID_USAGE ( 0x02 ),\
HID_LOGICAL_MIN ( 0x00 ),\
- HID_LOGICAL_MAX ( 0xff ),\
+ HID_LOGICAL_MAX_N ( 0xff, 2 ),\
HID_REPORT_SIZE ( 8 ),\
HID_REPORT_COUNT( report_size ),\
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ),\
/* Output */ \
HID_USAGE ( 0x03 ),\
HID_LOGICAL_MIN ( 0x00 ),\
- HID_LOGICAL_MAX ( 0xff ),\
+ HID_LOGICAL_MAX_N ( 0xff, 2 ),\
HID_REPORT_SIZE ( 8 ),\
HID_REPORT_COUNT( report_size ),\
HID_OUTPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ),\
diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c
index cde5e23a5..8c66477b3 100644
--- a/src/class/hid/hid_host.c
+++ b/src/class/hid/hid_host.c
@@ -37,16 +37,6 @@
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
-/*
- "KEYBOARD" : in_len=8 , out_len=1, usage_page=0x01, usage=0x06 # Generic Desktop, Keyboard
- "MOUSE" : in_len=4 , out_len=0, usage_page=0x01, usage=0x02 # Generic Desktop, Mouse
- "CONSUMER" : in_len=2 , out_len=0, usage_page=0x0C, usage=0x01 # Consumer, Consumer Control
- "SYS_CONTROL" : in_len=1 , out_len=0, usage_page=0x01, usage=0x80 # Generic Desktop, Sys Control
- "GAMEPAD" : in_len=6 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad
- "DIGITIZER" : in_len=5 , out_len=0, usage_page=0x0D, usage=0x02 # Digitizers, Pen
- "XAC_COMPATIBLE_GAMEPAD" : in_len=3 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad
- "RAW" : in_len=64, out_len=0, usage_page=0xFFAF, usage=0xAF # Vendor 0xFFAF "Adafruit", 0xAF
- */
typedef struct
{
uint8_t itf_num;
@@ -62,8 +52,8 @@ typedef struct
uint16_t epin_size;
uint16_t epout_size;
- uint8_t epin_buf[CFG_TUH_HID_EP_BUFSIZE];
- uint8_t epout_buf[CFG_TUH_HID_EP_BUFSIZE];
+ uint8_t epin_buf[CFG_TUH_HID_EPIN_BUFSIZE];
+ uint8_t epout_buf[CFG_TUH_HID_EPOUT_BUFSIZE];
} hidh_interface_t;
typedef struct
@@ -72,7 +62,7 @@ typedef struct
hidh_interface_t instances[CFG_TUH_HID];
} hidh_device_t;
-static hidh_device_t _hidh_dev[CFG_TUSB_HOST_DEVICE_MAX-1];
+static hidh_device_t _hidh_dev[CFG_TUH_DEVICE_MAX];
//------------- Internal prototypes -------------//
@@ -82,13 +72,8 @@ TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_a
static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf);
static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr);
-TU_ATTR_ALWAYS_INLINE static inline bool hidh_get_report(uint8_t dev_addr, hidh_interface_t* hid_itf)
-{
- return usbh_edpt_xfer(dev_addr, hid_itf->ep_in, hid_itf->epin_buf, hid_itf->epin_size);
-}
-
//--------------------------------------------------------------------+
-// Application API
+// Interface API
//--------------------------------------------------------------------+
uint8_t tuh_hid_instance_count(uint8_t dev_addr)
@@ -108,7 +93,11 @@ uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance)
return hid_itf->itf_protocol;
}
-bool tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance)
+//--------------------------------------------------------------------+
+// Control Endpoint API
+//--------------------------------------------------------------------+
+
+uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance)
{
hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
return hid_itf->protocol_mode;
@@ -196,6 +185,20 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u
return true;
}
+//--------------------------------------------------------------------+
+// Interrupt Endpoint API
+//--------------------------------------------------------------------+
+
+bool tuh_hid_receive_report(uint8_t dev_addr, uint8_t instance)
+{
+ hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
+
+ // claim endpoint
+ TU_VERIFY( usbh_edpt_claim(dev_addr, hid_itf->ep_in) );
+
+ return usbh_edpt_xfer(dev_addr, hid_itf->ep_in, hid_itf->epin_buf, hid_itf->epin_size);
+}
+
//bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance)
//{
// TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance));
@@ -225,11 +228,8 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint3
if ( dir == TUSB_DIR_IN )
{
TU_LOG2(" Get Report callback (%u, %u)\r\n", dev_addr, instance);
- TU_LOG1_MEM(hid_itf->epin_buf, 8, 2);
+ TU_LOG3_MEM(hid_itf->epin_buf, xferred_bytes, 2);
tuh_hid_report_received_cb(dev_addr, instance, hid_itf->epin_buf, xferred_bytes);
-
- // queue next report
- hidh_get_report(dev_addr, hid_itf);
}else
{
if (tuh_hid_report_sent_cb) tuh_hid_report_sent_cb(dev_addr, instance, hid_itf->epout_buf, xferred_bytes);
@@ -240,10 +240,13 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint3
void hidh_close(uint8_t dev_addr)
{
+ TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, );
+
hidh_device_t* hid_dev = get_dev(dev_addr);
+
if (tuh_hid_umount_cb)
{
- for ( uint8_t inst = 0; inst < hid_dev->inst_count; inst++ ) tuh_hid_umount_cb(dev_addr, inst);
+ for (uint8_t inst = 0; inst < hid_dev->inst_count; inst++ ) tuh_hid_umount_cb(dev_addr, inst);
}
tu_memclr(hid_dev, sizeof(hidh_device_t));
@@ -253,14 +256,24 @@ void hidh_close(uint8_t dev_addr)
// Enumeration
//--------------------------------------------------------------------+
-static bool config_get_protocol (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
+static bool config_set_protocol (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
static bool config_get_report_desc (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
static bool config_get_report_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
-bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length)
+static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len);
+
+bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len)
{
+ (void) max_len;
+
TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass);
+ TU_LOG2("HID opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr);
+
+ // len = interface + hid + n*endpoints
+ uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t);
+ TU_ASSERT(max_len >= drv_len);
+
uint8_t const *p_desc = (uint8_t const *) desc_itf;
//------------- HID descriptor -------------//
@@ -271,7 +284,7 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de
// not enough interface, try to increase CFG_TUH_HID
// TODO multiple devices
hidh_device_t* hid_dev = get_dev(dev_addr);
- TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID);
+ TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID, 0);
//------------- Endpoint Descriptor -------------//
p_desc = tu_desc_next(p_desc);
@@ -292,11 +305,10 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de
hid_itf->report_desc_type = desc_hid->bReportType;
hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength);
- hid_itf->protocol_mode = HID_PROTOCOL_REPORT; // Per Specs: default is report mode
+ // Per HID Specs: default is Report protocol, though we will force Boot protocol when set_config
+ hid_itf->protocol_mode = HID_PROTOCOL_BOOT;
if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) hid_itf->itf_protocol = desc_itf->bInterfaceProtocol;
- *p_length = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t);
-
return true;
}
@@ -324,68 +336,82 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num)
.wLength = 0
};
- TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, (hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE) ? config_get_protocol : config_get_report_desc) );
+ TU_ASSERT( tuh_control_xfer(dev_addr, &request, NULL, (hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE) ? config_set_protocol : config_get_report_desc) );
return true;
}
-static bool config_get_protocol(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result)
+// Force device to work in BOOT protocol
+static bool config_set_protocol(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result)
{
- // Stall is a valid response for SET_IDLE GET_PROTOCOL, therefore we could ignore its result
+ // Stall is a valid response for SET_IDLE, therefore we could ignore its result
(void) result;
uint8_t const itf_num = (uint8_t) request->wIndex;
uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num);
hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
- TU_LOG2("HID Get Protocol\r\n");
+ TU_LOG2("HID Set Protocol to Boot Mode\r\n");
+ hid_itf->protocol_mode = HID_PROTOCOL_BOOT;
tusb_control_request_t const new_request =
{
.bmRequestType_bit =
{
.recipient = TUSB_REQ_RCPT_INTERFACE,
.type = TUSB_REQ_TYPE_CLASS,
- .direction = TUSB_DIR_IN
+ .direction = TUSB_DIR_OUT
},
- .bRequest = HID_REQ_CONTROL_GET_PROTOCOL,
- .wValue = 0,
+ .bRequest = HID_REQ_CONTROL_SET_PROTOCOL,
+ .wValue = HID_PROTOCOL_BOOT,
.wIndex = hid_itf->itf_num,
- .wLength = 1
+ .wLength = 0
};
- TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, &hid_itf->protocol_mode, config_get_report_desc) );
- return false;
+ TU_ASSERT( tuh_control_xfer(dev_addr, &new_request, NULL, config_get_report_desc) );
+ return true;
}
static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result)
{
- // Stall is a valid response for SET_IDLE GET_PROTOCOL, therefore we could ignore its result
- (void) result;
+ // We can be here after SET_IDLE or SET_PROTOCOL (boot device)
+ // Trigger assert if result is not successful with set protocol
+ if ( request->bRequest != HID_REQ_CONTROL_SET_IDLE )
+ {
+ TU_ASSERT(result == XFER_RESULT_SUCCESS);
+ }
uint8_t const itf_num = (uint8_t) request->wIndex;
uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num);
hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
- // Get Report Descriptor
+ // Get Report Descriptor if possible
// using usbh enumeration buffer since report descriptor can be very long
- TU_ASSERT( hid_itf->report_desc_len <= CFG_TUH_ENUMERATION_BUFSZIE );
+ if( hid_itf->report_desc_len > CFG_TUH_ENUMERATION_BUFSIZE )
+ {
+ TU_LOG2("HID Skip Report Descriptor since it is too large %u bytes\r\n", hid_itf->report_desc_len);
- TU_LOG2("HID Get Report Descriptor\r\n");
- tusb_control_request_t const new_request =
+ // Driver is mounted without report descriptor
+ config_driver_mount_complete(dev_addr, instance, NULL, 0);
+ }else
{
- .bmRequestType_bit =
+ TU_LOG2("HID Get Report Descriptor\r\n");
+ tusb_control_request_t const new_request =
{
- .recipient = TUSB_REQ_RCPT_INTERFACE,
- .type = TUSB_REQ_TYPE_STANDARD,
- .direction = TUSB_DIR_IN
- },
- .bRequest = TUSB_REQ_GET_DESCRIPTOR,
- .wValue = tu_u16(hid_itf->report_desc_type, 0),
- .wIndex = itf_num,
- .wLength = hid_itf->report_desc_len
- };
+ .bmRequestType_bit =
+ {
+ .recipient = TUSB_REQ_RCPT_INTERFACE,
+ .type = TUSB_REQ_TYPE_STANDARD,
+ .direction = TUSB_DIR_IN
+ },
+ .bRequest = TUSB_REQ_GET_DESCRIPTOR,
+ .wValue = tu_u16(hid_itf->report_desc_type, 0),
+ .wIndex = itf_num,
+ .wLength = hid_itf->report_desc_len
+ };
+
+ TU_ASSERT(tuh_control_xfer(dev_addr, &new_request, usbh_get_enum_buf(), config_get_report_desc_complete));
+ }
- TU_ASSERT(tuh_control_xfer(dev_addr, &new_request, usbh_get_enum_buf(), config_get_report_desc_complete));
return true;
}
@@ -393,23 +419,26 @@ static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_reque
{
TU_ASSERT(XFER_RESULT_SUCCESS == result);
- uint8_t const itf_num = (uint8_t) request->wIndex;
- uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num);
- hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
+ uint8_t const itf_num = (uint8_t) request->wIndex;
+ uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num);
uint8_t const* desc_report = usbh_get_enum_buf();
uint16_t const desc_len = request->wLength;
+ config_driver_mount_complete(dev_addr, instance, desc_report, desc_len);
+
+ return true;
+}
+
+static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len)
+{
+ hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
+
// enumeration is complete
tuh_hid_mount_cb(dev_addr, instance, desc_report, desc_len);
- // queue transfer for IN endpoint
- hidh_get_report(dev_addr, hid_itf);
-
// notify usbh that driver enumeration is complete
- usbh_driver_set_config_complete(dev_addr, itf_num);
-
- return true;
+ usbh_driver_set_config_complete(dev_addr, hid_itf->itf_num);
}
//--------------------------------------------------------------------+
@@ -452,9 +481,9 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info_arr,
uint8_t const data8 = desc_report[0];
- TU_LOG2("tag = %d, type = %d, size = %d, data = ", tag, type, size);
- for(uint32_t i=0; i<size; i++) TU_LOG2("%02X ", desc_report[i]);
- TU_LOG2("\r\n");
+ TU_LOG(3, "tag = %d, type = %d, size = %d, data = ", tag, type, size);
+ for(uint32_t i=0; i<size; i++) TU_LOG(3, "%02X ", desc_report[i]);
+ TU_LOG(3, "\r\n");
switch(type)
{
diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h
index 2e4cce600..fe09b03b2 100644
--- a/src/class/hid/hid_host.h
+++ b/src/class/hid/hid_host.h
@@ -38,10 +38,15 @@
//--------------------------------------------------------------------+
// TODO Highspeed interrupt can be up to 512 bytes
-#ifndef CFG_TUH_HID_EP_BUFSIZE
-#define CFG_TUH_HID_EP_BUFSIZE 64
+#ifndef CFG_TUH_HID_EPIN_BUFSIZE
+#define CFG_TUH_HID_EPIN_BUFSIZE 64
#endif
+#ifndef CFG_TUH_HID_EPOUT_BUFSIZE
+#define CFG_TUH_HID_EPOUT_BUFSIZE 64
+#endif
+
+
typedef struct
{
uint8_t report_id;
@@ -54,7 +59,7 @@ typedef struct
} tuh_hid_report_info_t;
//--------------------------------------------------------------------+
-// Application API
+// Interface API
//--------------------------------------------------------------------+
// Get the number of HID instances
@@ -66,9 +71,18 @@ bool tuh_hid_mounted(uint8_t dev_addr, uint8_t instance);
// Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values
uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance);
-// Get current active protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1)
-// Note: as HID spec, device will be initialized in Report mode
-bool tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance);
+// Parse report descriptor into array of report_info struct and return number of reports.
+// For complicated report, application should write its own parser.
+uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED;
+
+//--------------------------------------------------------------------+
+// Control Endpoint API
+//--------------------------------------------------------------------+
+
+// Get current protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1)
+// Note: Device will be initialized in Boot protocol for simplicity.
+// Application can use set_protocol() to switch back to Report protocol.
+uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance);
// Set protocol to HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1)
// This function is only supported by Boot interface (tuh_n_hid_interface_protocol() != NONE)
@@ -78,13 +92,18 @@ bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol);
// report_type is either Intput, Output or Feature, (value from hid_report_type_t)
bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len);
-// Parse report descriptor into array of report_info struct and return number of reports.
-// For complicated report, application should write its own parser.
-uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED;
+//--------------------------------------------------------------------+
+// Interrupt Endpoint API
+//--------------------------------------------------------------------+
// Check if the interface is ready to use
//bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance);
+// Try to receive next report on Interrupt Endpoint. Immediately return
+// - true If succeeded, tuh_hid_report_received_cb() callback will be invoked when report is available
+// - false if failed to queue the transfer e.g endpoint is busy
+bool tuh_hid_receive_report(uint8_t dev_addr, uint8_t instance);
+
// Send report using interrupt endpoint
// If report_id > 0 (composite), it will be sent as 1st byte, then report contents. Otherwise only report content is sent.
//void tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t const* report, uint16_t len);
@@ -96,6 +115,8 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr,
// Invoked when device with hid interface is mounted
// Report descriptor is also available for use. tuh_hid_parse_report_descriptor()
// can be used to parse common/simple enough descriptor.
+// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped
+// therefore report_desc = NULL, desc_len = 0
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len);
// Invoked when device with hid interface is un-mounted
@@ -118,11 +139,11 @@ TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t ins
//--------------------------------------------------------------------+
// Internal Class Driver API
//--------------------------------------------------------------------+
-void hidh_init(void);
-bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length);
-bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num);
-bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
-void hidh_close(uint8_t dev_addr);
+void hidh_init (void);
+bool hidh_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len);
+bool hidh_set_config (uint8_t dev_addr, uint8_t itf_num);
+bool hidh_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
+void hidh_close (uint8_t dev_addr);
#ifdef __cplusplus
}
diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c
index 953ca26e6..eb85b668c 100644
--- a/src/class/midi/midi_device.c
+++ b/src/class/midi/midi_device.c
@@ -122,7 +122,12 @@ static void _prep_out_transaction (midid_interface_t* p_midi)
uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num)
{
(void) cable_num;
- return tu_fifo_count(&_midid_itf[itf].rx_ff);
+
+ midid_interface_t* midi = &_midid_itf[itf];
+ midid_stream_t const* stream = &midi->stream_read;
+
+ // when using with packet API stream total & index are both zero
+ return tu_fifo_count(&midi->rx_ff) + (stream->total - stream->index);
}
uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize)
@@ -197,9 +202,11 @@ uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, ui
bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4])
{
- midid_interface_t* p_midi = &_midid_itf[itf];
- uint32_t num_read = tu_fifo_read_n(&p_midi->rx_ff, packet, 4);
- _prep_out_transaction(p_midi);
+ midid_interface_t* midi = &_midid_itf[itf];
+ TU_VERIFY(midi->ep_out);
+
+ uint32_t const num_read = tu_fifo_read_n(&midi->rx_ff, packet, 4);
+ _prep_out_transaction(midi);
return (num_read == 4);
}
@@ -234,19 +241,19 @@ static uint32_t write_flush(midid_interface_t* midi)
uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize)
{
midid_interface_t* midi = &_midid_itf[itf];
- TU_VERIFY(midi->itf_num, 0);
+ TU_VERIFY(midi->ep_in, 0);
midid_stream_t* stream = &midi->stream_write;
- uint32_t total_written = 0;
uint32_t i = 0;
- while ( i < bufsize )
+ while ( (i < bufsize) && (tu_fifo_remaining(&midi->tx_ff) >= 4) )
{
uint8_t const data = buffer[i];
+ i++;
if ( stream->index == 0 )
{
- // new event packet
+ //------------- New event packet -------------//
uint8_t const msg = data >> 4;
@@ -308,9 +315,9 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const*
}
else
{
- // On-going (buffering) packet
+ //------------- On-going (buffering) packet -------------//
- TU_ASSERT(stream->index < 4, total_written);
+ TU_ASSERT(stream->index < 4, i);
stream->buffer[stream->index] = data;
stream->index++;
@@ -333,27 +340,20 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const*
// complete current event packet, reset stream
stream->index = stream->total = 0;
- // fifo overflow, here we assume FIFO is multiple of 4 and didn't check remaining before writing
- if ( count != 4 ) break;
-
- // updated written if succeeded
- total_written = i;
+ // FIFO overflown, since we already check fifo remaining. It is probably race condition
+ TU_ASSERT(count == 4, i);
}
-
- i++;
}
write_flush(midi);
- return total_written;
+ return i;
}
bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4])
{
midid_interface_t* midi = &_midid_itf[itf];
- if (midi->itf_num == 0) {
- return 0;
- }
+ TU_VERIFY(midi->ep_in);
if (tu_fifo_remaining(&midi->tx_ff) < 4) return false;
@@ -435,6 +435,7 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint
}
p_midi->itf_num = desc_midi->bInterfaceNumber;
+ (void) p_midi->itf_num;
// next descriptor
drv_len += tu_desc_len(p_desc);
diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c
index 7f13b4891..0fd592129 100644
--- a/src/class/msc/msc_device.c
+++ b/src/class/msc/msc_device.c
@@ -37,12 +37,17 @@
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
+
+// Can be selectively disabled to reduce logging when troubleshooting other driver
+#define MSC_DEBUG 2
+
enum
{
MSC_STAGE_CMD = 0,
MSC_STAGE_DATA,
MSC_STAGE_STATUS,
- MSC_STAGE_STATUS_SENT
+ MSC_STAGE_STATUS_SENT,
+ MSC_STAGE_NEED_RESET,
};
typedef struct
@@ -57,7 +62,7 @@ typedef struct
// Bulk Only Transfer (BOT) Protocol
uint8_t stage;
- uint32_t total_len;
+ uint32_t total_len; // byte to be transferred, can be smaller than total_bytes in cbw
uint32_t xferred_len; // numbered of bytes transferred so far in the Data Stage
// Sense Response Data
@@ -74,7 +79,55 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _mscd_buf[CFG_TUD_MSC_EP_
//--------------------------------------------------------------------+
static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize);
static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc);
+
static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc);
+static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint32_t xferred_bytes);
+
+TU_ATTR_ALWAYS_INLINE static inline bool is_data_in(uint8_t dir)
+{
+ return tu_bit_test(dir, 7);
+}
+
+static inline bool send_csw(uint8_t rhport, mscd_interface_t* p_msc)
+{
+ // Data residue is always = host expect - actual transferred
+ p_msc->csw.data_residue = p_msc->cbw.total_bytes - p_msc->xferred_len;
+
+ p_msc->stage = MSC_STAGE_STATUS_SENT;
+ return usbd_edpt_xfer(rhport, p_msc->ep_in , (uint8_t*) &p_msc->csw, sizeof(msc_csw_t));
+}
+
+static inline bool prepare_cbw(uint8_t rhport, mscd_interface_t* p_msc)
+{
+ p_msc->stage = MSC_STAGE_CMD;
+ return usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t));
+}
+
+static void fail_scsi_op(uint8_t rhport, mscd_interface_t* p_msc, uint8_t status)
+{
+ msc_cbw_t const * p_cbw = &p_msc->cbw;
+ msc_csw_t * p_csw = &p_msc->csw;
+
+ p_csw->status = status;
+ p_csw->data_residue = p_msc->cbw.total_bytes - p_msc->xferred_len;
+ p_msc->stage = MSC_STAGE_STATUS;
+
+ // failed but sense key is not set: default to Illegal Request
+ if ( p_msc->sense_key == 0 ) tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
+
+ // If there is data stage and not yet complete, stall it
+ if ( p_cbw->total_bytes && p_csw->data_residue )
+ {
+ if ( is_data_in(p_cbw->dir) )
+ {
+ usbd_edpt_stall(rhport, p_msc->ep_in);
+ }
+ else
+ {
+ usbd_edpt_stall(rhport, p_msc->ep_out);
+ }
+ }
+}
static inline uint32_t rdwr10_get_lba(uint8_t const command[])
{
@@ -85,21 +138,66 @@ static inline uint32_t rdwr10_get_lba(uint8_t const command[])
return tu_ntohl(lba);
}
-static inline uint16_t rdwr10_get_blockcount(uint8_t const command[])
+static inline uint16_t rdwr10_get_blockcount(msc_cbw_t const* cbw)
{
- // use offsetof to avoid pointer to the odd/misaligned address
- uint16_t const block_count = tu_unaligned_read16(command + offsetof(scsi_write10_t, block_count));
-
- // block count is in Big Endian
+ uint16_t const block_count = tu_unaligned_read16(cbw->command + offsetof(scsi_write10_t, block_count));
return tu_ntohs(block_count);
}
+static inline uint16_t rdwr10_get_blocksize(msc_cbw_t const* cbw)
+{
+ // first extract block count in the command
+ uint16_t const block_count = rdwr10_get_blockcount(cbw);
+
+ // invalid block count
+ if (block_count == 0) return 0;
+
+ return cbw->total_bytes / block_count;
+}
+
+uint8_t rdwr10_validate_cmd(msc_cbw_t const* cbw)
+{
+ uint8_t status = MSC_CSW_STATUS_PASSED;
+ uint16_t const block_count = rdwr10_get_blockcount(cbw);
+
+ if ( cbw->total_bytes == 0 )
+ {
+ if ( block_count )
+ {
+ TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di) or case 3 (Hn < Do) \r\n");
+ status = MSC_CSW_STATUS_PHASE_ERROR;
+ }else
+ {
+ // no data transfer, only exist in complaint test suite
+ }
+ }else
+ {
+ if ( SCSI_CMD_READ_10 == cbw->command[0] && !is_data_in(cbw->dir) )
+ {
+ TU_LOG(MSC_DEBUG, " SCSI case 10 (Ho <> Di)\r\n");
+ status = MSC_CSW_STATUS_PHASE_ERROR;
+ }
+ else if ( SCSI_CMD_WRITE_10 == cbw->command[0] && is_data_in(cbw->dir) )
+ {
+ TU_LOG(MSC_DEBUG, " SCSI case 8 (Hi <> Do)\r\n");
+ status = MSC_CSW_STATUS_PHASE_ERROR;
+ }
+ else if ( !block_count )
+ {
+ TU_LOG(MSC_DEBUG, " SCSI case 4 Hi > Dn\r\n");
+ status = MSC_CSW_STATUS_FAILED;
+ }
+ }
+
+ return status;
+}
+
//--------------------------------------------------------------------+
// Debug
//--------------------------------------------------------------------+
#if CFG_TUSB_DEBUG >= 2
-static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] =
+TU_ATTR_UNUSED static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] =
{
{ .key = SCSI_CMD_TEST_UNIT_READY , .data = "Test Unit Ready" },
{ .key = SCSI_CMD_INQUIRY , .data = "Inquiry" },
@@ -114,7 +212,7 @@ static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] =
{ .key = SCSI_CMD_WRITE_10 , .data = "Write10" }
};
-static tu_lookup_table_t const _msc_scsi_cmd_table =
+TU_ATTR_UNUSED static tu_lookup_table_t const _msc_scsi_cmd_table =
{
.count = TU_ARRAY_SIZE(_msc_scsi_cmd_lookup),
.items = _msc_scsi_cmd_lookup
@@ -170,35 +268,93 @@ uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
TU_ASSERT( usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in), 0 );
// Prepare for Command Block Wrapper
- if ( !usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)) )
- {
- TU_LOG_FAILED();
- TU_BREAKPOINT();
- }
+ TU_ASSERT( prepare_cbw(rhport, p_msc), drv_len);
return drv_len;
}
+static void proc_bot_reset(mscd_interface_t* p_msc)
+{
+ p_msc->stage = MSC_STAGE_CMD;
+ p_msc->total_len = 0;
+ p_msc->xferred_len = 0;
+
+ p_msc->sense_key = 0;
+ p_msc->add_sense_code = 0;
+ p_msc->add_sense_qualifier = 0;
+}
+
// Invoked when a control transfer occurred on an interface of this class
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
// return false to stall control endpoint (e.g unsupported request)
-bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * p_request)
+bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
{
// nothing to do with DATA & ACK stage
if (stage != CONTROL_STAGE_SETUP) return true;
- // Handle class request only
- TU_VERIFY(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
+ mscd_interface_t* p_msc = &_mscd_itf;
+
+ // Clear Endpoint Feature (stall) for recovery
+ if ( TUSB_REQ_TYPE_STANDARD == request->bmRequestType_bit.type &&
+ TUSB_REQ_RCPT_ENDPOINT == request->bmRequestType_bit.recipient &&
+ TUSB_REQ_CLEAR_FEATURE == request->bRequest &&
+ TUSB_REQ_FEATURE_EDPT_HALT == request->wValue )
+ {
+ uint8_t const ep_addr = tu_u16_low(request->wIndex);
+
+ if ( p_msc->stage == MSC_STAGE_NEED_RESET )
+ {
+ // reset recovery is required to recover from this stage
+ // Clear Stall request cannot resolve this -> continue to stall endpoint
+ usbd_edpt_stall(rhport, ep_addr);
+ }
+ else
+ {
+ if ( ep_addr == p_msc->ep_in )
+ {
+ if ( p_msc->stage == MSC_STAGE_STATUS )
+ {
+ // resume sending SCSI status if we are in this stage previously before stalled
+ TU_ASSERT( send_csw(rhport, p_msc) );
+ }
+ }
+ else if ( ep_addr == p_msc->ep_out )
+ {
+ if ( p_msc->stage == MSC_STAGE_CMD )
+ {
+ // part of reset recovery (probably due to invalid CBW) -> prepare for new command
+ // Note: skip if already queued previously
+ if ( usbd_edpt_ready(rhport, p_msc->ep_out) )
+ {
+ TU_ASSERT( prepare_cbw(rhport, p_msc) );
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ // From this point only handle class request only
+ TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
- switch ( p_request->bRequest )
+ switch ( request->bRequest )
{
case MSC_REQ_RESET:
- // TODO: Actually reset interface.
- tud_control_status(rhport, p_request);
+ TU_LOG(MSC_DEBUG, " MSC BOT Reset\r\n");
+ TU_VERIFY(request->wValue == 0 && request->wLength == 0);
+
+ // driver state reset
+ proc_bot_reset(p_msc);
+
+ tud_control_status(rhport, request);
break;
case MSC_REQ_GET_MAX_LUN:
{
+ TU_LOG(MSC_DEBUG, " MSC Get Max Lun\r\n");
+ TU_VERIFY(request->wValue == 0 && request->wLength == 1);
+
uint8_t maxlun = 1;
if (tud_msc_get_maxlun_cb) maxlun = tud_msc_get_maxlun_cb();
TU_VERIFY(maxlun);
@@ -206,7 +362,7 @@ bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
// MAX LUN is minus 1 by specs
maxlun--;
- tud_control_xfer(rhport, p_request, &maxlun, 1);
+ tud_control_xfer(rhport, request, &maxlun, 1);
}
break;
@@ -218,6 +374,8 @@ bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes)
{
+ (void) event;
+
mscd_interface_t* p_msc = &_mscd_itf;
msc_cbw_t const * p_cbw = &p_msc->cbw;
msc_csw_t * p_csw = &p_msc->csw;
@@ -229,46 +387,79 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
// Complete IN while waiting for CMD is usually Status of previous SCSI op, ignore it
if(ep_addr != p_msc->ep_out) return true;
- TU_ASSERT( event == XFER_RESULT_SUCCESS &&
- xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE );
+ if ( !(xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE) )
+ {
+ TU_LOG(MSC_DEBUG, " SCSI CBW is not valid\r\n");
- TU_LOG2(" SCSI Command: %s\r\n", tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0]));
- // TU_LOG2_MEM(p_cbw, xferred_bytes, 2);
+ // BOT 6.6.1 If CBW is not valid stall both endpoints until reset recovery
+ p_msc->stage = MSC_STAGE_NEED_RESET;
+
+ // invalid CBW stall both endpoints
+ usbd_edpt_stall(rhport, p_msc->ep_in);
+ usbd_edpt_stall(rhport, p_msc->ep_out);
+
+ return false;
+ }
+
+ TU_LOG(MSC_DEBUG, " SCSI Command: %s\r\n", tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0]));
+ //TU_LOG_MEM(MSC_DEBUG, p_cbw, xferred_bytes, 2);
p_csw->signature = MSC_CSW_SIGNATURE;
p_csw->tag = p_cbw->tag;
p_csw->data_residue = 0;
+ p_csw->status = MSC_CSW_STATUS_PASSED;
/*------------- Parse command and prepare DATA -------------*/
p_msc->stage = MSC_STAGE_DATA;
p_msc->total_len = p_cbw->total_bytes;
p_msc->xferred_len = 0;
- if (SCSI_CMD_READ_10 == p_cbw->command[0])
- {
- proc_read10_cmd(rhport, p_msc);
- }
- else if (SCSI_CMD_WRITE_10 == p_cbw->command[0])
+ // Read10 or Write10
+ if ( (SCSI_CMD_READ_10 == p_cbw->command[0]) || (SCSI_CMD_WRITE_10 == p_cbw->command[0]) )
{
- proc_write10_cmd(rhport, p_msc);
+ uint8_t const status = rdwr10_validate_cmd(p_cbw);
+
+ if ( status != MSC_CSW_STATUS_PASSED)
+ {
+ fail_scsi_op(rhport, p_msc, status);
+ }else if ( p_cbw->total_bytes )
+ {
+ if (SCSI_CMD_READ_10 == p_cbw->command[0])
+ {
+ proc_read10_cmd(rhport, p_msc);
+ }else
+ {
+ proc_write10_cmd(rhport, p_msc);
+ }
+ }else
+ {
+ // no data transfer, only exist in complaint test suite
+ p_msc->stage = MSC_STAGE_STATUS;
+ }
}
else
{
// For other SCSI commands
// 1. OUT : queue transfer (invoke app callback after done)
// 2. IN & Zero: Process if is built-in, else Invoke app callback. Skip DATA if zero length
- if ( (p_cbw->total_bytes > 0 ) && !tu_bit_test(p_cbw->dir, 7) )
+ if ( (p_cbw->total_bytes > 0 ) && !is_data_in(p_cbw->dir) )
{
- // queue transfer
- TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, p_msc->total_len) );
+ if (p_cbw->total_bytes > sizeof(_mscd_buf))
+ {
+ TU_LOG(MSC_DEBUG, " SCSI reject non READ10/WRITE10 with large data\r\n");
+ fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
+ }else
+ {
+ // Didn't check for case 9 (Ho > Dn), which requires examining scsi command first
+ // but it is OK to just receive data then responded with failed status
+ TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, p_msc->total_len) );
+ }
}else
{
- int32_t resplen;
-
// First process if it is a built-in commands
- resplen = proc_builtin_scsi(p_cbw->lun, p_cbw->command, _mscd_buf, sizeof(_mscd_buf));
+ int32_t resplen = proc_builtin_scsi(p_cbw->lun, p_cbw->command, _mscd_buf, sizeof(_mscd_buf));
- // Not built-in, invoke user callback
+ // Invoke user callback if not built-in
if ( (resplen < 0) && (p_msc->sense_key == 0) )
{
resplen = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, p_msc->total_len);
@@ -276,119 +467,90 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
if ( resplen < 0 )
{
- p_msc->total_len = 0;
- p_csw->status = MSC_CSW_STATUS_FAILED;
- p_msc->stage = MSC_STAGE_STATUS;
-
- // failed but senskey is not set: default to Illegal Request
- if ( p_msc->sense_key == 0 ) tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
-
- // Stall bulk In if needed
- if (p_cbw->total_bytes) usbd_edpt_stall(rhport, p_msc->ep_in);
+ // unsupported command
+ TU_LOG(MSC_DEBUG, " SCSI unsupported command\r\n");
+ fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
}
- else
+ else if (resplen == 0)
{
- p_msc->total_len = (uint32_t) resplen;
- p_csw->status = MSC_CSW_STATUS_PASSED;
-
- if (p_msc->total_len)
+ if (p_cbw->total_bytes)
{
- TU_ASSERT( p_cbw->total_bytes >= p_msc->total_len ); // cannot return more than host expect
- TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, p_msc->total_len) );
+ // 6.7 The 13 Cases: case 4 (Hi > Dn)
+ TU_LOG(MSC_DEBUG, " SCSI case 4 (Hi > Dn): %lu\r\n", p_cbw->total_bytes);
+ fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
}else
{
+ // case 1 Hn = Dn: all good
p_msc->stage = MSC_STAGE_STATUS;
}
}
+ else
+ {
+ if ( p_cbw->total_bytes == 0 )
+ {
+ // 6.7 The 13 Cases: case 2 (Hn < Di)
+ TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di): %lu\r\n", p_cbw->total_bytes);
+ fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
+ }else
+ {
+ // cannot return more than host expect
+ p_msc->total_len = tu_min32((uint32_t) resplen, p_cbw->total_bytes);
+ TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, p_msc->total_len) );
+ }
+ }
}
}
break;
case MSC_STAGE_DATA:
- TU_LOG2(" SCSI Data\r\n");
- //TU_LOG2_MEM(_mscd_buf, xferred_bytes, 2);
+ TU_LOG(MSC_DEBUG, " SCSI Data\r\n");
+ //TU_LOG_MEM(MSC_DEBUG, _mscd_buf, xferred_bytes, 2);
- // OUT transfer, invoke callback if needed
- if ( !tu_bit_test(p_cbw->dir, 7) )
+ if (SCSI_CMD_READ_10 == p_cbw->command[0])
{
- if ( SCSI_CMD_WRITE_10 != p_cbw->command[0] )
- {
- int32_t cb_result = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, p_msc->total_len);
+ p_msc->xferred_len += xferred_bytes;
- if ( cb_result < 0 )
- {
- p_csw->status = MSC_CSW_STATUS_FAILED;
- tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); // Sense = Invalid Command Operation
- }else
- {
- p_csw->status = MSC_CSW_STATUS_PASSED;
- }
- }
- else
+ if ( p_msc->xferred_len >= p_msc->total_len )
{
- uint16_t const block_sz = p_cbw->total_bytes / rdwr10_get_blockcount(p_cbw->command);
-
- // Adjust lba with transferred bytes
- uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz);
+ // Data Stage is complete
+ p_msc->stage = MSC_STAGE_STATUS;
+ }else
+ {
+ proc_read10_cmd(rhport, p_msc);
+ }
+ }
+ else if (SCSI_CMD_WRITE_10 == p_cbw->command[0])
+ {
+ proc_write10_new_data(rhport, p_msc, xferred_bytes);
+ }
+ else
+ {
+ p_msc->xferred_len += xferred_bytes;
- // Application can consume smaller bytes
- int32_t nbytes = tud_msc_write10_cb(p_cbw->lun, lba, p_msc->xferred_len % block_sz, _mscd_buf, xferred_bytes);
+ // OUT transfer, invoke callback if needed
+ if ( !is_data_in(p_cbw->dir) )
+ {
+ int32_t cb_result = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, p_msc->total_len);
- if ( nbytes < 0 )
+ if ( cb_result < 0 )
{
- // negative means error -> skip to status phase, status in CSW set to failed
- p_csw->data_residue = p_cbw->total_bytes - p_msc->xferred_len;
- p_csw->status = MSC_CSW_STATUS_FAILED;
- p_msc->stage = MSC_STAGE_STATUS;
-
- tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); // Sense = Invalid Command Operation
- break;
+ // unsupported command
+ TU_LOG(MSC_DEBUG, " SCSI unsupported command\r\n");
+ fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
}else
{
- // Application consume less than what we got (including zero)
- if ( nbytes < (int32_t) xferred_bytes )
- {
- if ( nbytes > 0 )
- {
- p_msc->xferred_len += nbytes;
- memmove(_mscd_buf, _mscd_buf+nbytes, xferred_bytes-nbytes);
- }
-
- // simulate an transfer complete with adjusted parameters --> this driver callback will fired again
- dcd_event_xfer_complete(rhport, p_msc->ep_out, xferred_bytes-nbytes, XFER_RESULT_SUCCESS, false);
-
- return true; // skip the rest
- }
- else
- {
- // Application consume all bytes in our buffer. Nothing to do, process with normal flow
- }
+ // TODO haven't implement this scenario any further yet
}
}
- }
- // Accumulate data so far
- p_msc->xferred_len += xferred_bytes;
-
- if ( p_msc->xferred_len >= p_msc->total_len )
- {
- // Data Stage is complete
- p_msc->stage = MSC_STAGE_STATUS;
- }
- else
- {
- // READ10 & WRITE10 Can be executed with large bulk of data e.g write 8K bytes (several flash write)
- // We break it into multiple smaller command whose data size is up to CFG_TUD_MSC_EP_BUFSIZE
- if (SCSI_CMD_READ_10 == p_cbw->command[0])
+ if ( p_msc->xferred_len >= p_msc->total_len )
{
- proc_read10_cmd(rhport, p_msc);
+ // Data Stage is complete
+ p_msc->stage = MSC_STAGE_STATUS;
}
- else if (SCSI_CMD_WRITE_10 == p_cbw->command[0])
- {
- proc_write10_cmd(rhport, p_msc);
- }else
+ else
{
- // No other command take more than one transfer yet -> unlikely error
+ // This scenario with command that take more than one transfer is already rejected at Command stage
TU_BREAKPOINT();
}
}
@@ -402,8 +564,8 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
// Wait for the Status phase to complete
if( (ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t)) )
{
- TU_LOG2(" SCSI Status: %u\r\n", p_csw->status);
- // TU_LOG2_MEM(p_csw, xferred_bytes, 2);
+ TU_LOG(MSC_DEBUG, " SCSI Status = %u\r\n", p_csw->status);
+ // TU_LOG_MEM(MSC_DEBUG, p_csw, xferred_bytes, 2);
// Invoke complete callback if defined
// Note: There is racing issue with samd51 + qspi flash testing with arduino
@@ -423,11 +585,11 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
break;
}
- // Move to default CMD stage
- p_msc->stage = MSC_STAGE_CMD;
-
- // Queue for the next CBW
- TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)) );
+ TU_ASSERT( prepare_cbw(rhport, p_msc) );
+ }else
+ {
+ // Any xfer ended here is consider unknown error, ignore it
+ TU_LOG1(" Warning expect SCSI Status but received unknown data\r\n");
}
break;
@@ -436,22 +598,30 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
if ( p_msc->stage == MSC_STAGE_STATUS )
{
- // Either endpoints is stalled, need to wait until it is cleared by host
- if ( usbd_edpt_stalled(rhport, p_msc->ep_in) || usbd_edpt_stalled(rhport, p_msc->ep_out) )
+ // skip status if epin is currently stalled, will do it when received Clear Stall request
+ if ( !usbd_edpt_stalled(rhport, p_msc->ep_in) )
{
- // simulate an transfer complete with adjusted parameters --> this driver callback will fired again
- // and response with status phase after halted endpoints are cleared.
- // note: use ep_out to prevent confusing with STATUS complete
- dcd_event_xfer_complete(rhport, p_msc->ep_out, 0, XFER_RESULT_SUCCESS, false);
+ if ( (p_cbw->total_bytes > p_msc->xferred_len) && is_data_in(p_cbw->dir) )
+ {
+ // 6.7 The 13 Cases: case 5 (Hi > Di): STALL before status
+ TU_LOG(MSC_DEBUG, " SCSI case 5 (Hi > Di): %lu > %lu\r\n", p_cbw->total_bytes, p_msc->xferred_len);
+ usbd_edpt_stall(rhport, p_msc->ep_in);
+ }else
+ {
+ TU_ASSERT( send_csw(rhport, p_msc) );
+ }
}
- else
- {
- // Move to Status Sent stage
- p_msc->stage = MSC_STAGE_STATUS_SENT;
- // Send SCSI Status
- TU_ASSERT(usbd_edpt_xfer(rhport, p_msc->ep_in , (uint8_t*) &p_msc->csw, sizeof(msc_csw_t)));
+ #if TU_CHECK_MCU(CXD56)
+ // WORKAROUND: cxd56 has its own nuttx usb stack which does not forward Set/ClearFeature(Endpoint) to DCD.
+ // There is no way for us to know when EP is un-stall, therefore we will unconditionally un-stall here and
+ // hope everything will work
+ if ( usbd_edpt_stalled(rhport, p_msc->ep_in) )
+ {
+ usbd_edpt_clear_stall(rhport, p_msc->ep_in);
+ send_csw(rhport, p_msc);
}
+ #endif
}
return true;
@@ -468,6 +638,8 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
(void) bufsize; // TODO refractor later
int32_t resplen;
+ mscd_interface_t* p_msc = &_mscd_itf;
+
switch ( scsi_cmd[0] )
{
case SCSI_CMD_TEST_UNIT_READY:
@@ -478,7 +650,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
resplen = - 1;
// If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable
- if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00);
+ if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00);
}
break;
@@ -494,7 +666,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
resplen = - 1;
// If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable
- if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00);
+ if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00);
}
}
break;
@@ -515,7 +687,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
resplen = -1;
// If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable
- if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00);
+ if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00);
}else
{
scsi_read_capacity10_resp_t read_capa10;
@@ -551,7 +723,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
resplen = -1;
// If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable
- if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00);
+ if ( p_msc->sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00);
}else
{
read_fmt_capa.block_num = tu_htonl(block_count);
@@ -596,9 +768,11 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
};
bool writable = true;
- if (tud_msc_is_writable_cb) {
- writable = tud_msc_is_writable_cb(lun);
+ if ( tud_msc_is_writable_cb )
+ {
+ writable = tud_msc_is_writable_cb(lun);
}
+
mode_resp.write_protected = !writable;
resplen = sizeof(mode_resp);
@@ -616,9 +790,9 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
sense_rsp.add_sense_len = sizeof(scsi_sense_fixed_resp_t) - 8;
- sense_rsp.sense_key = _mscd_itf.sense_key;
- sense_rsp.add_sense_code = _mscd_itf.add_sense_code;
- sense_rsp.add_sense_qualifier = _mscd_itf.add_sense_qualifier;
+ sense_rsp.sense_key = p_msc->sense_key;
+ sense_rsp.add_sense_code = p_msc->add_sense_code;
+ sense_rsp.add_sense_qualifier = p_msc->add_sense_qualifier;
resplen = sizeof(sense_rsp);
memcpy(buffer, &sense_rsp, resplen);
@@ -637,13 +811,9 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc)
{
msc_cbw_t const * p_cbw = &p_msc->cbw;
- msc_csw_t * p_csw = &p_msc->csw;
-
- uint16_t const block_cnt = rdwr10_get_blockcount(p_cbw->command);
- TU_ASSERT(block_cnt, ); // prevent div by zero
- uint16_t const block_sz = p_cbw->total_bytes / block_cnt;
- TU_ASSERT(block_sz, ); // prevent div by zero
+ // block size already verified not zero
+ uint16_t const block_sz = rdwr10_get_blocksize(p_cbw);
// Adjust lba with transferred bytes
uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz);
@@ -652,16 +822,18 @@ static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc)
int32_t nbytes = (int32_t) tu_min32(sizeof(_mscd_buf), p_cbw->total_bytes-p_msc->xferred_len);
// Application can consume smaller bytes
- nbytes = tud_msc_read10_cb(p_cbw->lun, lba, p_msc->xferred_len % block_sz, _mscd_buf, (uint32_t) nbytes);
+ uint32_t const offset = p_msc->xferred_len % block_sz;
+ nbytes = tud_msc_read10_cb(p_cbw->lun, lba, offset, _mscd_buf, (uint32_t) nbytes);
if ( nbytes < 0 )
{
- // negative means error -> pipe is stalled & status in CSW set to failed
- p_csw->data_residue = p_cbw->total_bytes - p_msc->xferred_len;
- p_csw->status = MSC_CSW_STATUS_FAILED;
+ // negative means error -> endpoint is stalled & status in CSW set to failed
+ TU_LOG(MSC_DEBUG, " tud_msc_read10_cb() return -1\r\n");
- tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); // Sense = Invalid Command Operation
- usbd_edpt_stall(rhport, p_msc->ep_in);
+ // Sense = Flash not ready for access
+ tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_MEDIUM_ERROR, 0x33, 0x00);
+
+ fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
}
else if ( nbytes == 0 )
{
@@ -678,16 +850,18 @@ static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc)
{
msc_cbw_t const * p_cbw = &p_msc->cbw;
bool writable = true;
- if (tud_msc_is_writable_cb) {
+
+ if ( tud_msc_is_writable_cb )
+ {
writable = tud_msc_is_writable_cb(p_cbw->lun);
}
- if (!writable) {
- msc_csw_t* p_csw = &p_msc->csw;
- p_csw->data_residue = p_cbw->total_bytes;
- p_csw->status = MSC_CSW_STATUS_FAILED;
- tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_DATA_PROTECT, 0x27, 0x00); // Sense = Write protected
- usbd_edpt_stall(rhport, p_msc->ep_out);
+ if ( !writable )
+ {
+ // Not writable, complete this SCSI op with error
+ // Sense = Write protected
+ tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_DATA_PROTECT, 0x27, 0x00);
+ fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
return;
}
@@ -698,4 +872,63 @@ static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc)
TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, nbytes), );
}
+// process new data arrived from WRITE10
+static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint32_t xferred_bytes)
+{
+ msc_cbw_t const * p_cbw = &p_msc->cbw;
+
+ // block size already verified not zero
+ uint16_t const block_sz = rdwr10_get_blocksize(p_cbw);
+
+ // Adjust lba with transferred bytes
+ uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz);
+
+ // Invoke callback to consume new data
+ uint32_t const offset = p_msc->xferred_len % block_sz;
+ int32_t nbytes = tud_msc_write10_cb(p_cbw->lun, lba, offset, _mscd_buf, xferred_bytes);
+
+ if ( nbytes < 0 )
+ {
+ // negative means error -> failed this scsi op
+ TU_LOG(MSC_DEBUG, " tud_msc_write10_cb() return -1\r\n");
+
+ // update actual byte before failed
+ p_msc->xferred_len += xferred_bytes;
+
+ // Sense = Flash not ready for access
+ tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_MEDIUM_ERROR, 0x33, 0x00);
+
+ fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
+ }else
+ {
+ // Application consume less than what we got (including zero)
+ if ( (uint32_t) nbytes < xferred_bytes )
+ {
+ if ( nbytes > 0 )
+ {
+ p_msc->xferred_len += nbytes;
+ memmove(_mscd_buf, _mscd_buf+nbytes, xferred_bytes-nbytes);
+ }
+
+ // simulate an transfer complete with adjusted parameters --> callback will be invoked with adjusted parameter
+ dcd_event_xfer_complete(rhport, p_msc->ep_out, xferred_bytes-nbytes, XFER_RESULT_SUCCESS, false);
+ }
+ else
+ {
+ // Application consume all bytes in our buffer
+ p_msc->xferred_len += xferred_bytes;
+
+ if ( p_msc->xferred_len >= p_msc->total_len )
+ {
+ // Data Stage is complete
+ p_msc->stage = MSC_STAGE_STATUS;
+ }else
+ {
+ // prepare to receive more data from host
+ proc_write10_cmd(rhport, p_msc);
+ }
+ }
+ }
+}
+
#endif
diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h
index 8f90ef4ad..d32694340 100644
--- a/src/class/msc/msc_device.h
+++ b/src/class/msc/msc_device.h
@@ -140,7 +140,7 @@ TU_ATTR_WEAK void tud_msc_write10_complete_cb(uint8_t lun);
// Invoked when command in tud_msc_scsi_cb is complete
TU_ATTR_WEAK void tud_msc_scsi_complete_cb(uint8_t lun, uint8_t const scsi_cmd[16]);
-// Hook to make a mass storage device read-only. TODO remove
+// Invoked to check if device is writable as part of SCSI WRITE10
TU_ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun);
//--------------------------------------------------------------------+
diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c
index 7f98ef9b1..8069353cd 100644
--- a/src/class/msc/msc_host.c
+++ b/src/class/msc/msc_host.c
@@ -69,13 +69,14 @@ typedef struct
msc_csw_t csw;
}msch_interface_t;
-CFG_TUSB_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUSB_HOST_DEVICE_MAX];
+CFG_TUSB_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUH_DEVICE_MAX];
// buffer used to read scsi information when mounted
// largest response data currently is inquiry TODO Inquiry is not part of enum anymore
CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4)
static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)];
+TU_ATTR_ALWAYS_INLINE
static inline msch_interface_t* get_itf(uint8_t dev_addr)
{
return &_msch_itf[dev_addr-1];
@@ -291,11 +292,13 @@ bool tuh_msc_reset(uint8_t dev_addr)
//--------------------------------------------------------------------+
void msch_init(void)
{
- tu_memclr(_msch_itf, sizeof(msch_interface_t)*CFG_TUSB_HOST_DEVICE_MAX);
+ tu_memclr(_msch_itf, sizeof(_msch_itf));
}
void msch_close(uint8_t dev_addr)
{
+ TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, );
+
msch_interface_t* p_msc = get_itf(dev_addr);
// invoke Application Callback
@@ -360,11 +363,15 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* c
static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw);
static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw);
-bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length)
+bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len)
{
TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass &&
MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol);
+ // msc driver length is fixed
+ uint16_t const drv_len = sizeof(tusb_desc_interface_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t);
+ TU_ASSERT(drv_len <= max_len);
+
msch_interface_t* p_msc = get_itf(dev_addr);
tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(desc_itf);
@@ -385,7 +392,6 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de
}
p_msc->itf_num = desc_itf->bInterfaceNumber;
- (*p_length) += sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t);
return true;
}
diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h
index ce4fe64dc..7718ad4fe 100644
--- a/src/class/msc/msc_host.h
+++ b/src/class/msc/msc_host.h
@@ -41,13 +41,6 @@
#define CFG_TUH_MSC_MAXLUN 4
#endif
-
-/** \addtogroup ClassDriver_MSC
- * @{
- * \defgroup MSC_Host Host
- * The interface API includes status checking function, data transferring function and callback functions
- * @{ */
-
typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw);
//--------------------------------------------------------------------+
@@ -113,17 +106,14 @@ TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr);
// Internal Class Driver API
//--------------------------------------------------------------------+
-void msch_init(void);
-bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t *p_length);
-bool msch_set_config(uint8_t dev_addr, uint8_t itf_num);
-bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
-void msch_close(uint8_t dev_addr);
+void msch_init (void);
+bool msch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len);
+bool msch_set_config (uint8_t dev_addr, uint8_t itf_num);
+void msch_close (uint8_t dev_addr);
+bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_MSC_HOST_H_ */
-
-/// @}
-/// @}
diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c
index 6718a97bf..8c59b4ea7 100644
--- a/src/class/vendor/vendor_device.c
+++ b/src/class/vendor/vendor_device.c
@@ -103,6 +103,13 @@ uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize)
return num_read;
}
+void tud_vendor_n_read_flush (uint8_t itf)
+{
+ vendord_interface_t* p_itf = &_vendord_itf[itf];
+ tu_fifo_clear(&p_itf->rx_ff);
+ _prep_out_transaction(p_itf);
+}
+
//--------------------------------------------------------------------+
// Write API
//--------------------------------------------------------------------+
@@ -199,6 +206,8 @@ uint16_t vendord_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, ui
TU_BREAKPOINT();
}
+ maybe_transmit(p_vendor);
+
return drv_len;
}
diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h
index b54194271..d71c2a3e9 100644
--- a/src/class/vendor/vendor_device.h
+++ b/src/class/vendor/vendor_device.h
@@ -44,7 +44,8 @@ bool tud_vendor_n_mounted (uint8_t itf);
uint32_t tud_vendor_n_available (uint8_t itf);
uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize);
-bool tud_vendor_n_peek (uint8_t itf, uint8_t* uv8);
+bool tud_vendor_n_peek (uint8_t itf, uint8_t* ui8);
+void tud_vendor_n_read_flush (uint8_t itf);
uint32_t tud_vendor_n_write (uint8_t itf, void const* buffer, uint32_t bufsize);
uint32_t tud_vendor_n_write_available (uint8_t itf);
@@ -58,7 +59,8 @@ uint32_t tud_vendor_n_write_str (uint8_t itf, char const* str);
static inline bool tud_vendor_mounted (void);
static inline uint32_t tud_vendor_available (void);
static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize);
-static inline bool tud_vendor_peek (uint8_t* uv8);
+static inline bool tud_vendor_peek (uint8_t* ui8);
+static inline void tud_vendor_read_flush (void);
static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize);
static inline uint32_t tud_vendor_write_str (char const* str);
static inline uint32_t tud_vendor_write_available (void);
@@ -94,9 +96,14 @@ static inline uint32_t tud_vendor_read (void* buffer, uint32_t bufsize)
return tud_vendor_n_read(0, buffer, bufsize);
}
-static inline bool tud_vendor_peek (uint8_t* uv8)
+static inline bool tud_vendor_peek (uint8_t* ui8)
{
- return tud_vendor_n_peek(0, uv8);
+ return tud_vendor_n_peek(0, ui8);
+}
+
+static inline void tud_vendor_read_flush(void)
+{
+ tud_vendor_n_read_flush(0);
}
static inline uint32_t tud_vendor_write (void const* buffer, uint32_t bufsize)
diff --git a/src/class/vendor/vendor_host.c b/src/class/vendor/vendor_host.c
index f7a6b2bf0..1e28e9af4 100644
--- a/src/class/vendor/vendor_host.c
+++ b/src/class/vendor/vendor_host.c
@@ -41,7 +41,7 @@
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-custom_interface_info_t custom_interface[CFG_TUSB_HOST_DEVICE_MAX];
+custom_interface_info_t custom_interface[CFG_TUH_DEVICE_MAX];
static tusb_error_t cush_validate_paras(uint8_t dev_addr, uint16_t vendor_id, uint16_t product_id, void * p_buffer, uint16_t length)
{
@@ -90,7 +90,7 @@ tusb_error_t tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t p
//--------------------------------------------------------------------+
void cush_init(void)
{
- tu_memclr(&custom_interface, sizeof(custom_interface_info_t) * CFG_TUSB_HOST_DEVICE_MAX);
+ tu_memclr(&custom_interface, sizeof(custom_interface_info_t) * CFG_TUH_DEVICE_MAX);
}
tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length)
diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h
index ece5d800a..fc4d3bc62 100644
--- a/src/common/tusb_common.h
+++ b/src/common/tusb_common.h
@@ -73,6 +73,23 @@
#include "tusb_error.h" // TODO remove
#include "tusb_timeout.h" // TODO remove
+//--------------------------------------------------------------------+
+// Internal Helper used by Host and Device Stack
+//--------------------------------------------------------------------+
+
+// Check if endpoint descriptor is valid per USB specs
+bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed);
+
+// Bind all endpoint of a interface descriptor to class driver
+void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* p_desc, uint16_t desc_len, uint8_t driver_id);
+
+// Calculate total length of n interfaces (depending on IAD)
+uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len);
+
+//--------------------------------------------------------------------+
+// Internal Inline Functions
+//--------------------------------------------------------------------+
+
//------------- Mem -------------//
#define tu_memclr(buffer, size) memset((buffer), 0, (size))
#define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var)))
@@ -88,13 +105,13 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u16(uint8_t high, uint8_t low)
return (uint16_t) ((((uint16_t) high) << 8) | low);
}
-TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte3(uint32_t uv32) { return TU_U32_BYTE3(uv32); }
-TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte2(uint32_t uv32) { return TU_U32_BYTE2(uv32); }
-TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte1(uint32_t uv32) { return TU_U32_BYTE1(uv32); }
-TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte0(uint32_t uv32) { return TU_U32_BYTE0(uv32); }
+TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte3(uint32_t ui32) { return TU_U32_BYTE3(ui32); }
+TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte2(uint32_t ui32) { return TU_U32_BYTE2(ui32); }
+TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte1(uint32_t ui32) { return TU_U32_BYTE1(ui32); }
+TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u32_byte0(uint32_t ui32) { return TU_U32_BYTE0(ui32); }
-TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_high(uint16_t uv16) { return TU_U16_HIGH(uv16); }
-TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_low (uint16_t uv16) { return TU_U16_LOW(uv16); }
+TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_high(uint16_t ui16) { return TU_U16_HIGH(ui16); }
+TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_low (uint16_t ui16) { return TU_U16_LOW(ui16); }
//------------- Bits -------------//
TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_bit_set (uint32_t value, uint8_t pos) { return value | TU_BIT(pos); }
@@ -123,7 +140,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_align4k (uint32_t value) { retur
TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_offset4k(uint32_t value) { return (value & 0xFFFUL); }
//------------- Mathematics -------------//
-TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_abs(int32_t value) { return (uint32_t)((value < 0) ? (-value) : value); }
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_div_ceil(uint32_t v, uint32_t d) { return (v + d -1)/d; }
/// inclusive range checking TODO remove
TU_ATTR_ALWAYS_INLINE static inline bool tu_within(uint32_t lower, uint32_t value, uint32_t upper)
@@ -305,11 +322,11 @@ void tu_print_var(uint8_t const* buf, uint32_t bufsize)
}
// Log with Level
-#define TU_LOG(n, ...) TU_LOG##n(__VA_ARGS__)
-#define TU_LOG_MEM(n, ...) TU_LOG##n##_MEM(__VA_ARGS__)
-#define TU_LOG_VAR(n, ...) TU_LOG##n##_VAR(__VA_ARGS__)
-#define TU_LOG_INT(n, ...) TU_LOG##n##_INT(__VA_ARGS__)
-#define TU_LOG_HEX(n, ...) TU_LOG##n##_HEX(__VA_ARGS__)
+#define TU_LOG(n, ...) TU_XSTRCAT(TU_LOG, n)(__VA_ARGS__)
+#define TU_LOG_MEM(n, ...) TU_XSTRCAT3(TU_LOG, n, _MEM)(__VA_ARGS__)
+#define TU_LOG_VAR(n, ...) TU_XSTRCAT3(TU_LOG, n, _VAR)(__VA_ARGS__)
+#define TU_LOG_INT(n, ...) TU_XSTRCAT3(TU_LOG, n, _INT)(__VA_ARGS__)
+#define TU_LOG_HEX(n, ...) TU_XSTRCAT3(TU_LOG, n, _HEX)(__VA_ARGS__)
#define TU_LOG_LOCATION() tu_printf("%s: %d:\r\n", __PRETTY_FUNCTION__, __LINE__)
#define TU_LOG_FAILED() tu_printf("%s: %d: Failed\r\n", __PRETTY_FUNCTION__, __LINE__)
@@ -317,8 +334,8 @@ void tu_print_var(uint8_t const* buf, uint32_t bufsize)
#define TU_LOG1 tu_printf
#define TU_LOG1_MEM tu_print_mem
#define TU_LOG1_VAR(_x) tu_print_var((uint8_t const*)(_x), sizeof(*(_x)))
-#define TU_LOG1_INT(_x) tu_printf(#_x " = %ld\n", (uint32_t) (_x) )
-#define TU_LOG1_HEX(_x) tu_printf(#_x " = %lX\n", (uint32_t) (_x) )
+#define TU_LOG1_INT(_x) tu_printf(#_x " = %ld\r\n", (uint32_t) (_x) )
+#define TU_LOG1_HEX(_x) tu_printf(#_x " = %lX\r\n", (uint32_t) (_x) )
// Log Level 2: Warn
#if CFG_TUSB_DEBUG >= 2
@@ -352,12 +369,17 @@ typedef struct
static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key)
{
+ static char not_found[11];
+
for(uint16_t i=0; i<p_table->count; i++)
{
if (p_table->items[i].key == key) return p_table->items[i].data;
}
- return NULL;
+ // not found return the key value in hex
+ sprintf(not_found, "0x%08lX", (unsigned long) key);
+
+ return not_found;
}
#endif // CFG_TUSB_DEBUG
@@ -373,6 +395,14 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3
#endif
// TODO replace all TU_LOGn with TU_LOG(n)
+
+#define TU_LOG0(...)
+#define TU_LOG0_MEM(...)
+#define TU_LOG0_VAR(...)
+#define TU_LOG0_INT(...)
+#define TU_LOG0_HEX(...)
+
+
#ifndef TU_LOG1
#define TU_LOG1(...)
#define TU_LOG1_MEM(...)
diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h
index 679060b20..d3adbbc2d 100644
--- a/src/common/tusb_compiler.h
+++ b/src/common/tusb_compiler.h
@@ -32,10 +32,14 @@
#ifndef _TUSB_COMPILER_H_
#define _TUSB_COMPILER_H_
-#define TU_STRING(x) #x ///< stringify without expand
-#define TU_XSTRING(x) TU_STRING(x) ///< expand then stringify
-#define TU_STRCAT(a, b) a##b ///< concat without expand
-#define TU_XSTRCAT(a, b) TU_STRCAT(a, b) ///< expand then concat
+#define TU_STRING(x) #x ///< stringify without expand
+#define TU_XSTRING(x) TU_STRING(x) ///< expand then stringify
+
+#define TU_STRCAT(a, b) a##b ///< concat without expand
+#define TU_STRCAT3(a, b, c) a##b##c ///< concat without expand
+
+#define TU_XSTRCAT(a, b) TU_STRCAT(a, b) ///< expand then concat
+#define TU_XSTRCAT3(a, b, c) TU_STRCAT3(a, b, c) ///< expand then concat 3 tokens
#if defined __COUNTER__ && __COUNTER__ != __COUNTER__
#define _TU_COUNTER_ __COUNTER__
@@ -48,6 +52,8 @@
#define TU_VERIFY_STATIC _Static_assert
#elif defined (__cplusplus) && __cplusplus >= 201103L
#define TU_VERIFY_STATIC static_assert
+#elif defined(__CCRX__)
+ #define TU_VERIFY_STATIC(const_expr, _mess) typedef char TU_XSTRCAT(Line, __LINE__)[(const_expr) ? 1 : 0];
#else
#define TU_VERIFY_STATIC(const_expr, _mess) enum { TU_XSTRCAT(_verify_static_, _TU_COUNTER_) = 1/(!!(const_expr)) }
#endif
@@ -73,6 +79,11 @@
#define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused
#define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used
+ #define TU_ATTR_PACKED_BEGIN
+ #define TU_ATTR_PACKED_END
+ #define TU_ATTR_BIT_FIELD_ORDER_BEGIN
+ #define TU_ATTR_BIT_FIELD_ORDER_END
+
// Endian conversion use well-known host to network (big endian) naming
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define TU_BYTE_ORDER TU_LITTLE_ENDIAN
@@ -83,6 +94,10 @@
#define TU_BSWAP16(u16) (__builtin_bswap16(u16))
#define TU_BSWAP32(u32) (__builtin_bswap32(u32))
+ // List of obsolete callback function that is renamed and should not be defined.
+ // Put it here since only gcc support this pragma
+ #pragma GCC poison tud_vendor_control_request_cb
+
#elif defined(__TI_COMPILER_VERSION__)
#define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes)))
#define TU_ATTR_SECTION(sec_name) __attribute__ ((section(#sec_name)))
@@ -93,6 +108,11 @@
#define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused
#define TU_ATTR_USED __attribute__ ((used))
+ #define TU_ATTR_PACKED_BEGIN
+ #define TU_ATTR_PACKED_END
+ #define TU_ATTR_BIT_FIELD_ORDER_BEGIN
+ #define TU_ATTR_BIT_FIELD_ORDER_END
+
// __BYTE_ORDER is defined in the TI ARM compiler, but not MSP430 (which is little endian)
#if ((__BYTE_ORDER__) == (__ORDER_LITTLE_ENDIAN__)) || defined(__MSP430__)
#define TU_BYTE_ORDER TU_LITTLE_ENDIAN
@@ -114,6 +134,11 @@
#define TU_ATTR_UNUSED __attribute__ ((unused)) // Function/Variable is meant to be possibly unused
#define TU_ATTR_USED __attribute__ ((used)) // Function/Variable is meant to be used
+ #define TU_ATTR_PACKED_BEGIN
+ #define TU_ATTR_PACKED_END
+ #define TU_ATTR_BIT_FIELD_ORDER_BEGIN
+ #define TU_ATTR_BIT_FIELD_ORDER_END
+
// Endian conversion use well-known host to network (big endian) naming
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define TU_BYTE_ORDER TU_LITTLE_ENDIAN
@@ -123,6 +148,32 @@
#define TU_BSWAP16(u16) (__iar_builtin_REV16(u16))
#define TU_BSWAP32(u32) (__iar_builtin_REV(u32))
+
+#elif defined(__CCRX__)
+ #define TU_ATTR_ALIGNED(Bytes)
+ #define TU_ATTR_SECTION(sec_name)
+ #define TU_ATTR_PACKED
+ #define TU_ATTR_WEAK
+ #define TU_ATTR_ALWAYS_INLINE
+ #define TU_ATTR_DEPRECATED(mess)
+ #define TU_ATTR_UNUSED
+ #define TU_ATTR_USED
+
+ #define TU_ATTR_PACKED_BEGIN _Pragma("pack")
+ #define TU_ATTR_PACKED_END _Pragma("packoption")
+ #define TU_ATTR_BIT_FIELD_ORDER_BEGIN _Pragma("bit_order right")
+ #define TU_ATTR_BIT_FIELD_ORDER_END _Pragma("bit_order")
+
+ // Endian conversion use well-known host to network (big endian) naming
+ #if defined(__LIT)
+ #define TU_BYTE_ORDER TU_LITTLE_ENDIAN
+ #else
+ #define TU_BYTE_ORDER TU_BIG_ENDIAN
+ #endif
+
+ #define TU_BSWAP16(u16) ((unsigned short)_builtin_revw((unsigned long)u16))
+ #define TU_BSWAP32(u32) (_builtin_revl(u32))
+
#else
#error "Compiler attribute porting is required"
#endif
@@ -149,11 +200,11 @@
#define tu_htonl(u32) (u32)
#define tu_ntohl(u32) (u32)
- #define tu_htole16(u16) (tu_bswap16(u16))
- #define tu_le16toh(u16) (tu_bswap16(u16))
+ #define tu_htole16(u16) (TU_BSWAP16(u16))
+ #define tu_le16toh(u16) (TU_BSWAP16(u16))
- #define tu_htole32(u32) (tu_bswap32(u32))
- #define tu_le32toh(u32) (tu_bswap32(u32))
+ #define tu_htole32(u32) (TU_BSWAP32(u32))
+ #define tu_le32toh(u32) (TU_BSWAP32(u32))
#else
#error Byte order is undefined
diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c
index 1eb886aa1..11b8fc5f3 100644
--- a/src/common/tusb_fifo.c
+++ b/src/common/tusb_fifo.c
@@ -323,9 +323,7 @@ static uint16_t advance_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset)
// We limit the index space of p such that a correct wrap around happens
// Check for a wrap around or if we are in unused index space - This has to be checked first!!
// We are exploiting the wrap around to the correct index
-
- // TODO warning: assuming signed overflow does not occur when assuming that (X + c) < X is always false [-Wstrict-overflow]
- if ((p > p + offset) || (p + offset > f->max_pointer_idx))
+ if ((p > (uint16_t)(p + offset)) || ((uint16_t)(p + offset) > f->max_pointer_idx))
{
p = (p + offset) + f->non_used_index_space;
}
@@ -342,7 +340,7 @@ static uint16_t backward_pointer(tu_fifo_t* f, uint16_t p, uint16_t offset)
// We limit the index space of p such that a correct wrap around happens
// Check for a wrap around or if we are in unused index space - This has to be checked first!!
// We are exploiting the wrap around to the correct index
- if ((p < p - offset) || (p - offset > f->max_pointer_idx))
+ if ((p < (uint16_t)(p - offset)) || ((uint16_t)(p - offset) > f->max_pointer_idx))
{
p = (p - offset) - f->non_used_index_space;
}
diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h
index cf299269d..18db289a1 100644
--- a/src/common/tusb_fifo.h
+++ b/src/common/tusb_fifo.h
@@ -86,8 +86,8 @@ typedef struct
.depth = _depth, \
.item_size = sizeof(_type), \
.overwritable = _overwritable, \
- .max_pointer_idx = 2*(_depth)-1, \
.non_used_index_space = UINT16_MAX - (2*(_depth)-1), \
+ .max_pointer_idx = 2*(_depth)-1, \
}
#define TU_FIFO_DEF(_name, _depth, _type, _overwritable) \
@@ -120,9 +120,9 @@ bool tu_fifo_peek (tu_fifo_t* f, void * p_buffer);
uint16_t tu_fifo_peek_n (tu_fifo_t* f, void * p_buffer, uint16_t n);
uint16_t tu_fifo_count (tu_fifo_t* f);
+uint16_t tu_fifo_remaining (tu_fifo_t* f);
bool tu_fifo_empty (tu_fifo_t* f);
bool tu_fifo_full (tu_fifo_t* f);
-uint16_t tu_fifo_remaining (tu_fifo_t* f);
bool tu_fifo_overflowed (tu_fifo_t* f);
void tu_fifo_correct_read_pointer (tu_fifo_t* f);
diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h
index ec58a3181..f26983a74 100644
--- a/src/common/tusb_types.h
+++ b/src/common/tusb_types.h
@@ -262,6 +262,10 @@ enum
// USB Descriptors
//--------------------------------------------------------------------+
+// Start of all packed definitions for compiler without per-type packed
+TU_ATTR_PACKED_BEGIN
+TU_ATTR_BIT_FIELD_ORDER_BEGIN
+
/// USB Device Descriptor
typedef struct TU_ATTR_PACKED
{
@@ -295,6 +299,8 @@ typedef struct TU_ATTR_PACKED
uint8_t bNumDeviceCaps ; ///< Number of device capability descriptors in the BOS
} tusb_desc_bos_t;
+TU_VERIFY_STATIC( sizeof(tusb_desc_bos_t) == 5, "size is not correct");
+
/// USB Configuration Descriptor
typedef struct TU_ATTR_PACKED
{
@@ -326,6 +332,8 @@ typedef struct TU_ATTR_PACKED
uint8_t iInterface ; ///< Index of string descriptor describing this interface
} tusb_desc_interface_t;
+TU_VERIFY_STATIC( sizeof(tusb_desc_interface_t) == 9, "size is not correct");
+
/// USB Endpoint Descriptor
typedef struct TU_ATTR_PACKED
{
@@ -342,9 +350,14 @@ typedef struct TU_ATTR_PACKED
} bmAttributes ; ///< This field describes the endpoint's attributes when it is configured using the bConfigurationValue. \n Bits 1..0: Transfer Type \n- 00 = Control \n- 01 = Isochronous \n- 10 = Bulk \n- 11 = Interrupt \n If not an isochronous endpoint, bits 5..2 are reserved and must be set to zero. If isochronous, they are defined as follows: \n Bits 3..2: Synchronization Type \n- 00 = No Synchronization \n- 01 = Asynchronous \n- 10 = Adaptive \n- 11 = Synchronous \n Bits 5..4: Usage Type \n- 00 = Data endpoint \n- 01 = Feedback endpoint \n- 10 = Implicit feedback Data endpoint \n- 11 = Reserved \n Refer to Chapter 5 of USB 2.0 specification for more information. \n All other bits are reserved and must be reset to zero. Reserved bits must be ignored by the host.
struct TU_ATTR_PACKED {
+#if defined(__CCRX__)
+ //FIXME the original defined bit field has a problem with the CCRX toolchain, so only a size field is defined
+ uint16_t size;
+#else
uint16_t size : 11; ///< Maximum packet size this endpoint is capable of sending or receiving when this configuration is selected. \n For isochronous endpoints, this value is used to reserve the bus time in the schedule, required for the per-(micro)frame data payloads. The pipe may, on an ongoing basis, actually use less bandwidth than that reserved. The device reports, if necessary, the actual bandwidth used via its normal, non-USB defined mechanisms. \n For all endpoints, bits 10..0 specify the maximum packet size (in bytes). \n For high-speed isochronous and interrupt endpoints: \n Bits 12..11 specify the number of additional transaction opportunities per microframe: \n- 00 = None (1 transaction per microframe) \n- 01 = 1 additional (2 per microframe) \n- 10 = 2 additional (3 per microframe) \n- 11 = Reserved \n Bits 15..13 are reserved and must be set to zero.
uint16_t hs_period_mult : 2;
uint16_t TU_RESERVED : 3;
+#endif
}wMaxPacketSize;
uint8_t bInterval ; ///< Interval for polling endpoint for data transfers. Expressed in frames or microframes depending on the device operating speed (i.e., either 1 millisecond or 125 us units). \n- For full-/high-speed isochronous endpoints, this value must be in the range from 1 to 16. The bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$). \n- For full-/low-speed interrupt endpoints, the value of this field may be from 1 to 255. \n- For high-speed interrupt endpoints, the bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$) . This value must be from 1 to 16. \n- For high-speed bulk/control OUT endpoints, the bInterval must specify the maximum NAK rate of the endpoint. A value of 0 indicates the endpoint never NAKs. Other values indicate at most 1 NAK each bInterval number of microframes. This value must be in the range from 0 to 255. \n Refer to Chapter 5 of USB 2.0 specification for more information.
@@ -359,7 +372,7 @@ typedef struct TU_ATTR_PACKED
uint8_t bNumInterfaces ; ///< Number of interfaces supported by this speed configuration
uint8_t bConfigurationValue ; ///< Value to use to select configuration
- uint8_t IConfiguration ; ///< Index of string descriptor
+ uint8_t iConfiguration ; ///< Index of string descriptor
uint8_t bmAttributes ; ///< Same as Configuration descriptor
uint8_t bMaxPower ; ///< Same as Configuration descriptor
} tusb_desc_other_speed_t;
@@ -374,11 +387,14 @@ typedef struct TU_ATTR_PACKED
uint8_t bDeviceClass ; ///< Class Code
uint8_t bDeviceSubClass ; ///< SubClass Code
uint8_t bDeviceProtocol ; ///< Protocol Code
+
uint8_t bMaxPacketSize0 ; ///< Maximum packet size for other speed
uint8_t bNumConfigurations ; ///< Number of Other-speed Configurations
uint8_t bReserved ; ///< Reserved for future use, must be zero
} tusb_desc_device_qualifier_t;
+TU_VERIFY_STATIC( sizeof(tusb_desc_device_qualifier_t) == 10, "size is not correct");
+
/// USB Interface Association Descriptor (IAD ECN)
typedef struct TU_ATTR_PACKED
{
@@ -468,11 +484,9 @@ typedef struct TU_ATTR_PACKED{
TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct");
-// TODO move to somewhere suitable
-static inline uint8_t bm_request_type(uint8_t direction, uint8_t type, uint8_t recipient)
-{
- return ((uint8_t) (direction << 7)) | ((uint8_t) (type << 5)) | (recipient);
-}
+
+TU_ATTR_PACKED_END // End of all packed definitions
+TU_ATTR_BIT_FIELD_ORDER_END
//--------------------------------------------------------------------+
// Endpoint helper
diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h
index 542809899..56ba8bcd1 100644
--- a/src/common/tusb_verify.h
+++ b/src/common/tusb_verify.h
@@ -75,7 +75,7 @@
#if CFG_TUSB_DEBUG
#include <stdio.h>
#define _MESS_ERR(_err) tu_printf("%s %d: failed, error = %s\r\n", __func__, __LINE__, tusb_strerr[_err])
- #define _MESS_FAILED() tu_printf("%s %d: assert failed\r\n", __func__, __LINE__)
+ #define _MESS_FAILED() tu_printf("%s %d: ASSERT FAILED\r\n", __func__, __LINE__)
#else
#define _MESS_ERR(_err) do {} while (0)
#define _MESS_FAILED() do {} while (0)
diff --git a/src/device/dcd.h b/src/device/dcd.h
index 63e97df96..d43a0dd9a 100644
--- a/src/device/dcd.h
+++ b/src/device/dcd.h
@@ -30,11 +30,24 @@
#include "common/tusb_common.h"
#include "osal/osal.h"
#include "common/tusb_fifo.h"
+#include "dcd_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
+//--------------------------------------------------------------------+
+// Configuration
+//--------------------------------------------------------------------+
+
+#ifndef CFG_TUD_ENDPPOINT_MAX
+ #define CFG_TUD_ENDPPOINT_MAX DCD_ATTR_ENDPOINT_MAX
+#endif
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF PROTYPES
+//--------------------------------------------------------------------+
+
typedef enum
{
DCD_EVENT_INVALID = 0,
@@ -124,6 +137,11 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re
// Configure endpoint's registers according to descriptor
bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_ep);
+// Close all non-control endpoints, cancel all pending transfers if any.
+// Invoked when switching from a non-zero Configuration by SET_CONFIGURE therefore
+// required for multiple configuration support.
+void dcd_edpt_close_all (uint8_t rhport);
+
// Close an endpoint.
// Since it is weak, caller must TU_ASSERT this function's existence before calling it.
void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK;
@@ -135,10 +153,11 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer
// This API is optional, may be useful for register-based for transferring data.
bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) TU_ATTR_WEAK;
-// Stall endpoint
+// Stall endpoint, any queuing transfer should be removed from endpoint
void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr);
// clear stall, data toggle is also reset to DATA0
+// This API never calls with control endpoints, since it is auto cleared when receiving setup packet
void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr);
//--------------------------------------------------------------------+
diff --git a/src/device/dcd_attr.h b/src/device/dcd_attr.h
new file mode 100644
index 000000000..a35fc0ac5
--- /dev/null
+++ b/src/device/dcd_attr.h
@@ -0,0 +1,164 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021, Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef TUSB_DCD_ATTR_H_
+#define TUSB_DCD_ATTR_H_
+
+#include "tusb_option.h"
+
+// Attribute includes
+// - ENDPOINT_MAX: max (logical) number of endpoint
+// - ENDPOINT_EXCLUSIVE_NUMBER: endpoint number with different direction IN and OUT aren't allowed,
+// e.g EP1 OUT & EP1 IN cannot exist together
+// - PORT_HIGHSPEED: mask to indicate which port support highspeed mode, bit0 for port0 and so on.
+
+//------------- NXP -------------//
+#if TU_CHECK_MCU(LPC11UXX) || TU_CHECK_MCU(LPC13XX) || TU_CHECK_MCU(LPC15XX)
+ #define DCD_ATTR_ENDPOINT_MAX 5
+
+#elif TU_CHECK_MCU(LPC175X_6X) || TU_CHECK_MCU(LPC177X_8X) || TU_CHECK_MCU(LPC40XX)
+ #define DCD_ATTR_ENDPOINT_MAX 16
+
+#elif TU_CHECK_MCU(LPC18XX) || TU_CHECK_MCU(LPC43XX)
+ // TODO USB0 has 6, USB1 has 4
+ #define DCD_ATTR_ENDPOINT_MAX 6
+
+#elif TU_CHECK_MCU(LPC51UXX)
+ #define DCD_ATTR_ENDPOINT_MAX 5
+
+#elif TU_CHECK_MCU(LPC54XXX)
+ // TODO USB0 has 5, USB1 has 6
+ #define DCD_ATTR_ENDPOINT_MAX 6
+
+#elif TU_CHECK_MCU(LPC55XX)
+ // TODO USB0 has 5, USB1 has 6
+ #define DCD_ATTR_ENDPOINT_MAX 6
+
+#elif TU_CHECK_MCU(MIMXRT10XX)
+ #define DCD_ATTR_ENDPOINT_MAX 8
+
+#elif TU_CHECK_MCU(MKL25ZXX) || TU_CHECK_MCU(K32L2BXX)
+ #define DCD_ATTR_ENDPOINT_MAX 16
+
+//------------- Nordic -------------//
+#elif TU_CHECK_MCU(NRF5X)
+ // 8 CBI + 1 ISO
+ #define DCD_ATTR_ENDPOINT_MAX 9
+
+//------------- Microchip -------------//
+#elif TU_CHECK_MCU(SAMD21) || TU_CHECK_MCU(SAMD51) || TU_CHECK_MCU(SAME5X) || \
+ TU_CHECK_MCU(SAMD11) || TU_CHECK_MCU(SAML21) || TU_CHECK_MCU(SAML22)
+ #define DCD_ATTR_ENDPOINT_MAX 8
+
+#elif TU_CHECK_MCU(SAMG)
+ #define DCD_ATTR_ENDPOINT_MAX 6
+ #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER
+
+#elif TU_CHECK_MCU(SAMX7X)
+ #define DCD_ATTR_ENDPOINT_MAX 10
+ #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER
+
+//------------- ST -------------//
+#elif TU_CHECK_MCU(STM32F0) || TU_CHECK_MCU(STM32F1) || TU_CHECK_MCU(STM32F3) || \
+ TU_CHECK_MCU(STM32L0) || TU_CHECK_MCU(STM32L1) || TU_CHECK_MCU(STM32L4)
+ // F1: F102, F103
+ // L4: L4x2, L4x3
+ #define DCD_ATTR_ENDPOINT_MAX 8
+
+#elif TU_CHECK_MCU(STM32F2) || TU_CHECK_MCU(STM32F4) || TU_CHECK_MCU(STM32F3)
+ // F1: F105, F107 only has 4
+ // L4: L4x5, L4x6 has 6
+ // For most mcu, FS has 4, HS has 6
+ #define DCD_ATTR_ENDPOINT_MAX 6
+
+#elif TU_CHECK_MCU(STM32F7)
+ // FS has 6, HS has 9
+ #define DCD_ATTR_ENDPOINT_MAX 9
+
+#elif TU_CHECK_MCU(STM32H7)
+ #define DCD_ATTR_ENDPOINT_MAX 9
+
+//------------- Sony -------------//
+#elif TU_CHECK_MCU(CXD56)
+ #define DCD_ATTR_ENDPOINT_MAX 7
+ #define DCD_ATTR_ENDPOINT_EXCLUSIVE_NUMBER
+
+//------------- TI -------------//
+#elif TU_CHECK_MCU(MSP430x5xx)
+ #define DCD_ATTR_ENDPOINT_MAX 8
+
+//------------- ValentyUSB -------------//
+#elif TU_CHECK_MCU(VALENTYUSB_EPTRI)
+ #define DCD_ATTR_ENDPOINT_MAX 16
+
+//------------- Nuvoton -------------//
+#elif TU_CHECK_MCU(NUC121) || TU_CHECK_MCU(NUC126)
+ #define DCD_ATTR_ENDPOINT_MAX 8
+
+#elif TU_CHECK_MCU(NUC120)
+ #define DCD_ATTR_ENDPOINT_MAX 6
+
+#elif TU_CHECK_MCU(NUC505)
+ #define DCD_ATTR_ENDPOINT_MAX 12
+
+//------------- Espressif -------------//
+#elif TU_CHECK_MCU(ESP32S2) || TU_CHECK_MCU(ESP32S3)
+ #define DCD_ATTR_ENDPOINT_MAX 6
+
+//------------- Dialog -------------//
+#elif TU_CHECK_MCU(DA1469X)
+ #define DCD_ATTR_ENDPOINT_MAX 4
+
+//------------- Raspberry Pi -------------//
+#elif TU_CHECK_MCU(RP2040)
+ #define DCD_ATTR_ENDPOINT_MAX 16
+
+//------------- Silabs -------------//
+#elif TU_CHECK_MCU(EFM32GG) || TU_CHECK_MCU(EFM32GG11) || TU_CHECK_MCU(EFM32GG12)
+ #define DCD_ATTR_ENDPOINT_MAX 7
+
+//------------- Renesas -------------//
+#elif TU_CHECK_MCU(RX63X) || TU_CHECK_MCU(RX65X) || TU_CHECK_MCU(RX72N)
+ #define DCD_ATTR_ENDPOINT_MAX 10
+
+//#elif TU_CHECK_MCU(MM32F327X)
+// #define DCD_ATTR_ENDPOINT_MAX not known yet
+
+//------------- GigaDevice -------------//
+#elif TU_CHECK_MCU(GD32VF103)
+ #define DCD_ATTR_ENDPOINT_MAX 4
+
+#else
+ #warning "DCD_ATTR_ENDPOINT_MAX is not defined for this MCU, default to 8"
+ #define DCD_ATTR_ENDPOINT_MAX 8
+#endif
+
+// Default to fullspeed if not defined
+//#ifndef PORT_HIGHSPEED
+// #define DCD_ATTR_PORT_HIGHSPEED 0x00
+//#endif
+
+#endif
diff --git a/src/device/usbd.c b/src/device/usbd.c
index 2935defd0..3043fc7bc 100644
--- a/src/device/usbd.c
+++ b/src/device/usbd.c
@@ -33,12 +33,15 @@
#include "device/usbd_pvt.h"
#include "device/dcd.h"
-#ifndef CFG_TUD_TASK_QUEUE_SZ
-#define CFG_TUD_TASK_QUEUE_SZ 16
-#endif
+//--------------------------------------------------------------------+
+// USBD Configuration
+//--------------------------------------------------------------------+
+
+// Debug level of USBD
+#define USBD_DBG 2
-#ifndef CFG_TUD_EP_MAX
-#define CFG_TUD_EP_MAX 9
+#ifndef CFG_TUD_TASK_QUEUE_SZ
+ #define CFG_TUD_TASK_QUEUE_SZ 16
#endif
//--------------------------------------------------------------------+
@@ -65,7 +68,7 @@ typedef struct
uint8_t speed;
uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid)
- uint8_t ep2drv[CFG_TUD_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid )
+ uint8_t ep2drv[CFG_TUD_ENDPPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid )
struct TU_ATTR_PACKED
{
@@ -74,7 +77,7 @@ typedef struct
volatile bool claimed : 1;
// TODO merge ep2drv here, 4-bit should be sufficient
- }ep_status[CFG_TUD_EP_MAX][2];
+ }ep_status[CFG_TUD_ENDPPOINT_MAX][2];
}usbd_device_t;
@@ -188,9 +191,9 @@ static usbd_class_driver_t const _usbd_driver[] =
},
#endif
- #if CFG_TUD_DFU_MODE
+ #if CFG_TUD_DFU
{
- DRIVER_NAME("DFU-MODE")
+ DRIVER_NAME("DFU")
.init = dfu_moded_init,
.reset = dfu_moded_reset,
.open = dfu_moded_open,
@@ -271,7 +274,6 @@ static osal_mutex_t _usbd_mutex;
//--------------------------------------------------------------------+
// Prototypes
//--------------------------------------------------------------------+
-static void mark_interface_endpoint(uint8_t ep2drv[][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id);
static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request);
static bool process_set_config(uint8_t rhport, uint8_t cfg_num);
static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request);
@@ -430,19 +432,22 @@ bool tud_init (uint8_t rhport)
return true;
}
-static void usbd_reset(uint8_t rhport)
+static void configuration_reset(uint8_t rhport)
{
- tu_varclr(&_usbd_dev);
+ for ( uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++ )
+ {
+ get_driver(i)->reset(rhport);
+ }
+ tu_varclr(&_usbd_dev);
memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping
memset(_usbd_dev.ep2drv , DRVID_INVALID, sizeof(_usbd_dev.ep2drv )); // invalid mapping
+}
+static void usbd_reset(uint8_t rhport)
+{
+ configuration_reset(rhport);
usbd_control_reset();
-
- for ( uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++ )
- {
- get_driver(i)->reset(rhport);
- }
}
bool tud_task_event_ready(void)
@@ -556,13 +561,28 @@ void tud_task (void)
break;
case DCD_EVENT_SUSPEND:
- TU_LOG2("\r\n");
- if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en);
+ // NOTE: When plugging/unplugging device, the D+/D- state are unstable and
+ // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ), which result in a series of event
+ // e.g suspend -> resume -> unplug/plug. Skip suspend/resume if not connected
+ if ( _usbd_dev.connected )
+ {
+ TU_LOG2(": Remote Wakeup = %u\r\n", _usbd_dev.remote_wakeup_en);
+ if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en);
+ }else
+ {
+ TU_LOG2(" Skipped\r\n");
+ }
break;
case DCD_EVENT_RESUME:
- TU_LOG2("\r\n");
- if (tud_resume_cb) tud_resume_cb();
+ if ( _usbd_dev.connected )
+ {
+ TU_LOG2("\r\n");
+ if (tud_resume_cb) tud_resume_cb();
+ }else
+ {
+ TU_LOG2(" Skipped\r\n");
+ }
break;
case DCD_EVENT_SOF:
@@ -669,9 +689,29 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
{
uint8_t const cfg_num = (uint8_t) p_request->wValue;
- if ( !_usbd_dev.cfg_num && cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) );
- _usbd_dev.cfg_num = cfg_num;
+ // Only process if new configure is different
+ if (_usbd_dev.cfg_num != cfg_num)
+ {
+ if ( _usbd_dev.cfg_num )
+ {
+ // already configured: need to clear all endpoints and driver first
+ TU_LOG(USBD_DBG, " Clear current Configuration (%u) before switching\r\n", _usbd_dev.cfg_num);
+
+ // close all non-control endpoints, cancel all pending transfers if any
+ dcd_edpt_close_all(rhport);
+
+ // close all drivers and current configured state except bus speed
+ uint8_t const speed = _usbd_dev.speed;
+ configuration_reset(rhport);
+ _usbd_dev.speed = speed; // restore speed
+ }
+
+ // switch to new configuration if not zero
+ if ( cfg_num ) TU_ASSERT( process_set_config(rhport, cfg_num) );
+ }
+
+ _usbd_dev.cfg_num = cfg_num;
tud_control_status(rhport, p_request);
}
break;
@@ -684,6 +724,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
// Only support remote wakeup for device feature
TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue);
+ TU_LOG(USBD_DBG, " Enable Remote Wakeup\r\n");
+
// Host may enable remote wake up before suspending especially HID device
_usbd_dev.remote_wakeup_en = true;
tud_control_status(rhport, p_request);
@@ -693,6 +735,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
// Only support remote wakeup for device feature
TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue);
+ TU_LOG(USBD_DBG, " Disable Remote Wakeup\r\n");
+
// Host may disable remote wake up after resuming
_usbd_dev.remote_wakeup_en = false;
tud_control_status(rhport, p_request);
@@ -730,16 +774,24 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
// driver doesn't use alternate settings or implement this
TU_VERIFY(TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type);
- if (TUSB_REQ_GET_INTERFACE == p_request->bRequest)
+ switch(p_request->bRequest)
{
- uint8_t alternate = 0;
- tud_control_xfer(rhport, p_request, &alternate, 1);
- }else if (TUSB_REQ_SET_INTERFACE == p_request->bRequest)
- {
- tud_control_status(rhport, p_request);
- } else
- {
- return false;
+ case TUSB_REQ_GET_INTERFACE:
+ case TUSB_REQ_SET_INTERFACE:
+ // Clear complete callback if driver set since it can also stall the request.
+ usbd_control_set_complete_callback(NULL);
+
+ if (TUSB_REQ_GET_INTERFACE == p_request->bRequest)
+ {
+ uint8_t alternate = 0;
+ tud_control_xfer(rhport, p_request, &alternate, 1);
+ }else
+ {
+ tud_control_status(rhport, p_request);
+ }
+ break;
+
+ default: return false;
}
}
}
@@ -822,7 +874,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
// This function parse configuration descriptor & open drivers accordingly
static bool process_set_config(uint8_t rhport, uint8_t cfg_num)
{
- tusb_desc_configuration_t const * desc_cfg = (tusb_desc_configuration_t const *) tud_descriptor_configuration_cb(cfg_num-1); // index is cfg_num-1
+ // index is cfg_num-1
+ tusb_desc_configuration_t const * desc_cfg = (tusb_desc_configuration_t const *) tud_descriptor_configuration_cb(cfg_num-1);
TU_ASSERT(desc_cfg != NULL && desc_cfg->bDescriptorType == TUSB_DESC_CONFIGURATION);
// Parse configuration descriptor
@@ -831,16 +884,16 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num)
// Parse interface descriptor
uint8_t const * p_desc = ((uint8_t const*) desc_cfg) + sizeof(tusb_desc_configuration_t);
- uint8_t const * desc_end = ((uint8_t const*) desc_cfg) + desc_cfg->wTotalLength;
+ uint8_t const * desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength);
while( p_desc < desc_end )
{
- tusb_desc_interface_assoc_t const * desc_itf_assoc = NULL;
+ tusb_desc_interface_assoc_t const * desc_iad = NULL;
// Class will always starts with Interface Association (if any) and then Interface descriptor
if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) )
{
- desc_itf_assoc = (tusb_desc_interface_assoc_t const *) p_desc;
+ desc_iad = (tusb_desc_interface_assoc_t const *) p_desc;
p_desc = tu_desc_next(p_desc); // next to Interface
}
@@ -849,6 +902,13 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num)
tusb_desc_interface_t const * desc_itf = (tusb_desc_interface_t const*) p_desc;
uint16_t const remaining_len = desc_end-p_desc;
+ // Interface number must not be used already
+ TU_ASSERT(DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber]);
+
+ // TODO usbd can calculate the total length used for driver --> driver open() does not need to calculate it
+ // uint16_t const drv_len = tu_desc_get_interface_total_len(desc_itf, desc_iad ? desc_iad->bInterfaceCount : 1, desc_end-p_desc);
+
+ // Find driver for this interface
uint8_t drv_id;
for (drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++)
{
@@ -860,30 +920,30 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num)
// Open successfully, check if length is correct
TU_ASSERT( sizeof(tusb_desc_interface_t) <= drv_len && drv_len <= remaining_len);
- // Interface number must not be used already
- TU_ASSERT(DRVID_INVALID == _usbd_dev.itf2drv[desc_itf->bInterfaceNumber]);
-
TU_LOG2(" %s opened\r\n", driver->name);
+
+ // bind interface to found driver
_usbd_dev.itf2drv[desc_itf->bInterfaceNumber] = drv_id;
- // If IAD exist, assign all interfaces to the same driver
- if (desc_itf_assoc)
+ // If using IAD, bind all interfaces to the same driver
+ if (desc_iad)
{
// IAD's first interface number and class should match with opened interface
- TU_ASSERT(desc_itf_assoc->bFirstInterface == desc_itf->bInterfaceNumber &&
- desc_itf_assoc->bFunctionClass == desc_itf->bInterfaceClass);
+ TU_ASSERT(desc_iad->bFirstInterface == desc_itf->bInterfaceNumber &&
+ desc_iad->bFunctionClass == desc_itf->bInterfaceClass);
- for(uint8_t i=1; i<desc_itf_assoc->bInterfaceCount; i++)
+ for(uint8_t i=1; i<desc_iad->bInterfaceCount; i++)
{
_usbd_dev.itf2drv[desc_itf->bInterfaceNumber+i] = drv_id;
}
}
- mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor
+ // bind all endpoints to found driver
+ tu_edpt_bind_driver(_usbd_dev.ep2drv, desc_itf, drv_len, drv_id);
p_desc += drv_len; // next interface
- break;
+ break; // exit driver find loop
}
}
@@ -897,25 +957,6 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num)
return true;
}
-// Helper marking endpoint of interface belongs to class driver
-static void mark_interface_endpoint(uint8_t ep2drv[][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id)
-{
- uint16_t len = 0;
-
- while( len < desc_len )
- {
- if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) )
- {
- uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress;
-
- ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id;
- }
-
- len = (uint16_t)(len + tu_desc_len(p_desc));
- p_desc = tu_desc_next(p_desc);
- }
-}
-
// return descriptor's buffer and update desc_len
static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request)
{
@@ -953,24 +994,34 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
tusb_desc_bos_t const* desc_bos = (tusb_desc_bos_t const*) tud_descriptor_bos_cb();
- uint16_t total_len;
// Use offsetof to avoid pointer to the odd/misaligned address
- memcpy(&total_len, (uint8_t*) desc_bos + offsetof(tusb_desc_bos_t, wTotalLength), 2);
+ uint16_t const total_len = tu_le16toh( tu_unaligned_read16((uint8_t*) desc_bos + offsetof(tusb_desc_bos_t, wTotalLength)) );
return tud_control_xfer(rhport, p_request, (void*) desc_bos, total_len);
}
break;
case TUSB_DESC_CONFIGURATION:
+ case TUSB_DESC_OTHER_SPEED_CONFIG:
{
- TU_LOG2(" Configuration[%u]\r\n", desc_index);
+ tusb_desc_configuration_t const* desc_config;
+
+ if ( desc_type == TUSB_DESC_CONFIGURATION )
+ {
+ TU_LOG2(" Configuration[%u]\r\n", desc_index);
+ desc_config = (tusb_desc_configuration_t const*) tud_descriptor_configuration_cb(desc_index);
+ }else
+ {
+ // Host only request this after getting Device Qualifier descriptor
+ TU_LOG2(" Other Speed Configuration\r\n");
+ TU_VERIFY( tud_descriptor_other_speed_configuration_cb );
+ desc_config = (tusb_desc_configuration_t const*) tud_descriptor_other_speed_configuration_cb(desc_index);
+ }
- tusb_desc_configuration_t const* desc_config = (tusb_desc_configuration_t const*) tud_descriptor_configuration_cb(desc_index);
TU_ASSERT(desc_config);
- uint16_t total_len;
// Use offsetof to avoid pointer to the odd/misaligned address
- memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2);
+ uint16_t const total_len = tu_le16toh( tu_unaligned_read16((uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength)) );
return tud_control_xfer(rhport, p_request, (void*) desc_config, total_len);
}
@@ -990,29 +1041,17 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
break;
case TUSB_DESC_DEVICE_QUALIFIER:
+ {
TU_LOG2(" Device Qualifier\r\n");
- // Host sends this request to ask why our device with USB BCD from 2.0
- // but is running at Full/Low Speed. If not highspeed capable stall this request,
- // otherwise return the descriptor that could work in highspeed mode
- if ( tud_descriptor_device_qualifier_cb )
- {
- uint8_t const* desc_qualifier = tud_descriptor_device_qualifier_cb();
- TU_ASSERT(desc_qualifier);
+ TU_VERIFY( tud_descriptor_device_qualifier_cb );
- // first byte of descriptor is its size
- return tud_control_xfer(rhport, p_request, (void*) desc_qualifier, desc_qualifier[0]);
- }else
- {
- return false;
- }
- break;
-
- case TUSB_DESC_OTHER_SPEED_CONFIG:
- TU_LOG2(" Other Speed Configuration\r\n");
+ uint8_t const* desc_qualifier = tud_descriptor_device_qualifier_cb();
+ TU_VERIFY(desc_qualifier);
- // After Device Qualifier descriptor is received host will ask for this descriptor
- return false; // not supported
+ // first byte of descriptor is its size
+ return tud_control_xfer(rhport, p_request, (void*) desc_qualifier, desc_qualifier[0]);
+ }
break;
default: return false;
@@ -1027,19 +1066,11 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr)
switch (event->event_id)
{
case DCD_EVENT_UNPLUGGED:
- // UNPLUGGED event can be bouncing, only processing if we are currently connected
- if ( _usbd_dev.connected )
- {
- _usbd_dev.connected = 0;
- _usbd_dev.addressed = 0;
- _usbd_dev.cfg_num = 0;
- _usbd_dev.suspended = 0;
- osal_queue_send(_usbd_q, event, in_isr);
- }
- break;
-
- case DCD_EVENT_SOF:
- return; // skip SOF event for now
+ _usbd_dev.connected = 0;
+ _usbd_dev.addressed = 0;
+ _usbd_dev.cfg_num = 0;
+ _usbd_dev.suspended = 0;
+ osal_queue_send(_usbd_q, event, in_isr);
break;
case DCD_EVENT_SUSPEND:
@@ -1063,6 +1094,17 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr)
}
break;
+ case DCD_EVENT_SOF:
+ // Some MCUs after running dcd_remote_wakeup() does not have way to detect the end of remote wakeup
+ // which last 1-15 ms. DCD can use SOF as a clear indicator that bus is back to operational
+ if ( _usbd_dev.suspended )
+ {
+ _usbd_dev.suspended = 0;
+ dcd_event_t const event_resume = { .rhport = event->rhport, .event_id = DCD_EVENT_RESUME };
+ osal_queue_send(_usbd_q, &event_resume, in_isr);
+ }
+ break;
+
default:
osal_queue_send(_usbd_q, event, in_isr);
break;
@@ -1150,38 +1192,8 @@ void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr)
bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep)
{
- TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, desc_ep->wMaxPacketSize.size);
-
- switch (desc_ep->bmAttributes.xfer)
- {
- case TUSB_XFER_ISOCHRONOUS:
- {
- uint16_t const max_epsize = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 1023);
- TU_ASSERT(desc_ep->wMaxPacketSize.size <= max_epsize);
- }
- break;
-
- case TUSB_XFER_BULK:
- if (_usbd_dev.speed == TUSB_SPEED_HIGH)
- {
- // Bulk highspeed must be EXACTLY 512
- TU_ASSERT(desc_ep->wMaxPacketSize.size == 512);
- }else
- {
- // TODO Bulk fullspeed can only be 8, 16, 32, 64
- TU_ASSERT(desc_ep->wMaxPacketSize.size <= 64);
- }
- break;
-
- case TUSB_XFER_INTERRUPT:
- {
- uint16_t const max_epsize = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 64);
- TU_ASSERT(desc_ep->wMaxPacketSize.size <= max_epsize);
- }
- break;
-
- default: return false;
- }
+ TU_ASSERT(tu_edpt_number(desc_ep->bEndpointAddress) < CFG_TUD_ENDPPOINT_MAX);
+ TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed));
return dcd_edpt_open(rhport, desc_ep);
}
@@ -1190,6 +1202,9 @@ bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr)
{
(void) rhport;
+ // TODO add this check later, also make sure we don't starve an out endpoint while suspending
+ // TU_VERIFY(tud_ready());
+
uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const dir = tu_edpt_dir(ep_addr);
@@ -1243,7 +1258,10 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const dir = tu_edpt_dir(ep_addr);
- TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes);
+ // TODO skip ready() check for now since enumeration also use this API
+ // TU_VERIFY(tud_ready());
+
+ TU_LOG2(" Queue EP %02X with %u bytes ...\r\n", ep_addr, total_bytes);
// Attempt to transfer on a busy endpoint, sound like an race condition !
TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0);
@@ -1254,14 +1272,13 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
if ( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) )
{
- TU_LOG2("OK\r\n");
return true;
}else
{
// DCD error, mark endpoint as ready to allow next transfer
_usbd_dev.ep_status[epnum][dir].busy = false;
_usbd_dev.ep_status[epnum][dir].claimed = 0;
- TU_LOG2("failed\r\n");
+ TU_LOG2("FAILED\r\n");
TU_BREAKPOINT();
return false;
}
@@ -1312,12 +1329,18 @@ bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr)
void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
{
+
uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const dir = tu_edpt_dir(ep_addr);
- dcd_edpt_stall(rhport, ep_addr);
- _usbd_dev.ep_status[epnum][dir].stalled = true;
- _usbd_dev.ep_status[epnum][dir].busy = true;
+ // only stalled if currently cleared
+ if ( !_usbd_dev.ep_status[epnum][dir].stalled )
+ {
+ TU_LOG(USBD_DBG, " Stall EP %02X\r\n", ep_addr);
+ dcd_edpt_stall(rhport, ep_addr);
+ _usbd_dev.ep_status[epnum][dir].stalled = true;
+ _usbd_dev.ep_status[epnum][dir].busy = true;
+ }
}
void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
@@ -1325,9 +1348,14 @@ void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const dir = tu_edpt_dir(ep_addr);
- dcd_edpt_clear_stall(rhport, ep_addr);
- _usbd_dev.ep_status[epnum][dir].stalled = false;
- _usbd_dev.ep_status[epnum][dir].busy = false;
+ // only clear if currently stalled
+ if ( _usbd_dev.ep_status[epnum][dir].stalled )
+ {
+ TU_LOG(USBD_DBG, " Clear Stall EP %02X\r\n", ep_addr);
+ dcd_edpt_clear_stall(rhport, ep_addr);
+ _usbd_dev.ep_status[epnum][dir].stalled = false;
+ _usbd_dev.ep_status[epnum][dir].busy = false;
+ }
}
bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr)
@@ -1351,7 +1379,13 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr)
TU_ASSERT(dcd_edpt_close, /**/);
TU_LOG2(" CLOSING Endpoint: 0x%02X\r\n", ep_addr);
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
+
dcd_edpt_close(rhport, ep_addr);
+ _usbd_dev.ep_status[epnum][dir].stalled = false;
+ _usbd_dev.ep_status[epnum][dir].busy = false;
+ _usbd_dev.ep_status[epnum][dir].claimed = false;
return;
}
diff --git a/src/device/usbd.h b/src/device/usbd.h
index 3857295d7..638d93094 100644
--- a/src/device/usbd.h
+++ b/src/device/usbd.h
@@ -24,18 +24,15 @@
* This file is part of the TinyUSB stack.
*/
-/** \ingroup group_usbd
- * @{ */
-
#ifndef _TUSB_USBD_H_
#define _TUSB_USBD_H_
+#include "common/tusb_common.h"
+
#ifdef __cplusplus
extern "C" {
#endif
-#include "common/tusb_common.h"
-
//--------------------------------------------------------------------+
// Application API
//--------------------------------------------------------------------+
@@ -103,10 +100,6 @@ bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request);
// Application return pointer to descriptor
uint8_t const * tud_descriptor_device_cb(void);
-// Invoked when received GET BOS DESCRIPTOR request
-// Application return pointer to descriptor
-TU_ATTR_WEAK uint8_t const * tud_descriptor_bos_cb(void);
-
// Invoked when received GET CONFIGURATION DESCRIPTOR request
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
uint8_t const * tud_descriptor_configuration_cb(uint8_t index);
@@ -115,10 +108,21 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index);
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid);
+// Invoked when received GET BOS DESCRIPTOR request
+// Application return pointer to descriptor
+TU_ATTR_WEAK uint8_t const * tud_descriptor_bos_cb(void);
+
// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
-// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
+// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
+// device_qualifier descriptor describes information about a high-speed capable device that would
+// change if the device were operating at the other speed. If not highspeed capable stall this request.
TU_ATTR_WEAK uint8_t const* tud_descriptor_device_qualifier_cb(void);
+// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
+// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
+// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
+TU_ATTR_WEAK uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index);
+
// Invoked when device is mounted (configured)
TU_ATTR_WEAK void tud_mount_cb(void);
@@ -236,7 +240,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval
#define TUD_HID_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epin, _epsize, _ep_interval) \
/* Interface */\
- 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\
+ 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? (uint8_t)HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\
/* HID descriptor */\
9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\
/* Endpoint In */\
@@ -249,7 +253,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
// Interface number, string index, protocol, report descriptor len, EP OUT & IN address, size & polling interval
#define TUD_HID_INOUT_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epout, _epin, _epsize, _ep_interval) \
/* Interface */\
- 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\
+ 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? (uint8_t)HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\
/* HID descriptor */\
9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\
/* Endpoint Out */\
@@ -542,6 +546,11 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
/* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\
TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_interval*/ 1)\
+// Calculate wMaxPacketSize of Endpoints
+#define TUD_AUDIO_EP_SIZE(_maxFrequency, _nBytesPerSample, _nChannels) \
+ ((((_maxFrequency + ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 7999 : 999)) / ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 8000 : 1000)) + 1) * _nBytesPerSample * _nChannels)
+
+
//------------- TUD_USBTMC/USB488 -------------//
#define TUD_USBTMC_APP_CLASS (TUSB_CLASS_APPLICATION_SPECIFIC)
#define TUD_USBTMC_APP_SUBCLASS 0x03u
@@ -600,17 +609,51 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
/* Function */ \
9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101)
-// Length of template descriptr: 18 bytes
-#define TUD_DFU_MODE_DESC_LEN (9 + 9)
+// Length of template descriptor: 9 bytes + number of alternatives * 9
+#define TUD_DFU_DESC_LEN(_alt_count) (9 + (_alt_count) * 9)
-// DFU runtime descriptor
-// Interface number, string index, attributes, detach timeout, transfer size
-#define TUD_DFU_MODE_DESCRIPTOR(_itfnum, _stridx, _attr, _timeout, _xfer_size) \
- /* Interface */ \
- 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx, \
+// Interface number, Alternate count, starting string index, attributes, detach timeout, transfer size
+// Note: Alternate count must be numberic or macro, string index is increased by one for each Alt interface
+#define TUD_DFU_DESCRIPTOR(_itfnum, _alt_count, _stridx, _attr, _timeout, _xfer_size) \
+ TU_XSTRCAT(_TUD_DFU_ALT_,_alt_count)(_itfnum, 0, _stridx), \
/* Function */ \
9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101)
+#define _TUD_DFU_ALT(_itfnum, _alt, _stridx) \
+ /* Interface */ \
+ 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx
+
+#define _TUD_DFU_ALT_1(_itfnum, _alt_count, _stridx) \
+ _TUD_DFU_ALT(_itfnum, _alt_count, _stridx)
+
+#define _TUD_DFU_ALT_2(_itfnum, _alt_count, _stridx) \
+ _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \
+ _TUD_DFU_ALT_1(_itfnum, _alt_count+1, _stridx+1)
+
+#define _TUD_DFU_ALT_3(_itfnum, _alt_count, _stridx) \
+ _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \
+ _TUD_DFU_ALT_2(_itfnum, _alt_count+1, _stridx+1)
+
+#define _TUD_DFU_ALT_4(_itfnum, _alt_count, _stridx) \
+ _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \
+ _TUD_DFU_ALT_3(_itfnum, _alt_count+1, _stridx+1)
+
+#define _TUD_DFU_ALT_5(_itfnum, _alt_count, _stridx) \
+ _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \
+ _TUD_DFU_ALT_4(_itfnum, _alt_count+1, _stridx+1)
+
+#define _TUD_DFU_ALT_6(_itfnum, _alt_count, _stridx) \
+ _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \
+ _TUD_DFU_ALT_5(_itfnum, _alt_count+1, _stridx+1)
+
+#define _TUD_DFU_ALT_7(_itfnum, _alt_count, _stridx) \
+ _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \
+ _TUD_DFU_ALT_6(_itfnum, _alt_count+1, _stridx+1)
+
+#define _TUD_DFU_ALT_8(_itfnum, _alt_count, _stridx) \
+ _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \
+ _TUD_DFU_ALT_7(_itfnum, _alt_count+1, _stridx+1)
+
//------------- CDC-ECM -------------//
@@ -698,7 +741,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb
/* Primary Interface */
#define TUD_BTH_PRI_ITF(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_interval, _ep_in, _ep_out, _ep_size) \
- 9, TUSB_DESC_INTERFACE, _itfnum, _stridx, 3, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, 0, \
+ 9, TUSB_DESC_INTERFACE, _itfnum, 0, 3, TUD_BT_APP_CLASS, TUD_BT_APP_SUBCLASS, TUD_BT_PROTOCOL_PRIMARY_CONTROLLER, _stridx, \
/* Endpoint In for events */ \
7, TUSB_DESC_ENDPOINT, _ep_evt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_evt_size), _ep_evt_interval, \
/* Endpoint In for ACL data */ \
diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c
index 724c652e6..7a8244699 100644
--- a/src/device/usbd_control.c
+++ b/src/device/usbd_control.c
@@ -186,6 +186,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result
{
TU_VERIFY(_ctrl_xfer.buffer);
memcpy(_ctrl_xfer.buffer, _usbd_ctrl_buf, xferred_bytes);
+ TU_LOG_MEM(2, _usbd_ctrl_buf, xferred_bytes, 2);
}
_ctrl_xfer.total_xferred += xferred_bytes;
diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h
index b8d34d7b6..7607b9895 100644
--- a/src/device/usbd_pvt.h
+++ b/src/device/usbd_pvt.h
@@ -56,7 +56,6 @@ typedef struct
// Note: The drivers array must be accessible at all time when stack is active
usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR_WEAK;
-
typedef bool (*usbd_control_xfer_cb_t)(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
//--------------------------------------------------------------------+
@@ -82,7 +81,7 @@ bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr);
// Release an endpoint without submitting a transfer
bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr);
-// Check if endpoint transferring is complete
+// Check if endpoint is busy transferring
bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr);
// Stall endpoint
@@ -94,6 +93,7 @@ void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr);
// Check if endpoint is stalled
bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr);
+// Check if endpoint is ready (not busy and not stalled)
TU_ATTR_ALWAYS_INLINE static inline
bool usbd_edpt_ready(uint8_t rhport, uint8_t ep_addr)
{
diff --git a/src/host/hcd.h b/src/host/hcd.h
index 7a9aadc73..eb53d2e80 100644
--- a/src/host/hcd.h
+++ b/src/host/hcd.h
@@ -30,6 +30,7 @@
#include "common/tusb_common.h"
#include "osal/osal.h"
#include "common/tusb_fifo.h"
+#include "hcd_attr.h"
#ifdef __cplusplus
extern "C" {
@@ -62,6 +63,7 @@ typedef struct
struct {
uint8_t hub_addr;
uint8_t hub_port;
+ uint8_t speed;
} connection;
// XFER_COMPLETE
@@ -84,12 +86,20 @@ typedef struct
// Max number of endpoints per device
enum {
// TODO better computation
- HCD_MAX_ENDPOINT = CFG_TUSB_HOST_DEVICE_MAX*(CFG_TUH_HUB + CFG_TUH_HID*2 + CFG_TUH_MSC*2 + CFG_TUH_CDC*3),
+ HCD_MAX_ENDPOINT = CFG_TUH_DEVICE_MAX*(CFG_TUH_HUB + CFG_TUH_HID*2 + CFG_TUH_MSC*2 + CFG_TUH_CDC*3),
HCD_MAX_XFER = HCD_MAX_ENDPOINT*2,
};
//#define HCD_MAX_ENDPOINT 16
//#define HCD_MAX_XFER 16
+
+typedef struct {
+ uint8_t rhport;
+ uint8_t hub_addr;
+ uint8_t hub_port;
+ uint8_t speed;
+} hcd_devtree_info_t;
+
#endif
//--------------------------------------------------------------------+
@@ -140,9 +150,16 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr);
//--------------------------------------------------------------------+
-// Event API (implemented by stack)
+// USBH implemented API
//--------------------------------------------------------------------+
+// Get device tree information of a device
+// USB device tree can be complicated and manged by USBH, this help HCD to retrieve
+// needed topology info to carry out its work
+extern void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t* devtree_info);
+
+//------------- Event API -------------//
+
// Called by HCD to notify stack
extern void hcd_event_handler(hcd_event_t const* event, bool in_isr);
diff --git a/src/host/hcd_attr.h b/src/host/hcd_attr.h
new file mode 100644
index 000000000..729fc407b
--- /dev/null
+++ b/src/host/hcd_attr.h
@@ -0,0 +1,105 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021, Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef TUSB_HCD_ATTR_H_
+#define TUSB_HCD_ATTR_H_
+
+#include "tusb_option.h"
+
+// Attribute includes
+// - ENDPOINT_MAX: max (logical) number of endpoint
+// - PORT_HIGHSPEED: mask to indicate which port support highspeed mode, bit0 for port0 and so on.
+
+//------------- NXP -------------//
+#if TU_CHECK_MCU(LPC175X_6X) || TU_CHECK_MCU(LPC177X_8X) || TU_CHECK_MCU(LPC40XX)
+ #define HCD_ATTR_OHCI
+
+#elif TU_CHECK_MCU(LPC18XX) || TU_CHECK_MCU(LPC43XX)
+ #define HCD_ATTR_EHCI_TRANSDIMENSION
+
+#elif TU_CHECK_MCU(LPC54XXX)
+ // #define HCD_ATTR_EHCI_NXP_PTD
+
+#elif TU_CHECK_MCU(LPC55XX)
+ // #define HCD_ATTR_EHCI_NXP_PTD
+
+#elif TU_CHECK_MCU(MIMXRT10XX)
+ #define HCD_ATTR_EHCI_TRANSDIMENSION
+
+#elif TU_CHECK_MCU(MKL25ZXX)
+
+//------------- Microchip -------------//
+#elif TU_CHECK_MCU(SAMD21) || TU_CHECK_MCU(SAMD51) || TU_CHECK_MCU(SAME5X) || \
+ TU_CHECK_MCU(SAMD11) || TU_CHECK_MCU(SAML21) || TU_CHECK_MCU(SAML22)
+
+#elif TU_CHECK_MCU(SAMG)
+
+#elif TU_CHECK_MCU(SAMX7X)
+
+//------------- ST -------------//
+#elif TU_CHECK_MCU(STM32F0) || TU_CHECK_MCU(STM32F1) || TU_CHECK_MCU(STM32F3) || \
+ TU_CHECK_MCU(STM32L0) || TU_CHECK_MCU(STM32L1) || TU_CHECK_MCU(STM32L4)
+
+#elif TU_CHECK_MCU(STM32F2) || TU_CHECK_MCU(STM32F4) || TU_CHECK_MCU(STM32F3)
+
+#elif TU_CHECK_MCU(STM32F7)
+
+#elif TU_CHECK_MCU(STM32H7)
+
+//------------- Sony -------------//
+#elif TU_CHECK_MCU(CXD56)
+
+//------------- Nuvoton -------------//
+#elif TU_CHECK_MCU(NUC505)
+
+//------------- Espressif -------------//
+#elif TU_CHECK_MCU(ESP32S2) || TU_CHECK_MCU(ESP32S3)
+
+//------------- Raspberry Pi -------------//
+#elif TU_CHECK_MCU(RP2040)
+
+//------------- Silabs -------------//
+#elif TU_CHECK_MCU(EFM32GG) || TU_CHECK_MCU(EFM32GG11) || TU_CHECK_MCU(EFM32GG12)
+
+//------------- Renesas -------------//
+#elif TU_CHECK_MCU(RX63X) || TU_CHECK_MCU(RX65X) || TU_CHECK_MCU(RX72N)
+
+//#elif TU_CHECK_MCU(MM32F327X)
+// #define DCD_ATTR_ENDPOINT_MAX not known yet
+
+//------------- GigaDevice -------------//
+#elif TU_CHECK_MCU(GD32VF103)
+
+#else
+// #warning "DCD_ATTR_ENDPOINT_MAX is not defined for this MCU, default to 8"
+#endif
+
+// Default to fullspeed if not defined
+//#ifndef PORT_HIGHSPEED
+// #define DCD_ATTR_PORT_HIGHSPEED 0x00
+//#endif
+
+#endif
diff --git a/src/host/hub.c b/src/host/hub.c
index b2761184d..fd4dbd04a 100644
--- a/src/host/hub.c
+++ b/src/host/hub.c
@@ -45,8 +45,14 @@ typedef struct
hub_port_status_response_t port_status;
} hub_interface_t;
-CFG_TUSB_MEM_SECTION static hub_interface_t hub_data[CFG_TUSB_HOST_DEVICE_MAX];
-TU_ATTR_ALIGNED(4) CFG_TUSB_MEM_SECTION static uint8_t _hub_buffer[sizeof(descriptor_hub_desc_t)];
+CFG_TUSB_MEM_SECTION static hub_interface_t hub_data[CFG_TUH_HUB];
+CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _hub_buffer[sizeof(descriptor_hub_desc_t)];
+
+TU_ATTR_ALWAYS_INLINE
+static inline hub_interface_t* get_itf(uint8_t dev_addr)
+{
+ return &hub_data[dev_addr-1-CFG_TUH_DEVICE_MAX];
+}
#if CFG_TUSB_DEBUG
static char const* const _hub_feature_str[] =
@@ -144,40 +150,49 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_con
//--------------------------------------------------------------------+
void hub_init(void)
{
- tu_memclr(hub_data, CFG_TUSB_HOST_DEVICE_MAX*sizeof( hub_interface_t));
+ tu_memclr(hub_data, sizeof(hub_data));
}
-bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length)
+bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len)
{
- // not support multiple TT yet
- if ( itf_desc->bInterfaceProtocol > 1 ) return false;
+ TU_VERIFY(TUSB_CLASS_HUB == itf_desc->bInterfaceClass &&
+ 0 == itf_desc->bInterfaceSubClass);
+
+ // hub driver does not support multiple TT yet
+ TU_VERIFY(itf_desc->bInterfaceProtocol <= 1);
- //------------- Open Interrupt Status Pipe -------------//
- tusb_desc_endpoint_t const *ep_desc;
- ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc);
+ // msc driver length is fixed
+ uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t);
+ TU_ASSERT(drv_len <= max_len);
- TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType);
- TU_ASSERT(TUSB_XFER_INTERRUPT == ep_desc->bmAttributes.xfer);
+ //------------- Interrupt Status endpoint -------------//
+ tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc);
+
+ TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType &&
+ TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0);
- TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc));
+ TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep));
- hub_data[dev_addr-1].itf_num = itf_desc->bInterfaceNumber;
- hub_data[dev_addr-1].ep_in = ep_desc->bEndpointAddress;
+ hub_interface_t* p_hub = get_itf(dev_addr);
- (*p_length) = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t);
+ p_hub->itf_num = itf_desc->bInterfaceNumber;
+ p_hub->ep_in = desc_ep->bEndpointAddress;
return true;
}
void hub_close(uint8_t dev_addr)
{
- tu_memclr(&hub_data[dev_addr-1], sizeof( hub_interface_t));
+ TU_VERIFY(dev_addr > CFG_TUH_DEVICE_MAX, );
+ hub_interface_t* p_hub = get_itf(dev_addr);
+
+ if (p_hub->ep_in) tu_memclr(p_hub, sizeof( hub_interface_t));
}
bool hub_status_pipe_queue(uint8_t dev_addr)
{
- hub_interface_t * p_hub = &hub_data[dev_addr-1];
- return usbh_edpt_xfer(dev_addr, p_hub->ep_in, &p_hub->status_change, 1);
+ hub_interface_t* hub_itf = get_itf(dev_addr);
+ return usbh_edpt_xfer(dev_addr, hub_itf->ep_in, &hub_itf->status_change, 1);
}
@@ -190,7 +205,7 @@ static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t
bool hub_set_config(uint8_t dev_addr, uint8_t itf_num)
{
- hub_interface_t* p_hub = &hub_data[dev_addr-1];
+ hub_interface_t* p_hub = get_itf(dev_addr);
TU_ASSERT(itf_num == p_hub->itf_num);
// Get Hub Descriptor
@@ -218,7 +233,7 @@ static bool config_set_port_power (uint8_t dev_addr, tusb_control_request_t cons
(void) request;
TU_ASSERT(XFER_RESULT_SUCCESS == result);
- hub_interface_t* p_hub = &hub_data[dev_addr-1];
+ hub_interface_t* p_hub = get_itf(dev_addr);
// only use number of ports in hub descriptor
descriptor_hub_desc_t const* desc_hub = (descriptor_hub_desc_t const*) _hub_buffer;
@@ -234,7 +249,7 @@ static bool config_set_port_power (uint8_t dev_addr, tusb_control_request_t cons
static bool config_port_power_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result)
{
TU_ASSERT(XFER_RESULT_SUCCESS == result);
- hub_interface_t* p_hub = &hub_data[dev_addr-1];
+ hub_interface_t* p_hub = get_itf(dev_addr);
if (request->wIndex == p_hub->port_count)
{
@@ -268,7 +283,7 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32
(void) ep_addr;
TU_ASSERT(result == XFER_RESULT_SUCCESS);
- hub_interface_t * p_hub = &hub_data[dev_addr-1];
+ hub_interface_t* p_hub = get_itf(dev_addr);
TU_LOG2(" Port Status Change = 0x%02X\r\n", p_hub->status_change);
@@ -290,7 +305,8 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32
static bool connection_get_status_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result)
{
TU_ASSERT(result == XFER_RESULT_SUCCESS);
- hub_interface_t * p_hub = &hub_data[dev_addr-1];
+
+ hub_interface_t* p_hub = get_itf(dev_addr);
uint8_t const port_num = (uint8_t) request->wIndex;
// Connection change
@@ -318,7 +334,7 @@ static bool connection_clear_conn_change_complete (uint8_t dev_addr, tusb_contro
{
TU_ASSERT(result == XFER_RESULT_SUCCESS);
- hub_interface_t * p_hub = &hub_data[dev_addr-1];
+ hub_interface_t* p_hub = get_itf(dev_addr);
uint8_t const port_num = (uint8_t) request->wIndex;
if ( p_hub->port_status.status.connection )
@@ -349,7 +365,7 @@ static bool connection_port_reset_complete (uint8_t dev_addr, tusb_control_reque
{
TU_ASSERT(result == XFER_RESULT_SUCCESS);
- // usbh_hub_t * p_hub = &hub_data[dev_addr-1];
+ // hub_interface_t* p_hub = get_itf(dev_addr);
uint8_t const port_num = (uint8_t) request->wIndex;
// submit attach event
diff --git a/src/host/hub.h b/src/host/hub.h
index a5111b8e7..c4d544193 100644
--- a/src/host/hub.h
+++ b/src/host/hub.h
@@ -181,11 +181,11 @@ bool hub_status_pipe_queue(uint8_t dev_addr);
//--------------------------------------------------------------------+
// Internal Class Driver API
//--------------------------------------------------------------------+
-void hub_init(void);
-bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length);
-bool hub_set_config(uint8_t dev_addr, uint8_t itf_num);
-bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
-void hub_close(uint8_t dev_addr);
+void hub_init (void);
+bool hub_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len);
+bool hub_set_config (uint8_t dev_addr, uint8_t itf_num);
+bool hub_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
+void hub_close (uint8_t dev_addr);
#ifdef __cplusplus
}
diff --git a/src/host/usbh.c b/src/host/usbh.c
index 59246a663..51b8f85b6 100644
--- a/src/host/usbh.c
+++ b/src/host/usbh.c
@@ -28,19 +28,100 @@
#if TUSB_OPT_HOST_ENABLED
-#ifndef CFG_TUH_TASK_QUEUE_SZ
-#define CFG_TUH_TASK_QUEUE_SZ 16
-#endif
-
#include "tusb.h"
#include "host/usbh.h"
#include "host/usbh_classdriver.h"
#include "hub.h"
-#include "usbh_hcd.h"
+
+//--------------------------------------------------------------------+
+// USBH Configuration
+//--------------------------------------------------------------------+
+
+// TODO remove,update
+#ifndef CFG_TUH_EP_MAX
+#define CFG_TUH_EP_MAX 9
+#endif
+
+#ifndef CFG_TUH_TASK_QUEUE_SZ
+#define CFG_TUH_TASK_QUEUE_SZ 16
+#endif
+
+// Debug level of USBD
+#define USBH_DBG_LVL 2
+
+//--------------------------------------------------------------------+
+// USBH-HCD common data structure
+//--------------------------------------------------------------------+
+
+typedef struct {
+ //------------- port -------------//
+ uint8_t rhport;
+ uint8_t hub_addr;
+ uint8_t hub_port;
+ uint8_t speed;
+
+ //------------- device descriptor -------------//
+ uint16_t vid;
+ uint16_t pid;
+
+ uint8_t ep0_size;
+ uint8_t i_manufacturer;
+ uint8_t i_product;
+ uint8_t i_serial;
+
+ //------------- configuration descriptor -------------//
+ // uint8_t interface_count; // bNumInterfaces alias
+
+ //------------- device -------------//
+ struct TU_ATTR_PACKED
+ {
+ uint8_t connected : 1;
+ uint8_t addressed : 1;
+ uint8_t configured : 1;
+ uint8_t suspended : 1;
+ };
+
+ volatile uint8_t state; // device state, value from enum tusbh_device_state_t
+
+ uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid)
+ uint8_t ep2drv[CFG_TUH_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid )
+
+ struct TU_ATTR_PACKED
+ {
+ volatile bool busy : 1;
+ volatile bool stalled : 1;
+ volatile bool claimed : 1;
+
+ // TODO merge ep2drv here, 4-bit should be sufficient
+ }ep_status[CFG_TUH_EP_MAX][2];
+
+ // Mutex for claiming endpoint, only needed when using with preempted RTOS
+#if CFG_TUSB_OS != OPT_OS_NONE
+ osal_mutex_def_t mutexdef;
+ osal_mutex_t mutex;
+#endif
+
+} usbh_device_t;
+
+typedef struct
+{
+ uint8_t rhport;
+ uint8_t hub_addr;
+ uint8_t hub_port;
+ uint8_t speed;
+
+ volatile uint8_t connected;
+} usbh_dev0_t;
+
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
+
+// Invalid driver ID in itf2drv[] ep2drv[][] mapping
+enum { DRVID_INVALID = 0xFFu };
+enum { ADDR_INVALID = 0xFFu };
+
#if CFG_TUSB_DEBUG >= 2
#define DRIVER_NAME(_name) .name = _name,
#else
@@ -52,7 +133,6 @@ static usbh_class_driver_t const usbh_class_drivers[] =
#if CFG_TUH_CDC
{
DRIVER_NAME("CDC")
- .class_code = TUSB_CLASS_CDC,
.init = cdch_init,
.open = cdch_open,
.set_config = cdch_set_config,
@@ -64,7 +144,6 @@ static usbh_class_driver_t const usbh_class_drivers[] =
#if CFG_TUH_MSC
{
DRIVER_NAME("MSC")
- .class_code = TUSB_CLASS_MSC,
.init = msch_init,
.open = msch_open,
.set_config = msch_set_config,
@@ -76,7 +155,6 @@ static usbh_class_driver_t const usbh_class_drivers[] =
#if CFG_TUH_HID
{
DRIVER_NAME("HID")
- .class_code = TUSB_CLASS_HID,
.init = hidh_init,
.open = hidh_open,
.set_config = hidh_set_config,
@@ -88,7 +166,6 @@ static usbh_class_driver_t const usbh_class_drivers[] =
#if CFG_TUH_HUB
{
DRIVER_NAME("HUB")
- .class_code = TUSB_CLASS_HUB,
.init = hub_init,
.open = hub_open,
.set_config = hub_set_config,
@@ -100,7 +177,6 @@ static usbh_class_driver_t const usbh_class_drivers[] =
#if CFG_TUH_VENDOR
{
DRIVER_NAME("VENDOR")
- .class_code = TUSB_CLASS_VENDOR_SPECIFIC,
.init = cush_init,
.open = cush_open_subtask,
.xfer_cb = cush_isr,
@@ -122,19 +198,32 @@ enum { CONFIG_NUM = 1 }; // default to use configuration 1
static bool _usbh_initialized = false;
-// including zero-address
-CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1];
+// Device with address = 0 for enumeration
+static usbh_dev0_t _dev0;
+
+// all devices excluding zero-address
+// hub address start from CFG_TUH_DEVICE_MAX+1
+CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[CFG_TUH_DEVICE_MAX + CFG_TUH_HUB];
// Event queue
// role device/host is used by OS NONE for mutex (disable usb isr)
OSAL_QUEUE_DEF(OPT_MODE_HOST, _usbh_qdef, CFG_TUH_TASK_QUEUE_SZ, hcd_event_t);
static osal_queue_t _usbh_q;
-CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSZIE];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE];
+
+//------------- Helper Function -------------//
+
+TU_ATTR_ALWAYS_INLINE
+static inline usbh_device_t* get_device(uint8_t dev_addr)
+{
+ TU_ASSERT(dev_addr, NULL);
+ return &_usbh_devices[dev_addr-1];
+}
-//------------- Helper Function Prototypes -------------//
static bool enum_new_device(hcd_event_t* event);
static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port);
+static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size);
// from usbh_control.c
extern bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
@@ -142,15 +231,28 @@ extern bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result
//--------------------------------------------------------------------+
// PUBLIC API (Parameter Verification is required)
//--------------------------------------------------------------------+
-bool tuh_device_configured(uint8_t dev_addr)
+bool tuh_mounted(uint8_t dev_addr)
+{
+ return get_device(dev_addr)->configured;
+}
+
+bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid)
{
- return _usbh_devices[dev_addr].configured;
+ *vid = *pid = 0;
+
+ TU_VERIFY(tuh_mounted(dev_addr));
+
+ usbh_device_t const* dev = get_device(dev_addr);
+
+ *vid = dev->vid;
+ *pid = dev->pid;
+
+ return true;
}
-tusb_speed_t tuh_device_get_speed (uint8_t const dev_addr)
+tusb_speed_t tuh_speed_get (uint8_t dev_addr)
{
- TU_ASSERT( dev_addr <= CFG_TUSB_HOST_DEVICE_MAX, TUSB_SPEED_INVALID);
- return (tusb_speed_t) _usbh_devices[dev_addr].speed;
+ return (tusb_speed_t) (dev_addr ? get_device(dev_addr)->speed : _dev0.speed);
}
#if CFG_TUSB_OS == OPT_OS_NONE
@@ -179,24 +281,25 @@ bool tuh_init(uint8_t rhport)
TU_LOG2("USBH init\r\n");
- tu_memclr(_usbh_devices, sizeof(usbh_device_t)*(CFG_TUSB_HOST_DEVICE_MAX+1));
+ tu_memclr(_usbh_devices, sizeof(_usbh_devices));
+ tu_memclr(&_dev0, sizeof(_dev0));
//------------- Enumeration & Reporter Task init -------------//
_usbh_q = osal_queue_create( &_usbh_qdef );
TU_ASSERT(_usbh_q != NULL);
//------------- Semaphore, Mutex for Control Pipe -------------//
- for(uint8_t i=0; i<CFG_TUSB_HOST_DEVICE_MAX+1; i++) // including address zero
+ for(uint8_t i=0; i<TU_ARRAY_SIZE(_usbh_devices); i++)
{
- usbh_device_t * const dev = &_usbh_devices[i];
+ usbh_device_t * dev = &_usbh_devices[i];
#if CFG_TUSB_OS != OPT_OS_NONE
dev->mutex = osal_mutex_create(&dev->mutexdef);
TU_ASSERT(dev->mutex);
#endif
- memset(dev->itf2drv, 0xff, sizeof(dev->itf2drv)); // invalid mapping
- memset(dev->ep2drv , 0xff, sizeof(dev->ep2drv )); // invalid mapping
+ memset(dev->itf2drv, DRVID_INVALID, sizeof(dev->itf2drv)); // invalid mapping
+ memset(dev->ep2drv , DRVID_INVALID, sizeof(dev->ep2drv )); // invalid mapping
}
// Class drivers init
@@ -267,26 +370,35 @@ void tuh_task(void)
case HCD_EVENT_XFER_COMPLETE:
{
- usbh_device_t* dev = &_usbh_devices[event.dev_addr];
uint8_t const ep_addr = event.xfer_complete.ep_addr;
uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const ep_dir = tu_edpt_dir(ep_addr);
TU_LOG2("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len);
- dev->ep_status[epnum][ep_dir].busy = false;
- dev->ep_status[epnum][ep_dir].claimed = 0;
-
- if ( 0 == epnum )
+ if (event.dev_addr == 0)
{
+ // device 0 only has control endpoint
+ TU_ASSERT(epnum == 0, );
usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
- }else
+ }
+ else
{
- uint8_t drv_id = dev->ep2drv[epnum][ep_dir];
- TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, );
+ usbh_device_t* dev = get_device(event.dev_addr);
+ dev->ep_status[epnum][ep_dir].busy = false;
+ dev->ep_status[epnum][ep_dir].claimed = 0;
+
+ if ( 0 == epnum )
+ {
+ usbh_control_xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
+ }else
+ {
+ uint8_t drv_id = dev->ep2drv[epnum][ep_dir];
+ TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, );
- TU_LOG2("%s xfer callback\r\n", usbh_class_drivers[drv_id].name);
- usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
+ TU_LOG2("%s xfer callback\r\n", usbh_class_drivers[drv_id].name);
+ usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
+ }
}
}
break;
@@ -306,7 +418,7 @@ void tuh_task(void)
uint8_t usbh_get_rhport(uint8_t dev_addr)
{
- return _usbh_devices[dev_addr].rhport;
+ return (dev_addr == 0) ? _dev0.rhport : get_device(dev_addr)->rhport;
}
uint8_t* usbh_get_enum_buf(void)
@@ -315,154 +427,28 @@ uint8_t* usbh_get_enum_buf(void)
}
//--------------------------------------------------------------------+
-// Endpoint API
+// HCD Event Handler
//--------------------------------------------------------------------+
-// TODO has some duplication code with device, refactor later
-bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr)
+void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t* devtree_info)
{
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
-
- usbh_device_t* dev = &_usbh_devices[dev_addr];
-
-#if CFG_TUSB_OS != OPT_OS_NONE
- // pre-check to help reducing mutex lock
- TU_VERIFY((dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0));
- osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER);
-#endif
-
- // can only claim the endpoint if it is not busy and not claimed yet.
- bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0);
- if (ret)
+ if (dev_addr)
{
- dev->ep_status[epnum][dir].claimed = 1;
- }
-
-#if CFG_TUSB_OS != OPT_OS_NONE
- osal_mutex_unlock(dev->mutex);
-#endif
-
- return ret;
-}
-
-// TODO has some duplication code with device, refactor later
-bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr)
-{
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
-
- usbh_device_t* dev = &_usbh_devices[dev_addr];
-
-#if CFG_TUSB_OS != OPT_OS_NONE
- osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER);
-#endif
+ usbh_device_t const* dev = get_device(dev_addr);
- // can only release the endpoint if it is claimed and not busy
- bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 1);
- if (ret)
- {
- dev->ep_status[epnum][dir].claimed = 0;
- }
-
-#if CFG_TUSB_OS != OPT_OS_NONE
- osal_mutex_unlock(dev->mutex);
-#endif
-
- return ret;
-}
-
-// TODO has some duplication code with device, refactor later
-bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
-{
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
-
- usbh_device_t* dev = &_usbh_devices[dev_addr];
-
- TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes);
-
- // Attempt to transfer on a busy endpoint, sound like an race condition !
- TU_ASSERT(dev->ep_status[epnum][dir].busy == 0);
-
- // Set busy first since the actual transfer can be complete before hcd_edpt_xfer()
- // could return and USBH task can preempt and clear the busy
- dev->ep_status[epnum][dir].busy = true;
-
- if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) )
- {
- TU_LOG2("OK\r\n");
- return true;
+ devtree_info->rhport = dev->rhport;
+ devtree_info->hub_addr = dev->hub_addr;
+ devtree_info->hub_port = dev->hub_port;
+ devtree_info->speed = dev->speed;
}else
{
- // HCD error, mark endpoint as ready to allow next transfer
- dev->ep_status[epnum][dir].busy = false;
- dev->ep_status[epnum][dir].claimed = 0;
- TU_LOG2("failed\r\n");
- TU_BREAKPOINT();
- return false;
+ devtree_info->rhport = _dev0.rhport;
+ devtree_info->hub_addr = _dev0.hub_addr;
+ devtree_info->hub_port = _dev0.hub_port;
+ devtree_info->speed = _dev0.speed;
}
}
-bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size)
-{
- TU_LOG2("Open EP Control with Size = %u\r\n", max_packet_size);
-
- tusb_desc_endpoint_t ep0_desc =
- {
- .bLength = sizeof(tusb_desc_endpoint_t),
- .bDescriptorType = TUSB_DESC_ENDPOINT,
- .bEndpointAddress = 0,
- .bmAttributes = { .xfer = TUSB_XFER_CONTROL },
- .wMaxPacketSize = { .size = max_packet_size },
- .bInterval = 0
- };
-
- return hcd_edpt_open(_usbh_devices[dev_addr].rhport, dev_addr, &ep0_desc);
-}
-
-bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep)
-{
- TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, desc_ep->wMaxPacketSize.size);
-
- bool ret = hcd_edpt_open(rhport, dev_addr, desc_ep);
-
- if (ret)
- {
- usbh_device_t* dev = &_usbh_devices[dev_addr];
-
- // new endpoints belongs to latest interface (last valid value)
- // TODO FIXME not true with ISO
- uint8_t drvid = 0xff;
- for(uint8_t i=0; i < sizeof(dev->itf2drv); i++)
- {
- if ( dev->itf2drv[i] == 0xff ) break;
- drvid = dev->itf2drv[i];
- }
- TU_ASSERT(drvid < USBH_CLASS_DRIVER_COUNT);
-
- uint8_t const ep_addr = desc_ep->bEndpointAddress;
- dev->ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = drvid;
- }
-
- return ret;
-}
-
-bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr)
-{
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
-
- usbh_device_t* dev = &_usbh_devices[dev_addr];
-
- return dev->ep_status[epnum][dir].busy;
-}
-
-
-//--------------------------------------------------------------------+
-// HCD Event Handler
-//--------------------------------------------------------------------+
-
void hcd_event_handler(hcd_event_t const* event, bool in_isr)
{
switch (event->event_id)
@@ -473,7 +459,6 @@ void hcd_event_handler(hcd_event_t const* event, bool in_isr)
}
}
-// interrupt caused by a TD (with IOC=1) in pipe of class class_code
void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr)
{
hcd_event_t event =
@@ -526,9 +511,11 @@ void hcd_event_device_remove(uint8_t hostid, bool in_isr)
void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port)
{
//------------- find the all devices (star-network) under port that is unplugged -------------//
- for (uint8_t dev_addr = 0; dev_addr <= CFG_TUSB_HOST_DEVICE_MAX; dev_addr ++)
+ // TODO mark as disconnected in ISR, also handle dev0
+ for ( uint8_t dev_id = 0; dev_id < TU_ARRAY_SIZE(_usbh_devices); dev_id++ )
{
- usbh_device_t* dev = &_usbh_devices[dev_addr];
+ usbh_device_t* dev = &_usbh_devices[dev_id];
+ uint8_t const dev_addr = dev_id+1;
// TODO Hub multiple level
if (dev->rhport == rhport &&
@@ -546,8 +533,8 @@ void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port
usbh_class_drivers[drv_id].close(dev_addr);
}
- memset(dev->itf2drv, 0xff, sizeof(dev->itf2drv)); // invalid mapping
- memset(dev->ep2drv , 0xff, sizeof(dev->ep2drv )); // invalid mapping
+ memset(dev->itf2drv, DRVID_INVALID, sizeof(dev->itf2drv)); // invalid mapping
+ memset(dev->ep2drv , DRVID_INVALID, sizeof(dev->ep2drv )); // invalid mapping
hcd_device_close(rhport, dev_addr);
@@ -559,24 +546,29 @@ void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port
//--------------------------------------------------------------------+
// INTERNAL HELPER
//--------------------------------------------------------------------+
-static uint8_t get_new_address(void)
+static uint8_t get_new_address(bool is_hub)
{
- for (uint8_t addr=1; addr <= CFG_TUSB_HOST_DEVICE_MAX; addr++)
+ uint8_t const start = (is_hub ? CFG_TUH_DEVICE_MAX : 0) + 1;
+ uint8_t const count = (is_hub ? CFG_TUH_HUB : CFG_TUH_DEVICE_MAX);
+
+ for (uint8_t i=0; i < count; i++)
{
- if (_usbh_devices[addr].state == TUSB_DEVICE_STATE_UNPLUG) return addr;
+ uint8_t const addr = start + i;
+ if (get_device(addr)->state == TUSB_DEVICE_STATE_UNPLUG) return addr;
}
- return CFG_TUSB_HOST_DEVICE_MAX+1;
+ return ADDR_INVALID;
}
void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num)
{
- usbh_device_t* dev = &_usbh_devices[dev_addr];
+ usbh_device_t* dev = get_device(dev_addr);
for(itf_num++; itf_num < sizeof(dev->itf2drv); itf_num++)
{
// continue with next valid interface
+ // TODO skip IAD binding interface such as CDCs
uint8_t const drv_id = dev->itf2drv[itf_num];
- if (drv_id != 0xff)
+ if (drv_id != DRVID_INVALID)
{
usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id];
TU_LOG2("%s set config: itf = %u\r\n", driver->name, itf_num);
@@ -613,6 +605,7 @@ static bool enum_get_config_desc_complete (uint8_t dev_addr, tusb_control_
static bool enum_set_config_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
static bool parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg);
+#if CFG_TUH_HUB
static bool enum_hub_clear_reset0_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result)
{
(void) dev_addr; (void) request;
@@ -625,12 +618,11 @@ static bool enum_hub_clear_reset1_complete(uint8_t dev_addr, tusb_control_reques
{
(void) dev_addr; (void) request;
TU_ASSERT(XFER_RESULT_SUCCESS == result);
- usbh_device_t* dev0 = &_usbh_devices[0];
enum_request_set_addr();
// done with hub, waiting for next data on status pipe
- (void) hub_status_pipe_queue( dev0->hub_addr );
+ (void) hub_status_pipe_queue( _dev0.hub_addr );
return true;
}
@@ -639,7 +631,6 @@ static bool enum_hub_get_status1_complete(uint8_t dev_addr, tusb_control_request
{
(void) dev_addr; (void) request;
TU_ASSERT(XFER_RESULT_SUCCESS == result);
- usbh_device_t* dev0 = &_usbh_devices[0];
hub_port_status_response_t port_status;
memcpy(&port_status, _usbh_ctrl_buf, sizeof(hub_port_status_response_t));
@@ -647,7 +638,7 @@ static bool enum_hub_get_status1_complete(uint8_t dev_addr, tusb_control_request
// Acknowledge Port Reset Change if Reset Successful
if (port_status.change.reset)
{
- TU_ASSERT( hub_port_clear_feature(dev0->hub_addr, dev0->hub_port, HUB_FEATURE_PORT_RESET_CHANGE, enum_hub_clear_reset1_complete) );
+ TU_ASSERT( hub_port_clear_feature(_dev0.hub_addr, _dev0.hub_port, HUB_FEATURE_PORT_RESET_CHANGE, enum_hub_clear_reset1_complete) );
}
return true;
@@ -657,7 +648,6 @@ static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request
{
(void) dev_addr; (void) request;
TU_ASSERT(XFER_RESULT_SUCCESS == result);
- usbh_device_t* dev0 = &_usbh_devices[0];
hub_port_status_response_t port_status;
memcpy(&port_status, _usbh_ctrl_buf, sizeof(hub_port_status_response_t));
@@ -668,74 +658,35 @@ static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request
return hub_status_pipe_queue(dev_addr);
}
- dev0->speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH :
+ _dev0.speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH :
(port_status.status.low_speed ) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL;
// Acknowledge Port Reset Change
if (port_status.change.reset)
{
- hub_port_clear_feature(dev0->hub_addr, dev0->hub_port, HUB_FEATURE_PORT_RESET_CHANGE, enum_hub_clear_reset0_complete);
+ hub_port_clear_feature(_dev0.hub_addr, _dev0.hub_port, HUB_FEATURE_PORT_RESET_CHANGE, enum_hub_clear_reset0_complete);
}
return true;
}
-
-
-static bool enum_request_set_addr(void)
-{
- // Set Address
- uint8_t const new_addr = get_new_address();
- TU_ASSERT(new_addr <= CFG_TUSB_HOST_DEVICE_MAX); // TODO notify application we reach max devices
-
- TU_LOG2("Set Address = %d\r\n", new_addr);
-
- usbh_device_t* dev0 = &_usbh_devices[0];
- usbh_device_t* new_dev = &_usbh_devices[new_addr];
-
- new_dev->rhport = dev0->rhport;
- new_dev->hub_addr = dev0->hub_addr;
- new_dev->hub_port = dev0->hub_port;
- new_dev->speed = dev0->speed;
- new_dev->connected = 1;
- new_dev->ep0_packet_size = ((tusb_desc_device_t*) _usbh_ctrl_buf)->bMaxPacketSize0;
-
- tusb_control_request_t const new_request =
- {
- .bmRequestType_bit =
- {
- .recipient = TUSB_REQ_RCPT_DEVICE,
- .type = TUSB_REQ_TYPE_STANDARD,
- .direction = TUSB_DIR_OUT
- },
- .bRequest = TUSB_REQ_SET_ADDRESS,
- .wValue = new_addr,
- .wIndex = 0,
- .wLength = 0
- };
-
- TU_ASSERT( tuh_control_xfer(0, &new_request, NULL, enum_set_address_complete) );
-
- return true;
-}
+#endif
static bool enum_new_device(hcd_event_t* event)
{
- usbh_device_t* dev0 = &_usbh_devices[0];
- dev0->rhport = event->rhport; // TODO refractor integrate to device_pool
- dev0->hub_addr = event->connection.hub_addr;
- dev0->hub_port = event->connection.hub_port;
- dev0->state = TUSB_DEVICE_STATE_UNPLUG;
+ _dev0.rhport = event->rhport; // TODO refractor integrate to device_pool
+ _dev0.hub_addr = event->connection.hub_addr;
+ _dev0.hub_port = event->connection.hub_port;
//------------- connected/disconnected directly with roothub -------------//
- if (dev0->hub_addr == 0)
+ if (_dev0.hub_addr == 0)
{
// wait until device is stable TODO non blocking
osal_task_delay(RESET_DELAY);
// device unplugged while delaying
- if ( !hcd_port_connect_status(dev0->rhport) ) return true;
+ if ( !hcd_port_connect_status(_dev0.rhport) ) return true;
- dev0->speed = hcd_port_speed_get( dev0->rhport );
+ _dev0.speed = hcd_port_speed_get(_dev0.rhport );
enum_request_addr0_device_desc();
}
@@ -745,7 +696,7 @@ static bool enum_new_device(hcd_event_t* event)
{
// wait until device is stable
osal_task_delay(RESET_DELAY);
- TU_ASSERT( hub_port_get_status(dev0->hub_addr, dev0->hub_port, _usbh_ctrl_buf, enum_hub_get_status0_complete) );
+ TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, enum_hub_get_status0_complete) );
}
#endif // CFG_TUH_HUB
@@ -755,7 +706,8 @@ static bool enum_new_device(hcd_event_t* event)
static bool enum_request_addr0_device_desc(void)
{
// TODO probably doesn't need to open/close each enumeration
- TU_ASSERT( usbh_edpt_control_open(0, 8) );
+ uint8_t const addr0 = 0;
+ TU_ASSERT( usbh_edpt_control_open(addr0, 8) );
//------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------//
TU_LOG2("Get 8 byte of Device Descriptor\r\n");
@@ -772,7 +724,7 @@ static bool enum_request_addr0_device_desc(void)
.wIndex = 0,
.wLength = 8
};
- TU_ASSERT( tuh_control_xfer(0, &request, _usbh_ctrl_buf, enum_get_addr0_device_desc_complete) );
+ TU_ASSERT( tuh_control_xfer(addr0, &request, _usbh_ctrl_buf, enum_get_addr0_device_desc_complete) );
return true;
}
@@ -783,25 +735,26 @@ static bool enum_get_addr0_device_desc_complete(uint8_t dev_addr, tusb_control_r
(void) request;
TU_ASSERT(0 == dev_addr);
- usbh_device_t* dev0 = &_usbh_devices[0];
-
if (XFER_RESULT_SUCCESS != result)
{
#if CFG_TUH_HUB
// TODO remove, waiting for next data on status pipe
- if (dev0->hub_addr != 0) hub_status_pipe_queue(dev0->hub_addr);
+ if (_dev0.hub_addr != 0) hub_status_pipe_queue(_dev0.hub_addr);
#endif
return false;
}
+ tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf;
+ TU_ASSERT( tu_desc_type(desc_device) == TUSB_DESC_DEVICE );
+
// Reset device again before Set Address
TU_LOG2("Port reset \r\n");
- if (dev0->hub_addr == 0)
+ if (_dev0.hub_addr == 0)
{
// connected directly to roothub
- hcd_port_reset( dev0->rhport ); // reset port after 8 byte descriptor
+ hcd_port_reset( _dev0.rhport ); // reset port after 8 byte descriptor
osal_task_delay(RESET_DELAY);
enum_request_set_addr();
@@ -810,18 +763,57 @@ static bool enum_get_addr0_device_desc_complete(uint8_t dev_addr, tusb_control_r
else
{
// after RESET_DELAY the hub_port_reset() already complete
- TU_ASSERT( hub_port_reset(dev0->hub_addr, dev0->hub_port, NULL) );
+ TU_ASSERT( hub_port_reset(_dev0.hub_addr, _dev0.hub_port, NULL) );
osal_task_delay(RESET_DELAY);
tuh_task(); // FIXME temporarily to clean up port_reset control transfer
- TU_ASSERT( hub_port_get_status(dev0->hub_addr, dev0->hub_port, _usbh_ctrl_buf, enum_hub_get_status1_complete) );
+ TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, enum_hub_get_status1_complete) );
}
#endif
return true;
}
+static bool enum_request_set_addr(void)
+{
+ uint8_t const addr0 = 0;
+ tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf;
+
+ // Get new address
+ uint8_t const new_addr = get_new_address(desc_device->bDeviceClass == TUSB_CLASS_HUB);
+ TU_ASSERT(new_addr != ADDR_INVALID);
+
+ TU_LOG2("Set Address = %d\r\n", new_addr);
+
+ usbh_device_t* new_dev = get_device(new_addr);
+
+ new_dev->rhport = _dev0.rhport;
+ new_dev->hub_addr = _dev0.hub_addr;
+ new_dev->hub_port = _dev0.hub_port;
+ new_dev->speed = _dev0.speed;
+ new_dev->connected = 1;
+ new_dev->ep0_size = desc_device->bMaxPacketSize0;
+
+ tusb_control_request_t const new_request =
+ {
+ .bmRequestType_bit =
+ {
+ .recipient = TUSB_REQ_RCPT_DEVICE,
+ .type = TUSB_REQ_TYPE_STANDARD,
+ .direction = TUSB_DIR_OUT
+ },
+ .bRequest = TUSB_REQ_SET_ADDRESS,
+ .wValue = new_addr,
+ .wIndex = 0,
+ .wLength = 0
+ };
+
+ TU_ASSERT( tuh_control_xfer(addr0, &new_request, NULL, enum_set_address_complete) );
+
+ return true;
+}
+
// After SET_ADDRESS is complete
static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result)
{
@@ -830,16 +822,14 @@ static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t c
uint8_t const new_addr = (uint8_t const) request->wValue;
- usbh_device_t* new_dev = &_usbh_devices[new_addr];
+ usbh_device_t* new_dev = get_device(new_addr);
new_dev->addressed = 1;
// TODO close device 0, may not be needed
- usbh_device_t* dev0 = &_usbh_devices[0];
- hcd_device_close(dev0->rhport, 0);
- dev0->state = TUSB_DEVICE_STATE_UNPLUG;
+ hcd_device_close(_dev0.rhport, 0);
// open control pipe for new address
- TU_ASSERT ( usbh_edpt_control_open(new_addr, new_dev->ep0_packet_size) );
+ TU_ASSERT( usbh_edpt_control_open(new_addr, new_dev->ep0_size) );
// Get full device descriptor
TU_LOG2("Get Device Descriptor\r\n");
@@ -868,10 +858,13 @@ static bool enum_get_device_desc_complete(uint8_t dev_addr, tusb_control_request
TU_ASSERT(XFER_RESULT_SUCCESS == result);
tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf;
- usbh_device_t* dev = &_usbh_devices[dev_addr];
+ usbh_device_t* dev = get_device(dev_addr);
- dev->vendor_id = desc_device->idVendor;
- dev->product_id = desc_device->idProduct;
+ dev->vid = desc_device->idVendor;
+ dev->pid = desc_device->idProduct;
+ dev->i_manufacturer = desc_device->iManufacturer;
+ dev->i_product = desc_device->iProduct;
+ dev->i_serial = desc_device->iSerialNumber;
// if (tuh_attach_cb) tuh_attach_cb((tusb_desc_device_t*) _usbh_ctrl_buf);
@@ -907,7 +900,7 @@ static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_r
// Use offsetof to avoid pointer to the odd/misaligned address
memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2);
- TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSZIE);
+ TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSIZE);
// Get full configuration descriptor
TU_LOG2("Get Configuration Descriptor\r\n");
@@ -938,7 +931,7 @@ static bool enum_get_config_desc_complete(uint8_t dev_addr, tusb_control_request
// Parse configuration & set up drivers
// Driver open aren't allowed to make any usb transfer yet
- parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf);
+ TU_ASSERT( parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf) );
TU_LOG2("Set Configuration = %d\r\n", CONFIG_NUM);
tusb_control_request_t const new_request =
@@ -966,76 +959,230 @@ static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t co
TU_ASSERT(XFER_RESULT_SUCCESS == result);
TU_LOG2("Device configured\r\n");
- usbh_device_t* dev = &_usbh_devices[dev_addr];
+ usbh_device_t* dev = get_device(dev_addr);
dev->configured = 1;
dev->state = TUSB_DEVICE_STATE_CONFIGURED;
- // Start the Set Configuration process for interfaces (itf = 0xff)
+ // Start the Set Configuration process for interfaces (itf = DRVID_INVALID)
// Since driver can perform control transfer within its set_config, this is done asynchronously.
// The process continue with next interface when class driver complete its sequence with usbh_driver_set_config_complete()
- // TODO use separated API instead of usig 0xff
- usbh_driver_set_config_complete(dev_addr, 0xff);
+ // TODO use separated API instead of using DRVID_INVALID
+ usbh_driver_set_config_complete(dev_addr, DRVID_INVALID);
return true;
}
static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg)
{
- usbh_device_t* dev = &_usbh_devices[dev_addr];
- uint8_t const* p_desc = (uint8_t const*) desc_cfg;
- p_desc = tu_desc_next(p_desc);
+ usbh_device_t* dev = get_device(dev_addr);
+
+ uint8_t const* desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength);
+ uint8_t const* p_desc = tu_desc_next(desc_cfg);
// parse each interfaces
- while( p_desc < _usbh_ctrl_buf + desc_cfg->wTotalLength )
+ while( p_desc < desc_end )
{
- // skip until we see interface descriptor
- if ( TUSB_DESC_INTERFACE != tu_desc_type(p_desc) )
- {
- p_desc = tu_desc_next(p_desc); // skip the descriptor, increase by the descriptor's length
- }else
+ // TODO Do we need to use IAD
+ tusb_desc_interface_assoc_t const * desc_iad = NULL;
+
+ // Class will always starts with Interface Association (if any) and then Interface descriptor
+ if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) )
{
- tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc;
+ desc_iad = (tusb_desc_interface_assoc_t const *) p_desc;
+ p_desc = tu_desc_next(p_desc);
+ }
- // Check if class is supported
+ TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) );
+
+ tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc;
+
+ // Interface number must not be used already
+ TU_ASSERT( dev->itf2drv[desc_itf->bInterfaceNumber] == DRVID_INVALID );
+
+ uint16_t const drv_len = tu_desc_get_interface_total_len(desc_itf, desc_iad ? desc_iad->bInterfaceCount : 1, desc_end-p_desc);
+ TU_ASSERT(drv_len);
+
+ if (desc_itf->bInterfaceClass == TUSB_CLASS_HUB && dev->hub_addr != 0)
+ {
+ // TODO Attach hub to Hub is not currently supported
+ // skip this interface
+ TU_LOG(USBH_DBG_LVL, "Only 1 level of HUB is supported\r\n");
+ }
+ else
+ {
+ // Find driver for this interface
uint8_t drv_id;
for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++)
{
- if ( usbh_class_drivers[drv_id].class_code == desc_itf->bInterfaceClass ) break;
- }
-
- if( drv_id >= USBH_CLASS_DRIVER_COUNT )
- {
- // skip unsupported class
- p_desc = tu_desc_next(p_desc);
- }
- else
- {
usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id];
- // Interface number must not be used already TODO alternate interface
- TU_ASSERT( dev->itf2drv[desc_itf->bInterfaceNumber] == 0xff );
- dev->itf2drv[desc_itf->bInterfaceNumber] = drv_id;
-
- if (desc_itf->bInterfaceClass == TUSB_CLASS_HUB && dev->hub_addr != 0)
- {
- // TODO Attach hub to Hub is not currently supported
- // skip this interface
- p_desc = tu_desc_next(p_desc);
- }
- else
+ if ( driver->open(dev->rhport, dev_addr, desc_itf, drv_len) )
{
- TU_LOG2("%s open\r\n", driver->name);
+ // open successfully
+ TU_LOG2(" Opened successfully\r\n");
+
+ // bind interface to found driver
+ dev->itf2drv[desc_itf->bInterfaceNumber] = drv_id;
- uint16_t itf_len = 0;
- TU_ASSERT( driver->open(dev->rhport, dev_addr, desc_itf, &itf_len) );
- TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) );
- p_desc += itf_len;
+ // If using IAD, bind all interfaces to the same driver
+ if (desc_iad)
+ {
+ // IAD's first interface number and class should match with opened interface
+ TU_ASSERT(desc_iad->bFirstInterface == desc_itf->bInterfaceNumber &&
+ desc_iad->bFunctionClass == desc_itf->bInterfaceClass);
+
+ for(uint8_t i=1; i<desc_iad->bInterfaceCount; i++)
+ {
+ dev->itf2drv[desc_itf->bInterfaceNumber+i] = drv_id;
+ }
+ }
+
+ // bind all endpoints to found driver
+ tu_edpt_bind_driver(dev->ep2drv, desc_itf, drv_len, drv_id);
+
+ break; // exit driver find loop
}
}
+
+ if( drv_id >= USBH_CLASS_DRIVER_COUNT )
+ {
+ TU_LOG(USBH_DBG_LVL, "Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n",
+ desc_itf->bInterfaceNumber, desc_itf->bInterfaceClass, desc_itf->bInterfaceSubClass, desc_itf->bInterfaceProtocol);
+ }
}
+
+ // next Interface or IAD descriptor
+ p_desc += drv_len;
}
return true;
}
+//--------------------------------------------------------------------+
+// Endpoint API
+//--------------------------------------------------------------------+
+
+// TODO has some duplication code with device, refactor later
+bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr)
+{
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
+
+ usbh_device_t* dev = get_device(dev_addr);
+
+#if CFG_TUSB_OS != OPT_OS_NONE
+ // pre-check to help reducing mutex lock
+ TU_VERIFY((dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0));
+ osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER);
+#endif
+
+ // can only claim the endpoint if it is not busy and not claimed yet.
+ bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0);
+ if (ret)
+ {
+ dev->ep_status[epnum][dir].claimed = 1;
+ }
+
+#if CFG_TUSB_OS != OPT_OS_NONE
+ osal_mutex_unlock(dev->mutex);
+#endif
+
+ return ret;
+}
+
+// TODO has some duplication code with device, refactor later
+bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr)
+{
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
+
+ usbh_device_t* dev = get_device(dev_addr);
+
+#if CFG_TUSB_OS != OPT_OS_NONE
+ osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER);
+#endif
+
+ // can only release the endpoint if it is claimed and not busy
+ bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 1);
+ if (ret)
+ {
+ dev->ep_status[epnum][dir].claimed = 0;
+ }
+
+#if CFG_TUSB_OS != OPT_OS_NONE
+ osal_mutex_unlock(dev->mutex);
+#endif
+
+ return ret;
+}
+
+// TODO has some duplication code with device, refactor later
+bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
+{
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
+
+ usbh_device_t* dev = get_device(dev_addr);
+
+ TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes);
+
+ // Attempt to transfer on a busy endpoint, sound like an race condition !
+ TU_ASSERT(dev->ep_status[epnum][dir].busy == 0);
+
+ // Set busy first since the actual transfer can be complete before hcd_edpt_xfer()
+ // could return and USBH task can preempt and clear the busy
+ dev->ep_status[epnum][dir].busy = true;
+
+ if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) )
+ {
+ TU_LOG2("OK\r\n");
+ return true;
+ }else
+ {
+ // HCD error, mark endpoint as ready to allow next transfer
+ dev->ep_status[epnum][dir].busy = false;
+ dev->ep_status[epnum][dir].claimed = 0;
+ TU_LOG2("failed\r\n");
+ TU_BREAKPOINT();
+ return false;
+ }
+}
+
+static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size)
+{
+ TU_LOG2("Open EP0 with Size = %u (addr = %u)\r\n", max_packet_size, dev_addr);
+
+ tusb_desc_endpoint_t ep0_desc =
+ {
+ .bLength = sizeof(tusb_desc_endpoint_t),
+ .bDescriptorType = TUSB_DESC_ENDPOINT,
+ .bEndpointAddress = 0,
+ .bmAttributes = { .xfer = TUSB_XFER_CONTROL },
+ .wMaxPacketSize = { .size = max_packet_size },
+ .bInterval = 0
+ };
+
+ return hcd_edpt_open(usbh_get_rhport(dev_addr), dev_addr, &ep0_desc);
+}
+
+bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep)
+{
+ usbh_device_t* dev = get_device(dev_addr);
+ TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) dev->speed));
+
+ return hcd_edpt_open(rhport, dev_addr, desc_ep);
+}
+
+bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr)
+{
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
+
+ usbh_device_t* dev = get_device(dev_addr);
+
+ return dev->ep_status[epnum][dir].busy;
+}
+
+
+
#endif
diff --git a/src/host/usbh.h b/src/host/usbh.h
index 4de6e7ba6..8411cad28 100644
--- a/src/host/usbh.h
+++ b/src/host/usbh.h
@@ -57,16 +57,25 @@ void tuh_task(void);
extern void hcd_int_handler(uint8_t rhport);
#define tuh_int_handler hcd_int_handler
-tusb_speed_t tuh_device_get_speed (uint8_t dev_addr);
+bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid);
+tusb_speed_t tuh_speed_get(uint8_t dev_addr);
-// Check if device is configured
-bool tuh_device_configured(uint8_t dev_addr);
+// Check if device is connected and configured
+bool tuh_mounted(uint8_t dev_addr);
+
+// Check if device is suspended
+static inline bool tuh_suspended(uint8_t dev_addr)
+{
+ // TODO implement suspend & resume on host
+ (void) dev_addr;
+ return false;
+}
// Check if device is ready to communicate with
TU_ATTR_ALWAYS_INLINE
-static inline bool tuh_device_ready(uint8_t dev_addr)
+static inline bool tuh_ready(uint8_t dev_addr)
{
- return tuh_device_configured(dev_addr);
+ return tuh_mounted(dev_addr) && !tuh_suspended(dev_addr);
}
// Carry out control transfer
diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h
index 07480fe8e..8bc2622aa 100644
--- a/src/host/usbh_classdriver.h
+++ b/src/host/usbh_classdriver.h
@@ -43,10 +43,8 @@ typedef struct {
char const* name;
#endif
- uint8_t class_code;
-
void (* const init )(void);
- bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t* outlen);
+ bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num);
bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
void (* const close )(uint8_t dev_addr);
@@ -73,6 +71,8 @@ bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_
// If caller does not make any transfer, it must release endpoint for others.
bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr);
+bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr);
+
// Check if endpoint transferring is complete
bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr);
diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c
index 4dbf8592a..9204576ac 100644
--- a/src/host/usbh_control.c
+++ b/src/host/usbh_control.c
@@ -29,7 +29,7 @@
#if TUSB_OPT_HOST_ENABLED
#include "tusb.h"
-#include "usbh_hcd.h"
+#include "usbh_classdriver.h"
enum
{
@@ -50,7 +50,7 @@ typedef struct
static usbh_control_xfer_t _ctrl_xfer;
//CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN
-//static uint8_t _tuh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSZIE];
+//static uint8_t _tuh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE];
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
@@ -59,16 +59,14 @@ static usbh_control_xfer_t _ctrl_xfer;
bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb)
{
// TODO need to claim the endpoint first
-
- usbh_device_t* dev = &_usbh_devices[dev_addr];
- const uint8_t rhport = dev->rhport;
+ const uint8_t rhport = usbh_get_rhport(dev_addr);
_ctrl_xfer.request = (*request);
_ctrl_xfer.buffer = buffer;
_ctrl_xfer.stage = STAGE_SETUP;
_ctrl_xfer.complete_cb = complete_cb;
- TU_LOG2("Control Setup: ");
+ TU_LOG2("Control Setup (addr = %u): ", dev_addr);
TU_LOG2_VAR(request);
TU_LOG2("\r\n");
@@ -89,8 +87,7 @@ bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t resu
(void) ep_addr;
(void) xferred_bytes;
- usbh_device_t* dev = &_usbh_devices[dev_addr];
- const uint8_t rhport = dev->rhport;
+ const uint8_t rhport = usbh_get_rhport(dev_addr);
tusb_control_request_t const * request = &_ctrl_xfer.request;
@@ -119,7 +116,7 @@ bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t resu
if (request->wLength)
{
- TU_LOG2("Control data:\r\n");
+ TU_LOG2("Control data (addr = %u):\r\n", dev_addr);
TU_LOG2_MEM(_ctrl_xfer.buffer, request->wLength, 2);
}
diff --git a/src/host/usbh_hcd.h b/src/host/usbh_hcd.h
deleted file mode 100644
index b3856d6b7..000000000
--- a/src/host/usbh_hcd.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Ha Thach (tinyusb.org)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * This file is part of the TinyUSB stack.
- */
-
-/** \ingroup Group_HCD
- * @{ */
-
-#ifndef _TUSB_USBH_HCD_H_
-#define _TUSB_USBH_HCD_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-//--------------------------------------------------------------------+
-// INCLUDE
-//--------------------------------------------------------------------+
-#include "common/tusb_common.h"
-#include "osal/osal.h"
-
-#ifndef CFG_TUH_EP_MAX
-#define CFG_TUH_EP_MAX 9
-#endif
-
-//--------------------------------------------------------------------+
-// USBH-HCD common data structure
-//--------------------------------------------------------------------+
-
-// TODO move to usbh.c
-typedef struct {
- //------------- port -------------//
- uint8_t rhport;
- uint8_t hub_addr;
- uint8_t hub_port;
- uint8_t speed;
-
- //------------- device descriptor -------------//
- uint16_t vendor_id;
- uint16_t product_id;
- uint8_t ep0_packet_size;
-
- //------------- configuration descriptor -------------//
- // uint8_t interface_count; // bNumInterfaces alias
-
- //------------- device -------------//
- struct TU_ATTR_PACKED
- {
- uint8_t connected : 1;
- uint8_t addressed : 1;
- uint8_t configured : 1;
- uint8_t suspended : 1;
- };
-
- volatile uint8_t state; // device state, value from enum tusbh_device_state_t
-
- uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid)
- uint8_t ep2drv[CFG_TUH_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid )
-
- struct TU_ATTR_PACKED
- {
- volatile bool busy : 1;
- volatile bool stalled : 1;
- volatile bool claimed : 1;
-
- // TODO merge ep2drv here, 4-bit should be sufficient
- }ep_status[CFG_TUH_EP_MAX][2];
-
- // Mutex for claiming endpoint, only needed when using with preempted RTOS
-#if CFG_TUSB_OS != OPT_OS_NONE
- osal_mutex_def_t mutexdef;
- osal_mutex_t mutex;
-#endif
-
-} usbh_device_t;
-
-extern usbh_device_t _usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; // including zero-address
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* _TUSB_USBH_HCD_H_ */
-
-/** @} */
diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c
index 59f728d08..7b0d8f86c 100644
--- a/src/portable/dialog/da146xx/dcd_da146xx.c
+++ b/src/portable/dialog/da146xx/dcd_da146xx.c
@@ -28,7 +28,7 @@
#if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_DA1469X
-#include "DA1469xAB.h"
+#include "mcu/mcu.h"
#include "device/dcd.h"
@@ -258,33 +258,6 @@ static const tusb_desc_endpoint_t ep0IN_desc =
#define XFER_CTL_BASE(_ep, _dir) &_dcd.xfer_status[_ep][_dir]
-// Function could be called when VBUS change was detected.
-void tusb_vbus_changed(bool present)
-{
- if (present != _dcd.vbus_present)
- {
- _dcd.vbus_present = present;
- if (present)
- {
- USB->USB_MCTRL_REG = USB_USB_MCTRL_REG_USBEN_Msk;
- USB->USB_NFSR_REG = 0;
- USB->USB_FAR_REG = 0x80;
- USB->USB_NFSR_REG = NFSR_NODE_RESET;
- USB->USB_TXMSK_REG = 0;
- USB->USB_RXMSK_REG = 0;
-
- USB->USB_MAMSK_REG = USB_USB_MAMSK_REG_USB_M_INTR_Msk |
- USB_USB_MAMSK_REG_USB_M_ALT_Msk |
- USB_USB_MAMSK_REG_USB_M_WARN_Msk;
- USB->USB_ALTMSK_REG = USB_USB_ALTMSK_REG_USB_M_RESET_Msk;
- }
- else
- {
- USB->USB_MCTRL_REG = 0;
- }
- }
-}
-
static void fill_tx_fifo(xfer_ctl_t * xfer)
{
int left_to_send;
@@ -763,7 +736,16 @@ static void handle_ep0_nak(void)
void dcd_init(uint8_t rhport)
{
USB->USB_MCTRL_REG = USB_USB_MCTRL_REG_USBEN_Msk;
- tusb_vbus_changed((CRG_TOP->ANA_STATUS_REG & CRG_TOP_ANA_STATUS_REG_VBUS_AVAILABLE_Msk) != 0);
+ USB->USB_NFSR_REG = 0;
+ USB->USB_FAR_REG = 0x80;
+ USB->USB_NFSR_REG = NFSR_NODE_RESET;
+ USB->USB_TXMSK_REG = 0;
+ USB->USB_RXMSK_REG = 0;
+
+ USB->USB_MAMSK_REG = USB_USB_MAMSK_REG_USB_M_INTR_Msk |
+ USB_USB_MAMSK_REG_USB_M_ALT_Msk |
+ USB_USB_MAMSK_REG_USB_M_WARN_Msk;
+ USB->USB_ALTMSK_REG = USB_USB_ALTMSK_REG_USB_M_RESET_Msk;
dcd_connect(rhport);
}
@@ -865,6 +847,12 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
return true;
}
+void dcd_edpt_close_all (uint8_t rhport)
+{
+ (void) rhport;
+ // TODO implement dcd_edpt_close_all()
+}
+
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
{
uint8_t const epnum = tu_edpt_number(ep_addr);
diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c
index 48788ba06..e3b7499cc 100644
--- a/src/portable/ehci/ehci.c
+++ b/src/portable/ehci/ehci.c
@@ -24,11 +24,9 @@
* This file is part of the TinyUSB stack.
*/
-#include "common/tusb_common.h"
+#include "host/hcd_attr.h"
-#if TUSB_OPT_HOST_ENABLED && \
- (CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || \
- CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX )
+#if TUSB_OPT_HOST_ENABLED && defined(HCD_ATTR_EHCI_TRANSDIMENSION)
//--------------------------------------------------------------------+
// INCLUDE
@@ -36,27 +34,44 @@
#include "osal/osal.h"
#include "host/hcd.h"
-#include "host/usbh_hcd.h"
-#include "hcd_ehci.h"
+#include "ehci_api.h"
#include "ehci.h"
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
+// Debug level of EHCI
+#define EHCI_DBG 2
+
+// Framelist size as small as possible to save SRAM
+#ifdef HCD_ATTR_EHCI_TRANSDIMENSION
+ // NXP Transdimension: 8 elements
+ #define FRAMELIST_SIZE_BIT_VALUE 7u
+ #define FRAMELIST_SIZE_USBCMD_VALUE (((FRAMELIST_SIZE_BIT_VALUE & 3) << EHCI_USBCMD_POS_FRAMELIST_SIZE) | \
+ ((FRAMELIST_SIZE_BIT_VALUE >> 2) << EHCI_USBCMD_POS_NXP_FRAMELIST_SIZE_MSB))
+#else
+ // STD EHCI: 256 elements
+ #define FRAMELIST_SIZE_BIT_VALUE 2u
+ #define FRAMELIST_SIZE_USBCMD_VALUE ((FRAMELIST_SIZE_BIT_VALUE & 3) << EHCI_USBCMD_POS_FRAMELIST_SIZE)
+#endif
+
+#define FRAMELIST_SIZE (1024 >> FRAMELIST_SIZE_BIT_VALUE)
+
typedef struct
{
- ehci_link_t period_framelist[EHCI_FRAMELIST_SIZE];
+ ehci_link_t period_framelist[FRAMELIST_SIZE];
- // for NXP ECHI, only implement 1 ms & 2 ms & 4 ms, 8 ms (framelist)
+ // TODO only implement 1 ms & 2 ms & 4 ms, 8 ms (framelist)
// [0] : 1ms, [1] : 2ms, [2] : 4ms, [3] : 8 ms
+ // TODO better implementation without dummy head to save SRAM
ehci_qhd_t period_head_arr[4];
// Note control qhd of dev0 is used as head of async list
struct {
ehci_qhd_t qhd;
ehci_qtd_t qtd;
- }control[CFG_TUSB_HOST_DEVICE_MAX+1];
+ }control[CFG_TUH_DEVICE_MAX+CFG_TUH_HUB+1];
ehci_qhd_t qhd_pool[HCD_MAX_ENDPOINT];
ehci_qtd_t qtd_pool[HCD_MAX_XFER] TU_ATTR_ALIGNED(32);
@@ -65,19 +80,17 @@ typedef struct
volatile uint32_t uframe_number;
}ehci_data_t;
-//--------------------------------------------------------------------+
-// INTERNAL OBJECT & FUNCTION DECLARATION
-//--------------------------------------------------------------------+
+
// Periodic frame list must be 4K alignment
CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4096) static ehci_data_t ehci_data;
//--------------------------------------------------------------------+
// PROTOTYPE
//--------------------------------------------------------------------+
-static inline ehci_link_t* get_period_head(uint8_t rhport, uint8_t interval_ms)
+static inline ehci_link_t* get_period_head(uint8_t rhport, uint32_t interval_ms)
{
(void) rhport;
- return (ehci_link_t*) &ehci_data.period_head_arr[ tu_log2( tu_min8(EHCI_FRAMELIST_SIZE, interval_ms) ) ];
+ return (ehci_link_t*) &ehci_data.period_head_arr[ tu_log2( tu_min32(FRAMELIST_SIZE, interval_ms) ) ];
}
static inline ehci_qhd_t* qhd_control(uint8_t dev_addr)
@@ -109,7 +122,7 @@ static inline bool qhd_has_xact_error (ehci_qhd_t * p_qhd)
//p_qhd->qtd_overlay.non_hs_period_missed_uframe || p_qhd->qtd_overlay.pingstate_err TODO split transaction error
}
-static void qhd_init (ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc);
+static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc);
static inline ehci_qtd_t* qtd_find_free (void);
static inline ehci_qtd_t* qtd_next (ehci_qtd_t const * p_qtd);
@@ -218,12 +231,13 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
ehci_data.regs->command_bm.async_adv_doorbell = 1;
}
-// EHCI controller init
-bool hcd_ehci_init(uint8_t rhport)
+bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg)
{
+ (void) capability_reg; // not used yet
+
tu_memclr(&ehci_data, sizeof(ehci_data_t));
- ehci_data.regs = (ehci_registers_t* ) hcd_ehci_register_addr(rhport);
+ ehci_data.regs = (ehci_registers_t* ) operatial_reg;
ehci_registers_t* regs = ehci_data.regs;
@@ -249,37 +263,38 @@ bool hcd_ehci_init(uint8_t rhport)
//------------- Periodic List -------------//
// Build the polling interval tree with 1 ms, 2 ms, 4 ms and 8 ms (framesize) only
- for(uint32_t i=0; i<4; i++)
+ for ( uint32_t i = 0; i < TU_ARRAY_SIZE(ehci_data.period_head_arr); i++ )
{
- ehci_data.period_head_arr[i].int_smask = 1; // queue head in period list must have smask non-zero
+ ehci_data.period_head_arr[i].int_smask = 1; // queue head in period list must have smask non-zero
ehci_data.period_head_arr[i].qtd_overlay.halted = 1; // dummy node, always inactive
}
ehci_link_t * const framelist = ehci_data.period_framelist;
- ehci_link_t * const period_1ms = get_period_head(rhport, 1);
+ ehci_link_t * const period_1ms = get_period_head(rhport, 1u);
+
// all links --> period_head_arr[0] (1ms)
// 0, 2, 4, 6 etc --> period_head_arr[1] (2ms)
// 1, 5 --> period_head_arr[2] (4ms)
// 3 --> period_head_arr[3] (8ms)
// TODO EHCI_FRAMELIST_SIZE with other size than 8
- for(uint32_t i=0; i<EHCI_FRAMELIST_SIZE; i++)
+ for(uint32_t i=0; i<FRAMELIST_SIZE; i++)
{
framelist[i].address = (uint32_t) period_1ms;
framelist[i].type = EHCI_QTYPE_QHD;
}
- for(uint32_t i=0; i<EHCI_FRAMELIST_SIZE; i+=2)
+ for(uint32_t i=0; i<FRAMELIST_SIZE; i+=2)
{
- list_insert(framelist + i, get_period_head(rhport, 2), EHCI_QTYPE_QHD);
+ list_insert(framelist + i, get_period_head(rhport, 2u), EHCI_QTYPE_QHD);
}
- for(uint32_t i=1; i<EHCI_FRAMELIST_SIZE; i+=4)
+ for(uint32_t i=1; i<FRAMELIST_SIZE; i+=4)
{
- list_insert(framelist + i, get_period_head(rhport, 4), EHCI_QTYPE_QHD);
+ list_insert(framelist + i, get_period_head(rhport, 4u), EHCI_QTYPE_QHD);
}
- list_insert(framelist+3, get_period_head(rhport, 8), EHCI_QTYPE_QHD);
+ list_insert(framelist+3, get_period_head(rhport, 8u), EHCI_QTYPE_QHD);
period_1ms->terminate = 1;
@@ -289,10 +304,9 @@ bool hcd_ehci_init(uint8_t rhport)
regs->nxp_tt_control = 0;
//------------- USB CMD Register -------------//
- regs->command |= TU_BIT(EHCI_USBCMD_POS_RUN_STOP) | TU_BIT(EHCI_USBCMD_POS_ASYNC_ENABLE)
- | TU_BIT(EHCI_USBCMD_POS_PERIOD_ENABLE) // TODO enable period list only there is int/iso endpoint
- | ((EHCI_CFG_FRAMELIST_SIZE_BITS & TU_BIN8(011)) << EHCI_USBCMD_POS_FRAMELIST_SZIE)
- | ((EHCI_CFG_FRAMELIST_SIZE_BITS >> 2) << EHCI_USBCMD_POS_NXP_FRAMELIST_SIZE_MSB);
+ regs->command |= TU_BIT(EHCI_USBCMD_POS_RUN_STOP) | TU_BIT(EHCI_USBCMD_POS_ASYNC_ENABLE) |
+ TU_BIT(EHCI_USBCMD_POS_PERIOD_ENABLE) | // TODO enable period list only there is int/iso endpoint
+ FRAMELIST_SIZE_USBCMD_VALUE;
//------------- ConfigFlag Register (skip) -------------//
regs->portsc_bm.port_power = 1; // enable port power
@@ -470,16 +484,16 @@ static void async_advance_isr(uint8_t rhport)
}
}
-static void port_connect_status_change_isr(uint8_t hostid)
+static void port_connect_status_change_isr(uint8_t rhport)
{
// NOTE There is an sequence plug->unplug->…..-> plug if device is powering with pre-plugged device
if (ehci_data.regs->portsc_bm.current_connect_status)
{
- hcd_port_reset(hostid);
- hcd_event_device_attach(hostid, true);
+ hcd_port_reset(rhport);
+ hcd_event_device_attach(rhport, true);
}else // device unplugged
{
- hcd_event_device_remove(hostid, true);
+ hcd_event_device_remove(rhport, true);
}
}
@@ -519,16 +533,16 @@ static void async_list_xfer_complete_isr(ehci_qhd_t * const async_head)
}while(p_qhd != async_head); // async list traversal, stop if loop around
}
-static void period_list_xfer_complete_isr(uint8_t hostid, uint8_t interval_ms)
+static void period_list_xfer_complete_isr(uint8_t hostid, uint32_t interval_ms)
{
uint16_t max_loop = 0;
- uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1);
+ uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1u);
ehci_link_t next_item = * get_period_head(hostid, interval_ms);
// TODO abstract max loop guard for period
while( !next_item.terminate &&
!(interval_ms > 1 && period_1ms_addr == tu_align32(next_item.address)) &&
- max_loop < (HCD_MAX_ENDPOINT + EHCI_MAX_ITD + EHCI_MAX_SITD)*CFG_TUSB_HOST_DEVICE_MAX)
+ max_loop < (HCD_MAX_ENDPOINT + EHCI_MAX_ITD + EHCI_MAX_SITD)*CFG_TUH_DEVICE_MAX)
{
switch ( next_item.type )
{
@@ -605,8 +619,8 @@ static void xfer_error_isr(uint8_t hostid)
}while(p_qhd != async_head); // async list traversal, stop if loop around
//------------- TODO refractor period list -------------//
- uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1);
- for (uint8_t interval_ms=1; interval_ms <= EHCI_FRAMELIST_SIZE; interval_ms *= 2)
+ uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1u);
+ for (uint32_t interval_ms=1; interval_ms <= FRAMELIST_SIZE; interval_ms *= 2)
{
ehci_link_t next_item = * get_period_head(hostid, interval_ms);
@@ -649,13 +663,15 @@ void hcd_int_handler(uint8_t rhport)
if (int_status & EHCI_INT_MASK_FRAMELIST_ROLLOVER)
{
- ehci_data.uframe_number += (EHCI_FRAMELIST_SIZE << 3);
+ ehci_data.uframe_number += (FRAMELIST_SIZE << 3);
}
if (int_status & EHCI_INT_MASK_PORT_CHANGE)
{
uint32_t port_status = regs->portsc & EHCI_PORTSC_MASK_ALL;
+ TU_LOG_HEX(EHCI_DBG, regs->portsc);
+
if (regs->portsc_bm.connect_status_change)
{
port_connect_status_change_isr(rhport);
@@ -677,7 +693,7 @@ void hcd_int_handler(uint8_t rhport)
if (int_status & EHCI_INT_MASK_NXP_PERIODIC)
{
- for (uint8_t i=1; i <= EHCI_FRAMELIST_SIZE; i *= 2)
+ for (uint32_t i=1; i <= FRAMELIST_SIZE; i *= 2)
{
period_list_xfer_complete_isr( rhport, i );
}
@@ -774,13 +790,16 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c
tu_memclr(p_qhd, sizeof(ehci_qhd_t));
}
+ hcd_devtree_info_t devtree_info;
+ hcd_devtree_get_info(dev_addr, &devtree_info);
+
uint8_t const xfer_type = ep_desc->bmAttributes.xfer;
uint8_t const interval = ep_desc->bInterval;
p_qhd->dev_addr = dev_addr;
p_qhd->fl_inactive_next_xact = 0;
p_qhd->ep_number = tu_edpt_number(ep_desc->bEndpointAddress);
- p_qhd->ep_speed = _usbh_devices[dev_addr].speed;
+ p_qhd->ep_speed = devtree_info.speed;
p_qhd->data_toggle_control= (xfer_type == TUSB_XFER_CONTROL) ? 1 : 0;
p_qhd->head_list_flag = (dev_addr == 0) ? 1 : 0; // addr0's endpoint is the static asyn list head
p_qhd->max_packet_size = ep_desc->wMaxPacketSize.size;
@@ -817,8 +836,8 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c
p_qhd->int_smask = p_qhd->fl_int_cmask = 0;
}
- p_qhd->fl_hub_addr = _usbh_devices[dev_addr].hub_addr;
- p_qhd->fl_hub_port = _usbh_devices[dev_addr].hub_port;
+ p_qhd->fl_hub_addr = devtree_info.hub_addr;
+ p_qhd->fl_hub_port = devtree_info.hub_port;
p_qhd->mult = 1; // TODO not use high bandwidth/park mode yet
//------------- HCD Management Data -------------//
diff --git a/src/portable/ehci/ehci.h b/src/portable/ehci/ehci.h
index 874195a0c..c2bee67a5 100644
--- a/src/portable/ehci/ehci.h
+++ b/src/portable/ehci/ehci.h
@@ -46,8 +46,6 @@
//--------------------------------------------------------------------+
// EHCI CONFIGURATION & CONSTANTS
//--------------------------------------------------------------------+
-#define EHCI_CFG_FRAMELIST_SIZE_BITS 7 /// Framelist Size (NXP specific) (0:1024) - (1:512) - (2:256) - (3:128) - (4:64) - (5:32) - (6:16) - (7:8)
-#define EHCI_FRAMELIST_SIZE (1024 >> EHCI_CFG_FRAMELIST_SIZE_BITS)
// TODO merge OHCI with EHCI
enum {
@@ -55,9 +53,6 @@ enum {
EHCI_MAX_SITD = 16
};
-//------------- Validation -------------//
-TU_VERIFY_STATIC(EHCI_CFG_FRAMELIST_SIZE_BITS <= 7, "incorrect value");
-
//--------------------------------------------------------------------+
// EHCI Data Structure
//--------------------------------------------------------------------+
@@ -294,7 +289,7 @@ enum ehci_interrupt_mask_{
enum ehci_usbcmd_pos_ {
EHCI_USBCMD_POS_RUN_STOP = 0,
- EHCI_USBCMD_POS_FRAMELIST_SZIE = 2,
+ EHCI_USBCMD_POS_FRAMELIST_SIZE = 2,
EHCI_USBCMD_POS_PERIOD_ENABLE = 4,
EHCI_USBCMD_POS_ASYNC_ENABLE = 5,
EHCI_USBCMD_POS_NXP_FRAMELIST_SIZE_MSB = 15,
@@ -411,7 +406,7 @@ typedef volatile struct
uint32_t wake_on_over_current_enable : 1; ///< Enables over-current conditions as wake-up events
uint32_t nxp_phy_clock_disable : 1; ///< NXP customized: the PHY can be put into Low Power Suspend – Clock Disable when the downstream device has been put into suspend mode or when no downstream device is connected. Low power suspend is completely under the control of software. 0: enable PHY clock, 1: disable PHY clock
uint32_t nxp_port_force_fullspeed : 1; ///< NXP customized: Writing this bit to a 1 will force the port to only connect at Full Speed. It disables the chirp sequence that allowsthe port to identify itself as High Speed. This is useful for testing FS configurations with a HS host, hub or device.
- uint32_t : 1;
+ uint32_t TU_RESERVED : 1;
uint32_t nxp_port_speed : 2; ///< NXP customized: This register field indicates the speed atwhich the port is operating. For HS mode operation in the host controllerand HS/FS operation in the device controller the port routing steers data to the Protocol engine. For FS and LS mode operation in the host controller, the port routing steers data to the Protocol Engine w/ Embedded Transaction Translator. 0x0: Fullspeed, 0x1: Lowspeed, 0x2: Highspeed
uint32_t TU_RESERVED : 4;
}portsc_bm;
diff --git a/src/portable/ehci/hcd_ehci.h b/src/portable/ehci/ehci_api.h
index 480d11eda..12e0a73d7 100644
--- a/src/portable/ehci/hcd_ehci.h
+++ b/src/portable/ehci/ehci_api.h
@@ -24,27 +24,19 @@
* This file is part of the TinyUSB stack.
*/
-#ifndef _TUSB_HCD_EHCI_H_
-#define _TUSB_HCD_EHCI_H_
+#ifndef _TUSB_EHCI_API_H_
+#define _TUSB_EHCI_API_H_
#ifdef __cplusplus
extern "C" {
#endif
-
-//--------------------------------------------------------------------+
-// API Implemented by HCD
-//--------------------------------------------------------------------+
-
-// Get operational address i.e EHCI Command register
-uint32_t hcd_ehci_register_addr(uint8_t rhport);
-
//--------------------------------------------------------------------+
// API Implemented by EHCI
//--------------------------------------------------------------------+
// Initialize EHCI driver
-extern bool hcd_ehci_init (uint8_t rhport);
+bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg);
#ifdef __cplusplus
}
diff --git a/src/portable/espressif/esp32sx/dcd_esp32sx.c b/src/portable/espressif/esp32sx/dcd_esp32sx.c
index d728487c2..cfbbab233 100644
--- a/src/portable/espressif/esp32sx/dcd_esp32sx.c
+++ b/src/portable/espressif/esp32sx/dcd_esp32sx.c
@@ -42,10 +42,6 @@
#include "device/dcd.h"
-// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval)
-// We disable SOF for now until needed later on
-#define USE_SOF 0
-
// Max number of bi-directional endpoints including EP0
// Note: ESP32S2 specs say there are only up to 5 IN active endpoints include EP0
// We should probably prohibit enabling Endpoint IN > 4 (not done yet)
@@ -92,11 +88,12 @@ static void bus_reset(void)
USB0.out_ep_reg[ep_num].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK
}
- USB0.dcfg &= ~USB_DEVADDR_M; // reset address
+ // clear device address
+ USB0.dcfg &= ~USB_DEVADDR_M;
- USB0.daintmsk |= USB_OUTEPMSK0_M | USB_INEPMSK0_M;
- USB0.doepmsk |= USB_SETUPMSK_M | USB_XFERCOMPLMSK;
- USB0.diepmsk |= USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M /*| USB_INTKNTXFEMPMSK_M*/;
+ USB0.daintmsk = USB_OUTEPMSK0_M | USB_INEPMSK0_M;
+ USB0.doepmsk = USB_SETUPMSK_M | USB_XFERCOMPLMSK;
+ USB0.diepmsk = USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M /*| USB_INTKNTXFEMPMSK_M*/;
// "USB Data FIFOs" section in reference manual
// Peripheral FIFO architecture
@@ -193,9 +190,6 @@ void dcd_init(uint8_t rhport)
USB0.gintsts = ~0U; //clear pending ints
USB0.gintmsk = USB_OTGINTMSK_M |
USB_MODEMISMSK_M |
- #if USE_SOF
- USB_SOFMSK_M |
- #endif
USB_RXFLVIMSK_M |
USB_ERLYSUSPMSK_M |
USB_USBSUSPMSK_M |
@@ -220,8 +214,17 @@ void dcd_remote_wakeup(uint8_t rhport)
{
(void)rhport;
- // TODO must manually clear this bit after 1-15 ms
- // USB0.DCTL |= USB_RMTWKUPSIG_M;
+ // set remote wakeup
+ USB0.dctl |= USB_RMTWKUPSIG_M;
+
+ // enable SOF to detect bus resume
+ USB0.gintsts = USB_SOF_M;
+ USB0.gintmsk |= USB_SOFMSK_M;
+
+ // Per specs: remote wakeup signal bit must be clear within 1-15ms
+ vTaskDelay(pdMS_TO_TICKS(1));
+
+ USB0.dctl &= ~USB_RMTWKUPSIG_M;
}
// connect by enabling internal pull-up resistor on D+/D-
@@ -260,9 +263,10 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt)
xfer->max_size = desc_edpt->wMaxPacketSize.size;
if (dir == TUSB_DIR_OUT) {
- out_ep[epnum].doepctl |= USB_USBACTEP0_M |
- desc_edpt->bmAttributes.xfer << USB_EPTYPE0_S |
- desc_edpt->wMaxPacketSize.size << USB_MPS0_S;
+ out_ep[epnum].doepctl |= USB_USBACTEP1_M |
+ desc_edpt->bmAttributes.xfer << USB_EPTYPE1_S |
+ (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_DO_SETD0PID1_M : 0) |
+ desc_edpt->wMaxPacketSize.size << USB_MPS1_S;
USB0.daintmsk |= (1 << (16 + epnum));
} else {
// "USB Data FIFOs" section in reference manual
@@ -312,65 +316,40 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt)
return true;
}
-bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
+void dcd_edpt_close_all(uint8_t rhport)
{
- (void)rhport;
+ (void) rhport;
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
+ usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]);
+ usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]);
- xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir);
- xfer->buffer = buffer;
- // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API
- xfer->total_len = total_bytes;
- xfer->queued_len = 0;
- xfer->short_packet = false;
+ // Disable non-control interrupt
+ USB0.daintmsk = USB_OUTEPMSK0_M | USB_INEPMSK0_M;
- uint16_t num_packets = (total_bytes / xfer->max_size);
- uint8_t short_packet_size = total_bytes % xfer->max_size;
+ for(uint8_t n = 1; n < EP_MAX; n++)
+ {
+ // disable OUT endpoint
+ out_ep[n].doepctl = 0;
+ xfer_status[n][TUSB_DIR_OUT].max_size = 0;
- // Zero-size packet is special case.
- if (short_packet_size > 0 || (total_bytes == 0)) {
- num_packets++;
+ // disable IN endpoint
+ in_ep[n].diepctl = 0;
+ xfer_status[n][TUSB_DIR_IN].max_size = 0;
}
- ESP_LOGV(TAG, "Transfer <-> EP%i, %s, pkgs: %i, bytes: %i",
- epnum, ((dir == TUSB_DIR_IN) ? "USB0.HOST (in)" : "HOST->DEV (out)"),
- num_packets, total_bytes);
-
- // IN and OUT endpoint xfers are interrupt-driven, we just schedule them
- // here.
- if (dir == TUSB_DIR_IN) {
- // A full IN transfer (multiple packets, possibly) triggers XFRC.
- USB0.in_ep_reg[epnum].dieptsiz = (num_packets << USB_D_PKTCNT0_S) | total_bytes;
- USB0.in_ep_reg[epnum].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M; // Enable | CNAK
-
- // Enable fifo empty interrupt only if there are something to put in the fifo.
- if(total_bytes != 0) {
- USB0.dtknqr4_fifoemptymsk |= (1 << epnum);
- }
- } else {
- // Each complete packet for OUT xfers triggers XFRC.
- USB0.out_ep_reg[epnum].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S);
- USB0.out_ep_reg[epnum].doepctl |= USB_EPENA0_M | USB_CNAK0_M;
- }
- return true;
+ _allocated_fifos = 1;
}
-#if 0 // TODO support dcd_edpt_xfer_fifo API
-bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
+bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
{
(void)rhport;
- // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1
- TU_ASSERT(ff->item_size == 1);
-
uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const dir = tu_edpt_dir(ep_addr);
xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir);
- xfer->buffer = NULL;
- xfer->ff = ff;
+ xfer->buffer = buffer;
+ // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API
xfer->total_len = total_bytes;
xfer->queued_len = 0;
xfer->short_packet = false;
@@ -405,6 +384,12 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16
}
return true;
}
+
+#if 0 // TODO support dcd_edpt_xfer_fifo API
+bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
+{
+ (void)rhport;
+}
#endif
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
@@ -748,8 +733,8 @@ static void _dcd_int_handler(void* arg)
(void) arg;
uint8_t const rhport = 0;
- const uint32_t int_status = USB0.gintsts;
- //const uint32_t int_msk = USB0.gintmsk;
+ const uint32_t int_msk = USB0.gintmsk;
+ const uint32_t int_status = USB0.gintsts & int_msk;
if (int_status & USB_USBRST_M) {
// start of reset
@@ -802,12 +787,15 @@ static void _dcd_int_handler(void* arg)
USB0.gotgint = otg_int;
}
-#if USE_SOF
if (int_status & USB_SOF_M) {
USB0.gintsts = USB_SOF_M;
- dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); // do nothing actually
+
+ // Disable SOF interrupt since currently only used for remote wakeup detection
+ USB0.gintmsk &= ~USB_SOFMSK_M;
+
+ dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true);
}
-#endif
+
if (int_status & USB_RXFLVI_M) {
// RXFLVL bit is read-only
diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c
index 13e56453d..526a6fb63 100644
--- a/src/portable/microchip/samd/dcd_samd.c
+++ b/src/portable/microchip/samd/dcd_samd.c
@@ -29,7 +29,7 @@
#if TUSB_OPT_DEVICE_ENABLED && \
(CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \
CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X || \
- CFG_TUSB_MCU == OPT_MCU_SAML22)
+ CFG_TUSB_MCU == OPT_MCU_SAML22 || CFG_TUSB_MCU == OPT_MCU_SAML21)
#include "sam.h"
#include "device/dcd.h"
@@ -125,7 +125,7 @@ void dcd_int_disable(uint8_t rhport)
}
#elif CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \
- CFG_TUSB_MCU == OPT_MCU_SAML22
+ CFG_TUSB_MCU == OPT_MCU_SAML22 || CFG_TUSB_MCU == OPT_MCU_SAML21
void dcd_int_enable(uint8_t rhport)
{
@@ -230,16 +230,24 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
if ( dir == TUSB_DIR_OUT )
{
ep->EPCFG.bit.EPTYPE0 = desc_edpt->bmAttributes.xfer + 1;
+ ep->EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ0 | USB_DEVICE_EPSTATUSCLR_DTGLOUT; // clear stall & dtoggle
ep->EPINTENSET.bit.TRCPT0 = true;
}else
{
ep->EPCFG.bit.EPTYPE1 = desc_edpt->bmAttributes.xfer + 1;
+ ep->EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ1 | USB_DEVICE_EPSTATUSCLR_DTGLIN; // clear stall & dtoggle
ep->EPINTENSET.bit.TRCPT1 = true;
}
return true;
}
+void dcd_edpt_close_all (uint8_t rhport)
+{
+ (void) rhport;
+ // TODO implement dcd_edpt_close_all()
+}
+
bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
{
(void) rhport;
diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c
index d50621ce4..81779c56b 100644
--- a/src/portable/microchip/samg/dcd_samg.c
+++ b/src/portable/microchip/samg/dcd_samg.c
@@ -269,6 +269,12 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
return true;
}
+void dcd_edpt_close_all (uint8_t rhport)
+{
+ (void) rhport;
+ // TODO implement dcd_edpt_close_all()
+}
+
// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack
bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
{
diff --git a/src/portable/microchip/samx7x/common_usb_regs.h b/src/portable/microchip/samx7x/common_usb_regs.h
new file mode 100644
index 000000000..d232f0bcb
--- /dev/null
+++ b/src/portable/microchip/samx7x/common_usb_regs.h
@@ -0,0 +1,2108 @@
+ /*
+* The MIT License (MIT)
+*
+* Copyright (c) 2019 Microchip Technology Inc.
+* Copyright (c) 2018, hathach (tinyusb.org)
+* Copyright (c) 2021, HiFiPhile
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+* This file is part of the TinyUSB stack.
+*/
+
+#ifndef _COMMON_USB_REGS_H_
+#define _COMMON_USB_REGS_H_
+
+#if CFG_TUSB_MCU == OPT_MCU_SAMX7X
+
+/* -------- DEVDMANXTDSC : (USBHS Offset: 0x00) (R/W 32) Device DMA Channel Next Descriptor Address Register -------- */
+
+#define DEVDMANXTDSC_OFFSET (0x00) /**< (DEVDMANXTDSC) Device DMA Channel Next Descriptor Address Register Offset */
+
+#define DEVDMANXTDSC_NXT_DSC_ADD_Pos 0 /**< (DEVDMANXTDSC) Next Descriptor Address Position */
+#define DEVDMANXTDSC_NXT_DSC_ADD (_U_(0xFFFFFFFF) << DEVDMANXTDSC_NXT_DSC_ADD_Pos) /**< (DEVDMANXTDSC) Next Descriptor Address Mask */
+#define DEVDMANXTDSC_Msk _U_(0xFFFFFFFF) /**< (DEVDMANXTDSC) Register Mask */
+
+
+/* -------- DEVDMAADDRESS : (USBHS Offset: 0x04) (R/W 32) Device DMA Channel Address Register -------- */
+
+#define DEVDMAADDRESS_OFFSET (0x04) /**< (DEVDMAADDRESS) Device DMA Channel Address Register Offset */
+
+#define DEVDMAADDRESS_BUFF_ADD_Pos 0 /**< (DEVDMAADDRESS) Buffer Address Position */
+#define DEVDMAADDRESS_BUFF_ADD (_U_(0xFFFFFFFF) << DEVDMAADDRESS_BUFF_ADD_Pos) /**< (DEVDMAADDRESS) Buffer Address Mask */
+#define DEVDMAADDRESS_Msk _U_(0xFFFFFFFF) /**< (DEVDMAADDRESS) Register Mask */
+
+
+/* -------- DEVDMACONTROL : (USBHS Offset: 0x08) (R/W 32) Device DMA Channel Control Register -------- */
+
+#define DEVDMACONTROL_OFFSET (0x08) /**< (DEVDMACONTROL) Device DMA Channel Control Register Offset */
+
+#define DEVDMACONTROL_CHANN_ENB_Pos 0 /**< (DEVDMACONTROL) Channel Enable Command Position */
+#define DEVDMACONTROL_CHANN_ENB (_U_(0x1) << DEVDMACONTROL_CHANN_ENB_Pos) /**< (DEVDMACONTROL) Channel Enable Command Mask */
+#define DEVDMACONTROL_LDNXT_DSC_Pos 1 /**< (DEVDMACONTROL) Load Next Channel Transfer Descriptor Enable Command Position */
+#define DEVDMACONTROL_LDNXT_DSC (_U_(0x1) << DEVDMACONTROL_LDNXT_DSC_Pos) /**< (DEVDMACONTROL) Load Next Channel Transfer Descriptor Enable Command Mask */
+#define DEVDMACONTROL_END_TR_EN_Pos 2 /**< (DEVDMACONTROL) End of Transfer Enable Control (OUT transfers only) Position */
+#define DEVDMACONTROL_END_TR_EN (_U_(0x1) << DEVDMACONTROL_END_TR_EN_Pos) /**< (DEVDMACONTROL) End of Transfer Enable Control (OUT transfers only) Mask */
+#define DEVDMACONTROL_END_B_EN_Pos 3 /**< (DEVDMACONTROL) End of Buffer Enable Control Position */
+#define DEVDMACONTROL_END_B_EN (_U_(0x1) << DEVDMACONTROL_END_B_EN_Pos) /**< (DEVDMACONTROL) End of Buffer Enable Control Mask */
+#define DEVDMACONTROL_END_TR_IT_Pos 4 /**< (DEVDMACONTROL) End of Transfer Interrupt Enable Position */
+#define DEVDMACONTROL_END_TR_IT (_U_(0x1) << DEVDMACONTROL_END_TR_IT_Pos) /**< (DEVDMACONTROL) End of Transfer Interrupt Enable Mask */
+#define DEVDMACONTROL_END_BUFFIT_Pos 5 /**< (DEVDMACONTROL) End of Buffer Interrupt Enable Position */
+#define DEVDMACONTROL_END_BUFFIT (_U_(0x1) << DEVDMACONTROL_END_BUFFIT_Pos) /**< (DEVDMACONTROL) End of Buffer Interrupt Enable Mask */
+#define DEVDMACONTROL_DESC_LD_IT_Pos 6 /**< (DEVDMACONTROL) Descriptor Loaded Interrupt Enable Position */
+#define DEVDMACONTROL_DESC_LD_IT (_U_(0x1) << DEVDMACONTROL_DESC_LD_IT_Pos) /**< (DEVDMACONTROL) Descriptor Loaded Interrupt Enable Mask */
+#define DEVDMACONTROL_BURST_LCK_Pos 7 /**< (DEVDMACONTROL) Burst Lock Enable Position */
+#define DEVDMACONTROL_BURST_LCK (_U_(0x1) << DEVDMACONTROL_BURST_LCK_Pos) /**< (DEVDMACONTROL) Burst Lock Enable Mask */
+#define DEVDMACONTROL_BUFF_LENGTH_Pos 16 /**< (DEVDMACONTROL) Buffer Byte Length (Write-only) Position */
+#define DEVDMACONTROL_BUFF_LENGTH (_U_(0xFFFF) << DEVDMACONTROL_BUFF_LENGTH_Pos) /**< (DEVDMACONTROL) Buffer Byte Length (Write-only) Mask */
+#define DEVDMACONTROL_Msk _U_(0xFFFF00FF) /**< (DEVDMACONTROL) Register Mask */
+
+
+/* -------- DEVDMASTATUS : (USBHS Offset: 0x0c) (R/W 32) Device DMA Channel Status Register -------- */
+
+#define DEVDMASTATUS_OFFSET (0x0C) /**< (DEVDMASTATUS) Device DMA Channel Status Register Offset */
+
+#define DEVDMASTATUS_CHANN_ENB_Pos 0 /**< (DEVDMASTATUS) Channel Enable Status Position */
+#define DEVDMASTATUS_CHANN_ENB (_U_(0x1) << DEVDMASTATUS_CHANN_ENB_Pos) /**< (DEVDMASTATUS) Channel Enable Status Mask */
+#define DEVDMASTATUS_CHANN_ACT_Pos 1 /**< (DEVDMASTATUS) Channel Active Status Position */
+#define DEVDMASTATUS_CHANN_ACT (_U_(0x1) << DEVDMASTATUS_CHANN_ACT_Pos) /**< (DEVDMASTATUS) Channel Active Status Mask */
+#define DEVDMASTATUS_END_TR_ST_Pos 4 /**< (DEVDMASTATUS) End of Channel Transfer Status Position */
+#define DEVDMASTATUS_END_TR_ST (_U_(0x1) << DEVDMASTATUS_END_TR_ST_Pos) /**< (DEVDMASTATUS) End of Channel Transfer Status Mask */
+#define DEVDMASTATUS_END_BF_ST_Pos 5 /**< (DEVDMASTATUS) End of Channel Buffer Status Position */
+#define DEVDMASTATUS_END_BF_ST (_U_(0x1) << DEVDMASTATUS_END_BF_ST_Pos) /**< (DEVDMASTATUS) End of Channel Buffer Status Mask */
+#define DEVDMASTATUS_DESC_LDST_Pos 6 /**< (DEVDMASTATUS) Descriptor Loaded Status Position */
+#define DEVDMASTATUS_DESC_LDST (_U_(0x1) << DEVDMASTATUS_DESC_LDST_Pos) /**< (DEVDMASTATUS) Descriptor Loaded Status Mask */
+#define DEVDMASTATUS_BUFF_COUNT_Pos 16 /**< (DEVDMASTATUS) Buffer Byte Count Position */
+#define DEVDMASTATUS_BUFF_COUNT (_U_(0xFFFF) << DEVDMASTATUS_BUFF_COUNT_Pos) /**< (DEVDMASTATUS) Buffer Byte Count Mask */
+#define DEVDMASTATUS_Msk _U_(0xFFFF0073) /**< (DEVDMASTATUS) Register Mask */
+
+
+/* -------- HSTDMANXTDSC : (USBHS Offset: 0x00) (R/W 32) Host DMA Channel Next Descriptor Address Register -------- */
+
+#define HSTDMANXTDSC_OFFSET (0x00) /**< (HSTDMANXTDSC) Host DMA Channel Next Descriptor Address Register Offset */
+
+#define HSTDMANXTDSC_NXT_DSC_ADD_Pos 0 /**< (HSTDMANXTDSC) Next Descriptor Address Position */
+#define HSTDMANXTDSC_NXT_DSC_ADD (_U_(0xFFFFFFFF) << HSTDMANXTDSC_NXT_DSC_ADD_Pos) /**< (HSTDMANXTDSC) Next Descriptor Address Mask */
+#define HSTDMANXTDSC_Msk _U_(0xFFFFFFFF) /**< (HSTDMANXTDSC) Register Mask */
+
+
+/* -------- HSTDMAADDRESS : (USBHS Offset: 0x04) (R/W 32) Host DMA Channel Address Register -------- */
+
+#define HSTDMAADDRESS_OFFSET (0x04) /**< (HSTDMAADDRESS) Host DMA Channel Address Register Offset */
+
+#define HSTDMAADDRESS_BUFF_ADD_Pos 0 /**< (HSTDMAADDRESS) Buffer Address Position */
+#define HSTDMAADDRESS_BUFF_ADD (_U_(0xFFFFFFFF) << HSTDMAADDRESS_BUFF_ADD_Pos) /**< (HSTDMAADDRESS) Buffer Address Mask */
+#define HSTDMAADDRESS_Msk _U_(0xFFFFFFFF) /**< (HSTDMAADDRESS) Register Mask */
+
+
+/* -------- HSTDMACONTROL : (USBHS Offset: 0x08) (R/W 32) Host DMA Channel Control Register -------- */
+
+#define HSTDMACONTROL_OFFSET (0x08) /**< (HSTDMACONTROL) Host DMA Channel Control Register Offset */
+
+#define HSTDMACONTROL_CHANN_ENB_Pos 0 /**< (HSTDMACONTROL) Channel Enable Command Position */
+#define HSTDMACONTROL_CHANN_ENB (_U_(0x1) << HSTDMACONTROL_CHANN_ENB_Pos) /**< (HSTDMACONTROL) Channel Enable Command Mask */
+#define HSTDMACONTROL_LDNXT_DSC_Pos 1 /**< (HSTDMACONTROL) Load Next Channel Transfer Descriptor Enable Command Position */
+#define HSTDMACONTROL_LDNXT_DSC (_U_(0x1) << HSTDMACONTROL_LDNXT_DSC_Pos) /**< (HSTDMACONTROL) Load Next Channel Transfer Descriptor Enable Command Mask */
+#define HSTDMACONTROL_END_TR_EN_Pos 2 /**< (HSTDMACONTROL) End of Transfer Enable Control (OUT transfers only) Position */
+#define HSTDMACONTROL_END_TR_EN (_U_(0x1) << HSTDMACONTROL_END_TR_EN_Pos) /**< (HSTDMACONTROL) End of Transfer Enable Control (OUT transfers only) Mask */
+#define HSTDMACONTROL_END_B_EN_Pos 3 /**< (HSTDMACONTROL) End of Buffer Enable Control Position */
+#define HSTDMACONTROL_END_B_EN (_U_(0x1) << HSTDMACONTROL_END_B_EN_Pos) /**< (HSTDMACONTROL) End of Buffer Enable Control Mask */
+#define HSTDMACONTROL_END_TR_IT_Pos 4 /**< (HSTDMACONTROL) End of Transfer Interrupt Enable Position */
+#define HSTDMACONTROL_END_TR_IT (_U_(0x1) << HSTDMACONTROL_END_TR_IT_Pos) /**< (HSTDMACONTROL) End of Transfer Interrupt Enable Mask */
+#define HSTDMACONTROL_END_BUFFIT_Pos 5 /**< (HSTDMACONTROL) End of Buffer Interrupt Enable Position */
+#define HSTDMACONTROL_END_BUFFIT (_U_(0x1) << HSTDMACONTROL_END_BUFFIT_Pos) /**< (HSTDMACONTROL) End of Buffer Interrupt Enable Mask */
+#define HSTDMACONTROL_DESC_LD_IT_Pos 6 /**< (HSTDMACONTROL) Descriptor Loaded Interrupt Enable Position */
+#define HSTDMACONTROL_DESC_LD_IT (_U_(0x1) << HSTDMACONTROL_DESC_LD_IT_Pos) /**< (HSTDMACONTROL) Descriptor Loaded Interrupt Enable Mask */
+#define HSTDMACONTROL_BURST_LCK_Pos 7 /**< (HSTDMACONTROL) Burst Lock Enable Position */
+#define HSTDMACONTROL_BURST_LCK (_U_(0x1) << HSTDMACONTROL_BURST_LCK_Pos) /**< (HSTDMACONTROL) Burst Lock Enable Mask */
+#define HSTDMACONTROL_BUFF_LENGTH_Pos 16 /**< (HSTDMACONTROL) Buffer Byte Length (Write-only) Position */
+#define HSTDMACONTROL_BUFF_LENGTH (_U_(0xFFFF) << HSTDMACONTROL_BUFF_LENGTH_Pos) /**< (HSTDMACONTROL) Buffer Byte Length (Write-only) Mask */
+#define HSTDMACONTROL_Msk _U_(0xFFFF00FF) /**< (HSTDMACONTROL) Register Mask */
+
+
+/* -------- HSTDMASTATUS : (USBHS Offset: 0x0c) (R/W 32) Host DMA Channel Status Register -------- */
+
+#define HSTDMASTATUS_OFFSET (0x0C) /**< (HSTDMASTATUS) Host DMA Channel Status Register Offset */
+
+#define HSTDMASTATUS_CHANN_ENB_Pos 0 /**< (HSTDMASTATUS) Channel Enable Status Position */
+#define HSTDMASTATUS_CHANN_ENB (_U_(0x1) << HSTDMASTATUS_CHANN_ENB_Pos) /**< (HSTDMASTATUS) Channel Enable Status Mask */
+#define HSTDMASTATUS_CHANN_ACT_Pos 1 /**< (HSTDMASTATUS) Channel Active Status Position */
+#define HSTDMASTATUS_CHANN_ACT (_U_(0x1) << HSTDMASTATUS_CHANN_ACT_Pos) /**< (HSTDMASTATUS) Channel Active Status Mask */
+#define HSTDMASTATUS_END_TR_ST_Pos 4 /**< (HSTDMASTATUS) End of Channel Transfer Status Position */
+#define HSTDMASTATUS_END_TR_ST (_U_(0x1) << HSTDMASTATUS_END_TR_ST_Pos) /**< (HSTDMASTATUS) End of Channel Transfer Status Mask */
+#define HSTDMASTATUS_END_BF_ST_Pos 5 /**< (HSTDMASTATUS) End of Channel Buffer Status Position */
+#define HSTDMASTATUS_END_BF_ST (_U_(0x1) << HSTDMASTATUS_END_BF_ST_Pos) /**< (HSTDMASTATUS) End of Channel Buffer Status Mask */
+#define HSTDMASTATUS_DESC_LDST_Pos 6 /**< (HSTDMASTATUS) Descriptor Loaded Status Position */
+#define HSTDMASTATUS_DESC_LDST (_U_(0x1) << HSTDMASTATUS_DESC_LDST_Pos) /**< (HSTDMASTATUS) Descriptor Loaded Status Mask */
+#define HSTDMASTATUS_BUFF_COUNT_Pos 16 /**< (HSTDMASTATUS) Buffer Byte Count Position */
+#define HSTDMASTATUS_BUFF_COUNT (_U_(0xFFFF) << HSTDMASTATUS_BUFF_COUNT_Pos) /**< (HSTDMASTATUS) Buffer Byte Count Mask */
+#define HSTDMASTATUS_Msk _U_(0xFFFF0073) /**< (HSTDMASTATUS) Register Mask */
+
+
+/* -------- DEVCTRL : (USBHS Offset: 0x00) (R/W 32) Device General Control Register -------- */
+
+#define DEVCTRL_OFFSET (0x00) /**< (DEVCTRL) Device General Control Register Offset */
+
+#define DEVCTRL_UADD_Pos 0 /**< (DEVCTRL) USB Address Position */
+#define DEVCTRL_UADD (_U_(0x7F) << DEVCTRL_UADD_Pos) /**< (DEVCTRL) USB Address Mask */
+#define DEVCTRL_ADDEN_Pos 7 /**< (DEVCTRL) Address Enable Position */
+#define DEVCTRL_ADDEN (_U_(0x1) << DEVCTRL_ADDEN_Pos) /**< (DEVCTRL) Address Enable Mask */
+#define DEVCTRL_DETACH_Pos 8 /**< (DEVCTRL) Detach Position */
+#define DEVCTRL_DETACH (_U_(0x1) << DEVCTRL_DETACH_Pos) /**< (DEVCTRL) Detach Mask */
+#define DEVCTRL_RMWKUP_Pos 9 /**< (DEVCTRL) Remote Wake-Up Position */
+#define DEVCTRL_RMWKUP (_U_(0x1) << DEVCTRL_RMWKUP_Pos) /**< (DEVCTRL) Remote Wake-Up Mask */
+#define DEVCTRL_SPDCONF_Pos 10 /**< (DEVCTRL) Mode Configuration Position */
+#define DEVCTRL_SPDCONF (_U_(0x3) << DEVCTRL_SPDCONF_Pos) /**< (DEVCTRL) Mode Configuration Mask */
+#define DEVCTRL_SPDCONF_NORMAL_Val _U_(0x0) /**< (DEVCTRL) The peripheral starts in Full-speed mode and performs a high-speed reset to switch to High-speed mode if the host is high-speed-capable. */
+#define DEVCTRL_SPDCONF_LOW_POWER_Val _U_(0x1) /**< (DEVCTRL) For a better consumption, if high speed is not needed. */
+#define DEVCTRL_SPDCONF_HIGH_SPEED_Val _U_(0x2) /**< (DEVCTRL) Forced high speed. */
+#define DEVCTRL_SPDCONF_FORCED_FS_Val _U_(0x3) /**< (DEVCTRL) The peripheral remains in Full-speed mode whatever the host speed capability. */
+#define DEVCTRL_SPDCONF_NORMAL (DEVCTRL_SPDCONF_NORMAL_Val << DEVCTRL_SPDCONF_Pos) /**< (DEVCTRL) The peripheral starts in Full-speed mode and performs a high-speed reset to switch to High-speed mode if the host is high-speed-capable. Position */
+#define DEVCTRL_SPDCONF_LOW_POWER (DEVCTRL_SPDCONF_LOW_POWER_Val << DEVCTRL_SPDCONF_Pos) /**< (DEVCTRL) For a better consumption, if high speed is not needed. Position */
+#define DEVCTRL_SPDCONF_HIGH_SPEED (DEVCTRL_SPDCONF_HIGH_SPEED_Val << DEVCTRL_SPDCONF_Pos) /**< (DEVCTRL) Forced high speed. Position */
+#define DEVCTRL_SPDCONF_FORCED_FS (DEVCTRL_SPDCONF_FORCED_FS_Val << DEVCTRL_SPDCONF_Pos) /**< (DEVCTRL) The peripheral remains in Full-speed mode whatever the host speed capability. Position */
+#define DEVCTRL_LS_Pos 12 /**< (DEVCTRL) Low-Speed Mode Force Position */
+#define DEVCTRL_LS (_U_(0x1) << DEVCTRL_LS_Pos) /**< (DEVCTRL) Low-Speed Mode Force Mask */
+#define DEVCTRL_TSTJ_Pos 13 /**< (DEVCTRL) Test mode J Position */
+#define DEVCTRL_TSTJ (_U_(0x1) << DEVCTRL_TSTJ_Pos) /**< (DEVCTRL) Test mode J Mask */
+#define DEVCTRL_TSTK_Pos 14 /**< (DEVCTRL) Test mode K Position */
+#define DEVCTRL_TSTK (_U_(0x1) << DEVCTRL_TSTK_Pos) /**< (DEVCTRL) Test mode K Mask */
+#define DEVCTRL_TSTPCKT_Pos 15 /**< (DEVCTRL) Test packet mode Position */
+#define DEVCTRL_TSTPCKT (_U_(0x1) << DEVCTRL_TSTPCKT_Pos) /**< (DEVCTRL) Test packet mode Mask */
+#define DEVCTRL_OPMODE2_Pos 16 /**< (DEVCTRL) Specific Operational mode Position */
+#define DEVCTRL_OPMODE2 (_U_(0x1) << DEVCTRL_OPMODE2_Pos) /**< (DEVCTRL) Specific Operational mode Mask */
+#define DEVCTRL_Msk _U_(0x1FFFF) /**< (DEVCTRL) Register Mask */
+
+#define DEVCTRL_OPMODE_Pos 16 /**< (DEVCTRL Position) Specific Operational mode */
+#define DEVCTRL_OPMODE (_U_(0x1) << DEVCTRL_OPMODE_Pos) /**< (DEVCTRL Mask) OPMODE */
+
+/* -------- DEVISR : (USBHS Offset: 0x04) (R/ 32) Device Global Interrupt Status Register -------- */
+
+#define DEVISR_OFFSET (0x04) /**< (DEVISR) Device Global Interrupt Status Register Offset */
+
+#define DEVISR_SUSP_Pos 0 /**< (DEVISR) Suspend Interrupt Position */
+#define DEVISR_SUSP (_U_(0x1) << DEVISR_SUSP_Pos) /**< (DEVISR) Suspend Interrupt Mask */
+#define DEVISR_MSOF_Pos 1 /**< (DEVISR) Micro Start of Frame Interrupt Position */
+#define DEVISR_MSOF (_U_(0x1) << DEVISR_MSOF_Pos) /**< (DEVISR) Micro Start of Frame Interrupt Mask */
+#define DEVISR_SOF_Pos 2 /**< (DEVISR) Start of Frame Interrupt Position */
+#define DEVISR_SOF (_U_(0x1) << DEVISR_SOF_Pos) /**< (DEVISR) Start of Frame Interrupt Mask */
+#define DEVISR_EORST_Pos 3 /**< (DEVISR) End of Reset Interrupt Position */
+#define DEVISR_EORST (_U_(0x1) << DEVISR_EORST_Pos) /**< (DEVISR) End of Reset Interrupt Mask */
+#define DEVISR_WAKEUP_Pos 4 /**< (DEVISR) Wake-Up Interrupt Position */
+#define DEVISR_WAKEUP (_U_(0x1) << DEVISR_WAKEUP_Pos) /**< (DEVISR) Wake-Up Interrupt Mask */
+#define DEVISR_EORSM_Pos 5 /**< (DEVISR) End of Resume Interrupt Position */
+#define DEVISR_EORSM (_U_(0x1) << DEVISR_EORSM_Pos) /**< (DEVISR) End of Resume Interrupt Mask */
+#define DEVISR_UPRSM_Pos 6 /**< (DEVISR) Upstream Resume Interrupt Position */
+#define DEVISR_UPRSM (_U_(0x1) << DEVISR_UPRSM_Pos) /**< (DEVISR) Upstream Resume Interrupt Mask */
+#define DEVISR_PEP_0_Pos 12 /**< (DEVISR) Endpoint 0 Interrupt Position */
+#define DEVISR_PEP_0 (_U_(0x1) << DEVISR_PEP_0_Pos) /**< (DEVISR) Endpoint 0 Interrupt Mask */
+#define DEVISR_PEP_1_Pos 13 /**< (DEVISR) Endpoint 1 Interrupt Position */
+#define DEVISR_PEP_1 (_U_(0x1) << DEVISR_PEP_1_Pos) /**< (DEVISR) Endpoint 1 Interrupt Mask */
+#define DEVISR_PEP_2_Pos 14 /**< (DEVISR) Endpoint 2 Interrupt Position */
+#define DEVISR_PEP_2 (_U_(0x1) << DEVISR_PEP_2_Pos) /**< (DEVISR) Endpoint 2 Interrupt Mask */
+#define DEVISR_PEP_3_Pos 15 /**< (DEVISR) Endpoint 3 Interrupt Position */
+#define DEVISR_PEP_3 (_U_(0x1) << DEVISR_PEP_3_Pos) /**< (DEVISR) Endpoint 3 Interrupt Mask */
+#define DEVISR_PEP_4_Pos 16 /**< (DEVISR) Endpoint 4 Interrupt Position */
+#define DEVISR_PEP_4 (_U_(0x1) << DEVISR_PEP_4_Pos) /**< (DEVISR) Endpoint 4 Interrupt Mask */
+#define DEVISR_PEP_5_Pos 17 /**< (DEVISR) Endpoint 5 Interrupt Position */
+#define DEVISR_PEP_5 (_U_(0x1) << DEVISR_PEP_5_Pos) /**< (DEVISR) Endpoint 5 Interrupt Mask */
+#define DEVISR_PEP_6_Pos 18 /**< (DEVISR) Endpoint 6 Interrupt Position */
+#define DEVISR_PEP_6 (_U_(0x1) << DEVISR_PEP_6_Pos) /**< (DEVISR) Endpoint 6 Interrupt Mask */
+#define DEVISR_PEP_7_Pos 19 /**< (DEVISR) Endpoint 7 Interrupt Position */
+#define DEVISR_PEP_7 (_U_(0x1) << DEVISR_PEP_7_Pos) /**< (DEVISR) Endpoint 7 Interrupt Mask */
+#define DEVISR_PEP_8_Pos 20 /**< (DEVISR) Endpoint 8 Interrupt Position */
+#define DEVISR_PEP_8 (_U_(0x1) << DEVISR_PEP_8_Pos) /**< (DEVISR) Endpoint 8 Interrupt Mask */
+#define DEVISR_PEP_9_Pos 21 /**< (DEVISR) Endpoint 9 Interrupt Position */
+#define DEVISR_PEP_9 (_U_(0x1) << DEVISR_PEP_9_Pos) /**< (DEVISR) Endpoint 9 Interrupt Mask */
+#define DEVISR_DMA_1_Pos 25 /**< (DEVISR) DMA Channel 1 Interrupt Position */
+#define DEVISR_DMA_1 (_U_(0x1) << DEVISR_DMA_1_Pos) /**< (DEVISR) DMA Channel 1 Interrupt Mask */
+#define DEVISR_DMA_2_Pos 26 /**< (DEVISR) DMA Channel 2 Interrupt Position */
+#define DEVISR_DMA_2 (_U_(0x1) << DEVISR_DMA_2_Pos) /**< (DEVISR) DMA Channel 2 Interrupt Mask */
+#define DEVISR_DMA_3_Pos 27 /**< (DEVISR) DMA Channel 3 Interrupt Position */
+#define DEVISR_DMA_3 (_U_(0x1) << DEVISR_DMA_3_Pos) /**< (DEVISR) DMA Channel 3 Interrupt Mask */
+#define DEVISR_DMA_4_Pos 28 /**< (DEVISR) DMA Channel 4 Interrupt Position */
+#define DEVISR_DMA_4 (_U_(0x1) << DEVISR_DMA_4_Pos) /**< (DEVISR) DMA Channel 4 Interrupt Mask */
+#define DEVISR_DMA_5_Pos 29 /**< (DEVISR) DMA Channel 5 Interrupt Position */
+#define DEVISR_DMA_5 (_U_(0x1) << DEVISR_DMA_5_Pos) /**< (DEVISR) DMA Channel 5 Interrupt Mask */
+#define DEVISR_DMA_6_Pos 30 /**< (DEVISR) DMA Channel 6 Interrupt Position */
+#define DEVISR_DMA_6 (_U_(0x1) << DEVISR_DMA_6_Pos) /**< (DEVISR) DMA Channel 6 Interrupt Mask */
+#define DEVISR_DMA_7_Pos 31 /**< (DEVISR) DMA Channel 7 Interrupt Position */
+#define DEVISR_DMA_7 (_U_(0x1) << DEVISR_DMA_7_Pos) /**< (DEVISR) DMA Channel 7 Interrupt Mask */
+#define DEVISR_Msk _U_(0xFE3FF07F) /**< (DEVISR) Register Mask */
+
+#define DEVISR_PEP__Pos 12 /**< (DEVISR Position) Endpoint x Interrupt */
+#define DEVISR_PEP_ (_U_(0x3FF) << DEVISR_PEP__Pos) /**< (DEVISR Mask) PEP_ */
+#define DEVISR_DMA__Pos 25 /**< (DEVISR Position) DMA Channel 7 Interrupt */
+#define DEVISR_DMA_ (_U_(0x7F) << DEVISR_DMA__Pos) /**< (DEVISR Mask) DMA_ */
+
+/* -------- DEVICR : (USBHS Offset: 0x08) (/W 32) Device Global Interrupt Clear Register -------- */
+
+#define DEVICR_OFFSET (0x08) /**< (DEVICR) Device Global Interrupt Clear Register Offset */
+
+#define DEVICR_SUSPC_Pos 0 /**< (DEVICR) Suspend Interrupt Clear Position */
+#define DEVICR_SUSPC (_U_(0x1) << DEVICR_SUSPC_Pos) /**< (DEVICR) Suspend Interrupt Clear Mask */
+#define DEVICR_MSOFC_Pos 1 /**< (DEVICR) Micro Start of Frame Interrupt Clear Position */
+#define DEVICR_MSOFC (_U_(0x1) << DEVICR_MSOFC_Pos) /**< (DEVICR) Micro Start of Frame Interrupt Clear Mask */
+#define DEVICR_SOFC_Pos 2 /**< (DEVICR) Start of Frame Interrupt Clear Position */
+#define DEVICR_SOFC (_U_(0x1) << DEVICR_SOFC_Pos) /**< (DEVICR) Start of Frame Interrupt Clear Mask */
+#define DEVICR_EORSTC_Pos 3 /**< (DEVICR) End of Reset Interrupt Clear Position */
+#define DEVICR_EORSTC (_U_(0x1) << DEVICR_EORSTC_Pos) /**< (DEVICR) End of Reset Interrupt Clear Mask */
+#define DEVICR_WAKEUPC_Pos 4 /**< (DEVICR) Wake-Up Interrupt Clear Position */
+#define DEVICR_WAKEUPC (_U_(0x1) << DEVICR_WAKEUPC_Pos) /**< (DEVICR) Wake-Up Interrupt Clear Mask */
+#define DEVICR_EORSMC_Pos 5 /**< (DEVICR) End of Resume Interrupt Clear Position */
+#define DEVICR_EORSMC (_U_(0x1) << DEVICR_EORSMC_Pos) /**< (DEVICR) End of Resume Interrupt Clear Mask */
+#define DEVICR_UPRSMC_Pos 6 /**< (DEVICR) Upstream Resume Interrupt Clear Position */
+#define DEVICR_UPRSMC (_U_(0x1) << DEVICR_UPRSMC_Pos) /**< (DEVICR) Upstream Resume Interrupt Clear Mask */
+#define DEVICR_Msk _U_(0x7F) /**< (DEVICR) Register Mask */
+
+
+/* -------- DEVIFR : (USBHS Offset: 0x0c) (/W 32) Device Global Interrupt Set Register -------- */
+
+#define DEVIFR_OFFSET (0x0C) /**< (DEVIFR) Device Global Interrupt Set Register Offset */
+
+#define DEVIFR_SUSPS_Pos 0 /**< (DEVIFR) Suspend Interrupt Set Position */
+#define DEVIFR_SUSPS (_U_(0x1) << DEVIFR_SUSPS_Pos) /**< (DEVIFR) Suspend Interrupt Set Mask */
+#define DEVIFR_MSOFS_Pos 1 /**< (DEVIFR) Micro Start of Frame Interrupt Set Position */
+#define DEVIFR_MSOFS (_U_(0x1) << DEVIFR_MSOFS_Pos) /**< (DEVIFR) Micro Start of Frame Interrupt Set Mask */
+#define DEVIFR_SOFS_Pos 2 /**< (DEVIFR) Start of Frame Interrupt Set Position */
+#define DEVIFR_SOFS (_U_(0x1) << DEVIFR_SOFS_Pos) /**< (DEVIFR) Start of Frame Interrupt Set Mask */
+#define DEVIFR_EORSTS_Pos 3 /**< (DEVIFR) End of Reset Interrupt Set Position */
+#define DEVIFR_EORSTS (_U_(0x1) << DEVIFR_EORSTS_Pos) /**< (DEVIFR) End of Reset Interrupt Set Mask */
+#define DEVIFR_WAKEUPS_Pos 4 /**< (DEVIFR) Wake-Up Interrupt Set Position */
+#define DEVIFR_WAKEUPS (_U_(0x1) << DEVIFR_WAKEUPS_Pos) /**< (DEVIFR) Wake-Up Interrupt Set Mask */
+#define DEVIFR_EORSMS_Pos 5 /**< (DEVIFR) End of Resume Interrupt Set Position */
+#define DEVIFR_EORSMS (_U_(0x1) << DEVIFR_EORSMS_Pos) /**< (DEVIFR) End of Resume Interrupt Set Mask */
+#define DEVIFR_UPRSMS_Pos 6 /**< (DEVIFR) Upstream Resume Interrupt Set Position */
+#define DEVIFR_UPRSMS (_U_(0x1) << DEVIFR_UPRSMS_Pos) /**< (DEVIFR) Upstream Resume Interrupt Set Mask */
+#define DEVIFR_DMA_1_Pos 25 /**< (DEVIFR) DMA Channel 1 Interrupt Set Position */
+#define DEVIFR_DMA_1 (_U_(0x1) << DEVIFR_DMA_1_Pos) /**< (DEVIFR) DMA Channel 1 Interrupt Set Mask */
+#define DEVIFR_DMA_2_Pos 26 /**< (DEVIFR) DMA Channel 2 Interrupt Set Position */
+#define DEVIFR_DMA_2 (_U_(0x1) << DEVIFR_DMA_2_Pos) /**< (DEVIFR) DMA Channel 2 Interrupt Set Mask */
+#define DEVIFR_DMA_3_Pos 27 /**< (DEVIFR) DMA Channel 3 Interrupt Set Position */
+#define DEVIFR_DMA_3 (_U_(0x1) << DEVIFR_DMA_3_Pos) /**< (DEVIFR) DMA Channel 3 Interrupt Set Mask */
+#define DEVIFR_DMA_4_Pos 28 /**< (DEVIFR) DMA Channel 4 Interrupt Set Position */
+#define DEVIFR_DMA_4 (_U_(0x1) << DEVIFR_DMA_4_Pos) /**< (DEVIFR) DMA Channel 4 Interrupt Set Mask */
+#define DEVIFR_DMA_5_Pos 29 /**< (DEVIFR) DMA Channel 5 Interrupt Set Position */
+#define DEVIFR_DMA_5 (_U_(0x1) << DEVIFR_DMA_5_Pos) /**< (DEVIFR) DMA Channel 5 Interrupt Set Mask */
+#define DEVIFR_DMA_6_Pos 30 /**< (DEVIFR) DMA Channel 6 Interrupt Set Position */
+#define DEVIFR_DMA_6 (_U_(0x1) << DEVIFR_DMA_6_Pos) /**< (DEVIFR) DMA Channel 6 Interrupt Set Mask */
+#define DEVIFR_DMA_7_Pos 31 /**< (DEVIFR) DMA Channel 7 Interrupt Set Position */
+#define DEVIFR_DMA_7 (_U_(0x1) << DEVIFR_DMA_7_Pos) /**< (DEVIFR) DMA Channel 7 Interrupt Set Mask */
+#define DEVIFR_Msk _U_(0xFE00007F) /**< (DEVIFR) Register Mask */
+
+#define DEVIFR_DMA__Pos 25 /**< (DEVIFR Position) DMA Channel 7 Interrupt Set */
+#define DEVIFR_DMA_ (_U_(0x7F) << DEVIFR_DMA__Pos) /**< (DEVIFR Mask) DMA_ */
+
+/* -------- DEVIMR : (USBHS Offset: 0x10) (R/ 32) Device Global Interrupt Mask Register -------- */
+
+#define DEVIMR_OFFSET (0x10) /**< (DEVIMR) Device Global Interrupt Mask Register Offset */
+
+#define DEVIMR_SUSPE_Pos 0 /**< (DEVIMR) Suspend Interrupt Mask Position */
+#define DEVIMR_SUSPE (_U_(0x1) << DEVIMR_SUSPE_Pos) /**< (DEVIMR) Suspend Interrupt Mask Mask */
+#define DEVIMR_MSOFE_Pos 1 /**< (DEVIMR) Micro Start of Frame Interrupt Mask Position */
+#define DEVIMR_MSOFE (_U_(0x1) << DEVIMR_MSOFE_Pos) /**< (DEVIMR) Micro Start of Frame Interrupt Mask Mask */
+#define DEVIMR_SOFE_Pos 2 /**< (DEVIMR) Start of Frame Interrupt Mask Position */
+#define DEVIMR_SOFE (_U_(0x1) << DEVIMR_SOFE_Pos) /**< (DEVIMR) Start of Frame Interrupt Mask Mask */
+#define DEVIMR_EORSTE_Pos 3 /**< (DEVIMR) End of Reset Interrupt Mask Position */
+#define DEVIMR_EORSTE (_U_(0x1) << DEVIMR_EORSTE_Pos) /**< (DEVIMR) End of Reset Interrupt Mask Mask */
+#define DEVIMR_WAKEUPE_Pos 4 /**< (DEVIMR) Wake-Up Interrupt Mask Position */
+#define DEVIMR_WAKEUPE (_U_(0x1) << DEVIMR_WAKEUPE_Pos) /**< (DEVIMR) Wake-Up Interrupt Mask Mask */
+#define DEVIMR_EORSME_Pos 5 /**< (DEVIMR) End of Resume Interrupt Mask Position */
+#define DEVIMR_EORSME (_U_(0x1) << DEVIMR_EORSME_Pos) /**< (DEVIMR) End of Resume Interrupt Mask Mask */
+#define DEVIMR_UPRSME_Pos 6 /**< (DEVIMR) Upstream Resume Interrupt Mask Position */
+#define DEVIMR_UPRSME (_U_(0x1) << DEVIMR_UPRSME_Pos) /**< (DEVIMR) Upstream Resume Interrupt Mask Mask */
+#define DEVIMR_PEP_0_Pos 12 /**< (DEVIMR) Endpoint 0 Interrupt Mask Position */
+#define DEVIMR_PEP_0 (_U_(0x1) << DEVIMR_PEP_0_Pos) /**< (DEVIMR) Endpoint 0 Interrupt Mask Mask */
+#define DEVIMR_PEP_1_Pos 13 /**< (DEVIMR) Endpoint 1 Interrupt Mask Position */
+#define DEVIMR_PEP_1 (_U_(0x1) << DEVIMR_PEP_1_Pos) /**< (DEVIMR) Endpoint 1 Interrupt Mask Mask */
+#define DEVIMR_PEP_2_Pos 14 /**< (DEVIMR) Endpoint 2 Interrupt Mask Position */
+#define DEVIMR_PEP_2 (_U_(0x1) << DEVIMR_PEP_2_Pos) /**< (DEVIMR) Endpoint 2 Interrupt Mask Mask */
+#define DEVIMR_PEP_3_Pos 15 /**< (DEVIMR) Endpoint 3 Interrupt Mask Position */
+#define DEVIMR_PEP_3 (_U_(0x1) << DEVIMR_PEP_3_Pos) /**< (DEVIMR) Endpoint 3 Interrupt Mask Mask */
+#define DEVIMR_PEP_4_Pos 16 /**< (DEVIMR) Endpoint 4 Interrupt Mask Position */
+#define DEVIMR_PEP_4 (_U_(0x1) << DEVIMR_PEP_4_Pos) /**< (DEVIMR) Endpoint 4 Interrupt Mask Mask */
+#define DEVIMR_PEP_5_Pos 17 /**< (DEVIMR) Endpoint 5 Interrupt Mask Position */
+#define DEVIMR_PEP_5 (_U_(0x1) << DEVIMR_PEP_5_Pos) /**< (DEVIMR) Endpoint 5 Interrupt Mask Mask */
+#define DEVIMR_PEP_6_Pos 18 /**< (DEVIMR) Endpoint 6 Interrupt Mask Position */
+#define DEVIMR_PEP_6 (_U_(0x1) << DEVIMR_PEP_6_Pos) /**< (DEVIMR) Endpoint 6 Interrupt Mask Mask */
+#define DEVIMR_PEP_7_Pos 19 /**< (DEVIMR) Endpoint 7 Interrupt Mask Position */
+#define DEVIMR_PEP_7 (_U_(0x1) << DEVIMR_PEP_7_Pos) /**< (DEVIMR) Endpoint 7 Interrupt Mask Mask */
+#define DEVIMR_PEP_8_Pos 20 /**< (DEVIMR) Endpoint 8 Interrupt Mask Position */
+#define DEVIMR_PEP_8 (_U_(0x1) << DEVIMR_PEP_8_Pos) /**< (DEVIMR) Endpoint 8 Interrupt Mask Mask */
+#define DEVIMR_PEP_9_Pos 21 /**< (DEVIMR) Endpoint 9 Interrupt Mask Position */
+#define DEVIMR_PEP_9 (_U_(0x1) << DEVIMR_PEP_9_Pos) /**< (DEVIMR) Endpoint 9 Interrupt Mask Mask */
+#define DEVIMR_DMA_1_Pos 25 /**< (DEVIMR) DMA Channel 1 Interrupt Mask Position */
+#define DEVIMR_DMA_1 (_U_(0x1) << DEVIMR_DMA_1_Pos) /**< (DEVIMR) DMA Channel 1 Interrupt Mask Mask */
+#define DEVIMR_DMA_2_Pos 26 /**< (DEVIMR) DMA Channel 2 Interrupt Mask Position */
+#define DEVIMR_DMA_2 (_U_(0x1) << DEVIMR_DMA_2_Pos) /**< (DEVIMR) DMA Channel 2 Interrupt Mask Mask */
+#define DEVIMR_DMA_3_Pos 27 /**< (DEVIMR) DMA Channel 3 Interrupt Mask Position */
+#define DEVIMR_DMA_3 (_U_(0x1) << DEVIMR_DMA_3_Pos) /**< (DEVIMR) DMA Channel 3 Interrupt Mask Mask */
+#define DEVIMR_DMA_4_Pos 28 /**< (DEVIMR) DMA Channel 4 Interrupt Mask Position */
+#define DEVIMR_DMA_4 (_U_(0x1) << DEVIMR_DMA_4_Pos) /**< (DEVIMR) DMA Channel 4 Interrupt Mask Mask */
+#define DEVIMR_DMA_5_Pos 29 /**< (DEVIMR) DMA Channel 5 Interrupt Mask Position */
+#define DEVIMR_DMA_5 (_U_(0x1) << DEVIMR_DMA_5_Pos) /**< (DEVIMR) DMA Channel 5 Interrupt Mask Mask */
+#define DEVIMR_DMA_6_Pos 30 /**< (DEVIMR) DMA Channel 6 Interrupt Mask Position */
+#define DEVIMR_DMA_6 (_U_(0x1) << DEVIMR_DMA_6_Pos) /**< (DEVIMR) DMA Channel 6 Interrupt Mask Mask */
+#define DEVIMR_DMA_7_Pos 31 /**< (DEVIMR) DMA Channel 7 Interrupt Mask Position */
+#define DEVIMR_DMA_7 (_U_(0x1) << DEVIMR_DMA_7_Pos) /**< (DEVIMR) DMA Channel 7 Interrupt Mask Mask */
+#define DEVIMR_Msk _U_(0xFE3FF07F) /**< (DEVIMR) Register Mask */
+
+#define DEVIMR_PEP__Pos 12 /**< (DEVIMR Position) Endpoint x Interrupt Mask */
+#define DEVIMR_PEP_ (_U_(0x3FF) << DEVIMR_PEP__Pos) /**< (DEVIMR Mask) PEP_ */
+#define DEVIMR_DMA__Pos 25 /**< (DEVIMR Position) DMA Channel 7 Interrupt Mask */
+#define DEVIMR_DMA_ (_U_(0x7F) << DEVIMR_DMA__Pos) /**< (DEVIMR Mask) DMA_ */
+
+/* -------- DEVIDR : (USBHS Offset: 0x14) (/W 32) Device Global Interrupt Disable Register -------- */
+
+#define DEVIDR_OFFSET (0x14) /**< (DEVIDR) Device Global Interrupt Disable Register Offset */
+
+#define DEVIDR_SUSPEC_Pos 0 /**< (DEVIDR) Suspend Interrupt Disable Position */
+#define DEVIDR_SUSPEC (_U_(0x1) << DEVIDR_SUSPEC_Pos) /**< (DEVIDR) Suspend Interrupt Disable Mask */
+#define DEVIDR_MSOFEC_Pos 1 /**< (DEVIDR) Micro Start of Frame Interrupt Disable Position */
+#define DEVIDR_MSOFEC (_U_(0x1) << DEVIDR_MSOFEC_Pos) /**< (DEVIDR) Micro Start of Frame Interrupt Disable Mask */
+#define DEVIDR_SOFEC_Pos 2 /**< (DEVIDR) Start of Frame Interrupt Disable Position */
+#define DEVIDR_SOFEC (_U_(0x1) << DEVIDR_SOFEC_Pos) /**< (DEVIDR) Start of Frame Interrupt Disable Mask */
+#define DEVIDR_EORSTEC_Pos 3 /**< (DEVIDR) End of Reset Interrupt Disable Position */
+#define DEVIDR_EORSTEC (_U_(0x1) << DEVIDR_EORSTEC_Pos) /**< (DEVIDR) End of Reset Interrupt Disable Mask */
+#define DEVIDR_WAKEUPEC_Pos 4 /**< (DEVIDR) Wake-Up Interrupt Disable Position */
+#define DEVIDR_WAKEUPEC (_U_(0x1) << DEVIDR_WAKEUPEC_Pos) /**< (DEVIDR) Wake-Up Interrupt Disable Mask */
+#define DEVIDR_EORSMEC_Pos 5 /**< (DEVIDR) End of Resume Interrupt Disable Position */
+#define DEVIDR_EORSMEC (_U_(0x1) << DEVIDR_EORSMEC_Pos) /**< (DEVIDR) End of Resume Interrupt Disable Mask */
+#define DEVIDR_UPRSMEC_Pos 6 /**< (DEVIDR) Upstream Resume Interrupt Disable Position */
+#define DEVIDR_UPRSMEC (_U_(0x1) << DEVIDR_UPRSMEC_Pos) /**< (DEVIDR) Upstream Resume Interrupt Disable Mask */
+#define DEVIDR_PEP_0_Pos 12 /**< (DEVIDR) Endpoint 0 Interrupt Disable Position */
+#define DEVIDR_PEP_0 (_U_(0x1) << DEVIDR_PEP_0_Pos) /**< (DEVIDR) Endpoint 0 Interrupt Disable Mask */
+#define DEVIDR_PEP_1_Pos 13 /**< (DEVIDR) Endpoint 1 Interrupt Disable Position */
+#define DEVIDR_PEP_1 (_U_(0x1) << DEVIDR_PEP_1_Pos) /**< (DEVIDR) Endpoint 1 Interrupt Disable Mask */
+#define DEVIDR_PEP_2_Pos 14 /**< (DEVIDR) Endpoint 2 Interrupt Disable Position */
+#define DEVIDR_PEP_2 (_U_(0x1) << DEVIDR_PEP_2_Pos) /**< (DEVIDR) Endpoint 2 Interrupt Disable Mask */
+#define DEVIDR_PEP_3_Pos 15 /**< (DEVIDR) Endpoint 3 Interrupt Disable Position */
+#define DEVIDR_PEP_3 (_U_(0x1) << DEVIDR_PEP_3_Pos) /**< (DEVIDR) Endpoint 3 Interrupt Disable Mask */
+#define DEVIDR_PEP_4_Pos 16 /**< (DEVIDR) Endpoint 4 Interrupt Disable Position */
+#define DEVIDR_PEP_4 (_U_(0x1) << DEVIDR_PEP_4_Pos) /**< (DEVIDR) Endpoint 4 Interrupt Disable Mask */
+#define DEVIDR_PEP_5_Pos 17 /**< (DEVIDR) Endpoint 5 Interrupt Disable Position */
+#define DEVIDR_PEP_5 (_U_(0x1) << DEVIDR_PEP_5_Pos) /**< (DEVIDR) Endpoint 5 Interrupt Disable Mask */
+#define DEVIDR_PEP_6_Pos 18 /**< (DEVIDR) Endpoint 6 Interrupt Disable Position */
+#define DEVIDR_PEP_6 (_U_(0x1) << DEVIDR_PEP_6_Pos) /**< (DEVIDR) Endpoint 6 Interrupt Disable Mask */
+#define DEVIDR_PEP_7_Pos 19 /**< (DEVIDR) Endpoint 7 Interrupt Disable Position */
+#define DEVIDR_PEP_7 (_U_(0x1) << DEVIDR_PEP_7_Pos) /**< (DEVIDR) Endpoint 7 Interrupt Disable Mask */
+#define DEVIDR_PEP_8_Pos 20 /**< (DEVIDR) Endpoint 8 Interrupt Disable Position */
+#define DEVIDR_PEP_8 (_U_(0x1) << DEVIDR_PEP_8_Pos) /**< (DEVIDR) Endpoint 8 Interrupt Disable Mask */
+#define DEVIDR_PEP_9_Pos 21 /**< (DEVIDR) Endpoint 9 Interrupt Disable Position */
+#define DEVIDR_PEP_9 (_U_(0x1) << DEVIDR_PEP_9_Pos) /**< (DEVIDR) Endpoint 9 Interrupt Disable Mask */
+#define DEVIDR_DMA_1_Pos 25 /**< (DEVIDR) DMA Channel 1 Interrupt Disable Position */
+#define DEVIDR_DMA_1 (_U_(0x1) << DEVIDR_DMA_1_Pos) /**< (DEVIDR) DMA Channel 1 Interrupt Disable Mask */
+#define DEVIDR_DMA_2_Pos 26 /**< (DEVIDR) DMA Channel 2 Interrupt Disable Position */
+#define DEVIDR_DMA_2 (_U_(0x1) << DEVIDR_DMA_2_Pos) /**< (DEVIDR) DMA Channel 2 Interrupt Disable Mask */
+#define DEVIDR_DMA_3_Pos 27 /**< (DEVIDR) DMA Channel 3 Interrupt Disable Position */
+#define DEVIDR_DMA_3 (_U_(0x1) << DEVIDR_DMA_3_Pos) /**< (DEVIDR) DMA Channel 3 Interrupt Disable Mask */
+#define DEVIDR_DMA_4_Pos 28 /**< (DEVIDR) DMA Channel 4 Interrupt Disable Position */
+#define DEVIDR_DMA_4 (_U_(0x1) << DEVIDR_DMA_4_Pos) /**< (DEVIDR) DMA Channel 4 Interrupt Disable Mask */
+#define DEVIDR_DMA_5_Pos 29 /**< (DEVIDR) DMA Channel 5 Interrupt Disable Position */
+#define DEVIDR_DMA_5 (_U_(0x1) << DEVIDR_DMA_5_Pos) /**< (DEVIDR) DMA Channel 5 Interrupt Disable Mask */
+#define DEVIDR_DMA_6_Pos 30 /**< (DEVIDR) DMA Channel 6 Interrupt Disable Position */
+#define DEVIDR_DMA_6 (_U_(0x1) << DEVIDR_DMA_6_Pos) /**< (DEVIDR) DMA Channel 6 Interrupt Disable Mask */
+#define DEVIDR_DMA_7_Pos 31 /**< (DEVIDR) DMA Channel 7 Interrupt Disable Position */
+#define DEVIDR_DMA_7 (_U_(0x1) << DEVIDR_DMA_7_Pos) /**< (DEVIDR) DMA Channel 7 Interrupt Disable Mask */
+#define DEVIDR_Msk _U_(0xFE3FF07F) /**< (DEVIDR) Register Mask */
+
+#define DEVIDR_PEP__Pos 12 /**< (DEVIDR Position) Endpoint x Interrupt Disable */
+#define DEVIDR_PEP_ (_U_(0x3FF) << DEVIDR_PEP__Pos) /**< (DEVIDR Mask) PEP_ */
+#define DEVIDR_DMA__Pos 25 /**< (DEVIDR Position) DMA Channel 7 Interrupt Disable */
+#define DEVIDR_DMA_ (_U_(0x7F) << DEVIDR_DMA__Pos) /**< (DEVIDR Mask) DMA_ */
+
+/* -------- DEVIER : (USBHS Offset: 0x18) (/W 32) Device Global Interrupt Enable Register -------- */
+
+#define DEVIER_OFFSET (0x18) /**< (DEVIER) Device Global Interrupt Enable Register Offset */
+
+#define DEVIER_SUSPES_Pos 0 /**< (DEVIER) Suspend Interrupt Enable Position */
+#define DEVIER_SUSPES (_U_(0x1) << DEVIER_SUSPES_Pos) /**< (DEVIER) Suspend Interrupt Enable Mask */
+#define DEVIER_MSOFES_Pos 1 /**< (DEVIER) Micro Start of Frame Interrupt Enable Position */
+#define DEVIER_MSOFES (_U_(0x1) << DEVIER_MSOFES_Pos) /**< (DEVIER) Micro Start of Frame Interrupt Enable Mask */
+#define DEVIER_SOFES_Pos 2 /**< (DEVIER) Start of Frame Interrupt Enable Position */
+#define DEVIER_SOFES (_U_(0x1) << DEVIER_SOFES_Pos) /**< (DEVIER) Start of Frame Interrupt Enable Mask */
+#define DEVIER_EORSTES_Pos 3 /**< (DEVIER) End of Reset Interrupt Enable Position */
+#define DEVIER_EORSTES (_U_(0x1) << DEVIER_EORSTES_Pos) /**< (DEVIER) End of Reset Interrupt Enable Mask */
+#define DEVIER_WAKEUPES_Pos 4 /**< (DEVIER) Wake-Up Interrupt Enable Position */
+#define DEVIER_WAKEUPES (_U_(0x1) << DEVIER_WAKEUPES_Pos) /**< (DEVIER) Wake-Up Interrupt Enable Mask */
+#define DEVIER_EORSMES_Pos 5 /**< (DEVIER) End of Resume Interrupt Enable Position */
+#define DEVIER_EORSMES (_U_(0x1) << DEVIER_EORSMES_Pos) /**< (DEVIER) End of Resume Interrupt Enable Mask */
+#define DEVIER_UPRSMES_Pos 6 /**< (DEVIER) Upstream Resume Interrupt Enable Position */
+#define DEVIER_UPRSMES (_U_(0x1) << DEVIER_UPRSMES_Pos) /**< (DEVIER) Upstream Resume Interrupt Enable Mask */
+#define DEVIER_PEP_0_Pos 12 /**< (DEVIER) Endpoint 0 Interrupt Enable Position */
+#define DEVIER_PEP_0 (_U_(0x1) << DEVIER_PEP_0_Pos) /**< (DEVIER) Endpoint 0 Interrupt Enable Mask */
+#define DEVIER_PEP_1_Pos 13 /**< (DEVIER) Endpoint 1 Interrupt Enable Position */
+#define DEVIER_PEP_1 (_U_(0x1) << DEVIER_PEP_1_Pos) /**< (DEVIER) Endpoint 1 Interrupt Enable Mask */
+#define DEVIER_PEP_2_Pos 14 /**< (DEVIER) Endpoint 2 Interrupt Enable Position */
+#define DEVIER_PEP_2 (_U_(0x1) << DEVIER_PEP_2_Pos) /**< (DEVIER) Endpoint 2 Interrupt Enable Mask */
+#define DEVIER_PEP_3_Pos 15 /**< (DEVIER) Endpoint 3 Interrupt Enable Position */
+#define DEVIER_PEP_3 (_U_(0x1) << DEVIER_PEP_3_Pos) /**< (DEVIER) Endpoint 3 Interrupt Enable Mask */
+#define DEVIER_PEP_4_Pos 16 /**< (DEVIER) Endpoint 4 Interrupt Enable Position */
+#define DEVIER_PEP_4 (_U_(0x1) << DEVIER_PEP_4_Pos) /**< (DEVIER) Endpoint 4 Interrupt Enable Mask */
+#define DEVIER_PEP_5_Pos 17 /**< (DEVIER) Endpoint 5 Interrupt Enable Position */
+#define DEVIER_PEP_5 (_U_(0x1) << DEVIER_PEP_5_Pos) /**< (DEVIER) Endpoint 5 Interrupt Enable Mask */
+#define DEVIER_PEP_6_Pos 18 /**< (DEVIER) Endpoint 6 Interrupt Enable Position */
+#define DEVIER_PEP_6 (_U_(0x1) << DEVIER_PEP_6_Pos) /**< (DEVIER) Endpoint 6 Interrupt Enable Mask */
+#define DEVIER_PEP_7_Pos 19 /**< (DEVIER) Endpoint 7 Interrupt Enable Position */
+#define DEVIER_PEP_7 (_U_(0x1) << DEVIER_PEP_7_Pos) /**< (DEVIER) Endpoint 7 Interrupt Enable Mask */
+#define DEVIER_PEP_8_Pos 20 /**< (DEVIER) Endpoint 8 Interrupt Enable Position */
+#define DEVIER_PEP_8 (_U_(0x1) << DEVIER_PEP_8_Pos) /**< (DEVIER) Endpoint 8 Interrupt Enable Mask */
+#define DEVIER_PEP_9_Pos 21 /**< (DEVIER) Endpoint 9 Interrupt Enable Position */
+#define DEVIER_PEP_9 (_U_(0x1) << DEVIER_PEP_9_Pos) /**< (DEVIER) Endpoint 9 Interrupt Enable Mask */
+#define DEVIER_DMA_1_Pos 25 /**< (DEVIER) DMA Channel 1 Interrupt Enable Position */
+#define DEVIER_DMA_1 (_U_(0x1) << DEVIER_DMA_1_Pos) /**< (DEVIER) DMA Channel 1 Interrupt Enable Mask */
+#define DEVIER_DMA_2_Pos 26 /**< (DEVIER) DMA Channel 2 Interrupt Enable Position */
+#define DEVIER_DMA_2 (_U_(0x1) << DEVIER_DMA_2_Pos) /**< (DEVIER) DMA Channel 2 Interrupt Enable Mask */
+#define DEVIER_DMA_3_Pos 27 /**< (DEVIER) DMA Channel 3 Interrupt Enable Position */
+#define DEVIER_DMA_3 (_U_(0x1) << DEVIER_DMA_3_Pos) /**< (DEVIER) DMA Channel 3 Interrupt Enable Mask */
+#define DEVIER_DMA_4_Pos 28 /**< (DEVIER) DMA Channel 4 Interrupt Enable Position */
+#define DEVIER_DMA_4 (_U_(0x1) << DEVIER_DMA_4_Pos) /**< (DEVIER) DMA Channel 4 Interrupt Enable Mask */
+#define DEVIER_DMA_5_Pos 29 /**< (DEVIER) DMA Channel 5 Interrupt Enable Position */
+#define DEVIER_DMA_5 (_U_(0x1) << DEVIER_DMA_5_Pos) /**< (DEVIER) DMA Channel 5 Interrupt Enable Mask */
+#define DEVIER_DMA_6_Pos 30 /**< (DEVIER) DMA Channel 6 Interrupt Enable Position */
+#define DEVIER_DMA_6 (_U_(0x1) << DEVIER_DMA_6_Pos) /**< (DEVIER) DMA Channel 6 Interrupt Enable Mask */
+#define DEVIER_DMA_7_Pos 31 /**< (DEVIER) DMA Channel 7 Interrupt Enable Position */
+#define DEVIER_DMA_7 (_U_(0x1) << DEVIER_DMA_7_Pos) /**< (DEVIER) DMA Channel 7 Interrupt Enable Mask */
+#define DEVIER_Msk _U_(0xFE3FF07F) /**< (DEVIER) Register Mask */
+
+#define DEVIER_PEP__Pos 12 /**< (DEVIER Position) Endpoint x Interrupt Enable */
+#define DEVIER_PEP_ (_U_(0x3FF) << DEVIER_PEP__Pos) /**< (DEVIER Mask) PEP_ */
+#define DEVIER_DMA__Pos 25 /**< (DEVIER Position) DMA Channel 7 Interrupt Enable */
+#define DEVIER_DMA_ (_U_(0x7F) << DEVIER_DMA__Pos) /**< (DEVIER Mask) DMA_ */
+
+/* -------- DEVEPT : (USBHS Offset: 0x1c) (R/W 32) Device Endpoint Register -------- */
+
+#define DEVEPT_OFFSET (0x1C) /**< (DEVEPT) Device Endpoint Register Offset */
+
+#define DEVEPT_EPEN0_Pos 0 /**< (DEVEPT) Endpoint 0 Enable Position */
+#define DEVEPT_EPEN0 (_U_(0x1) << DEVEPT_EPEN0_Pos) /**< (DEVEPT) Endpoint 0 Enable Mask */
+#define DEVEPT_EPEN1_Pos 1 /**< (DEVEPT) Endpoint 1 Enable Position */
+#define DEVEPT_EPEN1 (_U_(0x1) << DEVEPT_EPEN1_Pos) /**< (DEVEPT) Endpoint 1 Enable Mask */
+#define DEVEPT_EPEN2_Pos 2 /**< (DEVEPT) Endpoint 2 Enable Position */
+#define DEVEPT_EPEN2 (_U_(0x1) << DEVEPT_EPEN2_Pos) /**< (DEVEPT) Endpoint 2 Enable Mask */
+#define DEVEPT_EPEN3_Pos 3 /**< (DEVEPT) Endpoint 3 Enable Position */
+#define DEVEPT_EPEN3 (_U_(0x1) << DEVEPT_EPEN3_Pos) /**< (DEVEPT) Endpoint 3 Enable Mask */
+#define DEVEPT_EPEN4_Pos 4 /**< (DEVEPT) Endpoint 4 Enable Position */
+#define DEVEPT_EPEN4 (_U_(0x1) << DEVEPT_EPEN4_Pos) /**< (DEVEPT) Endpoint 4 Enable Mask */
+#define DEVEPT_EPEN5_Pos 5 /**< (DEVEPT) Endpoint 5 Enable Position */
+#define DEVEPT_EPEN5 (_U_(0x1) << DEVEPT_EPEN5_Pos) /**< (DEVEPT) Endpoint 5 Enable Mask */
+#define DEVEPT_EPEN6_Pos 6 /**< (DEVEPT) Endpoint 6 Enable Position */
+#define DEVEPT_EPEN6 (_U_(0x1) << DEVEPT_EPEN6_Pos) /**< (DEVEPT) Endpoint 6 Enable Mask */
+#define DEVEPT_EPEN7_Pos 7 /**< (DEVEPT) Endpoint 7 Enable Position */
+#define DEVEPT_EPEN7 (_U_(0x1) << DEVEPT_EPEN7_Pos) /**< (DEVEPT) Endpoint 7 Enable Mask */
+#define DEVEPT_EPEN8_Pos 8 /**< (DEVEPT) Endpoint 8 Enable Position */
+#define DEVEPT_EPEN8 (_U_(0x1) << DEVEPT_EPEN8_Pos) /**< (DEVEPT) Endpoint 8 Enable Mask */
+#define DEVEPT_EPEN9_Pos 9 /**< (DEVEPT) Endpoint 9 Enable Position */
+#define DEVEPT_EPEN9 (_U_(0x1) << DEVEPT_EPEN9_Pos) /**< (DEVEPT) Endpoint 9 Enable Mask */
+#define DEVEPT_EPRST0_Pos 16 /**< (DEVEPT) Endpoint 0 Reset Position */
+#define DEVEPT_EPRST0 (_U_(0x1) << DEVEPT_EPRST0_Pos) /**< (DEVEPT) Endpoint 0 Reset Mask */
+#define DEVEPT_EPRST1_Pos 17 /**< (DEVEPT) Endpoint 1 Reset Position */
+#define DEVEPT_EPRST1 (_U_(0x1) << DEVEPT_EPRST1_Pos) /**< (DEVEPT) Endpoint 1 Reset Mask */
+#define DEVEPT_EPRST2_Pos 18 /**< (DEVEPT) Endpoint 2 Reset Position */
+#define DEVEPT_EPRST2 (_U_(0x1) << DEVEPT_EPRST2_Pos) /**< (DEVEPT) Endpoint 2 Reset Mask */
+#define DEVEPT_EPRST3_Pos 19 /**< (DEVEPT) Endpoint 3 Reset Position */
+#define DEVEPT_EPRST3 (_U_(0x1) << DEVEPT_EPRST3_Pos) /**< (DEVEPT) Endpoint 3 Reset Mask */
+#define DEVEPT_EPRST4_Pos 20 /**< (DEVEPT) Endpoint 4 Reset Position */
+#define DEVEPT_EPRST4 (_U_(0x1) << DEVEPT_EPRST4_Pos) /**< (DEVEPT) Endpoint 4 Reset Mask */
+#define DEVEPT_EPRST5_Pos 21 /**< (DEVEPT) Endpoint 5 Reset Position */
+#define DEVEPT_EPRST5 (_U_(0x1) << DEVEPT_EPRST5_Pos) /**< (DEVEPT) Endpoint 5 Reset Mask */
+#define DEVEPT_EPRST6_Pos 22 /**< (DEVEPT) Endpoint 6 Reset Position */
+#define DEVEPT_EPRST6 (_U_(0x1) << DEVEPT_EPRST6_Pos) /**< (DEVEPT) Endpoint 6 Reset Mask */
+#define DEVEPT_EPRST7_Pos 23 /**< (DEVEPT) Endpoint 7 Reset Position */
+#define DEVEPT_EPRST7 (_U_(0x1) << DEVEPT_EPRST7_Pos) /**< (DEVEPT) Endpoint 7 Reset Mask */
+#define DEVEPT_EPRST8_Pos 24 /**< (DEVEPT) Endpoint 8 Reset Position */
+#define DEVEPT_EPRST8 (_U_(0x1) << DEVEPT_EPRST8_Pos) /**< (DEVEPT) Endpoint 8 Reset Mask */
+#define DEVEPT_EPRST9_Pos 25 /**< (DEVEPT) Endpoint 9 Reset Position */
+#define DEVEPT_EPRST9 (_U_(0x1) << DEVEPT_EPRST9_Pos) /**< (DEVEPT) Endpoint 9 Reset Mask */
+#define DEVEPT_Msk _U_(0x3FF03FF) /**< (DEVEPT) Register Mask */
+
+#define DEVEPT_EPEN_Pos 0 /**< (DEVEPT Position) Endpoint x Enable */
+#define DEVEPT_EPEN (_U_(0x3FF) << DEVEPT_EPEN_Pos) /**< (DEVEPT Mask) EPEN */
+#define DEVEPT_EPRST_Pos 16 /**< (DEVEPT Position) Endpoint 9 Reset */
+#define DEVEPT_EPRST (_U_(0x3FF) << DEVEPT_EPRST_Pos) /**< (DEVEPT Mask) EPRST */
+
+/* -------- DEVFNUM : (USBHS Offset: 0x20) (R/ 32) Device Frame Number Register -------- */
+
+#define DEVFNUM_OFFSET (0x20) /**< (DEVFNUM) Device Frame Number Register Offset */
+
+#define DEVFNUM_MFNUM_Pos 0 /**< (DEVFNUM) Micro Frame Number Position */
+#define DEVFNUM_MFNUM (_U_(0x7) << DEVFNUM_MFNUM_Pos) /**< (DEVFNUM) Micro Frame Number Mask */
+#define DEVFNUM_FNUM_Pos 3 /**< (DEVFNUM) Frame Number Position */
+#define DEVFNUM_FNUM (_U_(0x7FF) << DEVFNUM_FNUM_Pos) /**< (DEVFNUM) Frame Number Mask */
+#define DEVFNUM_FNCERR_Pos 15 /**< (DEVFNUM) Frame Number CRC Error Position */
+#define DEVFNUM_FNCERR (_U_(0x1) << DEVFNUM_FNCERR_Pos) /**< (DEVFNUM) Frame Number CRC Error Mask */
+#define DEVFNUM_Msk _U_(0xBFFF) /**< (DEVFNUM) Register Mask */
+
+
+/* -------- DEVEPTCFG : (USBHS Offset: 0x100) (R/W 32) Device Endpoint Configuration Register -------- */
+
+#define DEVEPTCFG_OFFSET (0x100) /**< (DEVEPTCFG) Device Endpoint Configuration Register Offset */
+
+#define DEVEPTCFG_ALLOC_Pos 1 /**< (DEVEPTCFG) Endpoint Memory Allocate Position */
+#define DEVEPTCFG_ALLOC (_U_(0x1) << DEVEPTCFG_ALLOC_Pos) /**< (DEVEPTCFG) Endpoint Memory Allocate Mask */
+#define DEVEPTCFG_EPBK_Pos 2 /**< (DEVEPTCFG) Endpoint Banks Position */
+#define DEVEPTCFG_EPBK (_U_(0x3) << DEVEPTCFG_EPBK_Pos) /**< (DEVEPTCFG) Endpoint Banks Mask */
+#define DEVEPTCFG_EPBK_1_BANK_Val _U_(0x0) /**< (DEVEPTCFG) Single-bank endpoint */
+#define DEVEPTCFG_EPBK_2_BANK_Val _U_(0x1) /**< (DEVEPTCFG) Double-bank endpoint */
+#define DEVEPTCFG_EPBK_3_BANK_Val _U_(0x2) /**< (DEVEPTCFG) Triple-bank endpoint */
+#define DEVEPTCFG_EPBK_1_BANK (DEVEPTCFG_EPBK_1_BANK_Val << DEVEPTCFG_EPBK_Pos) /**< (DEVEPTCFG) Single-bank endpoint Position */
+#define DEVEPTCFG_EPBK_2_BANK (DEVEPTCFG_EPBK_2_BANK_Val << DEVEPTCFG_EPBK_Pos) /**< (DEVEPTCFG) Double-bank endpoint Position */
+#define DEVEPTCFG_EPBK_3_BANK (DEVEPTCFG_EPBK_3_BANK_Val << DEVEPTCFG_EPBK_Pos) /**< (DEVEPTCFG) Triple-bank endpoint Position */
+#define DEVEPTCFG_EPSIZE_Pos 4 /**< (DEVEPTCFG) Endpoint Size Position */
+#define DEVEPTCFG_EPSIZE (_U_(0x7) << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) Endpoint Size Mask */
+#define DEVEPTCFG_EPSIZE_8_BYTE_Val _U_(0x0) /**< (DEVEPTCFG) 8 bytes */
+#define DEVEPTCFG_EPSIZE_16_BYTE_Val _U_(0x1) /**< (DEVEPTCFG) 16 bytes */
+#define DEVEPTCFG_EPSIZE_32_BYTE_Val _U_(0x2) /**< (DEVEPTCFG) 32 bytes */
+#define DEVEPTCFG_EPSIZE_64_BYTE_Val _U_(0x3) /**< (DEVEPTCFG) 64 bytes */
+#define DEVEPTCFG_EPSIZE_128_BYTE_Val _U_(0x4) /**< (DEVEPTCFG) 128 bytes */
+#define DEVEPTCFG_EPSIZE_256_BYTE_Val _U_(0x5) /**< (DEVEPTCFG) 256 bytes */
+#define DEVEPTCFG_EPSIZE_512_BYTE_Val _U_(0x6) /**< (DEVEPTCFG) 512 bytes */
+#define DEVEPTCFG_EPSIZE_1024_BYTE_Val _U_(0x7) /**< (DEVEPTCFG) 1024 bytes */
+#define DEVEPTCFG_EPSIZE_8_BYTE (DEVEPTCFG_EPSIZE_8_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 8 bytes Position */
+#define DEVEPTCFG_EPSIZE_16_BYTE (DEVEPTCFG_EPSIZE_16_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 16 bytes Position */
+#define DEVEPTCFG_EPSIZE_32_BYTE (DEVEPTCFG_EPSIZE_32_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 32 bytes Position */
+#define DEVEPTCFG_EPSIZE_64_BYTE (DEVEPTCFG_EPSIZE_64_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 64 bytes Position */
+#define DEVEPTCFG_EPSIZE_128_BYTE (DEVEPTCFG_EPSIZE_128_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 128 bytes Position */
+#define DEVEPTCFG_EPSIZE_256_BYTE (DEVEPTCFG_EPSIZE_256_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 256 bytes Position */
+#define DEVEPTCFG_EPSIZE_512_BYTE (DEVEPTCFG_EPSIZE_512_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 512 bytes Position */
+#define DEVEPTCFG_EPSIZE_1024_BYTE (DEVEPTCFG_EPSIZE_1024_BYTE_Val << DEVEPTCFG_EPSIZE_Pos) /**< (DEVEPTCFG) 1024 bytes Position */
+#define DEVEPTCFG_EPDIR_Pos 8 /**< (DEVEPTCFG) Endpoint Direction Position */
+#define DEVEPTCFG_EPDIR (_U_(0x1) << DEVEPTCFG_EPDIR_Pos) /**< (DEVEPTCFG) Endpoint Direction Mask */
+#define DEVEPTCFG_EPDIR_OUT_Val _U_(0x0) /**< (DEVEPTCFG) The endpoint direction is OUT. */
+#define DEVEPTCFG_EPDIR_IN_Val _U_(0x1) /**< (DEVEPTCFG) The endpoint direction is IN (nor for control endpoints). */
+#define DEVEPTCFG_EPDIR_OUT (DEVEPTCFG_EPDIR_OUT_Val << DEVEPTCFG_EPDIR_Pos) /**< (DEVEPTCFG) The endpoint direction is OUT. Position */
+#define DEVEPTCFG_EPDIR_IN (DEVEPTCFG_EPDIR_IN_Val << DEVEPTCFG_EPDIR_Pos) /**< (DEVEPTCFG) The endpoint direction is IN (nor for control endpoints). Position */
+#define DEVEPTCFG_AUTOSW_Pos 9 /**< (DEVEPTCFG) Automatic Switch Position */
+#define DEVEPTCFG_AUTOSW (_U_(0x1) << DEVEPTCFG_AUTOSW_Pos) /**< (DEVEPTCFG) Automatic Switch Mask */
+#define DEVEPTCFG_EPTYPE_Pos 11 /**< (DEVEPTCFG) Endpoint Type Position */
+#define DEVEPTCFG_EPTYPE (_U_(0x3) << DEVEPTCFG_EPTYPE_Pos) /**< (DEVEPTCFG) Endpoint Type Mask */
+#define DEVEPTCFG_EPTYPE_CTRL_Val _U_(0x0) /**< (DEVEPTCFG) Control */
+#define DEVEPTCFG_EPTYPE_ISO_Val _U_(0x1) /**< (DEVEPTCFG) Isochronous */
+#define DEVEPTCFG_EPTYPE_BLK_Val _U_(0x2) /**< (DEVEPTCFG) Bulk */
+#define DEVEPTCFG_EPTYPE_INTRPT_Val _U_(0x3) /**< (DEVEPTCFG) Interrupt */
+#define DEVEPTCFG_EPTYPE_CTRL (DEVEPTCFG_EPTYPE_CTRL_Val << DEVEPTCFG_EPTYPE_Pos) /**< (DEVEPTCFG) Control Position */
+#define DEVEPTCFG_EPTYPE_ISO (DEVEPTCFG_EPTYPE_ISO_Val << DEVEPTCFG_EPTYPE_Pos) /**< (DEVEPTCFG) Isochronous Position */
+#define DEVEPTCFG_EPTYPE_BLK (DEVEPTCFG_EPTYPE_BLK_Val << DEVEPTCFG_EPTYPE_Pos) /**< (DEVEPTCFG) Bulk Position */
+#define DEVEPTCFG_EPTYPE_INTRPT (DEVEPTCFG_EPTYPE_INTRPT_Val << DEVEPTCFG_EPTYPE_Pos) /**< (DEVEPTCFG) Interrupt Position */
+#define DEVEPTCFG_NBTRANS_Pos 13 /**< (DEVEPTCFG) Number of transactions per microframe for isochronous endpoint Position */
+#define DEVEPTCFG_NBTRANS (_U_(0x3) << DEVEPTCFG_NBTRANS_Pos) /**< (DEVEPTCFG) Number of transactions per microframe for isochronous endpoint Mask */
+#define DEVEPTCFG_NBTRANS_0_TRANS_Val _U_(0x0) /**< (DEVEPTCFG) Reserved to endpoint that does not have the high-bandwidth isochronous capability. */
+#define DEVEPTCFG_NBTRANS_1_TRANS_Val _U_(0x1) /**< (DEVEPTCFG) Default value: one transaction per microframe. */
+#define DEVEPTCFG_NBTRANS_2_TRANS_Val _U_(0x2) /**< (DEVEPTCFG) Two transactions per microframe. This endpoint should be configured as double-bank. */
+#define DEVEPTCFG_NBTRANS_3_TRANS_Val _U_(0x3) /**< (DEVEPTCFG) Three transactions per microframe. This endpoint should be configured as triple-bank. */
+#define DEVEPTCFG_NBTRANS_0_TRANS (DEVEPTCFG_NBTRANS_0_TRANS_Val << DEVEPTCFG_NBTRANS_Pos) /**< (DEVEPTCFG) Reserved to endpoint that does not have the high-bandwidth isochronous capability. Position */
+#define DEVEPTCFG_NBTRANS_1_TRANS (DEVEPTCFG_NBTRANS_1_TRANS_Val << DEVEPTCFG_NBTRANS_Pos) /**< (DEVEPTCFG) Default value: one transaction per microframe. Position */
+#define DEVEPTCFG_NBTRANS_2_TRANS (DEVEPTCFG_NBTRANS_2_TRANS_Val << DEVEPTCFG_NBTRANS_Pos) /**< (DEVEPTCFG) Two transactions per microframe. This endpoint should be configured as double-bank. Position */
+#define DEVEPTCFG_NBTRANS_3_TRANS (DEVEPTCFG_NBTRANS_3_TRANS_Val << DEVEPTCFG_NBTRANS_Pos) /**< (DEVEPTCFG) Three transactions per microframe. This endpoint should be configured as triple-bank. Position */
+#define DEVEPTCFG_Msk _U_(0x7B7E) /**< (DEVEPTCFG) Register Mask */
+
+
+/* -------- DEVEPTISR : (USBHS Offset: 0x130) (R/ 32) Device Endpoint Interrupt Status Register -------- */
+
+#define DEVEPTISR_OFFSET (0x130) /**< (DEVEPTISR) Device Endpoint Interrupt Status Register Offset */
+
+#define DEVEPTISR_TXINI_Pos 0 /**< (DEVEPTISR) Transmitted IN Data Interrupt Position */
+#define DEVEPTISR_TXINI (_U_(0x1) << DEVEPTISR_TXINI_Pos) /**< (DEVEPTISR) Transmitted IN Data Interrupt Mask */
+#define DEVEPTISR_RXOUTI_Pos 1 /**< (DEVEPTISR) Received OUT Data Interrupt Position */
+#define DEVEPTISR_RXOUTI (_U_(0x1) << DEVEPTISR_RXOUTI_Pos) /**< (DEVEPTISR) Received OUT Data Interrupt Mask */
+#define DEVEPTISR_OVERFI_Pos 5 /**< (DEVEPTISR) Overflow Interrupt Position */
+#define DEVEPTISR_OVERFI (_U_(0x1) << DEVEPTISR_OVERFI_Pos) /**< (DEVEPTISR) Overflow Interrupt Mask */
+#define DEVEPTISR_SHORTPACKET_Pos 7 /**< (DEVEPTISR) Short Packet Interrupt Position */
+#define DEVEPTISR_SHORTPACKET (_U_(0x1) << DEVEPTISR_SHORTPACKET_Pos) /**< (DEVEPTISR) Short Packet Interrupt Mask */
+#define DEVEPTISR_DTSEQ_Pos 8 /**< (DEVEPTISR) Data Toggle Sequence Position */
+#define DEVEPTISR_DTSEQ (_U_(0x3) << DEVEPTISR_DTSEQ_Pos) /**< (DEVEPTISR) Data Toggle Sequence Mask */
+#define DEVEPTISR_DTSEQ_DATA0_Val _U_(0x0) /**< (DEVEPTISR) Data0 toggle sequence */
+#define DEVEPTISR_DTSEQ_DATA1_Val _U_(0x1) /**< (DEVEPTISR) Data1 toggle sequence */
+#define DEVEPTISR_DTSEQ_DATA2_Val _U_(0x2) /**< (DEVEPTISR) Reserved for high-bandwidth isochronous endpoint */
+#define DEVEPTISR_DTSEQ_MDATA_Val _U_(0x3) /**< (DEVEPTISR) Reserved for high-bandwidth isochronous endpoint */
+#define DEVEPTISR_DTSEQ_DATA0 (DEVEPTISR_DTSEQ_DATA0_Val << DEVEPTISR_DTSEQ_Pos) /**< (DEVEPTISR) Data0 toggle sequence Position */
+#define DEVEPTISR_DTSEQ_DATA1 (DEVEPTISR_DTSEQ_DATA1_Val << DEVEPTISR_DTSEQ_Pos) /**< (DEVEPTISR) Data1 toggle sequence Position */
+#define DEVEPTISR_DTSEQ_DATA2 (DEVEPTISR_DTSEQ_DATA2_Val << DEVEPTISR_DTSEQ_Pos) /**< (DEVEPTISR) Reserved for high-bandwidth isochronous endpoint Position */
+#define DEVEPTISR_DTSEQ_MDATA (DEVEPTISR_DTSEQ_MDATA_Val << DEVEPTISR_DTSEQ_Pos) /**< (DEVEPTISR) Reserved for high-bandwidth isochronous endpoint Position */
+#define DEVEPTISR_NBUSYBK_Pos 12 /**< (DEVEPTISR) Number of Busy Banks Position */
+#define DEVEPTISR_NBUSYBK (_U_(0x3) << DEVEPTISR_NBUSYBK_Pos) /**< (DEVEPTISR) Number of Busy Banks Mask */
+#define DEVEPTISR_NBUSYBK_0_BUSY_Val _U_(0x0) /**< (DEVEPTISR) 0 busy bank (all banks free) */
+#define DEVEPTISR_NBUSYBK_1_BUSY_Val _U_(0x1) /**< (DEVEPTISR) 1 busy bank */
+#define DEVEPTISR_NBUSYBK_2_BUSY_Val _U_(0x2) /**< (DEVEPTISR) 2 busy banks */
+#define DEVEPTISR_NBUSYBK_3_BUSY_Val _U_(0x3) /**< (DEVEPTISR) 3 busy banks */
+#define DEVEPTISR_NBUSYBK_0_BUSY (DEVEPTISR_NBUSYBK_0_BUSY_Val << DEVEPTISR_NBUSYBK_Pos) /**< (DEVEPTISR) 0 busy bank (all banks free) Position */
+#define DEVEPTISR_NBUSYBK_1_BUSY (DEVEPTISR_NBUSYBK_1_BUSY_Val << DEVEPTISR_NBUSYBK_Pos) /**< (DEVEPTISR) 1 busy bank Position */
+#define DEVEPTISR_NBUSYBK_2_BUSY (DEVEPTISR_NBUSYBK_2_BUSY_Val << DEVEPTISR_NBUSYBK_Pos) /**< (DEVEPTISR) 2 busy banks Position */
+#define DEVEPTISR_NBUSYBK_3_BUSY (DEVEPTISR_NBUSYBK_3_BUSY_Val << DEVEPTISR_NBUSYBK_Pos) /**< (DEVEPTISR) 3 busy banks Position */
+#define DEVEPTISR_CURRBK_Pos 14 /**< (DEVEPTISR) Current Bank Position */
+#define DEVEPTISR_CURRBK (_U_(0x3) << DEVEPTISR_CURRBK_Pos) /**< (DEVEPTISR) Current Bank Mask */
+#define DEVEPTISR_CURRBK_BANK0_Val _U_(0x0) /**< (DEVEPTISR) Current bank is bank0 */
+#define DEVEPTISR_CURRBK_BANK1_Val _U_(0x1) /**< (DEVEPTISR) Current bank is bank1 */
+#define DEVEPTISR_CURRBK_BANK2_Val _U_(0x2) /**< (DEVEPTISR) Current bank is bank2 */
+#define DEVEPTISR_CURRBK_BANK0 (DEVEPTISR_CURRBK_BANK0_Val << DEVEPTISR_CURRBK_Pos) /**< (DEVEPTISR) Current bank is bank0 Position */
+#define DEVEPTISR_CURRBK_BANK1 (DEVEPTISR_CURRBK_BANK1_Val << DEVEPTISR_CURRBK_Pos) /**< (DEVEPTISR) Current bank is bank1 Position */
+#define DEVEPTISR_CURRBK_BANK2 (DEVEPTISR_CURRBK_BANK2_Val << DEVEPTISR_CURRBK_Pos) /**< (DEVEPTISR) Current bank is bank2 Position */
+#define DEVEPTISR_RWALL_Pos 16 /**< (DEVEPTISR) Read/Write Allowed Position */
+#define DEVEPTISR_RWALL (_U_(0x1) << DEVEPTISR_RWALL_Pos) /**< (DEVEPTISR) Read/Write Allowed Mask */
+#define DEVEPTISR_CFGOK_Pos 18 /**< (DEVEPTISR) Configuration OK Status Position */
+#define DEVEPTISR_CFGOK (_U_(0x1) << DEVEPTISR_CFGOK_Pos) /**< (DEVEPTISR) Configuration OK Status Mask */
+#define DEVEPTISR_BYCT_Pos 20 /**< (DEVEPTISR) Byte Count Position */
+#define DEVEPTISR_BYCT (_U_(0x7FF) << DEVEPTISR_BYCT_Pos) /**< (DEVEPTISR) Byte Count Mask */
+#define DEVEPTISR_Msk _U_(0x7FF5F3A3) /**< (DEVEPTISR) Register Mask */
+
+/* CTRL mode */
+#define DEVEPTISR_CTRL_RXSTPI_Pos 2 /**< (DEVEPTISR) Received SETUP Interrupt Position */
+#define DEVEPTISR_CTRL_RXSTPI (_U_(0x1) << DEVEPTISR_CTRL_RXSTPI_Pos) /**< (DEVEPTISR) Received SETUP Interrupt Mask */
+#define DEVEPTISR_CTRL_NAKOUTI_Pos 3 /**< (DEVEPTISR) NAKed OUT Interrupt Position */
+#define DEVEPTISR_CTRL_NAKOUTI (_U_(0x1) << DEVEPTISR_CTRL_NAKOUTI_Pos) /**< (DEVEPTISR) NAKed OUT Interrupt Mask */
+#define DEVEPTISR_CTRL_NAKINI_Pos 4 /**< (DEVEPTISR) NAKed IN Interrupt Position */
+#define DEVEPTISR_CTRL_NAKINI (_U_(0x1) << DEVEPTISR_CTRL_NAKINI_Pos) /**< (DEVEPTISR) NAKed IN Interrupt Mask */
+#define DEVEPTISR_CTRL_STALLEDI_Pos 6 /**< (DEVEPTISR) STALLed Interrupt Position */
+#define DEVEPTISR_CTRL_STALLEDI (_U_(0x1) << DEVEPTISR_CTRL_STALLEDI_Pos) /**< (DEVEPTISR) STALLed Interrupt Mask */
+#define DEVEPTISR_CTRL_CTRLDIR_Pos 17 /**< (DEVEPTISR) Control Direction Position */
+#define DEVEPTISR_CTRL_CTRLDIR (_U_(0x1) << DEVEPTISR_CTRL_CTRLDIR_Pos) /**< (DEVEPTISR) Control Direction Mask */
+#define DEVEPTISR_CTRL_Msk _U_(0x2005C) /**< (DEVEPTISR_CTRL) Register Mask */
+
+/* ISO mode */
+#define DEVEPTISR_ISO_UNDERFI_Pos 2 /**< (DEVEPTISR) Underflow Interrupt Position */
+#define DEVEPTISR_ISO_UNDERFI (_U_(0x1) << DEVEPTISR_ISO_UNDERFI_Pos) /**< (DEVEPTISR) Underflow Interrupt Mask */
+#define DEVEPTISR_ISO_HBISOINERRI_Pos 3 /**< (DEVEPTISR) High Bandwidth Isochronous IN Underflow Error Interrupt Position */
+#define DEVEPTISR_ISO_HBISOINERRI (_U_(0x1) << DEVEPTISR_ISO_HBISOINERRI_Pos) /**< (DEVEPTISR) High Bandwidth Isochronous IN Underflow Error Interrupt Mask */
+#define DEVEPTISR_ISO_HBISOFLUSHI_Pos 4 /**< (DEVEPTISR) High Bandwidth Isochronous IN Flush Interrupt Position */
+#define DEVEPTISR_ISO_HBISOFLUSHI (_U_(0x1) << DEVEPTISR_ISO_HBISOFLUSHI_Pos) /**< (DEVEPTISR) High Bandwidth Isochronous IN Flush Interrupt Mask */
+#define DEVEPTISR_ISO_CRCERRI_Pos 6 /**< (DEVEPTISR) CRC Error Interrupt Position */
+#define DEVEPTISR_ISO_CRCERRI (_U_(0x1) << DEVEPTISR_ISO_CRCERRI_Pos) /**< (DEVEPTISR) CRC Error Interrupt Mask */
+#define DEVEPTISR_ISO_ERRORTRANS_Pos 10 /**< (DEVEPTISR) High-bandwidth Isochronous OUT Endpoint Transaction Error Interrupt Position */
+#define DEVEPTISR_ISO_ERRORTRANS (_U_(0x1) << DEVEPTISR_ISO_ERRORTRANS_Pos) /**< (DEVEPTISR) High-bandwidth Isochronous OUT Endpoint Transaction Error Interrupt Mask */
+#define DEVEPTISR_ISO_Msk _U_(0x45C) /**< (DEVEPTISR_ISO) Register Mask */
+
+/* BLK mode */
+#define DEVEPTISR_BLK_RXSTPI_Pos 2 /**< (DEVEPTISR) Received SETUP Interrupt Position */
+#define DEVEPTISR_BLK_RXSTPI (_U_(0x1) << DEVEPTISR_BLK_RXSTPI_Pos) /**< (DEVEPTISR) Received SETUP Interrupt Mask */
+#define DEVEPTISR_BLK_NAKOUTI_Pos 3 /**< (DEVEPTISR) NAKed OUT Interrupt Position */
+#define DEVEPTISR_BLK_NAKOUTI (_U_(0x1) << DEVEPTISR_BLK_NAKOUTI_Pos) /**< (DEVEPTISR) NAKed OUT Interrupt Mask */
+#define DEVEPTISR_BLK_NAKINI_Pos 4 /**< (DEVEPTISR) NAKed IN Interrupt Position */
+#define DEVEPTISR_BLK_NAKINI (_U_(0x1) << DEVEPTISR_BLK_NAKINI_Pos) /**< (DEVEPTISR) NAKed IN Interrupt Mask */
+#define DEVEPTISR_BLK_STALLEDI_Pos 6 /**< (DEVEPTISR) STALLed Interrupt Position */
+#define DEVEPTISR_BLK_STALLEDI (_U_(0x1) << DEVEPTISR_BLK_STALLEDI_Pos) /**< (DEVEPTISR) STALLed Interrupt Mask */
+#define DEVEPTISR_BLK_CTRLDIR_Pos 17 /**< (DEVEPTISR) Control Direction Position */
+#define DEVEPTISR_BLK_CTRLDIR (_U_(0x1) << DEVEPTISR_BLK_CTRLDIR_Pos) /**< (DEVEPTISR) Control Direction Mask */
+#define DEVEPTISR_BLK_Msk _U_(0x2005C) /**< (DEVEPTISR_BLK) Register Mask */
+
+/* INTRPT mode */
+#define DEVEPTISR_INTRPT_RXSTPI_Pos 2 /**< (DEVEPTISR) Received SETUP Interrupt Position */
+#define DEVEPTISR_INTRPT_RXSTPI (_U_(0x1) << DEVEPTISR_INTRPT_RXSTPI_Pos) /**< (DEVEPTISR) Received SETUP Interrupt Mask */
+#define DEVEPTISR_INTRPT_NAKOUTI_Pos 3 /**< (DEVEPTISR) NAKed OUT Interrupt Position */
+#define DEVEPTISR_INTRPT_NAKOUTI (_U_(0x1) << DEVEPTISR_INTRPT_NAKOUTI_Pos) /**< (DEVEPTISR) NAKed OUT Interrupt Mask */
+#define DEVEPTISR_INTRPT_NAKINI_Pos 4 /**< (DEVEPTISR) NAKed IN Interrupt Position */
+#define DEVEPTISR_INTRPT_NAKINI (_U_(0x1) << DEVEPTISR_INTRPT_NAKINI_Pos) /**< (DEVEPTISR) NAKed IN Interrupt Mask */
+#define DEVEPTISR_INTRPT_STALLEDI_Pos 6 /**< (DEVEPTISR) STALLed Interrupt Position */
+#define DEVEPTISR_INTRPT_STALLEDI (_U_(0x1) << DEVEPTISR_INTRPT_STALLEDI_Pos) /**< (DEVEPTISR) STALLed Interrupt Mask */
+#define DEVEPTISR_INTRPT_CTRLDIR_Pos 17 /**< (DEVEPTISR) Control Direction Position */
+#define DEVEPTISR_INTRPT_CTRLDIR (_U_(0x1) << DEVEPTISR_INTRPT_CTRLDIR_Pos) /**< (DEVEPTISR) Control Direction Mask */
+#define DEVEPTISR_INTRPT_Msk _U_(0x2005C) /**< (DEVEPTISR_INTRPT) Register Mask */
+
+
+/* -------- DEVEPTICR : (USBHS Offset: 0x160) (/W 32) Device Endpoint Interrupt Clear Register -------- */
+
+#define DEVEPTICR_OFFSET (0x160) /**< (DEVEPTICR) Device Endpoint Interrupt Clear Register Offset */
+
+#define DEVEPTICR_TXINIC_Pos 0 /**< (DEVEPTICR) Transmitted IN Data Interrupt Clear Position */
+#define DEVEPTICR_TXINIC (_U_(0x1) << DEVEPTICR_TXINIC_Pos) /**< (DEVEPTICR) Transmitted IN Data Interrupt Clear Mask */
+#define DEVEPTICR_RXOUTIC_Pos 1 /**< (DEVEPTICR) Received OUT Data Interrupt Clear Position */
+#define DEVEPTICR_RXOUTIC (_U_(0x1) << DEVEPTICR_RXOUTIC_Pos) /**< (DEVEPTICR) Received OUT Data Interrupt Clear Mask */
+#define DEVEPTICR_OVERFIC_Pos 5 /**< (DEVEPTICR) Overflow Interrupt Clear Position */
+#define DEVEPTICR_OVERFIC (_U_(0x1) << DEVEPTICR_OVERFIC_Pos) /**< (DEVEPTICR) Overflow Interrupt Clear Mask */
+#define DEVEPTICR_SHORTPACKETC_Pos 7 /**< (DEVEPTICR) Short Packet Interrupt Clear Position */
+#define DEVEPTICR_SHORTPACKETC (_U_(0x1) << DEVEPTICR_SHORTPACKETC_Pos) /**< (DEVEPTICR) Short Packet Interrupt Clear Mask */
+#define DEVEPTICR_Msk _U_(0xA3) /**< (DEVEPTICR) Register Mask */
+
+/* CTRL mode */
+#define DEVEPTICR_CTRL_RXSTPIC_Pos 2 /**< (DEVEPTICR) Received SETUP Interrupt Clear Position */
+#define DEVEPTICR_CTRL_RXSTPIC (_U_(0x1) << DEVEPTICR_CTRL_RXSTPIC_Pos) /**< (DEVEPTICR) Received SETUP Interrupt Clear Mask */
+#define DEVEPTICR_CTRL_NAKOUTIC_Pos 3 /**< (DEVEPTICR) NAKed OUT Interrupt Clear Position */
+#define DEVEPTICR_CTRL_NAKOUTIC (_U_(0x1) << DEVEPTICR_CTRL_NAKOUTIC_Pos) /**< (DEVEPTICR) NAKed OUT Interrupt Clear Mask */
+#define DEVEPTICR_CTRL_NAKINIC_Pos 4 /**< (DEVEPTICR) NAKed IN Interrupt Clear Position */
+#define DEVEPTICR_CTRL_NAKINIC (_U_(0x1) << DEVEPTICR_CTRL_NAKINIC_Pos) /**< (DEVEPTICR) NAKed IN Interrupt Clear Mask */
+#define DEVEPTICR_CTRL_STALLEDIC_Pos 6 /**< (DEVEPTICR) STALLed Interrupt Clear Position */
+#define DEVEPTICR_CTRL_STALLEDIC (_U_(0x1) << DEVEPTICR_CTRL_STALLEDIC_Pos) /**< (DEVEPTICR) STALLed Interrupt Clear Mask */
+#define DEVEPTICR_CTRL_Msk _U_(0x5C) /**< (DEVEPTICR_CTRL) Register Mask */
+
+/* ISO mode */
+#define DEVEPTICR_ISO_UNDERFIC_Pos 2 /**< (DEVEPTICR) Underflow Interrupt Clear Position */
+#define DEVEPTICR_ISO_UNDERFIC (_U_(0x1) << DEVEPTICR_ISO_UNDERFIC_Pos) /**< (DEVEPTICR) Underflow Interrupt Clear Mask */
+#define DEVEPTICR_ISO_HBISOINERRIC_Pos 3 /**< (DEVEPTICR) High Bandwidth Isochronous IN Underflow Error Interrupt Clear Position */
+#define DEVEPTICR_ISO_HBISOINERRIC (_U_(0x1) << DEVEPTICR_ISO_HBISOINERRIC_Pos) /**< (DEVEPTICR) High Bandwidth Isochronous IN Underflow Error Interrupt Clear Mask */
+#define DEVEPTICR_ISO_HBISOFLUSHIC_Pos 4 /**< (DEVEPTICR) High Bandwidth Isochronous IN Flush Interrupt Clear Position */
+#define DEVEPTICR_ISO_HBISOFLUSHIC (_U_(0x1) << DEVEPTICR_ISO_HBISOFLUSHIC_Pos) /**< (DEVEPTICR) High Bandwidth Isochronous IN Flush Interrupt Clear Mask */
+#define DEVEPTICR_ISO_CRCERRIC_Pos 6 /**< (DEVEPTICR) CRC Error Interrupt Clear Position */
+#define DEVEPTICR_ISO_CRCERRIC (_U_(0x1) << DEVEPTICR_ISO_CRCERRIC_Pos) /**< (DEVEPTICR) CRC Error Interrupt Clear Mask */
+#define DEVEPTICR_ISO_Msk _U_(0x5C) /**< (DEVEPTICR_ISO) Register Mask */
+
+/* BLK mode */
+#define DEVEPTICR_BLK_RXSTPIC_Pos 2 /**< (DEVEPTICR) Received SETUP Interrupt Clear Position */
+#define DEVEPTICR_BLK_RXSTPIC (_U_(0x1) << DEVEPTICR_BLK_RXSTPIC_Pos) /**< (DEVEPTICR) Received SETUP Interrupt Clear Mask */
+#define DEVEPTICR_BLK_NAKOUTIC_Pos 3 /**< (DEVEPTICR) NAKed OUT Interrupt Clear Position */
+#define DEVEPTICR_BLK_NAKOUTIC (_U_(0x1) << DEVEPTICR_BLK_NAKOUTIC_Pos) /**< (DEVEPTICR) NAKed OUT Interrupt Clear Mask */
+#define DEVEPTICR_BLK_NAKINIC_Pos 4 /**< (DEVEPTICR) NAKed IN Interrupt Clear Position */
+#define DEVEPTICR_BLK_NAKINIC (_U_(0x1) << DEVEPTICR_BLK_NAKINIC_Pos) /**< (DEVEPTICR) NAKed IN Interrupt Clear Mask */
+#define DEVEPTICR_BLK_STALLEDIC_Pos 6 /**< (DEVEPTICR) STALLed Interrupt Clear Position */
+#define DEVEPTICR_BLK_STALLEDIC (_U_(0x1) << DEVEPTICR_BLK_STALLEDIC_Pos) /**< (DEVEPTICR) STALLed Interrupt Clear Mask */
+#define DEVEPTICR_BLK_Msk _U_(0x5C) /**< (DEVEPTICR_BLK) Register Mask */
+
+/* INTRPT mode */
+#define DEVEPTICR_INTRPT_RXSTPIC_Pos 2 /**< (DEVEPTICR) Received SETUP Interrupt Clear Position */
+#define DEVEPTICR_INTRPT_RXSTPIC (_U_(0x1) << DEVEPTICR_INTRPT_RXSTPIC_Pos) /**< (DEVEPTICR) Received SETUP Interrupt Clear Mask */
+#define DEVEPTICR_INTRPT_NAKOUTIC_Pos 3 /**< (DEVEPTICR) NAKed OUT Interrupt Clear Position */
+#define DEVEPTICR_INTRPT_NAKOUTIC (_U_(0x1) << DEVEPTICR_INTRPT_NAKOUTIC_Pos) /**< (DEVEPTICR) NAKed OUT Interrupt Clear Mask */
+#define DEVEPTICR_INTRPT_NAKINIC_Pos 4 /**< (DEVEPTICR) NAKed IN Interrupt Clear Position */
+#define DEVEPTICR_INTRPT_NAKINIC (_U_(0x1) << DEVEPTICR_INTRPT_NAKINIC_Pos) /**< (DEVEPTICR) NAKed IN Interrupt Clear Mask */
+#define DEVEPTICR_INTRPT_STALLEDIC_Pos 6 /**< (DEVEPTICR) STALLed Interrupt Clear Position */
+#define DEVEPTICR_INTRPT_STALLEDIC (_U_(0x1) << DEVEPTICR_INTRPT_STALLEDIC_Pos) /**< (DEVEPTICR) STALLed Interrupt Clear Mask */
+#define DEVEPTICR_INTRPT_Msk _U_(0x5C) /**< (DEVEPTICR_INTRPT) Register Mask */
+
+
+/* -------- DEVEPTIFR : (USBHS Offset: 0x190) (/W 32) Device Endpoint Interrupt Set Register -------- */
+
+#define DEVEPTIFR_OFFSET (0x190) /**< (DEVEPTIFR) Device Endpoint Interrupt Set Register Offset */
+
+#define DEVEPTIFR_TXINIS_Pos 0 /**< (DEVEPTIFR) Transmitted IN Data Interrupt Set Position */
+#define DEVEPTIFR_TXINIS (_U_(0x1) << DEVEPTIFR_TXINIS_Pos) /**< (DEVEPTIFR) Transmitted IN Data Interrupt Set Mask */
+#define DEVEPTIFR_RXOUTIS_Pos 1 /**< (DEVEPTIFR) Received OUT Data Interrupt Set Position */
+#define DEVEPTIFR_RXOUTIS (_U_(0x1) << DEVEPTIFR_RXOUTIS_Pos) /**< (DEVEPTIFR) Received OUT Data Interrupt Set Mask */
+#define DEVEPTIFR_OVERFIS_Pos 5 /**< (DEVEPTIFR) Overflow Interrupt Set Position */
+#define DEVEPTIFR_OVERFIS (_U_(0x1) << DEVEPTIFR_OVERFIS_Pos) /**< (DEVEPTIFR) Overflow Interrupt Set Mask */
+#define DEVEPTIFR_SHORTPACKETS_Pos 7 /**< (DEVEPTIFR) Short Packet Interrupt Set Position */
+#define DEVEPTIFR_SHORTPACKETS (_U_(0x1) << DEVEPTIFR_SHORTPACKETS_Pos) /**< (DEVEPTIFR) Short Packet Interrupt Set Mask */
+#define DEVEPTIFR_NBUSYBKS_Pos 12 /**< (DEVEPTIFR) Number of Busy Banks Interrupt Set Position */
+#define DEVEPTIFR_NBUSYBKS (_U_(0x1) << DEVEPTIFR_NBUSYBKS_Pos) /**< (DEVEPTIFR) Number of Busy Banks Interrupt Set Mask */
+#define DEVEPTIFR_Msk _U_(0x10A3) /**< (DEVEPTIFR) Register Mask */
+
+/* CTRL mode */
+#define DEVEPTIFR_CTRL_RXSTPIS_Pos 2 /**< (DEVEPTIFR) Received SETUP Interrupt Set Position */
+#define DEVEPTIFR_CTRL_RXSTPIS (_U_(0x1) << DEVEPTIFR_CTRL_RXSTPIS_Pos) /**< (DEVEPTIFR) Received SETUP Interrupt Set Mask */
+#define DEVEPTIFR_CTRL_NAKOUTIS_Pos 3 /**< (DEVEPTIFR) NAKed OUT Interrupt Set Position */
+#define DEVEPTIFR_CTRL_NAKOUTIS (_U_(0x1) << DEVEPTIFR_CTRL_NAKOUTIS_Pos) /**< (DEVEPTIFR) NAKed OUT Interrupt Set Mask */
+#define DEVEPTIFR_CTRL_NAKINIS_Pos 4 /**< (DEVEPTIFR) NAKed IN Interrupt Set Position */
+#define DEVEPTIFR_CTRL_NAKINIS (_U_(0x1) << DEVEPTIFR_CTRL_NAKINIS_Pos) /**< (DEVEPTIFR) NAKed IN Interrupt Set Mask */
+#define DEVEPTIFR_CTRL_STALLEDIS_Pos 6 /**< (DEVEPTIFR) STALLed Interrupt Set Position */
+#define DEVEPTIFR_CTRL_STALLEDIS (_U_(0x1) << DEVEPTIFR_CTRL_STALLEDIS_Pos) /**< (DEVEPTIFR) STALLed Interrupt Set Mask */
+#define DEVEPTIFR_CTRL_Msk _U_(0x5C) /**< (DEVEPTIFR_CTRL) Register Mask */
+
+/* ISO mode */
+#define DEVEPTIFR_ISO_UNDERFIS_Pos 2 /**< (DEVEPTIFR) Underflow Interrupt Set Position */
+#define DEVEPTIFR_ISO_UNDERFIS (_U_(0x1) << DEVEPTIFR_ISO_UNDERFIS_Pos) /**< (DEVEPTIFR) Underflow Interrupt Set Mask */
+#define DEVEPTIFR_ISO_HBISOINERRIS_Pos 3 /**< (DEVEPTIFR) High Bandwidth Isochronous IN Underflow Error Interrupt Set Position */
+#define DEVEPTIFR_ISO_HBISOINERRIS (_U_(0x1) << DEVEPTIFR_ISO_HBISOINERRIS_Pos) /**< (DEVEPTIFR) High Bandwidth Isochronous IN Underflow Error Interrupt Set Mask */
+#define DEVEPTIFR_ISO_HBISOFLUSHIS_Pos 4 /**< (DEVEPTIFR) High Bandwidth Isochronous IN Flush Interrupt Set Position */
+#define DEVEPTIFR_ISO_HBISOFLUSHIS (_U_(0x1) << DEVEPTIFR_ISO_HBISOFLUSHIS_Pos) /**< (DEVEPTIFR) High Bandwidth Isochronous IN Flush Interrupt Set Mask */
+#define DEVEPTIFR_ISO_CRCERRIS_Pos 6 /**< (DEVEPTIFR) CRC Error Interrupt Set Position */
+#define DEVEPTIFR_ISO_CRCERRIS (_U_(0x1) << DEVEPTIFR_ISO_CRCERRIS_Pos) /**< (DEVEPTIFR) CRC Error Interrupt Set Mask */
+#define DEVEPTIFR_ISO_Msk _U_(0x5C) /**< (DEVEPTIFR_ISO) Register Mask */
+
+/* BLK mode */
+#define DEVEPTIFR_BLK_RXSTPIS_Pos 2 /**< (DEVEPTIFR) Received SETUP Interrupt Set Position */
+#define DEVEPTIFR_BLK_RXSTPIS (_U_(0x1) << DEVEPTIFR_BLK_RXSTPIS_Pos) /**< (DEVEPTIFR) Received SETUP Interrupt Set Mask */
+#define DEVEPTIFR_BLK_NAKOUTIS_Pos 3 /**< (DEVEPTIFR) NAKed OUT Interrupt Set Position */
+#define DEVEPTIFR_BLK_NAKOUTIS (_U_(0x1) << DEVEPTIFR_BLK_NAKOUTIS_Pos) /**< (DEVEPTIFR) NAKed OUT Interrupt Set Mask */
+#define DEVEPTIFR_BLK_NAKINIS_Pos 4 /**< (DEVEPTIFR) NAKed IN Interrupt Set Position */
+#define DEVEPTIFR_BLK_NAKINIS (_U_(0x1) << DEVEPTIFR_BLK_NAKINIS_Pos) /**< (DEVEPTIFR) NAKed IN Interrupt Set Mask */
+#define DEVEPTIFR_BLK_STALLEDIS_Pos 6 /**< (DEVEPTIFR) STALLed Interrupt Set Position */
+#define DEVEPTIFR_BLK_STALLEDIS (_U_(0x1) << DEVEPTIFR_BLK_STALLEDIS_Pos) /**< (DEVEPTIFR) STALLed Interrupt Set Mask */
+#define DEVEPTIFR_BLK_Msk _U_(0x5C) /**< (DEVEPTIFR_BLK) Register Mask */
+
+/* INTRPT mode */
+#define DEVEPTIFR_INTRPT_RXSTPIS_Pos 2 /**< (DEVEPTIFR) Received SETUP Interrupt Set Position */
+#define DEVEPTIFR_INTRPT_RXSTPIS (_U_(0x1) << DEVEPTIFR_INTRPT_RXSTPIS_Pos) /**< (DEVEPTIFR) Received SETUP Interrupt Set Mask */
+#define DEVEPTIFR_INTRPT_NAKOUTIS_Pos 3 /**< (DEVEPTIFR) NAKed OUT Interrupt Set Position */
+#define DEVEPTIFR_INTRPT_NAKOUTIS (_U_(0x1) << DEVEPTIFR_INTRPT_NAKOUTIS_Pos) /**< (DEVEPTIFR) NAKed OUT Interrupt Set Mask */
+#define DEVEPTIFR_INTRPT_NAKINIS_Pos 4 /**< (DEVEPTIFR) NAKed IN Interrupt Set Position */
+#define DEVEPTIFR_INTRPT_NAKINIS (_U_(0x1) << DEVEPTIFR_INTRPT_NAKINIS_Pos) /**< (DEVEPTIFR) NAKed IN Interrupt Set Mask */
+#define DEVEPTIFR_INTRPT_STALLEDIS_Pos 6 /**< (DEVEPTIFR) STALLed Interrupt Set Position */
+#define DEVEPTIFR_INTRPT_STALLEDIS (_U_(0x1) << DEVEPTIFR_INTRPT_STALLEDIS_Pos) /**< (DEVEPTIFR) STALLed Interrupt Set Mask */
+#define DEVEPTIFR_INTRPT_Msk _U_(0x5C) /**< (DEVEPTIFR_INTRPT) Register Mask */
+
+
+/* -------- DEVEPTIMR : (USBHS Offset: 0x1c0) (R/ 32) Device Endpoint Interrupt Mask Register -------- */
+
+#define DEVEPTIMR_OFFSET (0x1C0) /**< (DEVEPTIMR) Device Endpoint Interrupt Mask Register Offset */
+
+#define DEVEPTIMR_TXINE_Pos 0 /**< (DEVEPTIMR) Transmitted IN Data Interrupt Position */
+#define DEVEPTIMR_TXINE (_U_(0x1) << DEVEPTIMR_TXINE_Pos) /**< (DEVEPTIMR) Transmitted IN Data Interrupt Mask */
+#define DEVEPTIMR_RXOUTE_Pos 1 /**< (DEVEPTIMR) Received OUT Data Interrupt Position */
+#define DEVEPTIMR_RXOUTE (_U_(0x1) << DEVEPTIMR_RXOUTE_Pos) /**< (DEVEPTIMR) Received OUT Data Interrupt Mask */
+#define DEVEPTIMR_OVERFE_Pos 5 /**< (DEVEPTIMR) Overflow Interrupt Position */
+#define DEVEPTIMR_OVERFE (_U_(0x1) << DEVEPTIMR_OVERFE_Pos) /**< (DEVEPTIMR) Overflow Interrupt Mask */
+#define DEVEPTIMR_SHORTPACKETE_Pos 7 /**< (DEVEPTIMR) Short Packet Interrupt Position */
+#define DEVEPTIMR_SHORTPACKETE (_U_(0x1) << DEVEPTIMR_SHORTPACKETE_Pos) /**< (DEVEPTIMR) Short Packet Interrupt Mask */
+#define DEVEPTIMR_NBUSYBKE_Pos 12 /**< (DEVEPTIMR) Number of Busy Banks Interrupt Position */
+#define DEVEPTIMR_NBUSYBKE (_U_(0x1) << DEVEPTIMR_NBUSYBKE_Pos) /**< (DEVEPTIMR) Number of Busy Banks Interrupt Mask */
+#define DEVEPTIMR_KILLBK_Pos 13 /**< (DEVEPTIMR) Kill IN Bank Position */
+#define DEVEPTIMR_KILLBK (_U_(0x1) << DEVEPTIMR_KILLBK_Pos) /**< (DEVEPTIMR) Kill IN Bank Mask */
+#define DEVEPTIMR_FIFOCON_Pos 14 /**< (DEVEPTIMR) FIFO Control Position */
+#define DEVEPTIMR_FIFOCON (_U_(0x1) << DEVEPTIMR_FIFOCON_Pos) /**< (DEVEPTIMR) FIFO Control Mask */
+#define DEVEPTIMR_EPDISHDMA_Pos 16 /**< (DEVEPTIMR) Endpoint Interrupts Disable HDMA Request Position */
+#define DEVEPTIMR_EPDISHDMA (_U_(0x1) << DEVEPTIMR_EPDISHDMA_Pos) /**< (DEVEPTIMR) Endpoint Interrupts Disable HDMA Request Mask */
+#define DEVEPTIMR_RSTDT_Pos 18 /**< (DEVEPTIMR) Reset Data Toggle Position */
+#define DEVEPTIMR_RSTDT (_U_(0x1) << DEVEPTIMR_RSTDT_Pos) /**< (DEVEPTIMR) Reset Data Toggle Mask */
+#define DEVEPTIMR_Msk _U_(0x570A3) /**< (DEVEPTIMR) Register Mask */
+
+/* CTRL mode */
+#define DEVEPTIMR_CTRL_RXSTPE_Pos 2 /**< (DEVEPTIMR) Received SETUP Interrupt Position */
+#define DEVEPTIMR_CTRL_RXSTPE (_U_(0x1) << DEVEPTIMR_CTRL_RXSTPE_Pos) /**< (DEVEPTIMR) Received SETUP Interrupt Mask */
+#define DEVEPTIMR_CTRL_NAKOUTE_Pos 3 /**< (DEVEPTIMR) NAKed OUT Interrupt Position */
+#define DEVEPTIMR_CTRL_NAKOUTE (_U_(0x1) << DEVEPTIMR_CTRL_NAKOUTE_Pos) /**< (DEVEPTIMR) NAKed OUT Interrupt Mask */
+#define DEVEPTIMR_CTRL_NAKINE_Pos 4 /**< (DEVEPTIMR) NAKed IN Interrupt Position */
+#define DEVEPTIMR_CTRL_NAKINE (_U_(0x1) << DEVEPTIMR_CTRL_NAKINE_Pos) /**< (DEVEPTIMR) NAKed IN Interrupt Mask */
+#define DEVEPTIMR_CTRL_STALLEDE_Pos 6 /**< (DEVEPTIMR) STALLed Interrupt Position */
+#define DEVEPTIMR_CTRL_STALLEDE (_U_(0x1) << DEVEPTIMR_CTRL_STALLEDE_Pos) /**< (DEVEPTIMR) STALLed Interrupt Mask */
+#define DEVEPTIMR_CTRL_NYETDIS_Pos 17 /**< (DEVEPTIMR) NYET Token Disable Position */
+#define DEVEPTIMR_CTRL_NYETDIS (_U_(0x1) << DEVEPTIMR_CTRL_NYETDIS_Pos) /**< (DEVEPTIMR) NYET Token Disable Mask */
+#define DEVEPTIMR_CTRL_STALLRQ_Pos 19 /**< (DEVEPTIMR) STALL Request Position */
+#define DEVEPTIMR_CTRL_STALLRQ (_U_(0x1) << DEVEPTIMR_CTRL_STALLRQ_Pos) /**< (DEVEPTIMR) STALL Request Mask */
+#define DEVEPTIMR_CTRL_Msk _U_(0xA005C) /**< (DEVEPTIMR_CTRL) Register Mask */
+
+/* ISO mode */
+#define DEVEPTIMR_ISO_UNDERFE_Pos 2 /**< (DEVEPTIMR) Underflow Interrupt Position */
+#define DEVEPTIMR_ISO_UNDERFE (_U_(0x1) << DEVEPTIMR_ISO_UNDERFE_Pos) /**< (DEVEPTIMR) Underflow Interrupt Mask */
+#define DEVEPTIMR_ISO_HBISOINERRE_Pos 3 /**< (DEVEPTIMR) High Bandwidth Isochronous IN Underflow Error Interrupt Position */
+#define DEVEPTIMR_ISO_HBISOINERRE (_U_(0x1) << DEVEPTIMR_ISO_HBISOINERRE_Pos) /**< (DEVEPTIMR) High Bandwidth Isochronous IN Underflow Error Interrupt Mask */
+#define DEVEPTIMR_ISO_HBISOFLUSHE_Pos 4 /**< (DEVEPTIMR) High Bandwidth Isochronous IN Flush Interrupt Position */
+#define DEVEPTIMR_ISO_HBISOFLUSHE (_U_(0x1) << DEVEPTIMR_ISO_HBISOFLUSHE_Pos) /**< (DEVEPTIMR) High Bandwidth Isochronous IN Flush Interrupt Mask */
+#define DEVEPTIMR_ISO_CRCERRE_Pos 6 /**< (DEVEPTIMR) CRC Error Interrupt Position */
+#define DEVEPTIMR_ISO_CRCERRE (_U_(0x1) << DEVEPTIMR_ISO_CRCERRE_Pos) /**< (DEVEPTIMR) CRC Error Interrupt Mask */
+#define DEVEPTIMR_ISO_MDATAE_Pos 8 /**< (DEVEPTIMR) MData Interrupt Position */
+#define DEVEPTIMR_ISO_MDATAE (_U_(0x1) << DEVEPTIMR_ISO_MDATAE_Pos) /**< (DEVEPTIMR) MData Interrupt Mask */
+#define DEVEPTIMR_ISO_DATAXE_Pos 9 /**< (DEVEPTIMR) DataX Interrupt Position */
+#define DEVEPTIMR_ISO_DATAXE (_U_(0x1) << DEVEPTIMR_ISO_DATAXE_Pos) /**< (DEVEPTIMR) DataX Interrupt Mask */
+#define DEVEPTIMR_ISO_ERRORTRANSE_Pos 10 /**< (DEVEPTIMR) Transaction Error Interrupt Position */
+#define DEVEPTIMR_ISO_ERRORTRANSE (_U_(0x1) << DEVEPTIMR_ISO_ERRORTRANSE_Pos) /**< (DEVEPTIMR) Transaction Error Interrupt Mask */
+#define DEVEPTIMR_ISO_Msk _U_(0x75C) /**< (DEVEPTIMR_ISO) Register Mask */
+
+/* BLK mode */
+#define DEVEPTIMR_BLK_RXSTPE_Pos 2 /**< (DEVEPTIMR) Received SETUP Interrupt Position */
+#define DEVEPTIMR_BLK_RXSTPE (_U_(0x1) << DEVEPTIMR_BLK_RXSTPE_Pos) /**< (DEVEPTIMR) Received SETUP Interrupt Mask */
+#define DEVEPTIMR_BLK_NAKOUTE_Pos 3 /**< (DEVEPTIMR) NAKed OUT Interrupt Position */
+#define DEVEPTIMR_BLK_NAKOUTE (_U_(0x1) << DEVEPTIMR_BLK_NAKOUTE_Pos) /**< (DEVEPTIMR) NAKed OUT Interrupt Mask */
+#define DEVEPTIMR_BLK_NAKINE_Pos 4 /**< (DEVEPTIMR) NAKed IN Interrupt Position */
+#define DEVEPTIMR_BLK_NAKINE (_U_(0x1) << DEVEPTIMR_BLK_NAKINE_Pos) /**< (DEVEPTIMR) NAKed IN Interrupt Mask */
+#define DEVEPTIMR_BLK_STALLEDE_Pos 6 /**< (DEVEPTIMR) STALLed Interrupt Position */
+#define DEVEPTIMR_BLK_STALLEDE (_U_(0x1) << DEVEPTIMR_BLK_STALLEDE_Pos) /**< (DEVEPTIMR) STALLed Interrupt Mask */
+#define DEVEPTIMR_BLK_NYETDIS_Pos 17 /**< (DEVEPTIMR) NYET Token Disable Position */
+#define DEVEPTIMR_BLK_NYETDIS (_U_(0x1) << DEVEPTIMR_BLK_NYETDIS_Pos) /**< (DEVEPTIMR) NYET Token Disable Mask */
+#define DEVEPTIMR_BLK_STALLRQ_Pos 19 /**< (DEVEPTIMR) STALL Request Position */
+#define DEVEPTIMR_BLK_STALLRQ (_U_(0x1) << DEVEPTIMR_BLK_STALLRQ_Pos) /**< (DEVEPTIMR) STALL Request Mask */
+#define DEVEPTIMR_BLK_Msk _U_(0xA005C) /**< (DEVEPTIMR_BLK) Register Mask */
+
+/* INTRPT mode */
+#define DEVEPTIMR_INTRPT_RXSTPE_Pos 2 /**< (DEVEPTIMR) Received SETUP Interrupt Position */
+#define DEVEPTIMR_INTRPT_RXSTPE (_U_(0x1) << DEVEPTIMR_INTRPT_RXSTPE_Pos) /**< (DEVEPTIMR) Received SETUP Interrupt Mask */
+#define DEVEPTIMR_INTRPT_NAKOUTE_Pos 3 /**< (DEVEPTIMR) NAKed OUT Interrupt Position */
+#define DEVEPTIMR_INTRPT_NAKOUTE (_U_(0x1) << DEVEPTIMR_INTRPT_NAKOUTE_Pos) /**< (DEVEPTIMR) NAKed OUT Interrupt Mask */
+#define DEVEPTIMR_INTRPT_NAKINE_Pos 4 /**< (DEVEPTIMR) NAKed IN Interrupt Position */
+#define DEVEPTIMR_INTRPT_NAKINE (_U_(0x1) << DEVEPTIMR_INTRPT_NAKINE_Pos) /**< (DEVEPTIMR) NAKed IN Interrupt Mask */
+#define DEVEPTIMR_INTRPT_STALLEDE_Pos 6 /**< (DEVEPTIMR) STALLed Interrupt Position */
+#define DEVEPTIMR_INTRPT_STALLEDE (_U_(0x1) << DEVEPTIMR_INTRPT_STALLEDE_Pos) /**< (DEVEPTIMR) STALLed Interrupt Mask */
+#define DEVEPTIMR_INTRPT_NYETDIS_Pos 17 /**< (DEVEPTIMR) NYET Token Disable Position */
+#define DEVEPTIMR_INTRPT_NYETDIS (_U_(0x1) << DEVEPTIMR_INTRPT_NYETDIS_Pos) /**< (DEVEPTIMR) NYET Token Disable Mask */
+#define DEVEPTIMR_INTRPT_STALLRQ_Pos 19 /**< (DEVEPTIMR) STALL Request Position */
+#define DEVEPTIMR_INTRPT_STALLRQ (_U_(0x1) << DEVEPTIMR_INTRPT_STALLRQ_Pos) /**< (DEVEPTIMR) STALL Request Mask */
+#define DEVEPTIMR_INTRPT_Msk _U_(0xA005C) /**< (DEVEPTIMR_INTRPT) Register Mask */
+
+
+/* -------- DEVEPTIER : (USBHS Offset: 0x1f0) (/W 32) Device Endpoint Interrupt Enable Register -------- */
+
+#define DEVEPTIER_OFFSET (0x1F0) /**< (DEVEPTIER) Device Endpoint Interrupt Enable Register Offset */
+
+#define DEVEPTIER_TXINES_Pos 0 /**< (DEVEPTIER) Transmitted IN Data Interrupt Enable Position */
+#define DEVEPTIER_TXINES (_U_(0x1) << DEVEPTIER_TXINES_Pos) /**< (DEVEPTIER) Transmitted IN Data Interrupt Enable Mask */
+#define DEVEPTIER_RXOUTES_Pos 1 /**< (DEVEPTIER) Received OUT Data Interrupt Enable Position */
+#define DEVEPTIER_RXOUTES (_U_(0x1) << DEVEPTIER_RXOUTES_Pos) /**< (DEVEPTIER) Received OUT Data Interrupt Enable Mask */
+#define DEVEPTIER_OVERFES_Pos 5 /**< (DEVEPTIER) Overflow Interrupt Enable Position */
+#define DEVEPTIER_OVERFES (_U_(0x1) << DEVEPTIER_OVERFES_Pos) /**< (DEVEPTIER) Overflow Interrupt Enable Mask */
+#define DEVEPTIER_SHORTPACKETES_Pos 7 /**< (DEVEPTIER) Short Packet Interrupt Enable Position */
+#define DEVEPTIER_SHORTPACKETES (_U_(0x1) << DEVEPTIER_SHORTPACKETES_Pos) /**< (DEVEPTIER) Short Packet Interrupt Enable Mask */
+#define DEVEPTIER_NBUSYBKES_Pos 12 /**< (DEVEPTIER) Number of Busy Banks Interrupt Enable Position */
+#define DEVEPTIER_NBUSYBKES (_U_(0x1) << DEVEPTIER_NBUSYBKES_Pos) /**< (DEVEPTIER) Number of Busy Banks Interrupt Enable Mask */
+#define DEVEPTIER_KILLBKS_Pos 13 /**< (DEVEPTIER) Kill IN Bank Position */
+#define DEVEPTIER_KILLBKS (_U_(0x1) << DEVEPTIER_KILLBKS_Pos) /**< (DEVEPTIER) Kill IN Bank Mask */
+#define DEVEPTIER_FIFOCONS_Pos 14 /**< (DEVEPTIER) FIFO Control Position */
+#define DEVEPTIER_FIFOCONS (_U_(0x1) << DEVEPTIER_FIFOCONS_Pos) /**< (DEVEPTIER) FIFO Control Mask */
+#define DEVEPTIER_EPDISHDMAS_Pos 16 /**< (DEVEPTIER) Endpoint Interrupts Disable HDMA Request Enable Position */
+#define DEVEPTIER_EPDISHDMAS (_U_(0x1) << DEVEPTIER_EPDISHDMAS_Pos) /**< (DEVEPTIER) Endpoint Interrupts Disable HDMA Request Enable Mask */
+#define DEVEPTIER_RSTDTS_Pos 18 /**< (DEVEPTIER) Reset Data Toggle Enable Position */
+#define DEVEPTIER_RSTDTS (_U_(0x1) << DEVEPTIER_RSTDTS_Pos) /**< (DEVEPTIER) Reset Data Toggle Enable Mask */
+#define DEVEPTIER_Msk _U_(0x570A3) /**< (DEVEPTIER) Register Mask */
+
+/* CTRL mode */
+#define DEVEPTIER_CTRL_RXSTPES_Pos 2 /**< (DEVEPTIER) Received SETUP Interrupt Enable Position */
+#define DEVEPTIER_CTRL_RXSTPES (_U_(0x1) << DEVEPTIER_CTRL_RXSTPES_Pos) /**< (DEVEPTIER) Received SETUP Interrupt Enable Mask */
+#define DEVEPTIER_CTRL_NAKOUTES_Pos 3 /**< (DEVEPTIER) NAKed OUT Interrupt Enable Position */
+#define DEVEPTIER_CTRL_NAKOUTES (_U_(0x1) << DEVEPTIER_CTRL_NAKOUTES_Pos) /**< (DEVEPTIER) NAKed OUT Interrupt Enable Mask */
+#define DEVEPTIER_CTRL_NAKINES_Pos 4 /**< (DEVEPTIER) NAKed IN Interrupt Enable Position */
+#define DEVEPTIER_CTRL_NAKINES (_U_(0x1) << DEVEPTIER_CTRL_NAKINES_Pos) /**< (DEVEPTIER) NAKed IN Interrupt Enable Mask */
+#define DEVEPTIER_CTRL_STALLEDES_Pos 6 /**< (DEVEPTIER) STALLed Interrupt Enable Position */
+#define DEVEPTIER_CTRL_STALLEDES (_U_(0x1) << DEVEPTIER_CTRL_STALLEDES_Pos) /**< (DEVEPTIER) STALLed Interrupt Enable Mask */
+#define DEVEPTIER_CTRL_NYETDISS_Pos 17 /**< (DEVEPTIER) NYET Token Disable Enable Position */
+#define DEVEPTIER_CTRL_NYETDISS (_U_(0x1) << DEVEPTIER_CTRL_NYETDISS_Pos) /**< (DEVEPTIER) NYET Token Disable Enable Mask */
+#define DEVEPTIER_CTRL_STALLRQS_Pos 19 /**< (DEVEPTIER) STALL Request Enable Position */
+#define DEVEPTIER_CTRL_STALLRQS (_U_(0x1) << DEVEPTIER_CTRL_STALLRQS_Pos) /**< (DEVEPTIER) STALL Request Enable Mask */
+#define DEVEPTIER_CTRL_Msk _U_(0xA005C) /**< (DEVEPTIER_CTRL) Register Mask */
+
+/* ISO mode */
+#define DEVEPTIER_ISO_UNDERFES_Pos 2 /**< (DEVEPTIER) Underflow Interrupt Enable Position */
+#define DEVEPTIER_ISO_UNDERFES (_U_(0x1) << DEVEPTIER_ISO_UNDERFES_Pos) /**< (DEVEPTIER) Underflow Interrupt Enable Mask */
+#define DEVEPTIER_ISO_HBISOINERRES_Pos 3 /**< (DEVEPTIER) High Bandwidth Isochronous IN Underflow Error Interrupt Enable Position */
+#define DEVEPTIER_ISO_HBISOINERRES (_U_(0x1) << DEVEPTIER_ISO_HBISOINERRES_Pos) /**< (DEVEPTIER) High Bandwidth Isochronous IN Underflow Error Interrupt Enable Mask */
+#define DEVEPTIER_ISO_HBISOFLUSHES_Pos 4 /**< (DEVEPTIER) High Bandwidth Isochronous IN Flush Interrupt Enable Position */
+#define DEVEPTIER_ISO_HBISOFLUSHES (_U_(0x1) << DEVEPTIER_ISO_HBISOFLUSHES_Pos) /**< (DEVEPTIER) High Bandwidth Isochronous IN Flush Interrupt Enable Mask */
+#define DEVEPTIER_ISO_CRCERRES_Pos 6 /**< (DEVEPTIER) CRC Error Interrupt Enable Position */
+#define DEVEPTIER_ISO_CRCERRES (_U_(0x1) << DEVEPTIER_ISO_CRCERRES_Pos) /**< (DEVEPTIER) CRC Error Interrupt Enable Mask */
+#define DEVEPTIER_ISO_MDATAES_Pos 8 /**< (DEVEPTIER) MData Interrupt Enable Position */
+#define DEVEPTIER_ISO_MDATAES (_U_(0x1) << DEVEPTIER_ISO_MDATAES_Pos) /**< (DEVEPTIER) MData Interrupt Enable Mask */
+#define DEVEPTIER_ISO_DATAXES_Pos 9 /**< (DEVEPTIER) DataX Interrupt Enable Position */
+#define DEVEPTIER_ISO_DATAXES (_U_(0x1) << DEVEPTIER_ISO_DATAXES_Pos) /**< (DEVEPTIER) DataX Interrupt Enable Mask */
+#define DEVEPTIER_ISO_ERRORTRANSES_Pos 10 /**< (DEVEPTIER) Transaction Error Interrupt Enable Position */
+#define DEVEPTIER_ISO_ERRORTRANSES (_U_(0x1) << DEVEPTIER_ISO_ERRORTRANSES_Pos) /**< (DEVEPTIER) Transaction Error Interrupt Enable Mask */
+#define DEVEPTIER_ISO_Msk _U_(0x75C) /**< (DEVEPTIER_ISO) Register Mask */
+
+/* BLK mode */
+#define DEVEPTIER_BLK_RXSTPES_Pos 2 /**< (DEVEPTIER) Received SETUP Interrupt Enable Position */
+#define DEVEPTIER_BLK_RXSTPES (_U_(0x1) << DEVEPTIER_BLK_RXSTPES_Pos) /**< (DEVEPTIER) Received SETUP Interrupt Enable Mask */
+#define DEVEPTIER_BLK_NAKOUTES_Pos 3 /**< (DEVEPTIER) NAKed OUT Interrupt Enable Position */
+#define DEVEPTIER_BLK_NAKOUTES (_U_(0x1) << DEVEPTIER_BLK_NAKOUTES_Pos) /**< (DEVEPTIER) NAKed OUT Interrupt Enable Mask */
+#define DEVEPTIER_BLK_NAKINES_Pos 4 /**< (DEVEPTIER) NAKed IN Interrupt Enable Position */
+#define DEVEPTIER_BLK_NAKINES (_U_(0x1) << DEVEPTIER_BLK_NAKINES_Pos) /**< (DEVEPTIER) NAKed IN Interrupt Enable Mask */
+#define DEVEPTIER_BLK_STALLEDES_Pos 6 /**< (DEVEPTIER) STALLed Interrupt Enable Position */
+#define DEVEPTIER_BLK_STALLEDES (_U_(0x1) << DEVEPTIER_BLK_STALLEDES_Pos) /**< (DEVEPTIER) STALLed Interrupt Enable Mask */
+#define DEVEPTIER_BLK_NYETDISS_Pos 17 /**< (DEVEPTIER) NYET Token Disable Enable Position */
+#define DEVEPTIER_BLK_NYETDISS (_U_(0x1) << DEVEPTIER_BLK_NYETDISS_Pos) /**< (DEVEPTIER) NYET Token Disable Enable Mask */
+#define DEVEPTIER_BLK_STALLRQS_Pos 19 /**< (DEVEPTIER) STALL Request Enable Position */
+#define DEVEPTIER_BLK_STALLRQS (_U_(0x1) << DEVEPTIER_BLK_STALLRQS_Pos) /**< (DEVEPTIER) STALL Request Enable Mask */
+#define DEVEPTIER_BLK_Msk _U_(0xA005C) /**< (DEVEPTIER_BLK) Register Mask */
+
+/* INTRPT mode */
+#define DEVEPTIER_INTRPT_RXSTPES_Pos 2 /**< (DEVEPTIER) Received SETUP Interrupt Enable Position */
+#define DEVEPTIER_INTRPT_RXSTPES (_U_(0x1) << DEVEPTIER_INTRPT_RXSTPES_Pos) /**< (DEVEPTIER) Received SETUP Interrupt Enable Mask */
+#define DEVEPTIER_INTRPT_NAKOUTES_Pos 3 /**< (DEVEPTIER) NAKed OUT Interrupt Enable Position */
+#define DEVEPTIER_INTRPT_NAKOUTES (_U_(0x1) << DEVEPTIER_INTRPT_NAKOUTES_Pos) /**< (DEVEPTIER) NAKed OUT Interrupt Enable Mask */
+#define DEVEPTIER_INTRPT_NAKINES_Pos 4 /**< (DEVEPTIER) NAKed IN Interrupt Enable Position */
+#define DEVEPTIER_INTRPT_NAKINES (_U_(0x1) << DEVEPTIER_INTRPT_NAKINES_Pos) /**< (DEVEPTIER) NAKed IN Interrupt Enable Mask */
+#define DEVEPTIER_INTRPT_STALLEDES_Pos 6 /**< (DEVEPTIER) STALLed Interrupt Enable Position */
+#define DEVEPTIER_INTRPT_STALLEDES (_U_(0x1) << DEVEPTIER_INTRPT_STALLEDES_Pos) /**< (DEVEPTIER) STALLed Interrupt Enable Mask */
+#define DEVEPTIER_INTRPT_NYETDISS_Pos 17 /**< (DEVEPTIER) NYET Token Disable Enable Position */
+#define DEVEPTIER_INTRPT_NYETDISS (_U_(0x1) << DEVEPTIER_INTRPT_NYETDISS_Pos) /**< (DEVEPTIER) NYET Token Disable Enable Mask */
+#define DEVEPTIER_INTRPT_STALLRQS_Pos 19 /**< (DEVEPTIER) STALL Request Enable Position */
+#define DEVEPTIER_INTRPT_STALLRQS (_U_(0x1) << DEVEPTIER_INTRPT_STALLRQS_Pos) /**< (DEVEPTIER) STALL Request Enable Mask */
+#define DEVEPTIER_INTRPT_Msk _U_(0xA005C) /**< (DEVEPTIER_INTRPT) Register Mask */
+
+
+/* -------- DEVEPTIDR : (USBHS Offset: 0x220) (/W 32) Device Endpoint Interrupt Disable Register -------- */
+
+#define DEVEPTIDR_OFFSET (0x220) /**< (DEVEPTIDR) Device Endpoint Interrupt Disable Register Offset */
+
+#define DEVEPTIDR_TXINEC_Pos 0 /**< (DEVEPTIDR) Transmitted IN Interrupt Clear Position */
+#define DEVEPTIDR_TXINEC (_U_(0x1) << DEVEPTIDR_TXINEC_Pos) /**< (DEVEPTIDR) Transmitted IN Interrupt Clear Mask */
+#define DEVEPTIDR_RXOUTEC_Pos 1 /**< (DEVEPTIDR) Received OUT Data Interrupt Clear Position */
+#define DEVEPTIDR_RXOUTEC (_U_(0x1) << DEVEPTIDR_RXOUTEC_Pos) /**< (DEVEPTIDR) Received OUT Data Interrupt Clear Mask */
+#define DEVEPTIDR_OVERFEC_Pos 5 /**< (DEVEPTIDR) Overflow Interrupt Clear Position */
+#define DEVEPTIDR_OVERFEC (_U_(0x1) << DEVEPTIDR_OVERFEC_Pos) /**< (DEVEPTIDR) Overflow Interrupt Clear Mask */
+#define DEVEPTIDR_SHORTPACKETEC_Pos 7 /**< (DEVEPTIDR) Shortpacket Interrupt Clear Position */
+#define DEVEPTIDR_SHORTPACKETEC (_U_(0x1) << DEVEPTIDR_SHORTPACKETEC_Pos) /**< (DEVEPTIDR) Shortpacket Interrupt Clear Mask */
+#define DEVEPTIDR_NBUSYBKEC_Pos 12 /**< (DEVEPTIDR) Number of Busy Banks Interrupt Clear Position */
+#define DEVEPTIDR_NBUSYBKEC (_U_(0x1) << DEVEPTIDR_NBUSYBKEC_Pos) /**< (DEVEPTIDR) Number of Busy Banks Interrupt Clear Mask */
+#define DEVEPTIDR_FIFOCONC_Pos 14 /**< (DEVEPTIDR) FIFO Control Clear Position */
+#define DEVEPTIDR_FIFOCONC (_U_(0x1) << DEVEPTIDR_FIFOCONC_Pos) /**< (DEVEPTIDR) FIFO Control Clear Mask */
+#define DEVEPTIDR_EPDISHDMAC_Pos 16 /**< (DEVEPTIDR) Endpoint Interrupts Disable HDMA Request Clear Position */
+#define DEVEPTIDR_EPDISHDMAC (_U_(0x1) << DEVEPTIDR_EPDISHDMAC_Pos) /**< (DEVEPTIDR) Endpoint Interrupts Disable HDMA Request Clear Mask */
+#define DEVEPTIDR_Msk _U_(0x150A3) /**< (DEVEPTIDR) Register Mask */
+
+/* CTRL mode */
+#define DEVEPTIDR_CTRL_RXSTPEC_Pos 2 /**< (DEVEPTIDR) Received SETUP Interrupt Clear Position */
+#define DEVEPTIDR_CTRL_RXSTPEC (_U_(0x1) << DEVEPTIDR_CTRL_RXSTPEC_Pos) /**< (DEVEPTIDR) Received SETUP Interrupt Clear Mask */
+#define DEVEPTIDR_CTRL_NAKOUTEC_Pos 3 /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Position */
+#define DEVEPTIDR_CTRL_NAKOUTEC (_U_(0x1) << DEVEPTIDR_CTRL_NAKOUTEC_Pos) /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Mask */
+#define DEVEPTIDR_CTRL_NAKINEC_Pos 4 /**< (DEVEPTIDR) NAKed IN Interrupt Clear Position */
+#define DEVEPTIDR_CTRL_NAKINEC (_U_(0x1) << DEVEPTIDR_CTRL_NAKINEC_Pos) /**< (DEVEPTIDR) NAKed IN Interrupt Clear Mask */
+#define DEVEPTIDR_CTRL_STALLEDEC_Pos 6 /**< (DEVEPTIDR) STALLed Interrupt Clear Position */
+#define DEVEPTIDR_CTRL_STALLEDEC (_U_(0x1) << DEVEPTIDR_CTRL_STALLEDEC_Pos) /**< (DEVEPTIDR) STALLed Interrupt Clear Mask */
+#define DEVEPTIDR_CTRL_NYETDISC_Pos 17 /**< (DEVEPTIDR) NYET Token Disable Clear Position */
+#define DEVEPTIDR_CTRL_NYETDISC (_U_(0x1) << DEVEPTIDR_CTRL_NYETDISC_Pos) /**< (DEVEPTIDR) NYET Token Disable Clear Mask */
+#define DEVEPTIDR_CTRL_STALLRQC_Pos 19 /**< (DEVEPTIDR) STALL Request Clear Position */
+#define DEVEPTIDR_CTRL_STALLRQC (_U_(0x1) << DEVEPTIDR_CTRL_STALLRQC_Pos) /**< (DEVEPTIDR) STALL Request Clear Mask */
+#define DEVEPTIDR_CTRL_Msk _U_(0xA005C) /**< (DEVEPTIDR_CTRL) Register Mask */
+
+/* ISO mode */
+#define DEVEPTIDR_ISO_UNDERFEC_Pos 2 /**< (DEVEPTIDR) Underflow Interrupt Clear Position */
+#define DEVEPTIDR_ISO_UNDERFEC (_U_(0x1) << DEVEPTIDR_ISO_UNDERFEC_Pos) /**< (DEVEPTIDR) Underflow Interrupt Clear Mask */
+#define DEVEPTIDR_ISO_HBISOINERREC_Pos 3 /**< (DEVEPTIDR) High Bandwidth Isochronous IN Underflow Error Interrupt Clear Position */
+#define DEVEPTIDR_ISO_HBISOINERREC (_U_(0x1) << DEVEPTIDR_ISO_HBISOINERREC_Pos) /**< (DEVEPTIDR) High Bandwidth Isochronous IN Underflow Error Interrupt Clear Mask */
+#define DEVEPTIDR_ISO_HBISOFLUSHEC_Pos 4 /**< (DEVEPTIDR) High Bandwidth Isochronous IN Flush Interrupt Clear Position */
+#define DEVEPTIDR_ISO_HBISOFLUSHEC (_U_(0x1) << DEVEPTIDR_ISO_HBISOFLUSHEC_Pos) /**< (DEVEPTIDR) High Bandwidth Isochronous IN Flush Interrupt Clear Mask */
+#define DEVEPTIDR_ISO_MDATAEC_Pos 8 /**< (DEVEPTIDR) MData Interrupt Clear Position */
+#define DEVEPTIDR_ISO_MDATAEC (_U_(0x1) << DEVEPTIDR_ISO_MDATAEC_Pos) /**< (DEVEPTIDR) MData Interrupt Clear Mask */
+#define DEVEPTIDR_ISO_DATAXEC_Pos 9 /**< (DEVEPTIDR) DataX Interrupt Clear Position */
+#define DEVEPTIDR_ISO_DATAXEC (_U_(0x1) << DEVEPTIDR_ISO_DATAXEC_Pos) /**< (DEVEPTIDR) DataX Interrupt Clear Mask */
+#define DEVEPTIDR_ISO_ERRORTRANSEC_Pos 10 /**< (DEVEPTIDR) Transaction Error Interrupt Clear Position */
+#define DEVEPTIDR_ISO_ERRORTRANSEC (_U_(0x1) << DEVEPTIDR_ISO_ERRORTRANSEC_Pos) /**< (DEVEPTIDR) Transaction Error Interrupt Clear Mask */
+#define DEVEPTIDR_ISO_Msk _U_(0x71C) /**< (DEVEPTIDR_ISO) Register Mask */
+
+/* BLK mode */
+#define DEVEPTIDR_BLK_RXSTPEC_Pos 2 /**< (DEVEPTIDR) Received SETUP Interrupt Clear Position */
+#define DEVEPTIDR_BLK_RXSTPEC (_U_(0x1) << DEVEPTIDR_BLK_RXSTPEC_Pos) /**< (DEVEPTIDR) Received SETUP Interrupt Clear Mask */
+#define DEVEPTIDR_BLK_NAKOUTEC_Pos 3 /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Position */
+#define DEVEPTIDR_BLK_NAKOUTEC (_U_(0x1) << DEVEPTIDR_BLK_NAKOUTEC_Pos) /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Mask */
+#define DEVEPTIDR_BLK_NAKINEC_Pos 4 /**< (DEVEPTIDR) NAKed IN Interrupt Clear Position */
+#define DEVEPTIDR_BLK_NAKINEC (_U_(0x1) << DEVEPTIDR_BLK_NAKINEC_Pos) /**< (DEVEPTIDR) NAKed IN Interrupt Clear Mask */
+#define DEVEPTIDR_BLK_STALLEDEC_Pos 6 /**< (DEVEPTIDR) STALLed Interrupt Clear Position */
+#define DEVEPTIDR_BLK_STALLEDEC (_U_(0x1) << DEVEPTIDR_BLK_STALLEDEC_Pos) /**< (DEVEPTIDR) STALLed Interrupt Clear Mask */
+#define DEVEPTIDR_BLK_NYETDISC_Pos 17 /**< (DEVEPTIDR) NYET Token Disable Clear Position */
+#define DEVEPTIDR_BLK_NYETDISC (_U_(0x1) << DEVEPTIDR_BLK_NYETDISC_Pos) /**< (DEVEPTIDR) NYET Token Disable Clear Mask */
+#define DEVEPTIDR_BLK_STALLRQC_Pos 19 /**< (DEVEPTIDR) STALL Request Clear Position */
+#define DEVEPTIDR_BLK_STALLRQC (_U_(0x1) << DEVEPTIDR_BLK_STALLRQC_Pos) /**< (DEVEPTIDR) STALL Request Clear Mask */
+#define DEVEPTIDR_BLK_Msk _U_(0xA005C) /**< (DEVEPTIDR_BLK) Register Mask */
+
+/* INTRPT mode */
+#define DEVEPTIDR_INTRPT_RXSTPEC_Pos 2 /**< (DEVEPTIDR) Received SETUP Interrupt Clear Position */
+#define DEVEPTIDR_INTRPT_RXSTPEC (_U_(0x1) << DEVEPTIDR_INTRPT_RXSTPEC_Pos) /**< (DEVEPTIDR) Received SETUP Interrupt Clear Mask */
+#define DEVEPTIDR_INTRPT_NAKOUTEC_Pos 3 /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Position */
+#define DEVEPTIDR_INTRPT_NAKOUTEC (_U_(0x1) << DEVEPTIDR_INTRPT_NAKOUTEC_Pos) /**< (DEVEPTIDR) NAKed OUT Interrupt Clear Mask */
+#define DEVEPTIDR_INTRPT_NAKINEC_Pos 4 /**< (DEVEPTIDR) NAKed IN Interrupt Clear Position */
+#define DEVEPTIDR_INTRPT_NAKINEC (_U_(0x1) << DEVEPTIDR_INTRPT_NAKINEC_Pos) /**< (DEVEPTIDR) NAKed IN Interrupt Clear Mask */
+#define DEVEPTIDR_INTRPT_STALLEDEC_Pos 6 /**< (DEVEPTIDR) STALLed Interrupt Clear Position */
+#define DEVEPTIDR_INTRPT_STALLEDEC (_U_(0x1) << DEVEPTIDR_INTRPT_STALLEDEC_Pos) /**< (DEVEPTIDR) STALLed Interrupt Clear Mask */
+#define DEVEPTIDR_INTRPT_NYETDISC_Pos 17 /**< (DEVEPTIDR) NYET Token Disable Clear Position */
+#define DEVEPTIDR_INTRPT_NYETDISC (_U_(0x1) << DEVEPTIDR_INTRPT_NYETDISC_Pos) /**< (DEVEPTIDR) NYET Token Disable Clear Mask */
+#define DEVEPTIDR_INTRPT_STALLRQC_Pos 19 /**< (DEVEPTIDR) STALL Request Clear Position */
+#define DEVEPTIDR_INTRPT_STALLRQC (_U_(0x1) << DEVEPTIDR_INTRPT_STALLRQC_Pos) /**< (DEVEPTIDR) STALL Request Clear Mask */
+#define DEVEPTIDR_INTRPT_Msk _U_(0xA005C) /**< (DEVEPTIDR_INTRPT) Register Mask */
+
+
+/* -------- HSTCTRL : (USBHS Offset: 0x400) (R/W 32) Host General Control Register -------- */
+
+#define HSTCTRL_OFFSET (0x400) /**< (HSTCTRL) Host General Control Register Offset */
+
+#define HSTCTRL_SOFE_Pos 8 /**< (HSTCTRL) Start of Frame Generation Enable Position */
+#define HSTCTRL_SOFE (_U_(0x1) << HSTCTRL_SOFE_Pos) /**< (HSTCTRL) Start of Frame Generation Enable Mask */
+#define HSTCTRL_RESET_Pos 9 /**< (HSTCTRL) Send USB Reset Position */
+#define HSTCTRL_RESET (_U_(0x1) << HSTCTRL_RESET_Pos) /**< (HSTCTRL) Send USB Reset Mask */
+#define HSTCTRL_RESUME_Pos 10 /**< (HSTCTRL) Send USB Resume Position */
+#define HSTCTRL_RESUME (_U_(0x1) << HSTCTRL_RESUME_Pos) /**< (HSTCTRL) Send USB Resume Mask */
+#define HSTCTRL_SPDCONF_Pos 12 /**< (HSTCTRL) Mode Configuration Position */
+#define HSTCTRL_SPDCONF (_U_(0x3) << HSTCTRL_SPDCONF_Pos) /**< (HSTCTRL) Mode Configuration Mask */
+#define HSTCTRL_SPDCONF_NORMAL_Val _U_(0x0) /**< (HSTCTRL) The host starts in Full-speed mode and performs a high-speed reset to switch to High-speed mode if the downstream peripheral is high-speed capable. */
+#define HSTCTRL_SPDCONF_LOW_POWER_Val _U_(0x1) /**< (HSTCTRL) For a better consumption, if high speed is not needed. */
+#define HSTCTRL_SPDCONF_HIGH_SPEED_Val _U_(0x2) /**< (HSTCTRL) Forced high speed. */
+#define HSTCTRL_SPDCONF_FORCED_FS_Val _U_(0x3) /**< (HSTCTRL) The host remains in Full-speed mode whatever the peripheral speed capability. */
+#define HSTCTRL_SPDCONF_NORMAL (HSTCTRL_SPDCONF_NORMAL_Val << HSTCTRL_SPDCONF_Pos) /**< (HSTCTRL) The host starts in Full-speed mode and performs a high-speed reset to switch to High-speed mode if the downstream peripheral is high-speed capable. Position */
+#define HSTCTRL_SPDCONF_LOW_POWER (HSTCTRL_SPDCONF_LOW_POWER_Val << HSTCTRL_SPDCONF_Pos) /**< (HSTCTRL) For a better consumption, if high speed is not needed. Position */
+#define HSTCTRL_SPDCONF_HIGH_SPEED (HSTCTRL_SPDCONF_HIGH_SPEED_Val << HSTCTRL_SPDCONF_Pos) /**< (HSTCTRL) Forced high speed. Position */
+#define HSTCTRL_SPDCONF_FORCED_FS (HSTCTRL_SPDCONF_FORCED_FS_Val << HSTCTRL_SPDCONF_Pos) /**< (HSTCTRL) The host remains in Full-speed mode whatever the peripheral speed capability. Position */
+#define HSTCTRL_Msk _U_(0x3700) /**< (HSTCTRL) Register Mask */
+
+
+/* -------- HSTISR : (USBHS Offset: 0x404) (R/ 32) Host Global Interrupt Status Register -------- */
+
+#define HSTISR_OFFSET (0x404) /**< (HSTISR) Host Global Interrupt Status Register Offset */
+
+#define HSTISR_DCONNI_Pos 0 /**< (HSTISR) Device Connection Interrupt Position */
+#define HSTISR_DCONNI (_U_(0x1) << HSTISR_DCONNI_Pos) /**< (HSTISR) Device Connection Interrupt Mask */
+#define HSTISR_DDISCI_Pos 1 /**< (HSTISR) Device Disconnection Interrupt Position */
+#define HSTISR_DDISCI (_U_(0x1) << HSTISR_DDISCI_Pos) /**< (HSTISR) Device Disconnection Interrupt Mask */
+#define HSTISR_RSTI_Pos 2 /**< (HSTISR) USB Reset Sent Interrupt Position */
+#define HSTISR_RSTI (_U_(0x1) << HSTISR_RSTI_Pos) /**< (HSTISR) USB Reset Sent Interrupt Mask */
+#define HSTISR_RSMEDI_Pos 3 /**< (HSTISR) Downstream Resume Sent Interrupt Position */
+#define HSTISR_RSMEDI (_U_(0x1) << HSTISR_RSMEDI_Pos) /**< (HSTISR) Downstream Resume Sent Interrupt Mask */
+#define HSTISR_RXRSMI_Pos 4 /**< (HSTISR) Upstream Resume Received Interrupt Position */
+#define HSTISR_RXRSMI (_U_(0x1) << HSTISR_RXRSMI_Pos) /**< (HSTISR) Upstream Resume Received Interrupt Mask */
+#define HSTISR_HSOFI_Pos 5 /**< (HSTISR) Host Start of Frame Interrupt Position */
+#define HSTISR_HSOFI (_U_(0x1) << HSTISR_HSOFI_Pos) /**< (HSTISR) Host Start of Frame Interrupt Mask */
+#define HSTISR_HWUPI_Pos 6 /**< (HSTISR) Host Wake-Up Interrupt Position */
+#define HSTISR_HWUPI (_U_(0x1) << HSTISR_HWUPI_Pos) /**< (HSTISR) Host Wake-Up Interrupt Mask */
+#define HSTISR_PEP_0_Pos 8 /**< (HSTISR) Pipe 0 Interrupt Position */
+#define HSTISR_PEP_0 (_U_(0x1) << HSTISR_PEP_0_Pos) /**< (HSTISR) Pipe 0 Interrupt Mask */
+#define HSTISR_PEP_1_Pos 9 /**< (HSTISR) Pipe 1 Interrupt Position */
+#define HSTISR_PEP_1 (_U_(0x1) << HSTISR_PEP_1_Pos) /**< (HSTISR) Pipe 1 Interrupt Mask */
+#define HSTISR_PEP_2_Pos 10 /**< (HSTISR) Pipe 2 Interrupt Position */
+#define HSTISR_PEP_2 (_U_(0x1) << HSTISR_PEP_2_Pos) /**< (HSTISR) Pipe 2 Interrupt Mask */
+#define HSTISR_PEP_3_Pos 11 /**< (HSTISR) Pipe 3 Interrupt Position */
+#define HSTISR_PEP_3 (_U_(0x1) << HSTISR_PEP_3_Pos) /**< (HSTISR) Pipe 3 Interrupt Mask */
+#define HSTISR_PEP_4_Pos 12 /**< (HSTISR) Pipe 4 Interrupt Position */
+#define HSTISR_PEP_4 (_U_(0x1) << HSTISR_PEP_4_Pos) /**< (HSTISR) Pipe 4 Interrupt Mask */
+#define HSTISR_PEP_5_Pos 13 /**< (HSTISR) Pipe 5 Interrupt Position */
+#define HSTISR_PEP_5 (_U_(0x1) << HSTISR_PEP_5_Pos) /**< (HSTISR) Pipe 5 Interrupt Mask */
+#define HSTISR_PEP_6_Pos 14 /**< (HSTISR) Pipe 6 Interrupt Position */
+#define HSTISR_PEP_6 (_U_(0x1) << HSTISR_PEP_6_Pos) /**< (HSTISR) Pipe 6 Interrupt Mask */
+#define HSTISR_PEP_7_Pos 15 /**< (HSTISR) Pipe 7 Interrupt Position */
+#define HSTISR_PEP_7 (_U_(0x1) << HSTISR_PEP_7_Pos) /**< (HSTISR) Pipe 7 Interrupt Mask */
+#define HSTISR_PEP_8_Pos 16 /**< (HSTISR) Pipe 8 Interrupt Position */
+#define HSTISR_PEP_8 (_U_(0x1) << HSTISR_PEP_8_Pos) /**< (HSTISR) Pipe 8 Interrupt Mask */
+#define HSTISR_PEP_9_Pos 17 /**< (HSTISR) Pipe 9 Interrupt Position */
+#define HSTISR_PEP_9 (_U_(0x1) << HSTISR_PEP_9_Pos) /**< (HSTISR) Pipe 9 Interrupt Mask */
+#define HSTISR_DMA_0_Pos 25 /**< (HSTISR) DMA Channel 0 Interrupt Position */
+#define HSTISR_DMA_0 (_U_(0x1) << HSTISR_DMA_0_Pos) /**< (HSTISR) DMA Channel 0 Interrupt Mask */
+#define HSTISR_DMA_1_Pos 26 /**< (HSTISR) DMA Channel 1 Interrupt Position */
+#define HSTISR_DMA_1 (_U_(0x1) << HSTISR_DMA_1_Pos) /**< (HSTISR) DMA Channel 1 Interrupt Mask */
+#define HSTISR_DMA_2_Pos 27 /**< (HSTISR) DMA Channel 2 Interrupt Position */
+#define HSTISR_DMA_2 (_U_(0x1) << HSTISR_DMA_2_Pos) /**< (HSTISR) DMA Channel 2 Interrupt Mask */
+#define HSTISR_DMA_3_Pos 28 /**< (HSTISR) DMA Channel 3 Interrupt Position */
+#define HSTISR_DMA_3 (_U_(0x1) << HSTISR_DMA_3_Pos) /**< (HSTISR) DMA Channel 3 Interrupt Mask */
+#define HSTISR_DMA_4_Pos 29 /**< (HSTISR) DMA Channel 4 Interrupt Position */
+#define HSTISR_DMA_4 (_U_(0x1) << HSTISR_DMA_4_Pos) /**< (HSTISR) DMA Channel 4 Interrupt Mask */
+#define HSTISR_DMA_5_Pos 30 /**< (HSTISR) DMA Channel 5 Interrupt Position */
+#define HSTISR_DMA_5 (_U_(0x1) << HSTISR_DMA_5_Pos) /**< (HSTISR) DMA Channel 5 Interrupt Mask */
+#define HSTISR_DMA_6_Pos 31 /**< (HSTISR) DMA Channel 6 Interrupt Position */
+#define HSTISR_DMA_6 (_U_(0x1) << HSTISR_DMA_6_Pos) /**< (HSTISR) DMA Channel 6 Interrupt Mask */
+#define HSTISR_Msk _U_(0xFE03FF7F) /**< (HSTISR) Register Mask */
+
+#define HSTISR_PEP__Pos 8 /**< (HSTISR Position) Pipe x Interrupt */
+#define HSTISR_PEP_ (_U_(0x3FF) << HSTISR_PEP__Pos) /**< (HSTISR Mask) PEP_ */
+#define HSTISR_DMA__Pos 25 /**< (HSTISR Position) DMA Channel 6 Interrupt */
+#define HSTISR_DMA_ (_U_(0x7F) << HSTISR_DMA__Pos) /**< (HSTISR Mask) DMA_ */
+
+/* -------- HSTICR : (USBHS Offset: 0x408) (/W 32) Host Global Interrupt Clear Register -------- */
+
+#define HSTICR_OFFSET (0x408) /**< (HSTICR) Host Global Interrupt Clear Register Offset */
+
+#define HSTICR_DCONNIC_Pos 0 /**< (HSTICR) Device Connection Interrupt Clear Position */
+#define HSTICR_DCONNIC (_U_(0x1) << HSTICR_DCONNIC_Pos) /**< (HSTICR) Device Connection Interrupt Clear Mask */
+#define HSTICR_DDISCIC_Pos 1 /**< (HSTICR) Device Disconnection Interrupt Clear Position */
+#define HSTICR_DDISCIC (_U_(0x1) << HSTICR_DDISCIC_Pos) /**< (HSTICR) Device Disconnection Interrupt Clear Mask */
+#define HSTICR_RSTIC_Pos 2 /**< (HSTICR) USB Reset Sent Interrupt Clear Position */
+#define HSTICR_RSTIC (_U_(0x1) << HSTICR_RSTIC_Pos) /**< (HSTICR) USB Reset Sent Interrupt Clear Mask */
+#define HSTICR_RSMEDIC_Pos 3 /**< (HSTICR) Downstream Resume Sent Interrupt Clear Position */
+#define HSTICR_RSMEDIC (_U_(0x1) << HSTICR_RSMEDIC_Pos) /**< (HSTICR) Downstream Resume Sent Interrupt Clear Mask */
+#define HSTICR_RXRSMIC_Pos 4 /**< (HSTICR) Upstream Resume Received Interrupt Clear Position */
+#define HSTICR_RXRSMIC (_U_(0x1) << HSTICR_RXRSMIC_Pos) /**< (HSTICR) Upstream Resume Received Interrupt Clear Mask */
+#define HSTICR_HSOFIC_Pos 5 /**< (HSTICR) Host Start of Frame Interrupt Clear Position */
+#define HSTICR_HSOFIC (_U_(0x1) << HSTICR_HSOFIC_Pos) /**< (HSTICR) Host Start of Frame Interrupt Clear Mask */
+#define HSTICR_HWUPIC_Pos 6 /**< (HSTICR) Host Wake-Up Interrupt Clear Position */
+#define HSTICR_HWUPIC (_U_(0x1) << HSTICR_HWUPIC_Pos) /**< (HSTICR) Host Wake-Up Interrupt Clear Mask */
+#define HSTICR_Msk _U_(0x7F) /**< (HSTICR) Register Mask */
+
+
+/* -------- HSTIFR : (USBHS Offset: 0x40c) (/W 32) Host Global Interrupt Set Register -------- */
+
+#define HSTIFR_OFFSET (0x40C) /**< (HSTIFR) Host Global Interrupt Set Register Offset */
+
+#define HSTIFR_DCONNIS_Pos 0 /**< (HSTIFR) Device Connection Interrupt Set Position */
+#define HSTIFR_DCONNIS (_U_(0x1) << HSTIFR_DCONNIS_Pos) /**< (HSTIFR) Device Connection Interrupt Set Mask */
+#define HSTIFR_DDISCIS_Pos 1 /**< (HSTIFR) Device Disconnection Interrupt Set Position */
+#define HSTIFR_DDISCIS (_U_(0x1) << HSTIFR_DDISCIS_Pos) /**< (HSTIFR) Device Disconnection Interrupt Set Mask */
+#define HSTIFR_RSTIS_Pos 2 /**< (HSTIFR) USB Reset Sent Interrupt Set Position */
+#define HSTIFR_RSTIS (_U_(0x1) << HSTIFR_RSTIS_Pos) /**< (HSTIFR) USB Reset Sent Interrupt Set Mask */
+#define HSTIFR_RSMEDIS_Pos 3 /**< (HSTIFR) Downstream Resume Sent Interrupt Set Position */
+#define HSTIFR_RSMEDIS (_U_(0x1) << HSTIFR_RSMEDIS_Pos) /**< (HSTIFR) Downstream Resume Sent Interrupt Set Mask */
+#define HSTIFR_RXRSMIS_Pos 4 /**< (HSTIFR) Upstream Resume Received Interrupt Set Position */
+#define HSTIFR_RXRSMIS (_U_(0x1) << HSTIFR_RXRSMIS_Pos) /**< (HSTIFR) Upstream Resume Received Interrupt Set Mask */
+#define HSTIFR_HSOFIS_Pos 5 /**< (HSTIFR) Host Start of Frame Interrupt Set Position */
+#define HSTIFR_HSOFIS (_U_(0x1) << HSTIFR_HSOFIS_Pos) /**< (HSTIFR) Host Start of Frame Interrupt Set Mask */
+#define HSTIFR_HWUPIS_Pos 6 /**< (HSTIFR) Host Wake-Up Interrupt Set Position */
+#define HSTIFR_HWUPIS (_U_(0x1) << HSTIFR_HWUPIS_Pos) /**< (HSTIFR) Host Wake-Up Interrupt Set Mask */
+#define HSTIFR_DMA_0_Pos 25 /**< (HSTIFR) DMA Channel 0 Interrupt Set Position */
+#define HSTIFR_DMA_0 (_U_(0x1) << HSTIFR_DMA_0_Pos) /**< (HSTIFR) DMA Channel 0 Interrupt Set Mask */
+#define HSTIFR_DMA_1_Pos 26 /**< (HSTIFR) DMA Channel 1 Interrupt Set Position */
+#define HSTIFR_DMA_1 (_U_(0x1) << HSTIFR_DMA_1_Pos) /**< (HSTIFR) DMA Channel 1 Interrupt Set Mask */
+#define HSTIFR_DMA_2_Pos 27 /**< (HSTIFR) DMA Channel 2 Interrupt Set Position */
+#define HSTIFR_DMA_2 (_U_(0x1) << HSTIFR_DMA_2_Pos) /**< (HSTIFR) DMA Channel 2 Interrupt Set Mask */
+#define HSTIFR_DMA_3_Pos 28 /**< (HSTIFR) DMA Channel 3 Interrupt Set Position */
+#define HSTIFR_DMA_3 (_U_(0x1) << HSTIFR_DMA_3_Pos) /**< (HSTIFR) DMA Channel 3 Interrupt Set Mask */
+#define HSTIFR_DMA_4_Pos 29 /**< (HSTIFR) DMA Channel 4 Interrupt Set Position */
+#define HSTIFR_DMA_4 (_U_(0x1) << HSTIFR_DMA_4_Pos) /**< (HSTIFR) DMA Channel 4 Interrupt Set Mask */
+#define HSTIFR_DMA_5_Pos 30 /**< (HSTIFR) DMA Channel 5 Interrupt Set Position */
+#define HSTIFR_DMA_5 (_U_(0x1) << HSTIFR_DMA_5_Pos) /**< (HSTIFR) DMA Channel 5 Interrupt Set Mask */
+#define HSTIFR_DMA_6_Pos 31 /**< (HSTIFR) DMA Channel 6 Interrupt Set Position */
+#define HSTIFR_DMA_6 (_U_(0x1) << HSTIFR_DMA_6_Pos) /**< (HSTIFR) DMA Channel 6 Interrupt Set Mask */
+#define HSTIFR_Msk _U_(0xFE00007F) /**< (HSTIFR) Register Mask */
+
+#define HSTIFR_DMA__Pos 25 /**< (HSTIFR Position) DMA Channel 6 Interrupt Set */
+#define HSTIFR_DMA_ (_U_(0x7F) << HSTIFR_DMA__Pos) /**< (HSTIFR Mask) DMA_ */
+
+/* -------- HSTIMR : (USBHS Offset: 0x410) (R/ 32) Host Global Interrupt Mask Register -------- */
+
+#define HSTIMR_OFFSET (0x410) /**< (HSTIMR) Host Global Interrupt Mask Register Offset */
+
+#define HSTIMR_DCONNIE_Pos 0 /**< (HSTIMR) Device Connection Interrupt Enable Position */
+#define HSTIMR_DCONNIE (_U_(0x1) << HSTIMR_DCONNIE_Pos) /**< (HSTIMR) Device Connection Interrupt Enable Mask */
+#define HSTIMR_DDISCIE_Pos 1 /**< (HSTIMR) Device Disconnection Interrupt Enable Position */
+#define HSTIMR_DDISCIE (_U_(0x1) << HSTIMR_DDISCIE_Pos) /**< (HSTIMR) Device Disconnection Interrupt Enable Mask */
+#define HSTIMR_RSTIE_Pos 2 /**< (HSTIMR) USB Reset Sent Interrupt Enable Position */
+#define HSTIMR_RSTIE (_U_(0x1) << HSTIMR_RSTIE_Pos) /**< (HSTIMR) USB Reset Sent Interrupt Enable Mask */
+#define HSTIMR_RSMEDIE_Pos 3 /**< (HSTIMR) Downstream Resume Sent Interrupt Enable Position */
+#define HSTIMR_RSMEDIE (_U_(0x1) << HSTIMR_RSMEDIE_Pos) /**< (HSTIMR) Downstream Resume Sent Interrupt Enable Mask */
+#define HSTIMR_RXRSMIE_Pos 4 /**< (HSTIMR) Upstream Resume Received Interrupt Enable Position */
+#define HSTIMR_RXRSMIE (_U_(0x1) << HSTIMR_RXRSMIE_Pos) /**< (HSTIMR) Upstream Resume Received Interrupt Enable Mask */
+#define HSTIMR_HSOFIE_Pos 5 /**< (HSTIMR) Host Start of Frame Interrupt Enable Position */
+#define HSTIMR_HSOFIE (_U_(0x1) << HSTIMR_HSOFIE_Pos) /**< (HSTIMR) Host Start of Frame Interrupt Enable Mask */
+#define HSTIMR_HWUPIE_Pos 6 /**< (HSTIMR) Host Wake-Up Interrupt Enable Position */
+#define HSTIMR_HWUPIE (_U_(0x1) << HSTIMR_HWUPIE_Pos) /**< (HSTIMR) Host Wake-Up Interrupt Enable Mask */
+#define HSTIMR_PEP_0_Pos 8 /**< (HSTIMR) Pipe 0 Interrupt Enable Position */
+#define HSTIMR_PEP_0 (_U_(0x1) << HSTIMR_PEP_0_Pos) /**< (HSTIMR) Pipe 0 Interrupt Enable Mask */
+#define HSTIMR_PEP_1_Pos 9 /**< (HSTIMR) Pipe 1 Interrupt Enable Position */
+#define HSTIMR_PEP_1 (_U_(0x1) << HSTIMR_PEP_1_Pos) /**< (HSTIMR) Pipe 1 Interrupt Enable Mask */
+#define HSTIMR_PEP_2_Pos 10 /**< (HSTIMR) Pipe 2 Interrupt Enable Position */
+#define HSTIMR_PEP_2 (_U_(0x1) << HSTIMR_PEP_2_Pos) /**< (HSTIMR) Pipe 2 Interrupt Enable Mask */
+#define HSTIMR_PEP_3_Pos 11 /**< (HSTIMR) Pipe 3 Interrupt Enable Position */
+#define HSTIMR_PEP_3 (_U_(0x1) << HSTIMR_PEP_3_Pos) /**< (HSTIMR) Pipe 3 Interrupt Enable Mask */
+#define HSTIMR_PEP_4_Pos 12 /**< (HSTIMR) Pipe 4 Interrupt Enable Position */
+#define HSTIMR_PEP_4 (_U_(0x1) << HSTIMR_PEP_4_Pos) /**< (HSTIMR) Pipe 4 Interrupt Enable Mask */
+#define HSTIMR_PEP_5_Pos 13 /**< (HSTIMR) Pipe 5 Interrupt Enable Position */
+#define HSTIMR_PEP_5 (_U_(0x1) << HSTIMR_PEP_5_Pos) /**< (HSTIMR) Pipe 5 Interrupt Enable Mask */
+#define HSTIMR_PEP_6_Pos 14 /**< (HSTIMR) Pipe 6 Interrupt Enable Position */
+#define HSTIMR_PEP_6 (_U_(0x1) << HSTIMR_PEP_6_Pos) /**< (HSTIMR) Pipe 6 Interrupt Enable Mask */
+#define HSTIMR_PEP_7_Pos 15 /**< (HSTIMR) Pipe 7 Interrupt Enable Position */
+#define HSTIMR_PEP_7 (_U_(0x1) << HSTIMR_PEP_7_Pos) /**< (HSTIMR) Pipe 7 Interrupt Enable Mask */
+#define HSTIMR_PEP_8_Pos 16 /**< (HSTIMR) Pipe 8 Interrupt Enable Position */
+#define HSTIMR_PEP_8 (_U_(0x1) << HSTIMR_PEP_8_Pos) /**< (HSTIMR) Pipe 8 Interrupt Enable Mask */
+#define HSTIMR_PEP_9_Pos 17 /**< (HSTIMR) Pipe 9 Interrupt Enable Position */
+#define HSTIMR_PEP_9 (_U_(0x1) << HSTIMR_PEP_9_Pos) /**< (HSTIMR) Pipe 9 Interrupt Enable Mask */
+#define HSTIMR_DMA_0_Pos 25 /**< (HSTIMR) DMA Channel 0 Interrupt Enable Position */
+#define HSTIMR_DMA_0 (_U_(0x1) << HSTIMR_DMA_0_Pos) /**< (HSTIMR) DMA Channel 0 Interrupt Enable Mask */
+#define HSTIMR_DMA_1_Pos 26 /**< (HSTIMR) DMA Channel 1 Interrupt Enable Position */
+#define HSTIMR_DMA_1 (_U_(0x1) << HSTIMR_DMA_1_Pos) /**< (HSTIMR) DMA Channel 1 Interrupt Enable Mask */
+#define HSTIMR_DMA_2_Pos 27 /**< (HSTIMR) DMA Channel 2 Interrupt Enable Position */
+#define HSTIMR_DMA_2 (_U_(0x1) << HSTIMR_DMA_2_Pos) /**< (HSTIMR) DMA Channel 2 Interrupt Enable Mask */
+#define HSTIMR_DMA_3_Pos 28 /**< (HSTIMR) DMA Channel 3 Interrupt Enable Position */
+#define HSTIMR_DMA_3 (_U_(0x1) << HSTIMR_DMA_3_Pos) /**< (HSTIMR) DMA Channel 3 Interrupt Enable Mask */
+#define HSTIMR_DMA_4_Pos 29 /**< (HSTIMR) DMA Channel 4 Interrupt Enable Position */
+#define HSTIMR_DMA_4 (_U_(0x1) << HSTIMR_DMA_4_Pos) /**< (HSTIMR) DMA Channel 4 Interrupt Enable Mask */
+#define HSTIMR_DMA_5_Pos 30 /**< (HSTIMR) DMA Channel 5 Interrupt Enable Position */
+#define HSTIMR_DMA_5 (_U_(0x1) << HSTIMR_DMA_5_Pos) /**< (HSTIMR) DMA Channel 5 Interrupt Enable Mask */
+#define HSTIMR_DMA_6_Pos 31 /**< (HSTIMR) DMA Channel 6 Interrupt Enable Position */
+#define HSTIMR_DMA_6 (_U_(0x1) << HSTIMR_DMA_6_Pos) /**< (HSTIMR) DMA Channel 6 Interrupt Enable Mask */
+#define HSTIMR_Msk _U_(0xFE03FF7F) /**< (HSTIMR) Register Mask */
+
+#define HSTIMR_PEP__Pos 8 /**< (HSTIMR Position) Pipe x Interrupt Enable */
+#define HSTIMR_PEP_ (_U_(0x3FF) << HSTIMR_PEP__Pos) /**< (HSTIMR Mask) PEP_ */
+#define HSTIMR_DMA__Pos 25 /**< (HSTIMR Position) DMA Channel 6 Interrupt Enable */
+#define HSTIMR_DMA_ (_U_(0x7F) << HSTIMR_DMA__Pos) /**< (HSTIMR Mask) DMA_ */
+
+/* -------- HSTIDR : (USBHS Offset: 0x414) (/W 32) Host Global Interrupt Disable Register -------- */
+
+#define HSTIDR_OFFSET (0x414) /**< (HSTIDR) Host Global Interrupt Disable Register Offset */
+
+#define HSTIDR_DCONNIEC_Pos 0 /**< (HSTIDR) Device Connection Interrupt Disable Position */
+#define HSTIDR_DCONNIEC (_U_(0x1) << HSTIDR_DCONNIEC_Pos) /**< (HSTIDR) Device Connection Interrupt Disable Mask */
+#define HSTIDR_DDISCIEC_Pos 1 /**< (HSTIDR) Device Disconnection Interrupt Disable Position */
+#define HSTIDR_DDISCIEC (_U_(0x1) << HSTIDR_DDISCIEC_Pos) /**< (HSTIDR) Device Disconnection Interrupt Disable Mask */
+#define HSTIDR_RSTIEC_Pos 2 /**< (HSTIDR) USB Reset Sent Interrupt Disable Position */
+#define HSTIDR_RSTIEC (_U_(0x1) << HSTIDR_RSTIEC_Pos) /**< (HSTIDR) USB Reset Sent Interrupt Disable Mask */
+#define HSTIDR_RSMEDIEC_Pos 3 /**< (HSTIDR) Downstream Resume Sent Interrupt Disable Position */
+#define HSTIDR_RSMEDIEC (_U_(0x1) << HSTIDR_RSMEDIEC_Pos) /**< (HSTIDR) Downstream Resume Sent Interrupt Disable Mask */
+#define HSTIDR_RXRSMIEC_Pos 4 /**< (HSTIDR) Upstream Resume Received Interrupt Disable Position */
+#define HSTIDR_RXRSMIEC (_U_(0x1) << HSTIDR_RXRSMIEC_Pos) /**< (HSTIDR) Upstream Resume Received Interrupt Disable Mask */
+#define HSTIDR_HSOFIEC_Pos 5 /**< (HSTIDR) Host Start of Frame Interrupt Disable Position */
+#define HSTIDR_HSOFIEC (_U_(0x1) << HSTIDR_HSOFIEC_Pos) /**< (HSTIDR) Host Start of Frame Interrupt Disable Mask */
+#define HSTIDR_HWUPIEC_Pos 6 /**< (HSTIDR) Host Wake-Up Interrupt Disable Position */
+#define HSTIDR_HWUPIEC (_U_(0x1) << HSTIDR_HWUPIEC_Pos) /**< (HSTIDR) Host Wake-Up Interrupt Disable Mask */
+#define HSTIDR_PEP_0_Pos 8 /**< (HSTIDR) Pipe 0 Interrupt Disable Position */
+#define HSTIDR_PEP_0 (_U_(0x1) << HSTIDR_PEP_0_Pos) /**< (HSTIDR) Pipe 0 Interrupt Disable Mask */
+#define HSTIDR_PEP_1_Pos 9 /**< (HSTIDR) Pipe 1 Interrupt Disable Position */
+#define HSTIDR_PEP_1 (_U_(0x1) << HSTIDR_PEP_1_Pos) /**< (HSTIDR) Pipe 1 Interrupt Disable Mask */
+#define HSTIDR_PEP_2_Pos 10 /**< (HSTIDR) Pipe 2 Interrupt Disable Position */
+#define HSTIDR_PEP_2 (_U_(0x1) << HSTIDR_PEP_2_Pos) /**< (HSTIDR) Pipe 2 Interrupt Disable Mask */
+#define HSTIDR_PEP_3_Pos 11 /**< (HSTIDR) Pipe 3 Interrupt Disable Position */
+#define HSTIDR_PEP_3 (_U_(0x1) << HSTIDR_PEP_3_Pos) /**< (HSTIDR) Pipe 3 Interrupt Disable Mask */
+#define HSTIDR_PEP_4_Pos 12 /**< (HSTIDR) Pipe 4 Interrupt Disable Position */
+#define HSTIDR_PEP_4 (_U_(0x1) << HSTIDR_PEP_4_Pos) /**< (HSTIDR) Pipe 4 Interrupt Disable Mask */
+#define HSTIDR_PEP_5_Pos 13 /**< (HSTIDR) Pipe 5 Interrupt Disable Position */
+#define HSTIDR_PEP_5 (_U_(0x1) << HSTIDR_PEP_5_Pos) /**< (HSTIDR) Pipe 5 Interrupt Disable Mask */
+#define HSTIDR_PEP_6_Pos 14 /**< (HSTIDR) Pipe 6 Interrupt Disable Position */
+#define HSTIDR_PEP_6 (_U_(0x1) << HSTIDR_PEP_6_Pos) /**< (HSTIDR) Pipe 6 Interrupt Disable Mask */
+#define HSTIDR_PEP_7_Pos 15 /**< (HSTIDR) Pipe 7 Interrupt Disable Position */
+#define HSTIDR_PEP_7 (_U_(0x1) << HSTIDR_PEP_7_Pos) /**< (HSTIDR) Pipe 7 Interrupt Disable Mask */
+#define HSTIDR_PEP_8_Pos 16 /**< (HSTIDR) Pipe 8 Interrupt Disable Position */
+#define HSTIDR_PEP_8 (_U_(0x1) << HSTIDR_PEP_8_Pos) /**< (HSTIDR) Pipe 8 Interrupt Disable Mask */
+#define HSTIDR_PEP_9_Pos 17 /**< (HSTIDR) Pipe 9 Interrupt Disable Position */
+#define HSTIDR_PEP_9 (_U_(0x1) << HSTIDR_PEP_9_Pos) /**< (HSTIDR) Pipe 9 Interrupt Disable Mask */
+#define HSTIDR_DMA_0_Pos 25 /**< (HSTIDR) DMA Channel 0 Interrupt Disable Position */
+#define HSTIDR_DMA_0 (_U_(0x1) << HSTIDR_DMA_0_Pos) /**< (HSTIDR) DMA Channel 0 Interrupt Disable Mask */
+#define HSTIDR_DMA_1_Pos 26 /**< (HSTIDR) DMA Channel 1 Interrupt Disable Position */
+#define HSTIDR_DMA_1 (_U_(0x1) << HSTIDR_DMA_1_Pos) /**< (HSTIDR) DMA Channel 1 Interrupt Disable Mask */
+#define HSTIDR_DMA_2_Pos 27 /**< (HSTIDR) DMA Channel 2 Interrupt Disable Position */
+#define HSTIDR_DMA_2 (_U_(0x1) << HSTIDR_DMA_2_Pos) /**< (HSTIDR) DMA Channel 2 Interrupt Disable Mask */
+#define HSTIDR_DMA_3_Pos 28 /**< (HSTIDR) DMA Channel 3 Interrupt Disable Position */
+#define HSTIDR_DMA_3 (_U_(0x1) << HSTIDR_DMA_3_Pos) /**< (HSTIDR) DMA Channel 3 Interrupt Disable Mask */
+#define HSTIDR_DMA_4_Pos 29 /**< (HSTIDR) DMA Channel 4 Interrupt Disable Position */
+#define HSTIDR_DMA_4 (_U_(0x1) << HSTIDR_DMA_4_Pos) /**< (HSTIDR) DMA Channel 4 Interrupt Disable Mask */
+#define HSTIDR_DMA_5_Pos 30 /**< (HSTIDR) DMA Channel 5 Interrupt Disable Position */
+#define HSTIDR_DMA_5 (_U_(0x1) << HSTIDR_DMA_5_Pos) /**< (HSTIDR) DMA Channel 5 Interrupt Disable Mask */
+#define HSTIDR_DMA_6_Pos 31 /**< (HSTIDR) DMA Channel 6 Interrupt Disable Position */
+#define HSTIDR_DMA_6 (_U_(0x1) << HSTIDR_DMA_6_Pos) /**< (HSTIDR) DMA Channel 6 Interrupt Disable Mask */
+#define HSTIDR_Msk _U_(0xFE03FF7F) /**< (HSTIDR) Register Mask */
+
+#define HSTIDR_PEP__Pos 8 /**< (HSTIDR Position) Pipe x Interrupt Disable */
+#define HSTIDR_PEP_ (_U_(0x3FF) << HSTIDR_PEP__Pos) /**< (HSTIDR Mask) PEP_ */
+#define HSTIDR_DMA__Pos 25 /**< (HSTIDR Position) DMA Channel 6 Interrupt Disable */
+#define HSTIDR_DMA_ (_U_(0x7F) << HSTIDR_DMA__Pos) /**< (HSTIDR Mask) DMA_ */
+
+/* -------- HSTIER : (USBHS Offset: 0x418) (/W 32) Host Global Interrupt Enable Register -------- */
+
+#define HSTIER_OFFSET (0x418) /**< (HSTIER) Host Global Interrupt Enable Register Offset */
+
+#define HSTIER_DCONNIES_Pos 0 /**< (HSTIER) Device Connection Interrupt Enable Position */
+#define HSTIER_DCONNIES (_U_(0x1) << HSTIER_DCONNIES_Pos) /**< (HSTIER) Device Connection Interrupt Enable Mask */
+#define HSTIER_DDISCIES_Pos 1 /**< (HSTIER) Device Disconnection Interrupt Enable Position */
+#define HSTIER_DDISCIES (_U_(0x1) << HSTIER_DDISCIES_Pos) /**< (HSTIER) Device Disconnection Interrupt Enable Mask */
+#define HSTIER_RSTIES_Pos 2 /**< (HSTIER) USB Reset Sent Interrupt Enable Position */
+#define HSTIER_RSTIES (_U_(0x1) << HSTIER_RSTIES_Pos) /**< (HSTIER) USB Reset Sent Interrupt Enable Mask */
+#define HSTIER_RSMEDIES_Pos 3 /**< (HSTIER) Downstream Resume Sent Interrupt Enable Position */
+#define HSTIER_RSMEDIES (_U_(0x1) << HSTIER_RSMEDIES_Pos) /**< (HSTIER) Downstream Resume Sent Interrupt Enable Mask */
+#define HSTIER_RXRSMIES_Pos 4 /**< (HSTIER) Upstream Resume Received Interrupt Enable Position */
+#define HSTIER_RXRSMIES (_U_(0x1) << HSTIER_RXRSMIES_Pos) /**< (HSTIER) Upstream Resume Received Interrupt Enable Mask */
+#define HSTIER_HSOFIES_Pos 5 /**< (HSTIER) Host Start of Frame Interrupt Enable Position */
+#define HSTIER_HSOFIES (_U_(0x1) << HSTIER_HSOFIES_Pos) /**< (HSTIER) Host Start of Frame Interrupt Enable Mask */
+#define HSTIER_HWUPIES_Pos 6 /**< (HSTIER) Host Wake-Up Interrupt Enable Position */
+#define HSTIER_HWUPIES (_U_(0x1) << HSTIER_HWUPIES_Pos) /**< (HSTIER) Host Wake-Up Interrupt Enable Mask */
+#define HSTIER_PEP_0_Pos 8 /**< (HSTIER) Pipe 0 Interrupt Enable Position */
+#define HSTIER_PEP_0 (_U_(0x1) << HSTIER_PEP_0_Pos) /**< (HSTIER) Pipe 0 Interrupt Enable Mask */
+#define HSTIER_PEP_1_Pos 9 /**< (HSTIER) Pipe 1 Interrupt Enable Position */
+#define HSTIER_PEP_1 (_U_(0x1) << HSTIER_PEP_1_Pos) /**< (HSTIER) Pipe 1 Interrupt Enable Mask */
+#define HSTIER_PEP_2_Pos 10 /**< (HSTIER) Pipe 2 Interrupt Enable Position */
+#define HSTIER_PEP_2 (_U_(0x1) << HSTIER_PEP_2_Pos) /**< (HSTIER) Pipe 2 Interrupt Enable Mask */
+#define HSTIER_PEP_3_Pos 11 /**< (HSTIER) Pipe 3 Interrupt Enable Position */
+#define HSTIER_PEP_3 (_U_(0x1) << HSTIER_PEP_3_Pos) /**< (HSTIER) Pipe 3 Interrupt Enable Mask */
+#define HSTIER_PEP_4_Pos 12 /**< (HSTIER) Pipe 4 Interrupt Enable Position */
+#define HSTIER_PEP_4 (_U_(0x1) << HSTIER_PEP_4_Pos) /**< (HSTIER) Pipe 4 Interrupt Enable Mask */
+#define HSTIER_PEP_5_Pos 13 /**< (HSTIER) Pipe 5 Interrupt Enable Position */
+#define HSTIER_PEP_5 (_U_(0x1) << HSTIER_PEP_5_Pos) /**< (HSTIER) Pipe 5 Interrupt Enable Mask */
+#define HSTIER_PEP_6_Pos 14 /**< (HSTIER) Pipe 6 Interrupt Enable Position */
+#define HSTIER_PEP_6 (_U_(0x1) << HSTIER_PEP_6_Pos) /**< (HSTIER) Pipe 6 Interrupt Enable Mask */
+#define HSTIER_PEP_7_Pos 15 /**< (HSTIER) Pipe 7 Interrupt Enable Position */
+#define HSTIER_PEP_7 (_U_(0x1) << HSTIER_PEP_7_Pos) /**< (HSTIER) Pipe 7 Interrupt Enable Mask */
+#define HSTIER_PEP_8_Pos 16 /**< (HSTIER) Pipe 8 Interrupt Enable Position */
+#define HSTIER_PEP_8 (_U_(0x1) << HSTIER_PEP_8_Pos) /**< (HSTIER) Pipe 8 Interrupt Enable Mask */
+#define HSTIER_PEP_9_Pos 17 /**< (HSTIER) Pipe 9 Interrupt Enable Position */
+#define HSTIER_PEP_9 (_U_(0x1) << HSTIER_PEP_9_Pos) /**< (HSTIER) Pipe 9 Interrupt Enable Mask */
+#define HSTIER_DMA_0_Pos 25 /**< (HSTIER) DMA Channel 0 Interrupt Enable Position */
+#define HSTIER_DMA_0 (_U_(0x1) << HSTIER_DMA_0_Pos) /**< (HSTIER) DMA Channel 0 Interrupt Enable Mask */
+#define HSTIER_DMA_1_Pos 26 /**< (HSTIER) DMA Channel 1 Interrupt Enable Position */
+#define HSTIER_DMA_1 (_U_(0x1) << HSTIER_DMA_1_Pos) /**< (HSTIER) DMA Channel 1 Interrupt Enable Mask */
+#define HSTIER_DMA_2_Pos 27 /**< (HSTIER) DMA Channel 2 Interrupt Enable Position */
+#define HSTIER_DMA_2 (_U_(0x1) << HSTIER_DMA_2_Pos) /**< (HSTIER) DMA Channel 2 Interrupt Enable Mask */
+#define HSTIER_DMA_3_Pos 28 /**< (HSTIER) DMA Channel 3 Interrupt Enable Position */
+#define HSTIER_DMA_3 (_U_(0x1) << HSTIER_DMA_3_Pos) /**< (HSTIER) DMA Channel 3 Interrupt Enable Mask */
+#define HSTIER_DMA_4_Pos 29 /**< (HSTIER) DMA Channel 4 Interrupt Enable Position */
+#define HSTIER_DMA_4 (_U_(0x1) << HSTIER_DMA_4_Pos) /**< (HSTIER) DMA Channel 4 Interrupt Enable Mask */
+#define HSTIER_DMA_5_Pos 30 /**< (HSTIER) DMA Channel 5 Interrupt Enable Position */
+#define HSTIER_DMA_5 (_U_(0x1) << HSTIER_DMA_5_Pos) /**< (HSTIER) DMA Channel 5 Interrupt Enable Mask */
+#define HSTIER_DMA_6_Pos 31 /**< (HSTIER) DMA Channel 6 Interrupt Enable Position */
+#define HSTIER_DMA_6 (_U_(0x1) << HSTIER_DMA_6_Pos) /**< (HSTIER) DMA Channel 6 Interrupt Enable Mask */
+#define HSTIER_Msk _U_(0xFE03FF7F) /**< (HSTIER) Register Mask */
+
+#define HSTIER_PEP__Pos 8 /**< (HSTIER Position) Pipe x Interrupt Enable */
+#define HSTIER_PEP_ (_U_(0x3FF) << HSTIER_PEP__Pos) /**< (HSTIER Mask) PEP_ */
+#define HSTIER_DMA__Pos 25 /**< (HSTIER Position) DMA Channel 6 Interrupt Enable */
+#define HSTIER_DMA_ (_U_(0x7F) << HSTIER_DMA__Pos) /**< (HSTIER Mask) DMA_ */
+
+/* -------- HSTPIP : (USBHS Offset: 0x41c) (R/W 32) Host Pipe Register -------- */
+
+#define HSTPIP_OFFSET (0x41C) /**< (HSTPIP) Host Pipe Register Offset */
+
+#define HSTPIP_PEN0_Pos 0 /**< (HSTPIP) Pipe 0 Enable Position */
+#define HSTPIP_PEN0 (_U_(0x1) << HSTPIP_PEN0_Pos) /**< (HSTPIP) Pipe 0 Enable Mask */
+#define HSTPIP_PEN1_Pos 1 /**< (HSTPIP) Pipe 1 Enable Position */
+#define HSTPIP_PEN1 (_U_(0x1) << HSTPIP_PEN1_Pos) /**< (HSTPIP) Pipe 1 Enable Mask */
+#define HSTPIP_PEN2_Pos 2 /**< (HSTPIP) Pipe 2 Enable Position */
+#define HSTPIP_PEN2 (_U_(0x1) << HSTPIP_PEN2_Pos) /**< (HSTPIP) Pipe 2 Enable Mask */
+#define HSTPIP_PEN3_Pos 3 /**< (HSTPIP) Pipe 3 Enable Position */
+#define HSTPIP_PEN3 (_U_(0x1) << HSTPIP_PEN3_Pos) /**< (HSTPIP) Pipe 3 Enable Mask */
+#define HSTPIP_PEN4_Pos 4 /**< (HSTPIP) Pipe 4 Enable Position */
+#define HSTPIP_PEN4 (_U_(0x1) << HSTPIP_PEN4_Pos) /**< (HSTPIP) Pipe 4 Enable Mask */
+#define HSTPIP_PEN5_Pos 5 /**< (HSTPIP) Pipe 5 Enable Position */
+#define HSTPIP_PEN5 (_U_(0x1) << HSTPIP_PEN5_Pos) /**< (HSTPIP) Pipe 5 Enable Mask */
+#define HSTPIP_PEN6_Pos 6 /**< (HSTPIP) Pipe 6 Enable Position */
+#define HSTPIP_PEN6 (_U_(0x1) << HSTPIP_PEN6_Pos) /**< (HSTPIP) Pipe 6 Enable Mask */
+#define HSTPIP_PEN7_Pos 7 /**< (HSTPIP) Pipe 7 Enable Position */
+#define HSTPIP_PEN7 (_U_(0x1) << HSTPIP_PEN7_Pos) /**< (HSTPIP) Pipe 7 Enable Mask */
+#define HSTPIP_PEN8_Pos 8 /**< (HSTPIP) Pipe 8 Enable Position */
+#define HSTPIP_PEN8 (_U_(0x1) << HSTPIP_PEN8_Pos) /**< (HSTPIP) Pipe 8 Enable Mask */
+#define HSTPIP_PRST0_Pos 16 /**< (HSTPIP) Pipe 0 Reset Position */
+#define HSTPIP_PRST0 (_U_(0x1) << HSTPIP_PRST0_Pos) /**< (HSTPIP) Pipe 0 Reset Mask */
+#define HSTPIP_PRST1_Pos 17 /**< (HSTPIP) Pipe 1 Reset Position */
+#define HSTPIP_PRST1 (_U_(0x1) << HSTPIP_PRST1_Pos) /**< (HSTPIP) Pipe 1 Reset Mask */
+#define HSTPIP_PRST2_Pos 18 /**< (HSTPIP) Pipe 2 Reset Position */
+#define HSTPIP_PRST2 (_U_(0x1) << HSTPIP_PRST2_Pos) /**< (HSTPIP) Pipe 2 Reset Mask */
+#define HSTPIP_PRST3_Pos 19 /**< (HSTPIP) Pipe 3 Reset Position */
+#define HSTPIP_PRST3 (_U_(0x1) << HSTPIP_PRST3_Pos) /**< (HSTPIP) Pipe 3 Reset Mask */
+#define HSTPIP_PRST4_Pos 20 /**< (HSTPIP) Pipe 4 Reset Position */
+#define HSTPIP_PRST4 (_U_(0x1) << HSTPIP_PRST4_Pos) /**< (HSTPIP) Pipe 4 Reset Mask */
+#define HSTPIP_PRST5_Pos 21 /**< (HSTPIP) Pipe 5 Reset Position */
+#define HSTPIP_PRST5 (_U_(0x1) << HSTPIP_PRST5_Pos) /**< (HSTPIP) Pipe 5 Reset Mask */
+#define HSTPIP_PRST6_Pos 22 /**< (HSTPIP) Pipe 6 Reset Position */
+#define HSTPIP_PRST6 (_U_(0x1) << HSTPIP_PRST6_Pos) /**< (HSTPIP) Pipe 6 Reset Mask */
+#define HSTPIP_PRST7_Pos 23 /**< (HSTPIP) Pipe 7 Reset Position */
+#define HSTPIP_PRST7 (_U_(0x1) << HSTPIP_PRST7_Pos) /**< (HSTPIP) Pipe 7 Reset Mask */
+#define HSTPIP_PRST8_Pos 24 /**< (HSTPIP) Pipe 8 Reset Position */
+#define HSTPIP_PRST8 (_U_(0x1) << HSTPIP_PRST8_Pos) /**< (HSTPIP) Pipe 8 Reset Mask */
+#define HSTPIP_Msk _U_(0x1FF01FF) /**< (HSTPIP) Register Mask */
+
+#define HSTPIP_PEN_Pos 0 /**< (HSTPIP Position) Pipe x Enable */
+#define HSTPIP_PEN (_U_(0x1FF) << HSTPIP_PEN_Pos) /**< (HSTPIP Mask) PEN */
+#define HSTPIP_PRST_Pos 16 /**< (HSTPIP Position) Pipe 8 Reset */
+#define HSTPIP_PRST (_U_(0x1FF) << HSTPIP_PRST_Pos) /**< (HSTPIP Mask) PRST */
+
+/* -------- HSTFNUM : (USBHS Offset: 0x420) (R/W 32) Host Frame Number Register -------- */
+
+#define HSTFNUM_OFFSET (0x420) /**< (HSTFNUM) Host Frame Number Register Offset */
+
+#define HSTFNUM_MFNUM_Pos 0 /**< (HSTFNUM) Micro Frame Number Position */
+#define HSTFNUM_MFNUM (_U_(0x7) << HSTFNUM_MFNUM_Pos) /**< (HSTFNUM) Micro Frame Number Mask */
+#define HSTFNUM_FNUM_Pos 3 /**< (HSTFNUM) Frame Number Position */
+#define HSTFNUM_FNUM (_U_(0x7FF) << HSTFNUM_FNUM_Pos) /**< (HSTFNUM) Frame Number Mask */
+#define HSTFNUM_FLENHIGH_Pos 16 /**< (HSTFNUM) Frame Length Position */
+#define HSTFNUM_FLENHIGH (_U_(0xFF) << HSTFNUM_FLENHIGH_Pos) /**< (HSTFNUM) Frame Length Mask */
+#define HSTFNUM_Msk _U_(0xFF3FFF) /**< (HSTFNUM) Register Mask */
+
+
+/* -------- HSTADDR1 : (USBHS Offset: 0x424) (R/W 32) Host Address 1 Register -------- */
+
+#define HSTADDR1_OFFSET (0x424) /**< (HSTADDR1) Host Address 1 Register Offset */
+
+#define HSTADDR1_HSTADDRP0_Pos 0 /**< (HSTADDR1) USB Host Address Position */
+#define HSTADDR1_HSTADDRP0 (_U_(0x7F) << HSTADDR1_HSTADDRP0_Pos) /**< (HSTADDR1) USB Host Address Mask */
+#define HSTADDR1_HSTADDRP1_Pos 8 /**< (HSTADDR1) USB Host Address Position */
+#define HSTADDR1_HSTADDRP1 (_U_(0x7F) << HSTADDR1_HSTADDRP1_Pos) /**< (HSTADDR1) USB Host Address Mask */
+#define HSTADDR1_HSTADDRP2_Pos 16 /**< (HSTADDR1) USB Host Address Position */
+#define HSTADDR1_HSTADDRP2 (_U_(0x7F) << HSTADDR1_HSTADDRP2_Pos) /**< (HSTADDR1) USB Host Address Mask */
+#define HSTADDR1_HSTADDRP3_Pos 24 /**< (HSTADDR1) USB Host Address Position */
+#define HSTADDR1_HSTADDRP3 (_U_(0x7F) << HSTADDR1_HSTADDRP3_Pos) /**< (HSTADDR1) USB Host Address Mask */
+#define HSTADDR1_Msk _U_(0x7F7F7F7F) /**< (HSTADDR1) Register Mask */
+
+
+/* -------- HSTADDR2 : (USBHS Offset: 0x428) (R/W 32) Host Address 2 Register -------- */
+
+#define HSTADDR2_OFFSET (0x428) /**< (HSTADDR2) Host Address 2 Register Offset */
+
+#define HSTADDR2_HSTADDRP4_Pos 0 /**< (HSTADDR2) USB Host Address Position */
+#define HSTADDR2_HSTADDRP4 (_U_(0x7F) << HSTADDR2_HSTADDRP4_Pos) /**< (HSTADDR2) USB Host Address Mask */
+#define HSTADDR2_HSTADDRP5_Pos 8 /**< (HSTADDR2) USB Host Address Position */
+#define HSTADDR2_HSTADDRP5 (_U_(0x7F) << HSTADDR2_HSTADDRP5_Pos) /**< (HSTADDR2) USB Host Address Mask */
+#define HSTADDR2_HSTADDRP6_Pos 16 /**< (HSTADDR2) USB Host Address Position */
+#define HSTADDR2_HSTADDRP6 (_U_(0x7F) << HSTADDR2_HSTADDRP6_Pos) /**< (HSTADDR2) USB Host Address Mask */
+#define HSTADDR2_HSTADDRP7_Pos 24 /**< (HSTADDR2) USB Host Address Position */
+#define HSTADDR2_HSTADDRP7 (_U_(0x7F) << HSTADDR2_HSTADDRP7_Pos) /**< (HSTADDR2) USB Host Address Mask */
+#define HSTADDR2_Msk _U_(0x7F7F7F7F) /**< (HSTADDR2) Register Mask */
+
+
+/* -------- HSTADDR3 : (USBHS Offset: 0x42c) (R/W 32) Host Address 3 Register -------- */
+
+#define HSTADDR3_OFFSET (0x42C) /**< (HSTADDR3) Host Address 3 Register Offset */
+
+#define HSTADDR3_HSTADDRP8_Pos 0 /**< (HSTADDR3) USB Host Address Position */
+#define HSTADDR3_HSTADDRP8 (_U_(0x7F) << HSTADDR3_HSTADDRP8_Pos) /**< (HSTADDR3) USB Host Address Mask */
+#define HSTADDR3_HSTADDRP9_Pos 8 /**< (HSTADDR3) USB Host Address Position */
+#define HSTADDR3_HSTADDRP9 (_U_(0x7F) << HSTADDR3_HSTADDRP9_Pos) /**< (HSTADDR3) USB Host Address Mask */
+#define HSTADDR3_Msk _U_(0x7F7F) /**< (HSTADDR3) Register Mask */
+
+
+/* -------- HSTPIPCFG : (USBHS Offset: 0x500) (R/W 32) Host Pipe Configuration Register -------- */
+
+#define HSTPIPCFG_OFFSET (0x500) /**< (HSTPIPCFG) Host Pipe Configuration Register Offset */
+
+#define HSTPIPCFG_ALLOC_Pos 1 /**< (HSTPIPCFG) Pipe Memory Allocate Position */
+#define HSTPIPCFG_ALLOC (_U_(0x1) << HSTPIPCFG_ALLOC_Pos) /**< (HSTPIPCFG) Pipe Memory Allocate Mask */
+#define HSTPIPCFG_PBK_Pos 2 /**< (HSTPIPCFG) Pipe Banks Position */
+#define HSTPIPCFG_PBK (_U_(0x3) << HSTPIPCFG_PBK_Pos) /**< (HSTPIPCFG) Pipe Banks Mask */
+#define HSTPIPCFG_PBK_1_BANK_Val _U_(0x0) /**< (HSTPIPCFG) Single-bank pipe */
+#define HSTPIPCFG_PBK_2_BANK_Val _U_(0x1) /**< (HSTPIPCFG) Double-bank pipe */
+#define HSTPIPCFG_PBK_3_BANK_Val _U_(0x2) /**< (HSTPIPCFG) Triple-bank pipe */
+#define HSTPIPCFG_PBK_1_BANK (HSTPIPCFG_PBK_1_BANK_Val << HSTPIPCFG_PBK_Pos) /**< (HSTPIPCFG) Single-bank pipe Position */
+#define HSTPIPCFG_PBK_2_BANK (HSTPIPCFG_PBK_2_BANK_Val << HSTPIPCFG_PBK_Pos) /**< (HSTPIPCFG) Double-bank pipe Position */
+#define HSTPIPCFG_PBK_3_BANK (HSTPIPCFG_PBK_3_BANK_Val << HSTPIPCFG_PBK_Pos) /**< (HSTPIPCFG) Triple-bank pipe Position */
+#define HSTPIPCFG_PSIZE_Pos 4 /**< (HSTPIPCFG) Pipe Size Position */
+#define HSTPIPCFG_PSIZE (_U_(0x7) << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) Pipe Size Mask */
+#define HSTPIPCFG_PSIZE_8_BYTE_Val _U_(0x0) /**< (HSTPIPCFG) 8 bytes */
+#define HSTPIPCFG_PSIZE_16_BYTE_Val _U_(0x1) /**< (HSTPIPCFG) 16 bytes */
+#define HSTPIPCFG_PSIZE_32_BYTE_Val _U_(0x2) /**< (HSTPIPCFG) 32 bytes */
+#define HSTPIPCFG_PSIZE_64_BYTE_Val _U_(0x3) /**< (HSTPIPCFG) 64 bytes */
+#define HSTPIPCFG_PSIZE_128_BYTE_Val _U_(0x4) /**< (HSTPIPCFG) 128 bytes */
+#define HSTPIPCFG_PSIZE_256_BYTE_Val _U_(0x5) /**< (HSTPIPCFG) 256 bytes */
+#define HSTPIPCFG_PSIZE_512_BYTE_Val _U_(0x6) /**< (HSTPIPCFG) 512 bytes */
+#define HSTPIPCFG_PSIZE_1024_BYTE_Val _U_(0x7) /**< (HSTPIPCFG) 1024 bytes */
+#define HSTPIPCFG_PSIZE_8_BYTE (HSTPIPCFG_PSIZE_8_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 8 bytes Position */
+#define HSTPIPCFG_PSIZE_16_BYTE (HSTPIPCFG_PSIZE_16_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 16 bytes Position */
+#define HSTPIPCFG_PSIZE_32_BYTE (HSTPIPCFG_PSIZE_32_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 32 bytes Position */
+#define HSTPIPCFG_PSIZE_64_BYTE (HSTPIPCFG_PSIZE_64_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 64 bytes Position */
+#define HSTPIPCFG_PSIZE_128_BYTE (HSTPIPCFG_PSIZE_128_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 128 bytes Position */
+#define HSTPIPCFG_PSIZE_256_BYTE (HSTPIPCFG_PSIZE_256_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 256 bytes Position */
+#define HSTPIPCFG_PSIZE_512_BYTE (HSTPIPCFG_PSIZE_512_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 512 bytes Position */
+#define HSTPIPCFG_PSIZE_1024_BYTE (HSTPIPCFG_PSIZE_1024_BYTE_Val << HSTPIPCFG_PSIZE_Pos) /**< (HSTPIPCFG) 1024 bytes Position */
+#define HSTPIPCFG_PTOKEN_Pos 8 /**< (HSTPIPCFG) Pipe Token Position */
+#define HSTPIPCFG_PTOKEN (_U_(0x3) << HSTPIPCFG_PTOKEN_Pos) /**< (HSTPIPCFG) Pipe Token Mask */
+#define HSTPIPCFG_PTOKEN_SETUP_Val _U_(0x0) /**< (HSTPIPCFG) SETUP */
+#define HSTPIPCFG_PTOKEN_IN_Val _U_(0x1) /**< (HSTPIPCFG) IN */
+#define HSTPIPCFG_PTOKEN_OUT_Val _U_(0x2) /**< (HSTPIPCFG) OUT */
+#define HSTPIPCFG_PTOKEN_SETUP (HSTPIPCFG_PTOKEN_SETUP_Val << HSTPIPCFG_PTOKEN_Pos) /**< (HSTPIPCFG) SETUP Position */
+#define HSTPIPCFG_PTOKEN_IN (HSTPIPCFG_PTOKEN_IN_Val << HSTPIPCFG_PTOKEN_Pos) /**< (HSTPIPCFG) IN Position */
+#define HSTPIPCFG_PTOKEN_OUT (HSTPIPCFG_PTOKEN_OUT_Val << HSTPIPCFG_PTOKEN_Pos) /**< (HSTPIPCFG) OUT Position */
+#define HSTPIPCFG_AUTOSW_Pos 10 /**< (HSTPIPCFG) Automatic Switch Position */
+#define HSTPIPCFG_AUTOSW (_U_(0x1) << HSTPIPCFG_AUTOSW_Pos) /**< (HSTPIPCFG) Automatic Switch Mask */
+#define HSTPIPCFG_PTYPE_Pos 12 /**< (HSTPIPCFG) Pipe Type Position */
+#define HSTPIPCFG_PTYPE (_U_(0x3) << HSTPIPCFG_PTYPE_Pos) /**< (HSTPIPCFG) Pipe Type Mask */
+#define HSTPIPCFG_PTYPE_CTRL_Val _U_(0x0) /**< (HSTPIPCFG) Control */
+#define HSTPIPCFG_PTYPE_ISO_Val _U_(0x1) /**< (HSTPIPCFG) Isochronous */
+#define HSTPIPCFG_PTYPE_BLK_Val _U_(0x2) /**< (HSTPIPCFG) Bulk */
+#define HSTPIPCFG_PTYPE_INTRPT_Val _U_(0x3) /**< (HSTPIPCFG) Interrupt */
+#define HSTPIPCFG_PTYPE_CTRL (HSTPIPCFG_PTYPE_CTRL_Val << HSTPIPCFG_PTYPE_Pos) /**< (HSTPIPCFG) Control Position */
+#define HSTPIPCFG_PTYPE_ISO (HSTPIPCFG_PTYPE_ISO_Val << HSTPIPCFG_PTYPE_Pos) /**< (HSTPIPCFG) Isochronous Position */
+#define HSTPIPCFG_PTYPE_BLK (HSTPIPCFG_PTYPE_BLK_Val << HSTPIPCFG_PTYPE_Pos) /**< (HSTPIPCFG) Bulk Position */
+#define HSTPIPCFG_PTYPE_INTRPT (HSTPIPCFG_PTYPE_INTRPT_Val << HSTPIPCFG_PTYPE_Pos) /**< (HSTPIPCFG) Interrupt Position */
+#define HSTPIPCFG_PEPNUM_Pos 16 /**< (HSTPIPCFG) Pipe Endpoint Number Position */
+#define HSTPIPCFG_PEPNUM (_U_(0xF) << HSTPIPCFG_PEPNUM_Pos) /**< (HSTPIPCFG) Pipe Endpoint Number Mask */
+#define HSTPIPCFG_INTFRQ_Pos 24 /**< (HSTPIPCFG) Pipe Interrupt Request Frequency Position */
+#define HSTPIPCFG_INTFRQ (_U_(0xFF) << HSTPIPCFG_INTFRQ_Pos) /**< (HSTPIPCFG) Pipe Interrupt Request Frequency Mask */
+#define HSTPIPCFG_Msk _U_(0xFF0F377E) /**< (HSTPIPCFG) Register Mask */
+
+/* CTRL_BULK mode */
+#define HSTPIPCFG_CTRL_BULK_PINGEN_Pos 20 /**< (HSTPIPCFG) Ping Enable Position */
+#define HSTPIPCFG_CTRL_BULK_PINGEN (_U_(0x1) << HSTPIPCFG_CTRL_BULK_PINGEN_Pos) /**< (HSTPIPCFG) Ping Enable Mask */
+#define HSTPIPCFG_CTRL_BULK_BINTERVAL_Pos 24 /**< (HSTPIPCFG) bInterval Parameter for the Bulk-Out/Ping Transaction Position */
+#define HSTPIPCFG_CTRL_BULK_BINTERVAL (_U_(0xFF) << HSTPIPCFG_CTRL_BULK_BINTERVAL_Pos) /**< (HSTPIPCFG) bInterval Parameter for the Bulk-Out/Ping Transaction Mask */
+#define HSTPIPCFG_CTRL_BULK_Msk _U_(0xFF100000) /**< (HSTPIPCFG_CTRL_BULK) Register Mask */
+
+
+/* -------- HSTPIPISR : (USBHS Offset: 0x530) (R/ 32) Host Pipe Status Register -------- */
+
+#define HSTPIPISR_OFFSET (0x530) /**< (HSTPIPISR) Host Pipe Status Register Offset */
+
+#define HSTPIPISR_RXINI_Pos 0 /**< (HSTPIPISR) Received IN Data Interrupt Position */
+#define HSTPIPISR_RXINI (_U_(0x1) << HSTPIPISR_RXINI_Pos) /**< (HSTPIPISR) Received IN Data Interrupt Mask */
+#define HSTPIPISR_TXOUTI_Pos 1 /**< (HSTPIPISR) Transmitted OUT Data Interrupt Position */
+#define HSTPIPISR_TXOUTI (_U_(0x1) << HSTPIPISR_TXOUTI_Pos) /**< (HSTPIPISR) Transmitted OUT Data Interrupt Mask */
+#define HSTPIPISR_PERRI_Pos 3 /**< (HSTPIPISR) Pipe Error Interrupt Position */
+#define HSTPIPISR_PERRI (_U_(0x1) << HSTPIPISR_PERRI_Pos) /**< (HSTPIPISR) Pipe Error Interrupt Mask */
+#define HSTPIPISR_NAKEDI_Pos 4 /**< (HSTPIPISR) NAKed Interrupt Position */
+#define HSTPIPISR_NAKEDI (_U_(0x1) << HSTPIPISR_NAKEDI_Pos) /**< (HSTPIPISR) NAKed Interrupt Mask */
+#define HSTPIPISR_OVERFI_Pos 5 /**< (HSTPIPISR) Overflow Interrupt Position */
+#define HSTPIPISR_OVERFI (_U_(0x1) << HSTPIPISR_OVERFI_Pos) /**< (HSTPIPISR) Overflow Interrupt Mask */
+#define HSTPIPISR_SHORTPACKETI_Pos 7 /**< (HSTPIPISR) Short Packet Interrupt Position */
+#define HSTPIPISR_SHORTPACKETI (_U_(0x1) << HSTPIPISR_SHORTPACKETI_Pos) /**< (HSTPIPISR) Short Packet Interrupt Mask */
+#define HSTPIPISR_DTSEQ_Pos 8 /**< (HSTPIPISR) Data Toggle Sequence Position */
+#define HSTPIPISR_DTSEQ (_U_(0x3) << HSTPIPISR_DTSEQ_Pos) /**< (HSTPIPISR) Data Toggle Sequence Mask */
+#define HSTPIPISR_DTSEQ_DATA0_Val _U_(0x0) /**< (HSTPIPISR) Data0 toggle sequence */
+#define HSTPIPISR_DTSEQ_DATA1_Val _U_(0x1) /**< (HSTPIPISR) Data1 toggle sequence */
+#define HSTPIPISR_DTSEQ_DATA0 (HSTPIPISR_DTSEQ_DATA0_Val << HSTPIPISR_DTSEQ_Pos) /**< (HSTPIPISR) Data0 toggle sequence Position */
+#define HSTPIPISR_DTSEQ_DATA1 (HSTPIPISR_DTSEQ_DATA1_Val << HSTPIPISR_DTSEQ_Pos) /**< (HSTPIPISR) Data1 toggle sequence Position */
+#define HSTPIPISR_NBUSYBK_Pos 12 /**< (HSTPIPISR) Number of Busy Banks Position */
+#define HSTPIPISR_NBUSYBK (_U_(0x3) << HSTPIPISR_NBUSYBK_Pos) /**< (HSTPIPISR) Number of Busy Banks Mask */
+#define HSTPIPISR_NBUSYBK_0_BUSY_Val _U_(0x0) /**< (HSTPIPISR) 0 busy bank (all banks free) */
+#define HSTPIPISR_NBUSYBK_1_BUSY_Val _U_(0x1) /**< (HSTPIPISR) 1 busy bank */
+#define HSTPIPISR_NBUSYBK_2_BUSY_Val _U_(0x2) /**< (HSTPIPISR) 2 busy banks */
+#define HSTPIPISR_NBUSYBK_3_BUSY_Val _U_(0x3) /**< (HSTPIPISR) 3 busy banks */
+#define HSTPIPISR_NBUSYBK_0_BUSY (HSTPIPISR_NBUSYBK_0_BUSY_Val << HSTPIPISR_NBUSYBK_Pos) /**< (HSTPIPISR) 0 busy bank (all banks free) Position */
+#define HSTPIPISR_NBUSYBK_1_BUSY (HSTPIPISR_NBUSYBK_1_BUSY_Val << HSTPIPISR_NBUSYBK_Pos) /**< (HSTPIPISR) 1 busy bank Position */
+#define HSTPIPISR_NBUSYBK_2_BUSY (HSTPIPISR_NBUSYBK_2_BUSY_Val << HSTPIPISR_NBUSYBK_Pos) /**< (HSTPIPISR) 2 busy banks Position */
+#define HSTPIPISR_NBUSYBK_3_BUSY (HSTPIPISR_NBUSYBK_3_BUSY_Val << HSTPIPISR_NBUSYBK_Pos) /**< (HSTPIPISR) 3 busy banks Position */
+#define HSTPIPISR_CURRBK_Pos 14 /**< (HSTPIPISR) Current Bank Position */
+#define HSTPIPISR_CURRBK (_U_(0x3) << HSTPIPISR_CURRBK_Pos) /**< (HSTPIPISR) Current Bank Mask */
+#define HSTPIPISR_CURRBK_BANK0_Val _U_(0x0) /**< (HSTPIPISR) Current bank is bank0 */
+#define HSTPIPISR_CURRBK_BANK1_Val _U_(0x1) /**< (HSTPIPISR) Current bank is bank1 */
+#define HSTPIPISR_CURRBK_BANK2_Val _U_(0x2) /**< (HSTPIPISR) Current bank is bank2 */
+#define HSTPIPISR_CURRBK_BANK0 (HSTPIPISR_CURRBK_BANK0_Val << HSTPIPISR_CURRBK_Pos) /**< (HSTPIPISR) Current bank is bank0 Position */
+#define HSTPIPISR_CURRBK_BANK1 (HSTPIPISR_CURRBK_BANK1_Val << HSTPIPISR_CURRBK_Pos) /**< (HSTPIPISR) Current bank is bank1 Position */
+#define HSTPIPISR_CURRBK_BANK2 (HSTPIPISR_CURRBK_BANK2_Val << HSTPIPISR_CURRBK_Pos) /**< (HSTPIPISR) Current bank is bank2 Position */
+#define HSTPIPISR_RWALL_Pos 16 /**< (HSTPIPISR) Read/Write Allowed Position */
+#define HSTPIPISR_RWALL (_U_(0x1) << HSTPIPISR_RWALL_Pos) /**< (HSTPIPISR) Read/Write Allowed Mask */
+#define HSTPIPISR_CFGOK_Pos 18 /**< (HSTPIPISR) Configuration OK Status Position */
+#define HSTPIPISR_CFGOK (_U_(0x1) << HSTPIPISR_CFGOK_Pos) /**< (HSTPIPISR) Configuration OK Status Mask */
+#define HSTPIPISR_PBYCT_Pos 20 /**< (HSTPIPISR) Pipe Byte Count Position */
+#define HSTPIPISR_PBYCT (_U_(0x7FF) << HSTPIPISR_PBYCT_Pos) /**< (HSTPIPISR) Pipe Byte Count Mask */
+#define HSTPIPISR_Msk _U_(0x7FF5F3BB) /**< (HSTPIPISR) Register Mask */
+
+/* CTRL mode */
+#define HSTPIPISR_CTRL_TXSTPI_Pos 2 /**< (HSTPIPISR) Transmitted SETUP Interrupt Position */
+#define HSTPIPISR_CTRL_TXSTPI (_U_(0x1) << HSTPIPISR_CTRL_TXSTPI_Pos) /**< (HSTPIPISR) Transmitted SETUP Interrupt Mask */
+#define HSTPIPISR_CTRL_RXSTALLDI_Pos 6 /**< (HSTPIPISR) Received STALLed Interrupt Position */
+#define HSTPIPISR_CTRL_RXSTALLDI (_U_(0x1) << HSTPIPISR_CTRL_RXSTALLDI_Pos) /**< (HSTPIPISR) Received STALLed Interrupt Mask */
+#define HSTPIPISR_CTRL_Msk _U_(0x44) /**< (HSTPIPISR_CTRL) Register Mask */
+
+/* ISO mode */
+#define HSTPIPISR_ISO_UNDERFI_Pos 2 /**< (HSTPIPISR) Underflow Interrupt Position */
+#define HSTPIPISR_ISO_UNDERFI (_U_(0x1) << HSTPIPISR_ISO_UNDERFI_Pos) /**< (HSTPIPISR) Underflow Interrupt Mask */
+#define HSTPIPISR_ISO_CRCERRI_Pos 6 /**< (HSTPIPISR) CRC Error Interrupt Position */
+#define HSTPIPISR_ISO_CRCERRI (_U_(0x1) << HSTPIPISR_ISO_CRCERRI_Pos) /**< (HSTPIPISR) CRC Error Interrupt Mask */
+#define HSTPIPISR_ISO_Msk _U_(0x44) /**< (HSTPIPISR_ISO) Register Mask */
+
+/* BLK mode */
+#define HSTPIPISR_BLK_TXSTPI_Pos 2 /**< (HSTPIPISR) Transmitted SETUP Interrupt Position */
+#define HSTPIPISR_BLK_TXSTPI (_U_(0x1) << HSTPIPISR_BLK_TXSTPI_Pos) /**< (HSTPIPISR) Transmitted SETUP Interrupt Mask */
+#define HSTPIPISR_BLK_RXSTALLDI_Pos 6 /**< (HSTPIPISR) Received STALLed Interrupt Position */
+#define HSTPIPISR_BLK_RXSTALLDI (_U_(0x1) << HSTPIPISR_BLK_RXSTALLDI_Pos) /**< (HSTPIPISR) Received STALLed Interrupt Mask */
+#define HSTPIPISR_BLK_Msk _U_(0x44) /**< (HSTPIPISR_BLK) Register Mask */
+
+/* INTRPT mode */
+#define HSTPIPISR_INTRPT_UNDERFI_Pos 2 /**< (HSTPIPISR) Underflow Interrupt Position */
+#define HSTPIPISR_INTRPT_UNDERFI (_U_(0x1) << HSTPIPISR_INTRPT_UNDERFI_Pos) /**< (HSTPIPISR) Underflow Interrupt Mask */
+#define HSTPIPISR_INTRPT_RXSTALLDI_Pos 6 /**< (HSTPIPISR) Received STALLed Interrupt Position */
+#define HSTPIPISR_INTRPT_RXSTALLDI (_U_(0x1) << HSTPIPISR_INTRPT_RXSTALLDI_Pos) /**< (HSTPIPISR) Received STALLed Interrupt Mask */
+#define HSTPIPISR_INTRPT_Msk _U_(0x44) /**< (HSTPIPISR_INTRPT) Register Mask */
+
+
+/* -------- HSTPIPICR : (USBHS Offset: 0x560) (/W 32) Host Pipe Clear Register -------- */
+
+#define HSTPIPICR_OFFSET (0x560) /**< (HSTPIPICR) Host Pipe Clear Register Offset */
+
+#define HSTPIPICR_RXINIC_Pos 0 /**< (HSTPIPICR) Received IN Data Interrupt Clear Position */
+#define HSTPIPICR_RXINIC (_U_(0x1) << HSTPIPICR_RXINIC_Pos) /**< (HSTPIPICR) Received IN Data Interrupt Clear Mask */
+#define HSTPIPICR_TXOUTIC_Pos 1 /**< (HSTPIPICR) Transmitted OUT Data Interrupt Clear Position */
+#define HSTPIPICR_TXOUTIC (_U_(0x1) << HSTPIPICR_TXOUTIC_Pos) /**< (HSTPIPICR) Transmitted OUT Data Interrupt Clear Mask */
+#define HSTPIPICR_NAKEDIC_Pos 4 /**< (HSTPIPICR) NAKed Interrupt Clear Position */
+#define HSTPIPICR_NAKEDIC (_U_(0x1) << HSTPIPICR_NAKEDIC_Pos) /**< (HSTPIPICR) NAKed Interrupt Clear Mask */
+#define HSTPIPICR_OVERFIC_Pos 5 /**< (HSTPIPICR) Overflow Interrupt Clear Position */
+#define HSTPIPICR_OVERFIC (_U_(0x1) << HSTPIPICR_OVERFIC_Pos) /**< (HSTPIPICR) Overflow Interrupt Clear Mask */
+#define HSTPIPICR_SHORTPACKETIC_Pos 7 /**< (HSTPIPICR) Short Packet Interrupt Clear Position */
+#define HSTPIPICR_SHORTPACKETIC (_U_(0x1) << HSTPIPICR_SHORTPACKETIC_Pos) /**< (HSTPIPICR) Short Packet Interrupt Clear Mask */
+#define HSTPIPICR_Msk _U_(0xB3) /**< (HSTPIPICR) Register Mask */
+
+/* CTRL mode */
+#define HSTPIPICR_CTRL_TXSTPIC_Pos 2 /**< (HSTPIPICR) Transmitted SETUP Interrupt Clear Position */
+#define HSTPIPICR_CTRL_TXSTPIC (_U_(0x1) << HSTPIPICR_CTRL_TXSTPIC_Pos) /**< (HSTPIPICR) Transmitted SETUP Interrupt Clear Mask */
+#define HSTPIPICR_CTRL_RXSTALLDIC_Pos 6 /**< (HSTPIPICR) Received STALLed Interrupt Clear Position */
+#define HSTPIPICR_CTRL_RXSTALLDIC (_U_(0x1) << HSTPIPICR_CTRL_RXSTALLDIC_Pos) /**< (HSTPIPICR) Received STALLed Interrupt Clear Mask */
+#define HSTPIPICR_CTRL_Msk _U_(0x44) /**< (HSTPIPICR_CTRL) Register Mask */
+
+/* ISO mode */
+#define HSTPIPICR_ISO_UNDERFIC_Pos 2 /**< (HSTPIPICR) Underflow Interrupt Clear Position */
+#define HSTPIPICR_ISO_UNDERFIC (_U_(0x1) << HSTPIPICR_ISO_UNDERFIC_Pos) /**< (HSTPIPICR) Underflow Interrupt Clear Mask */
+#define HSTPIPICR_ISO_CRCERRIC_Pos 6 /**< (HSTPIPICR) CRC Error Interrupt Clear Position */
+#define HSTPIPICR_ISO_CRCERRIC (_U_(0x1) << HSTPIPICR_ISO_CRCERRIC_Pos) /**< (HSTPIPICR) CRC Error Interrupt Clear Mask */
+#define HSTPIPICR_ISO_Msk _U_(0x44) /**< (HSTPIPICR_ISO) Register Mask */
+
+/* BLK mode */
+#define HSTPIPICR_BLK_TXSTPIC_Pos 2 /**< (HSTPIPICR) Transmitted SETUP Interrupt Clear Position */
+#define HSTPIPICR_BLK_TXSTPIC (_U_(0x1) << HSTPIPICR_BLK_TXSTPIC_Pos) /**< (HSTPIPICR) Transmitted SETUP Interrupt Clear Mask */
+#define HSTPIPICR_BLK_RXSTALLDIC_Pos 6 /**< (HSTPIPICR) Received STALLed Interrupt Clear Position */
+#define HSTPIPICR_BLK_RXSTALLDIC (_U_(0x1) << HSTPIPICR_BLK_RXSTALLDIC_Pos) /**< (HSTPIPICR) Received STALLed Interrupt Clear Mask */
+#define HSTPIPICR_BLK_Msk _U_(0x44) /**< (HSTPIPICR_BLK) Register Mask */
+
+/* INTRPT mode */
+#define HSTPIPICR_INTRPT_UNDERFIC_Pos 2 /**< (HSTPIPICR) Underflow Interrupt Clear Position */
+#define HSTPIPICR_INTRPT_UNDERFIC (_U_(0x1) << HSTPIPICR_INTRPT_UNDERFIC_Pos) /**< (HSTPIPICR) Underflow Interrupt Clear Mask */
+#define HSTPIPICR_INTRPT_RXSTALLDIC_Pos 6 /**< (HSTPIPICR) Received STALLed Interrupt Clear Position */
+#define HSTPIPICR_INTRPT_RXSTALLDIC (_U_(0x1) << HSTPIPICR_INTRPT_RXSTALLDIC_Pos) /**< (HSTPIPICR) Received STALLed Interrupt Clear Mask */
+#define HSTPIPICR_INTRPT_Msk _U_(0x44) /**< (HSTPIPICR_INTRPT) Register Mask */
+
+
+/* -------- HSTPIPIFR : (USBHS Offset: 0x590) (/W 32) Host Pipe Set Register -------- */
+
+#define HSTPIPIFR_OFFSET (0x590) /**< (HSTPIPIFR) Host Pipe Set Register Offset */
+
+#define HSTPIPIFR_RXINIS_Pos 0 /**< (HSTPIPIFR) Received IN Data Interrupt Set Position */
+#define HSTPIPIFR_RXINIS (_U_(0x1) << HSTPIPIFR_RXINIS_Pos) /**< (HSTPIPIFR) Received IN Data Interrupt Set Mask */
+#define HSTPIPIFR_TXOUTIS_Pos 1 /**< (HSTPIPIFR) Transmitted OUT Data Interrupt Set Position */
+#define HSTPIPIFR_TXOUTIS (_U_(0x1) << HSTPIPIFR_TXOUTIS_Pos) /**< (HSTPIPIFR) Transmitted OUT Data Interrupt Set Mask */
+#define HSTPIPIFR_PERRIS_Pos 3 /**< (HSTPIPIFR) Pipe Error Interrupt Set Position */
+#define HSTPIPIFR_PERRIS (_U_(0x1) << HSTPIPIFR_PERRIS_Pos) /**< (HSTPIPIFR) Pipe Error Interrupt Set Mask */
+#define HSTPIPIFR_NAKEDIS_Pos 4 /**< (HSTPIPIFR) NAKed Interrupt Set Position */
+#define HSTPIPIFR_NAKEDIS (_U_(0x1) << HSTPIPIFR_NAKEDIS_Pos) /**< (HSTPIPIFR) NAKed Interrupt Set Mask */
+#define HSTPIPIFR_OVERFIS_Pos 5 /**< (HSTPIPIFR) Overflow Interrupt Set Position */
+#define HSTPIPIFR_OVERFIS (_U_(0x1) << HSTPIPIFR_OVERFIS_Pos) /**< (HSTPIPIFR) Overflow Interrupt Set Mask */
+#define HSTPIPIFR_SHORTPACKETIS_Pos 7 /**< (HSTPIPIFR) Short Packet Interrupt Set Position */
+#define HSTPIPIFR_SHORTPACKETIS (_U_(0x1) << HSTPIPIFR_SHORTPACKETIS_Pos) /**< (HSTPIPIFR) Short Packet Interrupt Set Mask */
+#define HSTPIPIFR_NBUSYBKS_Pos 12 /**< (HSTPIPIFR) Number of Busy Banks Set Position */
+#define HSTPIPIFR_NBUSYBKS (_U_(0x1) << HSTPIPIFR_NBUSYBKS_Pos) /**< (HSTPIPIFR) Number of Busy Banks Set Mask */
+#define HSTPIPIFR_Msk _U_(0x10BB) /**< (HSTPIPIFR) Register Mask */
+
+/* CTRL mode */
+#define HSTPIPIFR_CTRL_TXSTPIS_Pos 2 /**< (HSTPIPIFR) Transmitted SETUP Interrupt Set Position */
+#define HSTPIPIFR_CTRL_TXSTPIS (_U_(0x1) << HSTPIPIFR_CTRL_TXSTPIS_Pos) /**< (HSTPIPIFR) Transmitted SETUP Interrupt Set Mask */
+#define HSTPIPIFR_CTRL_RXSTALLDIS_Pos 6 /**< (HSTPIPIFR) Received STALLed Interrupt Set Position */
+#define HSTPIPIFR_CTRL_RXSTALLDIS (_U_(0x1) << HSTPIPIFR_CTRL_RXSTALLDIS_Pos) /**< (HSTPIPIFR) Received STALLed Interrupt Set Mask */
+#define HSTPIPIFR_CTRL_Msk _U_(0x44) /**< (HSTPIPIFR_CTRL) Register Mask */
+
+/* ISO mode */
+#define HSTPIPIFR_ISO_UNDERFIS_Pos 2 /**< (HSTPIPIFR) Underflow Interrupt Set Position */
+#define HSTPIPIFR_ISO_UNDERFIS (_U_(0x1) << HSTPIPIFR_ISO_UNDERFIS_Pos) /**< (HSTPIPIFR) Underflow Interrupt Set Mask */
+#define HSTPIPIFR_ISO_CRCERRIS_Pos 6 /**< (HSTPIPIFR) CRC Error Interrupt Set Position */
+#define HSTPIPIFR_ISO_CRCERRIS (_U_(0x1) << HSTPIPIFR_ISO_CRCERRIS_Pos) /**< (HSTPIPIFR) CRC Error Interrupt Set Mask */
+#define HSTPIPIFR_ISO_Msk _U_(0x44) /**< (HSTPIPIFR_ISO) Register Mask */
+
+/* BLK mode */
+#define HSTPIPIFR_BLK_TXSTPIS_Pos 2 /**< (HSTPIPIFR) Transmitted SETUP Interrupt Set Position */
+#define HSTPIPIFR_BLK_TXSTPIS (_U_(0x1) << HSTPIPIFR_BLK_TXSTPIS_Pos) /**< (HSTPIPIFR) Transmitted SETUP Interrupt Set Mask */
+#define HSTPIPIFR_BLK_RXSTALLDIS_Pos 6 /**< (HSTPIPIFR) Received STALLed Interrupt Set Position */
+#define HSTPIPIFR_BLK_RXSTALLDIS (_U_(0x1) << HSTPIPIFR_BLK_RXSTALLDIS_Pos) /**< (HSTPIPIFR) Received STALLed Interrupt Set Mask */
+#define HSTPIPIFR_BLK_Msk _U_(0x44) /**< (HSTPIPIFR_BLK) Register Mask */
+
+/* INTRPT mode */
+#define HSTPIPIFR_INTRPT_UNDERFIS_Pos 2 /**< (HSTPIPIFR) Underflow Interrupt Set Position */
+#define HSTPIPIFR_INTRPT_UNDERFIS (_U_(0x1) << HSTPIPIFR_INTRPT_UNDERFIS_Pos) /**< (HSTPIPIFR) Underflow Interrupt Set Mask */
+#define HSTPIPIFR_INTRPT_RXSTALLDIS_Pos 6 /**< (HSTPIPIFR) Received STALLed Interrupt Set Position */
+#define HSTPIPIFR_INTRPT_RXSTALLDIS (_U_(0x1) << HSTPIPIFR_INTRPT_RXSTALLDIS_Pos) /**< (HSTPIPIFR) Received STALLed Interrupt Set Mask */
+#define HSTPIPIFR_INTRPT_Msk _U_(0x44) /**< (HSTPIPIFR_INTRPT) Register Mask */
+
+
+/* -------- HSTPIPIMR : (USBHS Offset: 0x5c0) (R/ 32) Host Pipe Mask Register -------- */
+
+#define HSTPIPIMR_OFFSET (0x5C0) /**< (HSTPIPIMR) Host Pipe Mask Register Offset */
+
+#define HSTPIPIMR_RXINE_Pos 0 /**< (HSTPIPIMR) Received IN Data Interrupt Enable Position */
+#define HSTPIPIMR_RXINE (_U_(0x1) << HSTPIPIMR_RXINE_Pos) /**< (HSTPIPIMR) Received IN Data Interrupt Enable Mask */
+#define HSTPIPIMR_TXOUTE_Pos 1 /**< (HSTPIPIMR) Transmitted OUT Data Interrupt Enable Position */
+#define HSTPIPIMR_TXOUTE (_U_(0x1) << HSTPIPIMR_TXOUTE_Pos) /**< (HSTPIPIMR) Transmitted OUT Data Interrupt Enable Mask */
+#define HSTPIPIMR_PERRE_Pos 3 /**< (HSTPIPIMR) Pipe Error Interrupt Enable Position */
+#define HSTPIPIMR_PERRE (_U_(0x1) << HSTPIPIMR_PERRE_Pos) /**< (HSTPIPIMR) Pipe Error Interrupt Enable Mask */
+#define HSTPIPIMR_NAKEDE_Pos 4 /**< (HSTPIPIMR) NAKed Interrupt Enable Position */
+#define HSTPIPIMR_NAKEDE (_U_(0x1) << HSTPIPIMR_NAKEDE_Pos) /**< (HSTPIPIMR) NAKed Interrupt Enable Mask */
+#define HSTPIPIMR_OVERFIE_Pos 5 /**< (HSTPIPIMR) Overflow Interrupt Enable Position */
+#define HSTPIPIMR_OVERFIE (_U_(0x1) << HSTPIPIMR_OVERFIE_Pos) /**< (HSTPIPIMR) Overflow Interrupt Enable Mask */
+#define HSTPIPIMR_SHORTPACKETIE_Pos 7 /**< (HSTPIPIMR) Short Packet Interrupt Enable Position */
+#define HSTPIPIMR_SHORTPACKETIE (_U_(0x1) << HSTPIPIMR_SHORTPACKETIE_Pos) /**< (HSTPIPIMR) Short Packet Interrupt Enable Mask */
+#define HSTPIPIMR_NBUSYBKE_Pos 12 /**< (HSTPIPIMR) Number of Busy Banks Interrupt Enable Position */
+#define HSTPIPIMR_NBUSYBKE (_U_(0x1) << HSTPIPIMR_NBUSYBKE_Pos) /**< (HSTPIPIMR) Number of Busy Banks Interrupt Enable Mask */
+#define HSTPIPIMR_FIFOCON_Pos 14 /**< (HSTPIPIMR) FIFO Control Position */
+#define HSTPIPIMR_FIFOCON (_U_(0x1) << HSTPIPIMR_FIFOCON_Pos) /**< (HSTPIPIMR) FIFO Control Mask */
+#define HSTPIPIMR_PDISHDMA_Pos 16 /**< (HSTPIPIMR) Pipe Interrupts Disable HDMA Request Enable Position */
+#define HSTPIPIMR_PDISHDMA (_U_(0x1) << HSTPIPIMR_PDISHDMA_Pos) /**< (HSTPIPIMR) Pipe Interrupts Disable HDMA Request Enable Mask */
+#define HSTPIPIMR_PFREEZE_Pos 17 /**< (HSTPIPIMR) Pipe Freeze Position */
+#define HSTPIPIMR_PFREEZE (_U_(0x1) << HSTPIPIMR_PFREEZE_Pos) /**< (HSTPIPIMR) Pipe Freeze Mask */
+#define HSTPIPIMR_RSTDT_Pos 18 /**< (HSTPIPIMR) Reset Data Toggle Position */
+#define HSTPIPIMR_RSTDT (_U_(0x1) << HSTPIPIMR_RSTDT_Pos) /**< (HSTPIPIMR) Reset Data Toggle Mask */
+#define HSTPIPIMR_Msk _U_(0x750BB) /**< (HSTPIPIMR) Register Mask */
+
+/* CTRL mode */
+#define HSTPIPIMR_CTRL_TXSTPE_Pos 2 /**< (HSTPIPIMR) Transmitted SETUP Interrupt Enable Position */
+#define HSTPIPIMR_CTRL_TXSTPE (_U_(0x1) << HSTPIPIMR_CTRL_TXSTPE_Pos) /**< (HSTPIPIMR) Transmitted SETUP Interrupt Enable Mask */
+#define HSTPIPIMR_CTRL_RXSTALLDE_Pos 6 /**< (HSTPIPIMR) Received STALLed Interrupt Enable Position */
+#define HSTPIPIMR_CTRL_RXSTALLDE (_U_(0x1) << HSTPIPIMR_CTRL_RXSTALLDE_Pos) /**< (HSTPIPIMR) Received STALLed Interrupt Enable Mask */
+#define HSTPIPIMR_CTRL_Msk _U_(0x44) /**< (HSTPIPIMR_CTRL) Register Mask */
+
+/* ISO mode */
+#define HSTPIPIMR_ISO_UNDERFIE_Pos 2 /**< (HSTPIPIMR) Underflow Interrupt Enable Position */
+#define HSTPIPIMR_ISO_UNDERFIE (_U_(0x1) << HSTPIPIMR_ISO_UNDERFIE_Pos) /**< (HSTPIPIMR) Underflow Interrupt Enable Mask */
+#define HSTPIPIMR_ISO_CRCERRE_Pos 6 /**< (HSTPIPIMR) CRC Error Interrupt Enable Position */
+#define HSTPIPIMR_ISO_CRCERRE (_U_(0x1) << HSTPIPIMR_ISO_CRCERRE_Pos) /**< (HSTPIPIMR) CRC Error Interrupt Enable Mask */
+#define HSTPIPIMR_ISO_Msk _U_(0x44) /**< (HSTPIPIMR_ISO) Register Mask */
+
+/* BLK mode */
+#define HSTPIPIMR_BLK_TXSTPE_Pos 2 /**< (HSTPIPIMR) Transmitted SETUP Interrupt Enable Position */
+#define HSTPIPIMR_BLK_TXSTPE (_U_(0x1) << HSTPIPIMR_BLK_TXSTPE_Pos) /**< (HSTPIPIMR) Transmitted SETUP Interrupt Enable Mask */
+#define HSTPIPIMR_BLK_RXSTALLDE_Pos 6 /**< (HSTPIPIMR) Received STALLed Interrupt Enable Position */
+#define HSTPIPIMR_BLK_RXSTALLDE (_U_(0x1) << HSTPIPIMR_BLK_RXSTALLDE_Pos) /**< (HSTPIPIMR) Received STALLed Interrupt Enable Mask */
+#define HSTPIPIMR_BLK_Msk _U_(0x44) /**< (HSTPIPIMR_BLK) Register Mask */
+
+/* INTRPT mode */
+#define HSTPIPIMR_INTRPT_UNDERFIE_Pos 2 /**< (HSTPIPIMR) Underflow Interrupt Enable Position */
+#define HSTPIPIMR_INTRPT_UNDERFIE (_U_(0x1) << HSTPIPIMR_INTRPT_UNDERFIE_Pos) /**< (HSTPIPIMR) Underflow Interrupt Enable Mask */
+#define HSTPIPIMR_INTRPT_RXSTALLDE_Pos 6 /**< (HSTPIPIMR) Received STALLed Interrupt Enable Position */
+#define HSTPIPIMR_INTRPT_RXSTALLDE (_U_(0x1) << HSTPIPIMR_INTRPT_RXSTALLDE_Pos) /**< (HSTPIPIMR) Received STALLed Interrupt Enable Mask */
+#define HSTPIPIMR_INTRPT_Msk _U_(0x44) /**< (HSTPIPIMR_INTRPT) Register Mask */
+
+
+/* -------- HSTPIPIER : (USBHS Offset: 0x5f0) (/W 32) Host Pipe Enable Register -------- */
+
+#define HSTPIPIER_OFFSET (0x5F0) /**< (HSTPIPIER) Host Pipe Enable Register Offset */
+
+#define HSTPIPIER_RXINES_Pos 0 /**< (HSTPIPIER) Received IN Data Interrupt Enable Position */
+#define HSTPIPIER_RXINES (_U_(0x1) << HSTPIPIER_RXINES_Pos) /**< (HSTPIPIER) Received IN Data Interrupt Enable Mask */
+#define HSTPIPIER_TXOUTES_Pos 1 /**< (HSTPIPIER) Transmitted OUT Data Interrupt Enable Position */
+#define HSTPIPIER_TXOUTES (_U_(0x1) << HSTPIPIER_TXOUTES_Pos) /**< (HSTPIPIER) Transmitted OUT Data Interrupt Enable Mask */
+#define HSTPIPIER_PERRES_Pos 3 /**< (HSTPIPIER) Pipe Error Interrupt Enable Position */
+#define HSTPIPIER_PERRES (_U_(0x1) << HSTPIPIER_PERRES_Pos) /**< (HSTPIPIER) Pipe Error Interrupt Enable Mask */
+#define HSTPIPIER_NAKEDES_Pos 4 /**< (HSTPIPIER) NAKed Interrupt Enable Position */
+#define HSTPIPIER_NAKEDES (_U_(0x1) << HSTPIPIER_NAKEDES_Pos) /**< (HSTPIPIER) NAKed Interrupt Enable Mask */
+#define HSTPIPIER_OVERFIES_Pos 5 /**< (HSTPIPIER) Overflow Interrupt Enable Position */
+#define HSTPIPIER_OVERFIES (_U_(0x1) << HSTPIPIER_OVERFIES_Pos) /**< (HSTPIPIER) Overflow Interrupt Enable Mask */
+#define HSTPIPIER_SHORTPACKETIES_Pos 7 /**< (HSTPIPIER) Short Packet Interrupt Enable Position */
+#define HSTPIPIER_SHORTPACKETIES (_U_(0x1) << HSTPIPIER_SHORTPACKETIES_Pos) /**< (HSTPIPIER) Short Packet Interrupt Enable Mask */
+#define HSTPIPIER_NBUSYBKES_Pos 12 /**< (HSTPIPIER) Number of Busy Banks Enable Position */
+#define HSTPIPIER_NBUSYBKES (_U_(0x1) << HSTPIPIER_NBUSYBKES_Pos) /**< (HSTPIPIER) Number of Busy Banks Enable Mask */
+#define HSTPIPIER_PDISHDMAS_Pos 16 /**< (HSTPIPIER) Pipe Interrupts Disable HDMA Request Enable Position */
+#define HSTPIPIER_PDISHDMAS (_U_(0x1) << HSTPIPIER_PDISHDMAS_Pos) /**< (HSTPIPIER) Pipe Interrupts Disable HDMA Request Enable Mask */
+#define HSTPIPIER_PFREEZES_Pos 17 /**< (HSTPIPIER) Pipe Freeze Enable Position */
+#define HSTPIPIER_PFREEZES (_U_(0x1) << HSTPIPIER_PFREEZES_Pos) /**< (HSTPIPIER) Pipe Freeze Enable Mask */
+#define HSTPIPIER_RSTDTS_Pos 18 /**< (HSTPIPIER) Reset Data Toggle Enable Position */
+#define HSTPIPIER_RSTDTS (_U_(0x1) << HSTPIPIER_RSTDTS_Pos) /**< (HSTPIPIER) Reset Data Toggle Enable Mask */
+#define HSTPIPIER_Msk _U_(0x710BB) /**< (HSTPIPIER) Register Mask */
+
+/* CTRL mode */
+#define HSTPIPIER_CTRL_TXSTPES_Pos 2 /**< (HSTPIPIER) Transmitted SETUP Interrupt Enable Position */
+#define HSTPIPIER_CTRL_TXSTPES (_U_(0x1) << HSTPIPIER_CTRL_TXSTPES_Pos) /**< (HSTPIPIER) Transmitted SETUP Interrupt Enable Mask */
+#define HSTPIPIER_CTRL_RXSTALLDES_Pos 6 /**< (HSTPIPIER) Received STALLed Interrupt Enable Position */
+#define HSTPIPIER_CTRL_RXSTALLDES (_U_(0x1) << HSTPIPIER_CTRL_RXSTALLDES_Pos) /**< (HSTPIPIER) Received STALLed Interrupt Enable Mask */
+#define HSTPIPIER_CTRL_Msk _U_(0x44) /**< (HSTPIPIER_CTRL) Register Mask */
+
+/* ISO mode */
+#define HSTPIPIER_ISO_UNDERFIES_Pos 2 /**< (HSTPIPIER) Underflow Interrupt Enable Position */
+#define HSTPIPIER_ISO_UNDERFIES (_U_(0x1) << HSTPIPIER_ISO_UNDERFIES_Pos) /**< (HSTPIPIER) Underflow Interrupt Enable Mask */
+#define HSTPIPIER_ISO_CRCERRES_Pos 6 /**< (HSTPIPIER) CRC Error Interrupt Enable Position */
+#define HSTPIPIER_ISO_CRCERRES (_U_(0x1) << HSTPIPIER_ISO_CRCERRES_Pos) /**< (HSTPIPIER) CRC Error Interrupt Enable Mask */
+#define HSTPIPIER_ISO_Msk _U_(0x44) /**< (HSTPIPIER_ISO) Register Mask */
+
+/* BLK mode */
+#define HSTPIPIER_BLK_TXSTPES_Pos 2 /**< (HSTPIPIER) Transmitted SETUP Interrupt Enable Position */
+#define HSTPIPIER_BLK_TXSTPES (_U_(0x1) << HSTPIPIER_BLK_TXSTPES_Pos) /**< (HSTPIPIER) Transmitted SETUP Interrupt Enable Mask */
+#define HSTPIPIER_BLK_RXSTALLDES_Pos 6 /**< (HSTPIPIER) Received STALLed Interrupt Enable Position */
+#define HSTPIPIER_BLK_RXSTALLDES (_U_(0x1) << HSTPIPIER_BLK_RXSTALLDES_Pos) /**< (HSTPIPIER) Received STALLed Interrupt Enable Mask */
+#define HSTPIPIER_BLK_Msk _U_(0x44) /**< (HSTPIPIER_BLK) Register Mask */
+
+/* INTRPT mode */
+#define HSTPIPIER_INTRPT_UNDERFIES_Pos 2 /**< (HSTPIPIER) Underflow Interrupt Enable Position */
+#define HSTPIPIER_INTRPT_UNDERFIES (_U_(0x1) << HSTPIPIER_INTRPT_UNDERFIES_Pos) /**< (HSTPIPIER) Underflow Interrupt Enable Mask */
+#define HSTPIPIER_INTRPT_RXSTALLDES_Pos 6 /**< (HSTPIPIER) Received STALLed Interrupt Enable Position */
+#define HSTPIPIER_INTRPT_RXSTALLDES (_U_(0x1) << HSTPIPIER_INTRPT_RXSTALLDES_Pos) /**< (HSTPIPIER) Received STALLed Interrupt Enable Mask */
+#define HSTPIPIER_INTRPT_Msk _U_(0x44) /**< (HSTPIPIER_INTRPT) Register Mask */
+
+
+/* -------- HSTPIPIDR : (USBHS Offset: 0x620) (/W 32) Host Pipe Disable Register -------- */
+
+#define HSTPIPIDR_OFFSET (0x620) /**< (HSTPIPIDR) Host Pipe Disable Register Offset */
+
+#define HSTPIPIDR_RXINEC_Pos 0 /**< (HSTPIPIDR) Received IN Data Interrupt Disable Position */
+#define HSTPIPIDR_RXINEC (_U_(0x1) << HSTPIPIDR_RXINEC_Pos) /**< (HSTPIPIDR) Received IN Data Interrupt Disable Mask */
+#define HSTPIPIDR_TXOUTEC_Pos 1 /**< (HSTPIPIDR) Transmitted OUT Data Interrupt Disable Position */
+#define HSTPIPIDR_TXOUTEC (_U_(0x1) << HSTPIPIDR_TXOUTEC_Pos) /**< (HSTPIPIDR) Transmitted OUT Data Interrupt Disable Mask */
+#define HSTPIPIDR_PERREC_Pos 3 /**< (HSTPIPIDR) Pipe Error Interrupt Disable Position */
+#define HSTPIPIDR_PERREC (_U_(0x1) << HSTPIPIDR_PERREC_Pos) /**< (HSTPIPIDR) Pipe Error Interrupt Disable Mask */
+#define HSTPIPIDR_NAKEDEC_Pos 4 /**< (HSTPIPIDR) NAKed Interrupt Disable Position */
+#define HSTPIPIDR_NAKEDEC (_U_(0x1) << HSTPIPIDR_NAKEDEC_Pos) /**< (HSTPIPIDR) NAKed Interrupt Disable Mask */
+#define HSTPIPIDR_OVERFIEC_Pos 5 /**< (HSTPIPIDR) Overflow Interrupt Disable Position */
+#define HSTPIPIDR_OVERFIEC (_U_(0x1) << HSTPIPIDR_OVERFIEC_Pos) /**< (HSTPIPIDR) Overflow Interrupt Disable Mask */
+#define HSTPIPIDR_SHORTPACKETIEC_Pos 7 /**< (HSTPIPIDR) Short Packet Interrupt Disable Position */
+#define HSTPIPIDR_SHORTPACKETIEC (_U_(0x1) << HSTPIPIDR_SHORTPACKETIEC_Pos) /**< (HSTPIPIDR) Short Packet Interrupt Disable Mask */
+#define HSTPIPIDR_NBUSYBKEC_Pos 12 /**< (HSTPIPIDR) Number of Busy Banks Disable Position */
+#define HSTPIPIDR_NBUSYBKEC (_U_(0x1) << HSTPIPIDR_NBUSYBKEC_Pos) /**< (HSTPIPIDR) Number of Busy Banks Disable Mask */
+#define HSTPIPIDR_FIFOCONC_Pos 14 /**< (HSTPIPIDR) FIFO Control Disable Position */
+#define HSTPIPIDR_FIFOCONC (_U_(0x1) << HSTPIPIDR_FIFOCONC_Pos) /**< (HSTPIPIDR) FIFO Control Disable Mask */
+#define HSTPIPIDR_PDISHDMAC_Pos 16 /**< (HSTPIPIDR) Pipe Interrupts Disable HDMA Request Disable Position */
+#define HSTPIPIDR_PDISHDMAC (_U_(0x1) << HSTPIPIDR_PDISHDMAC_Pos) /**< (HSTPIPIDR) Pipe Interrupts Disable HDMA Request Disable Mask */
+#define HSTPIPIDR_PFREEZEC_Pos 17 /**< (HSTPIPIDR) Pipe Freeze Disable Position */
+#define HSTPIPIDR_PFREEZEC (_U_(0x1) << HSTPIPIDR_PFREEZEC_Pos) /**< (HSTPIPIDR) Pipe Freeze Disable Mask */
+#define HSTPIPIDR_Msk _U_(0x350BB) /**< (HSTPIPIDR) Register Mask */
+
+/* CTRL mode */
+#define HSTPIPIDR_CTRL_TXSTPEC_Pos 2 /**< (HSTPIPIDR) Transmitted SETUP Interrupt Disable Position */
+#define HSTPIPIDR_CTRL_TXSTPEC (_U_(0x1) << HSTPIPIDR_CTRL_TXSTPEC_Pos) /**< (HSTPIPIDR) Transmitted SETUP Interrupt Disable Mask */
+#define HSTPIPIDR_CTRL_RXSTALLDEC_Pos 6 /**< (HSTPIPIDR) Received STALLed Interrupt Disable Position */
+#define HSTPIPIDR_CTRL_RXSTALLDEC (_U_(0x1) << HSTPIPIDR_CTRL_RXSTALLDEC_Pos) /**< (HSTPIPIDR) Received STALLed Interrupt Disable Mask */
+#define HSTPIPIDR_CTRL_Msk _U_(0x44) /**< (HSTPIPIDR_CTRL) Register Mask */
+
+/* ISO mode */
+#define HSTPIPIDR_ISO_UNDERFIEC_Pos 2 /**< (HSTPIPIDR) Underflow Interrupt Disable Position */
+#define HSTPIPIDR_ISO_UNDERFIEC (_U_(0x1) << HSTPIPIDR_ISO_UNDERFIEC_Pos) /**< (HSTPIPIDR) Underflow Interrupt Disable Mask */
+#define HSTPIPIDR_ISO_CRCERREC_Pos 6 /**< (HSTPIPIDR) CRC Error Interrupt Disable Position */
+#define HSTPIPIDR_ISO_CRCERREC (_U_(0x1) << HSTPIPIDR_ISO_CRCERREC_Pos) /**< (HSTPIPIDR) CRC Error Interrupt Disable Mask */
+#define HSTPIPIDR_ISO_Msk _U_(0x44) /**< (HSTPIPIDR_ISO) Register Mask */
+
+/* BLK mode */
+#define HSTPIPIDR_BLK_TXSTPEC_Pos 2 /**< (HSTPIPIDR) Transmitted SETUP Interrupt Disable Position */
+#define HSTPIPIDR_BLK_TXSTPEC (_U_(0x1) << HSTPIPIDR_BLK_TXSTPEC_Pos) /**< (HSTPIPIDR) Transmitted SETUP Interrupt Disable Mask */
+#define HSTPIPIDR_BLK_RXSTALLDEC_Pos 6 /**< (HSTPIPIDR) Received STALLed Interrupt Disable Position */
+#define HSTPIPIDR_BLK_RXSTALLDEC (_U_(0x1) << HSTPIPIDR_BLK_RXSTALLDEC_Pos) /**< (HSTPIPIDR) Received STALLed Interrupt Disable Mask */
+#define HSTPIPIDR_BLK_Msk _U_(0x44) /**< (HSTPIPIDR_BLK) Register Mask */
+
+/* INTRPT mode */
+#define HSTPIPIDR_INTRPT_UNDERFIEC_Pos 2 /**< (HSTPIPIDR) Underflow Interrupt Disable Position */
+#define HSTPIPIDR_INTRPT_UNDERFIEC (_U_(0x1) << HSTPIPIDR_INTRPT_UNDERFIEC_Pos) /**< (HSTPIPIDR) Underflow Interrupt Disable Mask */
+#define HSTPIPIDR_INTRPT_RXSTALLDEC_Pos 6 /**< (HSTPIPIDR) Received STALLed Interrupt Disable Position */
+#define HSTPIPIDR_INTRPT_RXSTALLDEC (_U_(0x1) << HSTPIPIDR_INTRPT_RXSTALLDEC_Pos) /**< (HSTPIPIDR) Received STALLed Interrupt Disable Mask */
+#define HSTPIPIDR_INTRPT_Msk _U_(0x44) /**< (HSTPIPIDR_INTRPT) Register Mask */
+
+
+/* -------- HSTPIPINRQ : (USBHS Offset: 0x650) (R/W 32) Host Pipe IN Request Register -------- */
+
+#define HSTPIPINRQ_OFFSET (0x650) /**< (HSTPIPINRQ) Host Pipe IN Request Register Offset */
+
+#define HSTPIPINRQ_INRQ_Pos 0 /**< (HSTPIPINRQ) IN Request Number before Freeze Position */
+#define HSTPIPINRQ_INRQ (_U_(0xFF) << HSTPIPINRQ_INRQ_Pos) /**< (HSTPIPINRQ) IN Request Number before Freeze Mask */
+#define HSTPIPINRQ_INMODE_Pos 8 /**< (HSTPIPINRQ) IN Request Mode Position */
+#define HSTPIPINRQ_INMODE (_U_(0x1) << HSTPIPINRQ_INMODE_Pos) /**< (HSTPIPINRQ) IN Request Mode Mask */
+#define HSTPIPINRQ_Msk _U_(0x1FF) /**< (HSTPIPINRQ) Register Mask */
+
+
+/* -------- HSTPIPERR : (USBHS Offset: 0x680) (R/W 32) Host Pipe Error Register -------- */
+
+#define HSTPIPERR_OFFSET (0x680) /**< (HSTPIPERR) Host Pipe Error Register Offset */
+
+#define HSTPIPERR_DATATGL_Pos 0 /**< (HSTPIPERR) Data Toggle Error Position */
+#define HSTPIPERR_DATATGL (_U_(0x1) << HSTPIPERR_DATATGL_Pos) /**< (HSTPIPERR) Data Toggle Error Mask */
+#define HSTPIPERR_DATAPID_Pos 1 /**< (HSTPIPERR) Data PID Error Position */
+#define HSTPIPERR_DATAPID (_U_(0x1) << HSTPIPERR_DATAPID_Pos) /**< (HSTPIPERR) Data PID Error Mask */
+#define HSTPIPERR_PID_Pos 2 /**< (HSTPIPERR) Data PID Error Position */
+#define HSTPIPERR_PID (_U_(0x1) << HSTPIPERR_PID_Pos) /**< (HSTPIPERR) Data PID Error Mask */
+#define HSTPIPERR_TIMEOUT_Pos 3 /**< (HSTPIPERR) Time-Out Error Position */
+#define HSTPIPERR_TIMEOUT (_U_(0x1) << HSTPIPERR_TIMEOUT_Pos) /**< (HSTPIPERR) Time-Out Error Mask */
+#define HSTPIPERR_CRC16_Pos 4 /**< (HSTPIPERR) CRC16 Error Position */
+#define HSTPIPERR_CRC16 (_U_(0x1) << HSTPIPERR_CRC16_Pos) /**< (HSTPIPERR) CRC16 Error Mask */
+#define HSTPIPERR_COUNTER_Pos 5 /**< (HSTPIPERR) Error Counter Position */
+#define HSTPIPERR_COUNTER (_U_(0x3) << HSTPIPERR_COUNTER_Pos) /**< (HSTPIPERR) Error Counter Mask */
+#define HSTPIPERR_Msk _U_(0x7F) /**< (HSTPIPERR) Register Mask */
+
+#define HSTPIPERR_CRC_Pos 4 /**< (HSTPIPERR Position) CRCx6 Error */
+#define HSTPIPERR_CRC (_U_(0x1) << HSTPIPERR_CRC_Pos) /**< (HSTPIPERR Mask) CRC */
+
+/* -------- CTRL : (USBHS Offset: 0x800) (R/W 32) General Control Register -------- */
+
+#define CTRL_OFFSET (0x800) /**< (CTRL) General Control Register Offset */
+
+#define CTRL_RDERRE_Pos 4 /**< (CTRL) Remote Device Connection Error Interrupt Enable Position */
+#define CTRL_RDERRE (_U_(0x1) << CTRL_RDERRE_Pos) /**< (CTRL) Remote Device Connection Error Interrupt Enable Mask */
+#define CTRL_VBUSHWC_Pos 8 /**< (CTRL) VBUS Hardware Control Position */
+#define CTRL_VBUSHWC (_U_(0x1) << CTRL_VBUSHWC_Pos) /**< (CTRL) VBUS Hardware Control Mask */
+#define CTRL_FRZCLK_Pos 14 /**< (CTRL) Freeze USB Clock Position */
+#define CTRL_FRZCLK (_U_(0x1) << CTRL_FRZCLK_Pos) /**< (CTRL) Freeze USB Clock Mask */
+#define CTRL_USBE_Pos 15 /**< (CTRL) USBHS Enable Position */
+#define CTRL_USBE (_U_(0x1) << CTRL_USBE_Pos) /**< (CTRL) USBHS Enable Mask */
+#define CTRL_UID_Pos 24 /**< (CTRL) UID Pin Enable Position */
+#define CTRL_UID (_U_(0x1) << CTRL_UID_Pos) /**< (CTRL) UID Pin Enable Mask */
+#define CTRL_UIMOD_Pos 25 /**< (CTRL) USBHS Mode Position */
+#define CTRL_UIMOD (_U_(0x1) << CTRL_UIMOD_Pos) /**< (CTRL) USBHS Mode Mask */
+#define CTRL_UIMOD_HOST_Val _U_(0x0) /**< (CTRL) The module is in USB Host mode. */
+#define CTRL_UIMOD_DEVICE_Val _U_(0x1) /**< (CTRL) The module is in USB Device mode. */
+#define CTRL_UIMOD_HOST (CTRL_UIMOD_HOST_Val << CTRL_UIMOD_Pos) /**< (CTRL) The module is in USB Host mode. Position */
+#define CTRL_UIMOD_DEVICE (CTRL_UIMOD_DEVICE_Val << CTRL_UIMOD_Pos) /**< (CTRL) The module is in USB Device mode. Position */
+#define CTRL_Msk _U_(0x300C110) /**< (CTRL) Register Mask */
+
+
+/* -------- SR : (USBHS Offset: 0x804) (R/ 32) General Status Register -------- */
+
+#define SR_OFFSET (0x804) /**< (SR) General Status Register Offset */
+
+#define SR_RDERRI_Pos 4 /**< (SR) Remote Device Connection Error Interrupt (Host mode only) Position */
+#define SR_RDERRI (_U_(0x1) << SR_RDERRI_Pos) /**< (SR) Remote Device Connection Error Interrupt (Host mode only) Mask */
+#define SR_SPEED_Pos 12 /**< (SR) Speed Status (Device mode only) Position */
+#define SR_SPEED (_U_(0x3) << SR_SPEED_Pos) /**< (SR) Speed Status (Device mode only) Mask */
+#define SR_SPEED_FULL_SPEED_Val _U_(0x0) /**< (SR) Full-Speed mode */
+#define SR_SPEED_HIGH_SPEED_Val _U_(0x1) /**< (SR) High-Speed mode */
+#define SR_SPEED_LOW_SPEED_Val _U_(0x2) /**< (SR) Low-Speed mode */
+#define SR_SPEED_FULL_SPEED (SR_SPEED_FULL_SPEED_Val << SR_SPEED_Pos) /**< (SR) Full-Speed mode Position */
+#define SR_SPEED_HIGH_SPEED (SR_SPEED_HIGH_SPEED_Val << SR_SPEED_Pos) /**< (SR) High-Speed mode Position */
+#define SR_SPEED_LOW_SPEED (SR_SPEED_LOW_SPEED_Val << SR_SPEED_Pos) /**< (SR) Low-Speed mode Position */
+#define SR_CLKUSABLE_Pos 14 /**< (SR) UTMI Clock Usable Position */
+#define SR_CLKUSABLE (_U_(0x1) << SR_CLKUSABLE_Pos) /**< (SR) UTMI Clock Usable Mask */
+#define SR_Msk _U_(0x7010) /**< (SR) Register Mask */
+
+
+/* -------- SCR : (USBHS Offset: 0x808) (/W 32) General Status Clear Register -------- */
+
+#define SCR_OFFSET (0x808) /**< (SCR) General Status Clear Register Offset */
+
+#define SCR_RDERRIC_Pos 4 /**< (SCR) Remote Device Connection Error Interrupt Clear Position */
+#define SCR_RDERRIC (_U_(0x1) << SCR_RDERRIC_Pos) /**< (SCR) Remote Device Connection Error Interrupt Clear Mask */
+#define SCR_Msk _U_(0x10) /**< (SCR) Register Mask */
+
+
+/* -------- SFR : (USBHS Offset: 0x80c) (/W 32) General Status Set Register -------- */
+
+#define SFR_OFFSET (0x80C) /**< (SFR) General Status Set Register Offset */
+
+#define SFR_RDERRIS_Pos 4 /**< (SFR) Remote Device Connection Error Interrupt Set Position */
+#define SFR_RDERRIS (_U_(0x1) << SFR_RDERRIS_Pos) /**< (SFR) Remote Device Connection Error Interrupt Set Mask */
+#define SFR_VBUSRQS_Pos 9 /**< (SFR) VBUS Request Set Position */
+#define SFR_VBUSRQS (_U_(0x1) << SFR_VBUSRQS_Pos) /**< (SFR) VBUS Request Set Mask */
+#define SFR_Msk _U_(0x210) /**< (SFR) Register Mask */
+
+
+/** \brief DEVDMA hardware registers */
+typedef struct
+{
+ __IO uint32_t DEVDMANXTDSC; /**< (DEVDMA Offset: 0x00) Device DMA Channel Next Descriptor Address Register */
+ __IO uint32_t DEVDMAADDRESS; /**< (DEVDMA Offset: 0x04) Device DMA Channel Address Register */
+ __IO uint32_t DEVDMACONTROL; /**< (DEVDMA Offset: 0x08) Device DMA Channel Control Register */
+ __IO uint32_t DEVDMASTATUS; /**< (DEVDMA Offset: 0x0C) Device DMA Channel Status Register */
+} devdma_t;
+
+/** \brief HSTDMA hardware registers */
+typedef struct
+{
+ __IO uint32_t HSTDMANXTDSC; /**< (HSTDMA Offset: 0x00) Host DMA Channel Next Descriptor Address Register */
+ __IO uint32_t HSTDMAADDRESS; /**< (HSTDMA Offset: 0x04) Host DMA Channel Address Register */
+ __IO uint32_t HSTDMACONTROL; /**< (HSTDMA Offset: 0x08) Host DMA Channel Control Register */
+ __IO uint32_t HSTDMASTATUS; /**< (HSTDMA Offset: 0x0C) Host DMA Channel Status Register */
+} hstdma_t;
+
+/** \brief USBHS hardware registers */
+typedef struct
+{
+ __IO uint32_t DEVCTRL; /**< (USBHS Offset: 0x00) Device General Control Register */
+ __I uint32_t DEVISR; /**< (USBHS Offset: 0x04) Device Global Interrupt Status Register */
+ __O uint32_t DEVICR; /**< (USBHS Offset: 0x08) Device Global Interrupt Clear Register */
+ __O uint32_t DEVIFR; /**< (USBHS Offset: 0x0C) Device Global Interrupt Set Register */
+ __I uint32_t DEVIMR; /**< (USBHS Offset: 0x10) Device Global Interrupt Mask Register */
+ __O uint32_t DEVIDR; /**< (USBHS Offset: 0x14) Device Global Interrupt Disable Register */
+ __O uint32_t DEVIER; /**< (USBHS Offset: 0x18) Device Global Interrupt Enable Register */
+ __IO uint32_t DEVEPT; /**< (USBHS Offset: 0x1C) Device Endpoint Register */
+ __I uint32_t DEVFNUM; /**< (USBHS Offset: 0x20) Device Frame Number Register */
+ __I uint8_t Reserved1[220];
+ __IO uint32_t DEVEPTCFG[10]; /**< (USBHS Offset: 0x100) Device Endpoint Configuration Register */
+ __I uint8_t Reserved2[8];
+ __I uint32_t DEVEPTISR[10]; /**< (USBHS Offset: 0x130) Device Endpoint Interrupt Status Register */
+ __I uint8_t Reserved3[8];
+ __O uint32_t DEVEPTICR[10]; /**< (USBHS Offset: 0x160) Device Endpoint Interrupt Clear Register */
+ __I uint8_t Reserved4[8];
+ __O uint32_t DEVEPTIFR[10]; /**< (USBHS Offset: 0x190) Device Endpoint Interrupt Set Register */
+ __I uint8_t Reserved5[8];
+ __I uint32_t DEVEPTIMR[10]; /**< (USBHS Offset: 0x1C0) Device Endpoint Interrupt Mask Register */
+ __I uint8_t Reserved6[8];
+ __O uint32_t DEVEPTIER[10]; /**< (USBHS Offset: 0x1F0) Device Endpoint Interrupt Enable Register */
+ __I uint8_t Reserved7[8];
+ __O uint32_t DEVEPTIDR[10]; /**< (USBHS Offset: 0x220) Device Endpoint Interrupt Disable Register */
+ __I uint8_t Reserved8[200];
+ devdma_t DEVDMA[7]; /**< Offset: 0x310 Device DMA Channel Next Descriptor Address Register */
+ __I uint8_t Reserved9[128];
+ __IO uint32_t HSTCTRL; /**< (USBHS Offset: 0x400) Host General Control Register */
+ __I uint32_t HSTISR; /**< (USBHS Offset: 0x404) Host Global Interrupt Status Register */
+ __O uint32_t HSTICR; /**< (USBHS Offset: 0x408) Host Global Interrupt Clear Register */
+ __O uint32_t HSTIFR; /**< (USBHS Offset: 0x40C) Host Global Interrupt Set Register */
+ __I uint32_t HSTIMR; /**< (USBHS Offset: 0x410) Host Global Interrupt Mask Register */
+ __O uint32_t HSTIDR; /**< (USBHS Offset: 0x414) Host Global Interrupt Disable Register */
+ __O uint32_t HSTIER; /**< (USBHS Offset: 0x418) Host Global Interrupt Enable Register */
+ __IO uint32_t HSTPIP; /**< (USBHS Offset: 0x41C) Host Pipe Register */
+ __IO uint32_t HSTFNUM; /**< (USBHS Offset: 0x420) Host Frame Number Register */
+ __IO uint32_t HSTADDR1; /**< (USBHS Offset: 0x424) Host Address 1 Register */
+ __IO uint32_t HSTADDR2; /**< (USBHS Offset: 0x428) Host Address 2 Register */
+ __IO uint32_t HSTADDR3; /**< (USBHS Offset: 0x42C) Host Address 3 Register */
+ __I uint8_t Reserved10[208];
+ __IO uint32_t HSTPIPCFG[10]; /**< (USBHS Offset: 0x500) Host Pipe Configuration Register */
+ __I uint8_t Reserved11[8];
+ __I uint32_t HSTPIPISR[10]; /**< (USBHS Offset: 0x530) Host Pipe Status Register */
+ __I uint8_t Reserved12[8];
+ __O uint32_t HSTPIPICR[10]; /**< (USBHS Offset: 0x560) Host Pipe Clear Register */
+ __I uint8_t Reserved13[8];
+ __O uint32_t HSTPIPIFR[10]; /**< (USBHS Offset: 0x590) Host Pipe Set Register */
+ __I uint8_t Reserved14[8];
+ __I uint32_t HSTPIPIMR[10]; /**< (USBHS Offset: 0x5C0) Host Pipe Mask Register */
+ __I uint8_t Reserved15[8];
+ __O uint32_t HSTPIPIER[10]; /**< (USBHS Offset: 0x5F0) Host Pipe Enable Register */
+ __I uint8_t Reserved16[8];
+ __O uint32_t HSTPIPIDR[10]; /**< (USBHS Offset: 0x620) Host Pipe Disable Register */
+ __I uint8_t Reserved17[8];
+ __IO uint32_t HSTPIPINRQ[10]; /**< (USBHS Offset: 0x650) Host Pipe IN Request Register */
+ __I uint8_t Reserved18[8];
+ __IO uint32_t HSTPIPERR[10]; /**< (USBHS Offset: 0x680) Host Pipe Error Register */
+ __I uint8_t Reserved19[104];
+ hstdma_t HSTDMA[7]; /**< Offset: 0x710 Host DMA Channel Next Descriptor Address Register */
+ __I uint8_t Reserved20[128];
+ __IO uint32_t CTRL; /**< (USBHS Offset: 0x800) General Control Register */
+ __I uint32_t SR; /**< (USBHS Offset: 0x804) General Status Register */
+ __O uint32_t SCR; /**< (USBHS Offset: 0x808) General Status Clear Register */
+ __O uint32_t SFR; /**< (USBHS Offset: 0x80C) General Status Set Register */
+} dcd_registers_t;
+
+#define USB_REG ((dcd_registers_t *)0x40038000U) /**< \brief (USBHS) Base Address */
+
+#define EP_MAX 10
+
+#define FIFO_RAM_ADDR 0xA0100000u
+
+// Errata: The DMA feature is not available for Pipe/Endpoint 7
+#define EP_DMA_SUPPORT(epnum) (epnum >= 1 && epnum <= 6)
+
+#else // TODO : SAM3U
+
+
+#endif
+
+#endif /* _COMMON_USB_REGS_H_ */
diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c
new file mode 100644
index 000000000..032547e47
--- /dev/null
+++ b/src/portable/microchip/samx7x/dcd_samx7x.c
@@ -0,0 +1,768 @@
+/*
+* The MIT License (MIT)
+*
+* Copyright (c) 2018, hathach (tinyusb.org)
+* Copyright (c) 2021, HiFiPhile
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+* This file is part of the TinyUSB stack.
+*/
+
+#include "tusb_option.h"
+
+#if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_SAMX7X
+
+#include "device/dcd.h"
+#include "sam.h"
+#include "common_usb_regs.h"
+//--------------------------------------------------------------------+
+// MACRO TYPEDEF CONSTANT ENUM DECLARATION
+//--------------------------------------------------------------------+
+
+// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval)
+// We disable SOF for now until needed later on
+#ifndef USE_SOF
+# define USE_SOF 0
+#endif
+
+// Dual bank can imporve performance, but need 2 times bigger packet buffer
+// As SAM7x has only 4KB packet buffer, use with caution !
+// Enable in FS mode as packets are smaller
+#ifndef USE_DUAL_BANK
+# if TUD_OPT_HIGH_SPEED
+# define USE_DUAL_BANK 0
+# else
+# define USE_DUAL_BANK 1
+# endif
+#endif
+
+#define EP_GET_FIFO_PTR(ep, scale) (((TU_XSTRCAT(TU_STRCAT(uint, scale),_t) (*)[0x8000 / ((scale) / 8)])FIFO_RAM_ADDR)[(ep)])
+
+// DMA Channel Transfer Descriptor
+typedef struct {
+ volatile uint32_t next_desc;
+ volatile uint32_t buff_addr;
+ volatile uint32_t chnl_ctrl;
+ uint32_t padding;
+} dma_desc_t;
+
+// Transfer control context
+typedef struct {
+ uint8_t * buffer;
+ uint16_t total_len;
+ uint16_t queued_len;
+ uint16_t max_packet_size;
+ uint8_t interval;
+ tu_fifo_t * fifo;
+} xfer_ctl_t;
+
+static tusb_speed_t get_speed(void);
+static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix);
+
+// DMA descriptors shouldn't be placed in ITCM !
+CFG_TUSB_MEM_SECTION static dma_desc_t dma_desc[6];
+
+static xfer_ctl_t xfer_status[EP_MAX];
+
+static const tusb_desc_endpoint_t ep0_desc =
+{
+ .bEndpointAddress = 0x00,
+ .wMaxPacketSize = { .size = CFG_TUD_ENDPOINT0_SIZE },
+};
+
+TU_ATTR_ALWAYS_INLINE static inline void CleanInValidateCache(uint32_t *addr, int32_t size)
+{
+ if (SCB->CCR & SCB_CCR_DC_Msk)
+ {
+ SCB_CleanInvalidateDCache_by_Addr(addr, size);
+ }
+ else
+ {
+ __DSB();
+ __ISB();
+ }
+}
+//------------------------------------------------------------------
+// Device API
+//------------------------------------------------------------------
+
+// Initialize controller to device mode
+void dcd_init (uint8_t rhport)
+{
+ dcd_connect(rhport);
+}
+
+// Enable device interrupt
+void dcd_int_enable (uint8_t rhport)
+{
+ (void) rhport;
+ NVIC_EnableIRQ((IRQn_Type) ID_USBHS);
+}
+
+// Disable device interrupt
+void dcd_int_disable (uint8_t rhport)
+{
+ (void) rhport;
+ NVIC_DisableIRQ((IRQn_Type) ID_USBHS);
+}
+
+// Receive Set Address request, mcu port must also include status IN response
+void dcd_set_address (uint8_t rhport, uint8_t dev_addr)
+{
+ (void) dev_addr;
+ // DCD can only set address after status for this request is complete
+ // do it at dcd_edpt0_status_complete()
+
+ // Response with zlp status
+ dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0);
+}
+
+// Wake up host
+void dcd_remote_wakeup (uint8_t rhport)
+{
+ (void) rhport;
+ USB_REG->DEVCTRL |= DEVCTRL_RMWKUP;
+}
+
+// Connect by enabling internal pull-up resistor on D+/D-
+void dcd_connect(uint8_t rhport)
+{
+ (void) rhport;
+ dcd_int_disable(rhport);
+ // Enable the USB controller in device mode
+ USB_REG->CTRL = CTRL_UIMOD | CTRL_USBE;
+ while (!(USB_REG->SR & SR_CLKUSABLE));
+#if TUD_OPT_HIGH_SPEED
+ USB_REG->DEVCTRL &= ~DEVCTRL_SPDCONF;
+#else
+ USB_REG->DEVCTRL |= DEVCTRL_SPDCONF_LOW_POWER;
+#endif
+ // Enable the End Of Reset, Suspend & Wakeup interrupts
+ USB_REG->DEVIER = (DEVIER_EORSTES | DEVIER_SUSPES | DEVIER_WAKEUPES);
+#if USE_SOF
+ USB_REG->DEVIER = DEVIER_SOFES;
+#endif
+ // Clear the End Of Reset, SOF & Wakeup interrupts
+ USB_REG->DEVICR = (DEVICR_EORSTC | DEVICR_SOFC | DEVICR_WAKEUPC);
+ // Manually set the Suspend Interrupt
+ USB_REG->DEVIFR |= DEVIFR_SUSPS;
+ // Ack the Wakeup Interrupt
+ USB_REG->DEVICR = DEVICR_WAKEUPC;
+ // Attach the device
+ USB_REG->DEVCTRL &= ~DEVCTRL_DETACH;
+ // Freeze USB clock
+ USB_REG->CTRL |= CTRL_FRZCLK;
+}
+
+// Disconnect by disabling internal pull-up resistor on D+/D-
+void dcd_disconnect(uint8_t rhport)
+{
+ (void) rhport;
+ dcd_int_disable(rhport);
+ // Disable all endpoints
+ USB_REG->DEVEPT &= ~(0x3FF << DEVEPT_EPEN0_Pos);
+ // Unfreeze USB clock
+ USB_REG->CTRL &= ~CTRL_FRZCLK;
+ while (!(USB_REG->SR & SR_CLKUSABLE));
+ // Clear all the pending interrupts
+ USB_REG->DEVICR = DEVICR_Msk;
+ // Disable all interrupts
+ USB_REG->DEVIDR = DEVIDR_Msk;
+ // Detach the device
+ USB_REG->DEVCTRL |= DEVCTRL_DETACH;
+ // Disable the device address
+ USB_REG->DEVCTRL &=~(DEVCTRL_ADDEN | DEVCTRL_UADD);
+}
+
+static tusb_speed_t get_speed(void)
+{
+ switch (USB_REG->SR & SR_SPEED) {
+ case SR_SPEED_FULL_SPEED:
+ default:
+ return TUSB_SPEED_FULL;
+ case SR_SPEED_HIGH_SPEED:
+ return TUSB_SPEED_HIGH;
+ case SR_SPEED_LOW_SPEED:
+ return TUSB_SPEED_LOW;
+ }
+}
+
+static void dcd_ep_handler(uint8_t ep_ix)
+{
+ uint32_t int_status = USB_REG->DEVEPTISR[ep_ix];
+ int_status &= USB_REG->DEVEPTIMR[ep_ix];
+
+ uint16_t count = (USB_REG->DEVEPTISR[ep_ix] &
+ DEVEPTISR_BYCT) >> DEVEPTISR_BYCT_Pos;
+ xfer_ctl_t *xfer = &xfer_status[ep_ix];
+
+ if (ep_ix == 0U)
+ {
+ static uint8_t ctrl_dir;
+
+ if (int_status & DEVEPTISR_CTRL_RXSTPI)
+ {
+ ctrl_dir = (USB_REG->DEVEPTISR[0] & DEVEPTISR_CTRL_CTRLDIR) >> DEVEPTISR_CTRL_CTRLDIR_Pos;
+ // Setup packet should always be 8 bytes. If not, ignore it, and try again.
+ if (count == 8)
+ {
+ uint8_t *ptr = EP_GET_FIFO_PTR(0,8);
+ dcd_event_setup_received(0, ptr, true);
+ }
+ // Ack and disable SETUP interrupt
+ USB_REG->DEVEPTICR[0] = DEVEPTICR_CTRL_RXSTPIC;
+ USB_REG->DEVEPTIDR[0] = DEVEPTIDR_CTRL_RXSTPEC;
+ }
+ if (int_status & DEVEPTISR_RXOUTI)
+ {
+ uint8_t *ptr = EP_GET_FIFO_PTR(0,8);
+
+ if (count && xfer->total_len)
+ {
+ uint16_t remain = xfer->total_len - xfer->queued_len;
+ if (count > remain)
+ {
+ count = remain;
+ }
+ if (xfer->buffer)
+ {
+ memcpy(xfer->buffer + xfer->queued_len, ptr, count);
+ } else
+ {
+ tu_fifo_write_n(xfer->fifo, ptr, count);
+ }
+ xfer->queued_len = (uint16_t)(xfer->queued_len + count);
+ }
+ // Acknowledge the interrupt
+ USB_REG->DEVEPTICR[0] = DEVEPTICR_RXOUTIC;
+ if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len))
+ {
+ // RX COMPLETE
+ dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true);
+ // Disable the interrupt
+ USB_REG->DEVEPTIDR[0] = DEVEPTIDR_RXOUTEC;
+ // Re-enable SETUP interrupt
+ if (ctrl_dir == 1)
+ {
+ USB_REG->DEVEPTIER[0] = DEVEPTIER_CTRL_RXSTPES;
+ }
+ }
+ }
+ if (int_status & DEVEPTISR_TXINI)
+ {
+ // Disable the interrupt
+ USB_REG->DEVEPTIDR[0] = DEVEPTIDR_TXINEC;
+ if ((xfer->total_len != xfer->queued_len))
+ {
+ // TX not complete
+ dcd_transmit_packet(xfer, 0);
+ } else
+ {
+ // TX complete
+ dcd_event_xfer_complete(0, 0x80 + 0, xfer->total_len, XFER_RESULT_SUCCESS, true);
+ // Re-enable SETUP interrupt
+ if (ctrl_dir == 0)
+ {
+ USB_REG->DEVEPTIER[0] = DEVEPTIER_CTRL_RXSTPES;
+ }
+ }
+ }
+ } else
+ {
+ if (int_status & DEVEPTISR_RXOUTI)
+ {
+ if (count && xfer->total_len)
+ {
+ uint16_t remain = xfer->total_len - xfer->queued_len;
+ if (count > remain)
+ {
+ count = remain;
+ }
+ uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8);
+ if (xfer->buffer)
+ {
+ memcpy(xfer->buffer + xfer->queued_len, ptr, count);
+ } else {
+ tu_fifo_write_n(xfer->fifo, ptr, count);
+ }
+ xfer->queued_len = (uint16_t)(xfer->queued_len + count);
+ }
+ // Clear the FIFO control flag to receive more data.
+ USB_REG->DEVEPTIDR[ep_ix] = DEVEPTIDR_FIFOCONC;
+ // Acknowledge the interrupt
+ USB_REG->DEVEPTICR[ep_ix] = DEVEPTICR_RXOUTIC;
+ if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len))
+ {
+ // RX COMPLETE
+ dcd_event_xfer_complete(0, ep_ix, xfer->queued_len, XFER_RESULT_SUCCESS, true);
+ // Disable the interrupt
+ USB_REG->DEVEPTIDR[ep_ix] = DEVEPTIDR_RXOUTEC;
+ // Though the host could still send, we don't know.
+ }
+ }
+ if (int_status & DEVEPTISR_TXINI)
+ {
+ // Acknowledge the interrupt
+ USB_REG->DEVEPTICR[ep_ix] = DEVEPTICR_TXINIC;
+ if ((xfer->total_len != xfer->queued_len))
+ {
+ // TX not complete
+ dcd_transmit_packet(xfer, ep_ix);
+ } else
+ {
+ // TX complete
+ dcd_event_xfer_complete(0, 0x80 + ep_ix, xfer->total_len, XFER_RESULT_SUCCESS, true);
+ // Disable the interrupt
+ USB_REG->DEVEPTIDR[ep_ix] = DEVEPTIDR_TXINEC;
+ }
+ }
+ }
+}
+
+static void dcd_dma_handler(uint8_t ep_ix)
+{
+ uint32_t status = USB_REG->DEVDMA[ep_ix - 1].DEVDMASTATUS;
+ if (status & DEVDMASTATUS_CHANN_ENB)
+ {
+ return; // Ignore EOT_STA interrupt
+ }
+ // Disable DMA interrupt
+ USB_REG->DEVIDR = DEVIDR_DMA_1 << (ep_ix - 1);
+
+ xfer_ctl_t *xfer = &xfer_status[ep_ix];
+ uint16_t count = xfer->total_len - ((status & DEVDMASTATUS_BUFF_COUNT) >> DEVDMASTATUS_BUFF_COUNT_Pos);
+ if(USB_REG->DEVEPTCFG[ep_ix] & DEVEPTCFG_EPDIR)
+ {
+ dcd_event_xfer_complete(0, 0x80 + ep_ix, count, XFER_RESULT_SUCCESS, true);
+ } else
+ {
+ dcd_event_xfer_complete(0, ep_ix, count, XFER_RESULT_SUCCESS, true);
+ }
+}
+
+void dcd_int_handler(uint8_t rhport)
+{
+ (void) rhport;
+ uint32_t int_status = USB_REG->DEVISR;
+ int_status &= USB_REG->DEVIMR;
+ // End of reset interrupt
+ if (int_status & DEVISR_EORST)
+ {
+ // Unfreeze USB clock
+ USB_REG->CTRL &= ~CTRL_FRZCLK;
+ while(!(USB_REG->SR & SR_CLKUSABLE));
+ // Reset all endpoints
+ for (int ep_ix = 1; ep_ix < EP_MAX; ep_ix++)
+ {
+ USB_REG->DEVEPT |= 1 << (DEVEPT_EPRST0_Pos + ep_ix);
+ USB_REG->DEVEPT &=~(1 << (DEVEPT_EPRST0_Pos + ep_ix));
+ }
+ dcd_edpt_open (0, &ep0_desc);
+ USB_REG->DEVICR = DEVICR_EORSTC;
+ USB_REG->DEVICR = DEVICR_WAKEUPC;
+ USB_REG->DEVICR = DEVICR_SUSPC;
+ USB_REG->DEVIER = DEVIER_SUSPES;
+
+ dcd_event_bus_reset(rhport, get_speed(), true);
+ }
+ // End of Wakeup interrupt
+ if (int_status & DEVISR_WAKEUP)
+ {
+ USB_REG->CTRL &= ~CTRL_FRZCLK;
+ while (!(USB_REG->SR & SR_CLKUSABLE));
+ USB_REG->DEVICR = DEVICR_WAKEUPC;
+ USB_REG->DEVIDR = DEVIDR_WAKEUPEC;
+ USB_REG->DEVIER = DEVIER_SUSPES;
+
+ dcd_event_bus_signal(0, DCD_EVENT_RESUME, true);
+ }
+ // Suspend interrupt
+ if (int_status & DEVISR_SUSP)
+ {
+ // Unfreeze USB clock
+ USB_REG->CTRL &= ~CTRL_FRZCLK;
+ while (!(USB_REG->SR & SR_CLKUSABLE));
+ USB_REG->DEVICR = DEVICR_SUSPC;
+ USB_REG->DEVIDR = DEVIDR_SUSPEC;
+ USB_REG->DEVIER = DEVIER_WAKEUPES;
+ USB_REG->CTRL |= CTRL_FRZCLK;
+
+ dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true);
+ }
+#if USE_SOF
+ if(int_status & DEVISR_SOF)
+ {
+ USB_REG->DEVICR = DEVICR_SOFC;
+
+ dcd_event_bus_signal(0, DCD_EVENT_SOF, true);
+ }
+#endif
+ // Endpoints interrupt
+ for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++)
+ {
+ if (int_status & (DEVISR_PEP_0 << ep_ix))
+ {
+ dcd_ep_handler(ep_ix);
+ }
+ }
+ // Endpoints DMA interrupt
+ for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++)
+ {
+ if (EP_DMA_SUPPORT(ep_ix))
+ {
+ if (int_status & (DEVISR_DMA_1 << (ep_ix - 1)))
+ {
+ dcd_dma_handler(ep_ix);
+ }
+ }
+ }
+}
+
+//--------------------------------------------------------------------+
+// Endpoint API
+//--------------------------------------------------------------------+
+// Invoked when a control transfer's status stage is complete.
+// May help DCD to prepare for next control transfer, this API is optional.
+void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request)
+{
+ (void) rhport;
+
+ if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE &&
+ request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD &&
+ request->bRequest == TUSB_REQ_SET_ADDRESS )
+ {
+ uint8_t const dev_addr = (uint8_t) request->wValue;
+
+ USB_REG->DEVCTRL |= dev_addr | DEVCTRL_ADDEN;
+ }
+}
+
+// Configure endpoint's registers according to descriptor
+bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
+{
+ (void) rhport;
+ uint8_t const epnum = tu_edpt_number(ep_desc->bEndpointAddress);
+ uint8_t const dir = tu_edpt_dir(ep_desc->bEndpointAddress);
+ uint16_t const epMaxPktSize = ep_desc->wMaxPacketSize.size;
+ tusb_xfer_type_t const eptype = (tusb_xfer_type_t)ep_desc->bmAttributes.xfer;
+ uint8_t fifoSize = 0; // FIFO size
+ uint16_t defaultEndpointSize = 8; // Default size of Endpoint
+ // Find upper 2 power number of epMaxPktSize
+ if (epMaxPktSize)
+ {
+ while (defaultEndpointSize < epMaxPktSize)
+ {
+ fifoSize++;
+ defaultEndpointSize <<= 1;
+ }
+ }
+ xfer_status[epnum].max_packet_size = epMaxPktSize;
+
+ USB_REG->DEVEPT |= 1 << (DEVEPT_EPRST0_Pos + epnum);
+ USB_REG->DEVEPT &=~(1 << (DEVEPT_EPRST0_Pos + epnum));
+
+ if (epnum == 0)
+ {
+ // Enable the control endpoint - Endpoint 0
+ USB_REG->DEVEPT |= DEVEPT_EPEN0;
+ // Configure the Endpoint 0 configuration register
+ USB_REG->DEVEPTCFG[0] =
+ (
+ (fifoSize << DEVEPTCFG_EPSIZE_Pos) |
+ (TUSB_XFER_CONTROL << DEVEPTCFG_EPTYPE_Pos) |
+ (DEVEPTCFG_EPBK_1_BANK << DEVEPTCFG_EPBK_Pos) |
+ DEVEPTCFG_ALLOC
+ );
+ USB_REG->DEVEPTIER[0] = DEVEPTIER_RSTDTS;
+ USB_REG->DEVEPTIDR[0] = DEVEPTIDR_CTRL_STALLRQC;
+ if (DEVEPTISR_CFGOK == (USB_REG->DEVEPTISR[0] & DEVEPTISR_CFGOK))
+ {
+ // Endpoint configuration is successful
+ USB_REG->DEVEPTIER[0] = DEVEPTIER_CTRL_RXSTPES;
+ // Enable Endpoint 0 Interrupts
+ USB_REG->DEVIER = DEVIER_PEP_0;
+ return true;
+ } else
+ {
+ // Endpoint configuration is not successful
+ return false;
+ }
+ } else
+ {
+ // Enable the endpoint
+ USB_REG->DEVEPT |= ((0x01 << epnum) << DEVEPT_EPEN0_Pos);
+ // Set up the maxpacket size, fifo start address fifosize
+ // and enable the interrupt. CLear the data toggle.
+ // AUTOSW is needed for DMA ack !
+ USB_REG->DEVEPTCFG[epnum] =
+ (
+ (fifoSize << DEVEPTCFG_EPSIZE_Pos) |
+ (eptype << DEVEPTCFG_EPTYPE_Pos) |
+ (DEVEPTCFG_EPBK_1_BANK << DEVEPTCFG_EPBK_Pos) |
+ DEVEPTCFG_AUTOSW |
+ ((dir & 0x01) << DEVEPTCFG_EPDIR_Pos)
+ );
+ if (eptype == TUSB_XFER_ISOCHRONOUS)
+ {
+ USB_REG->DEVEPTCFG[epnum] |= DEVEPTCFG_NBTRANS_1_TRANS;
+ }
+#if USE_DUAL_BANK
+ if (eptype == TUSB_XFER_ISOCHRONOUS || eptype == TUSB_XFER_BULK)
+ {
+ USB_REG->DEVEPTCFG[epnum] |= DEVEPTCFG_EPBK_2_BANK;
+ }
+#endif
+ USB_REG->DEVEPTCFG[epnum] |= DEVEPTCFG_ALLOC;
+ USB_REG->DEVEPTIER[epnum] = DEVEPTIER_RSTDTS;
+ USB_REG->DEVEPTIDR[epnum] = DEVEPTIDR_CTRL_STALLRQC;
+ if (DEVEPTISR_CFGOK == (USB_REG->DEVEPTISR[epnum] & DEVEPTISR_CFGOK))
+ {
+ USB_REG->DEVIER = ((0x01 << epnum) << DEVIER_PEP_0_Pos);
+ return true;
+ } else
+ {
+ // Endpoint configuration is not successful
+ return false;
+ }
+ }
+}
+
+void dcd_edpt_close_all (uint8_t rhport)
+{
+ (void) rhport;
+ // TODO implement dcd_edpt_close_all()
+}
+
+void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
+{
+ (void) rhport;
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+
+ // Disable endpoint interrupt
+ USB_REG->DEVIDR = 1 << (DEVIDR_PEP_0_Pos + epnum);
+ // Disable EP
+ USB_REG->DEVEPT &=~(1 << (DEVEPT_EPEN0_Pos + epnum));
+}
+
+static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix)
+{
+ uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len);
+ if (len)
+ {
+ if (len > xfer->max_packet_size)
+ {
+ len = xfer->max_packet_size;
+ }
+ uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8);
+ if(xfer->buffer)
+ {
+ memcpy(ptr, xfer->buffer + xfer->queued_len, len);
+ }
+ else
+ {
+ tu_fifo_read_n(xfer->fifo, ptr, len);
+ }
+ __DSB();
+ __ISB();
+ xfer->queued_len = (uint16_t)(xfer->queued_len + len);
+ }
+ if (ep_ix == 0U)
+ {
+ // Control endpoint: clear the interrupt flag to send the data
+ USB_REG->DEVEPTICR[0] = DEVEPTICR_TXINIC;
+ } else
+ {
+ // Other endpoint types: clear the FIFO control flag to send the data
+ USB_REG->DEVEPTIDR[ep_ix] = DEVEPTIDR_FIFOCONC;
+ }
+ USB_REG->DEVEPTIER[ep_ix] = DEVEPTIER_TXINES;
+}
+
+// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack
+bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
+{
+ (void) rhport;
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
+
+ xfer_ctl_t * xfer = &xfer_status[epnum];
+
+ xfer->buffer = buffer;
+ xfer->total_len = total_bytes;
+ xfer->queued_len = 0;
+ xfer->fifo = NULL;
+
+ if (EP_DMA_SUPPORT(epnum) && total_bytes != 0)
+ {
+ // Force the CPU to flush the buffer. We increase the size by 32 because the call aligns the
+ // address to 32-byte boundaries.
+ CleanInValidateCache((uint32_t*) tu_align((uint32_t) buffer, 4), total_bytes + 31);
+ uint32_t udd_dma_ctrl = total_bytes << DEVDMACONTROL_BUFF_LENGTH_Pos;
+ if (dir == TUSB_DIR_OUT)
+ {
+ udd_dma_ctrl |= DEVDMACONTROL_END_TR_IT | DEVDMACONTROL_END_TR_EN;
+ } else {
+ udd_dma_ctrl |= DEVDMACONTROL_END_B_EN;
+ }
+ USB_REG->DEVDMA[epnum - 1].DEVDMAADDRESS = (uint32_t)buffer;
+ udd_dma_ctrl |= DEVDMACONTROL_END_BUFFIT | DEVDMACONTROL_CHANN_ENB;
+ // Disable IRQs to have a short sequence
+ // between read of EOT_STA and DMA enable
+ uint32_t irq_state = __get_PRIMASK();
+ __disable_irq();
+ if (!(USB_REG->DEVDMA[epnum - 1].DEVDMASTATUS & DEVDMASTATUS_END_TR_ST))
+ {
+ USB_REG->DEVDMA[epnum - 1].DEVDMACONTROL = udd_dma_ctrl;
+ USB_REG->DEVIER = DEVIER_DMA_1 << (epnum - 1);
+ __set_PRIMASK(irq_state);
+ return true;
+ }
+ __set_PRIMASK(irq_state);
+
+ // Here a ZLP has been recieved
+ // and the DMA transfer must be not started.
+ // It is the end of transfer
+ return false;
+ } else
+ {
+ if (dir == TUSB_DIR_OUT)
+ {
+ USB_REG->DEVEPTIER[epnum] = DEVEPTIER_RXOUTES;
+ } else
+ {
+ dcd_transmit_packet(xfer,epnum);
+ }
+ }
+ return true;
+}
+
+// The number of bytes has to be given explicitly to allow more flexible control of how many
+// bytes should be written and second to keep the return value free to give back a boolean
+// success message. If total_bytes is too big, the FIFO will copy only what is available
+// into the USB buffer!
+bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
+{
+ (void) rhport;
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
+
+ xfer_ctl_t * xfer = &xfer_status[epnum];
+ if(epnum == 0x80)
+ xfer = &xfer_status[EP_MAX];
+
+ xfer->buffer = NULL;
+ xfer->total_len = total_bytes;
+ xfer->queued_len = 0;
+ xfer->fifo = ff;
+
+ if (EP_DMA_SUPPORT(epnum) && total_bytes != 0)
+ {
+ tu_fifo_buffer_info_t info;
+ uint32_t udd_dma_ctrl_lin = DEVDMACONTROL_CHANN_ENB;
+ uint32_t udd_dma_ctrl_wrap = DEVDMACONTROL_CHANN_ENB | DEVDMACONTROL_END_BUFFIT;
+ if (dir == TUSB_DIR_OUT)
+ {
+ tu_fifo_get_write_info(ff, &info);
+ udd_dma_ctrl_lin |= DEVDMACONTROL_END_TR_IT | DEVDMACONTROL_END_TR_EN;
+ udd_dma_ctrl_wrap |= DEVDMACONTROL_END_TR_IT | DEVDMACONTROL_END_TR_EN;
+ } else {
+ tu_fifo_get_read_info(ff, &info);
+ if(info.len_wrap == 0)
+ {
+ udd_dma_ctrl_lin |= DEVDMACONTROL_END_B_EN;
+ }
+ udd_dma_ctrl_wrap |= DEVDMACONTROL_END_B_EN;
+ }
+
+ // Clean invalidate cache of linear part
+ CleanInValidateCache((uint32_t*) tu_align((uint32_t) info.ptr_lin, 4), info.len_lin + 31);
+
+ USB_REG->DEVDMA[epnum - 1].DEVDMAADDRESS = (uint32_t)info.ptr_lin;
+ if (info.len_wrap)
+ {
+ // Clean invalidate cache of wrapped part
+ CleanInValidateCache((uint32_t*) tu_align((uint32_t) info.ptr_wrap, 4), info.len_wrap + 31);
+
+ dma_desc[epnum - 1].next_desc = 0;
+ dma_desc[epnum - 1].buff_addr = (uint32_t)info.ptr_wrap;
+ dma_desc[epnum - 1].chnl_ctrl =
+ udd_dma_ctrl_wrap | (info.len_wrap << DEVDMACONTROL_BUFF_LENGTH_Pos);
+ // Clean cache of wrapped DMA descriptor
+ CleanInValidateCache((uint32_t*)&dma_desc[epnum - 1], sizeof(dma_desc_t));
+
+ udd_dma_ctrl_lin |= DEVDMASTATUS_DESC_LDST;
+ USB_REG->DEVDMA[epnum - 1].DEVDMANXTDSC = (uint32_t)&dma_desc[epnum - 1];
+ } else {
+ udd_dma_ctrl_lin |= DEVDMACONTROL_END_BUFFIT;
+ }
+ udd_dma_ctrl_lin |= (info.len_lin << DEVDMACONTROL_BUFF_LENGTH_Pos);
+ // Disable IRQs to have a short sequence
+ // between read of EOT_STA and DMA enable
+ uint32_t irq_state = __get_PRIMASK();
+ __disable_irq();
+ if (!(USB_REG->DEVDMA[epnum - 1].DEVDMASTATUS & DEVDMASTATUS_END_TR_ST))
+ {
+ USB_REG->DEVDMA[epnum - 1].DEVDMACONTROL = udd_dma_ctrl_lin;
+ USB_REG->DEVIER = DEVIER_DMA_1 << (epnum - 1);
+ __set_PRIMASK(irq_state);
+ return true;
+ }
+ __set_PRIMASK(irq_state);
+
+ // Here a ZLP has been recieved
+ // and the DMA transfer must be not started.
+ // It is the end of transfer
+ return false;
+ } else
+ {
+ if (dir == TUSB_DIR_OUT)
+ {
+ USB_REG->DEVEPTIER[epnum] = DEVEPTIER_RXOUTES;
+ } else
+ {
+ dcd_transmit_packet(xfer,epnum);
+ }
+ }
+ return true;
+}
+
+// Stall endpoint
+void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr)
+{
+ (void) rhport;
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ USB_REG->DEVEPTIER[epnum] = DEVEPTIER_CTRL_STALLRQS;
+ // Re-enable SETUP interrupt
+ if (epnum == 0)
+ {
+ USB_REG->DEVEPTIER[0] = DEVEPTIER_CTRL_RXSTPES;
+ }
+}
+
+// clear stall, data toggle is also reset to DATA0
+void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
+{
+ (void) rhport;
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ USB_REG->DEVEPTIDR[epnum] = DEVEPTIDR_CTRL_STALLRQC;
+ USB_REG->DEVEPTIER[epnum] = HSTPIPIER_RSTDTS;
+}
+
+#endif
diff --git a/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c b/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c
index 31b1f7080..6cc0fcac3 100644
--- a/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c
+++ b/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c
@@ -339,6 +339,12 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
return true;
}
+void dcd_edpt_close_all (uint8_t rhport)
+{
+ (void) rhport;
+ // TODO implement dcd_edpt_close_all()
+}
+
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
{
(void) rhport;
diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c
index 977ec6cdb..f40ba2d4f 100644
--- a/src/portable/nordic/nrf5x/dcd_nrf5x.c
+++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c
@@ -85,7 +85,7 @@ static struct
// Number of pending DMA that is started but not handled yet by dcd_int_handler().
// Since nRF can only carry one DMA can run at a time, this value is normally be either 0 or 1.
// However, in critical section with interrupt disabled, the DMA can be finished and added up
- // until handled by dcd_init_handler() when exiting critical section.
+ // until handled by dcd_int_handler() when exiting critical section.
volatile uint8_t dma_pending;
}_dcd;
@@ -108,13 +108,21 @@ static inline uint32_t NVIC_GetEnableIRQ(IRQn_Type IRQn)
}
#endif
+// check if we are in ISR
+TU_ATTR_ALWAYS_INLINE static inline bool is_in_isr(void)
+{
+ return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) ? true : false;
+}
+
// helper to start DMA
+// TODO use Cortex M4 LDREX and STREX command (atomic) to have better mutex access to EasyDMA
+// since current implementation does not 100% guarded against race condition
static void edpt_dma_start(volatile uint32_t* reg_startep)
{
// Only one dma can be active
if ( _dcd.dma_pending )
{
- if (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk)
+ if (is_in_isr())
{
// Called within ISR, use usbd task to defer later
usbd_defer_func( (osal_task_func_t) edpt_dma_start, (void*) reg_startep, true );
@@ -159,6 +167,17 @@ static void edpt_dma_end(void)
_dcd.dma_pending = 0;
}
+// helper to set TASKS_EP0STATUS / TASKS_EP0RCVOUT since they also need EasyDMA
+// However TASKS_EP0STATUS doesn't trigger any DMA transfer and got ENDED event subsequently
+// Therefore dma_running state will be corrected right away
+void start_ep0_task(volatile uint32_t* reg_task)
+{
+ edpt_dma_start(reg_task);
+
+ // correct the dma_running++ in dma start
+ if (_dcd.dma_pending) _dcd.dma_pending--;
+}
+
// helper getting td
static inline xfer_td_t* get_td(uint8_t epnum, uint8_t dir)
{
@@ -187,7 +206,8 @@ static void xact_out_dma(uint8_t epnum)
}
else
{
- xact_len = (uint8_t)NRF_USBD->SIZE.EPOUT[epnum];
+ // limit xact len to remaining length
+ xact_len = tu_min16((uint16_t) NRF_USBD->SIZE.EPOUT[epnum], xfer->total_len - xfer->actual_len);
// Trigger DMA move data from Endpoint -> SRAM
NRF_USBD->EPOUT[epnum].PTR = (uint32_t) xfer->buffer;
@@ -258,14 +278,8 @@ void dcd_remote_wakeup(uint8_t rhport)
(void) rhport;
// Bring controller out of low power mode
+ // will start wakeup when USBWUALLOWED is set
NRF_USBD->LOWPOWER = 0;
-
- // Initiate RESUME signal
- NRF_USBD->DPDMVALUE = USBD_DPDMVALUE_STATE_Resume;
- NRF_USBD->TASKS_DPDMDRIVE = 1;
-
- // TODO There is no USBEVENT Resume interrupt
- // We may manually raise DCD_EVENT_RESUME event here
}
// disconnect by disabling internal pull-up resistor on D+/D-
@@ -293,8 +307,9 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
{
(void) rhport;
- uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress);
- uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress);
+ uint8_t const ep_addr = desc_edpt->bEndpointAddress;
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
_dcd.xfer[epnum][dir].mps = desc_edpt->wMaxPacketSize.size;
@@ -320,10 +335,13 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
{
// SPLIT ISO buffer when ISO IN endpoint is already opened.
if (_dcd.xfer[EP_ISO_NUM][TUSB_DIR_IN].mps) NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN;
+
// Clear old events
NRF_USBD->EVENTS_ENDISOOUT = 0;
+
// Clear SOF event in case interrupt was not enabled yet.
if ((NRF_USBD->INTEN & USBD_INTEN_SOF_Msk) == 0) NRF_USBD->EVENTS_SOF = 0;
+
// Enable SOF and ISOOUT interrupts, and ISOOUT endpoint.
NRF_USBD->INTENSET = USBD_INTENSET_ENDISOOUT_Msk | USBD_INTENSET_SOF_Msk;
NRF_USBD->EPOUTEN |= USBD_EPOUTEN_ISOOUT_Msk;
@@ -331,20 +349,60 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
else
{
NRF_USBD->EVENTS_ENDISOIN = 0;
+
// SPLIT ISO buffer when ISO OUT endpoint is already opened.
if (_dcd.xfer[EP_ISO_NUM][TUSB_DIR_OUT].mps) NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN;
+
// Clear SOF event in case interrupt was not enabled yet.
if ((NRF_USBD->INTEN & USBD_INTEN_SOF_Msk) == 0) NRF_USBD->EVENTS_SOF = 0;
+
// Enable SOF and ISOIN interrupts, and ISOIN endpoint.
NRF_USBD->INTENSET = USBD_INTENSET_ENDISOIN_Msk | USBD_INTENSET_SOF_Msk;
NRF_USBD->EPINEN |= USBD_EPINEN_ISOIN_Msk;
}
}
+
+ // clear stall and reset DataToggle
+ NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_UnStall << USBD_EPSTALL_STALL_Pos) | ep_addr;
+ NRF_USBD->DTOGGLE = (USBD_DTOGGLE_VALUE_Data0 << USBD_DTOGGLE_VALUE_Pos) | ep_addr;
+
__ISB(); __DSB();
return true;
}
+void dcd_edpt_close_all (uint8_t rhport)
+{
+ // disable interrupt to prevent race condition
+ dcd_int_disable(rhport);
+
+ // disable all non-control (bulk + interrupt) endpoints
+ for ( uint8_t ep = 1; ep < EP_CBI_COUNT; ep++ )
+ {
+ NRF_USBD->INTENCLR = TU_BIT(USBD_INTEN_ENDEPOUT0_Pos + ep) | TU_BIT(USBD_INTEN_ENDEPIN0_Pos + ep);
+
+ NRF_USBD->TASKS_STARTEPIN[ep] = 0;
+ NRF_USBD->TASKS_STARTEPOUT[ep] = 0;
+
+ tu_memclr(_dcd.xfer[ep], 2*sizeof(xfer_td_t));
+ }
+
+ // disable both ISO
+ NRF_USBD->INTENCLR = USBD_INTENCLR_SOF_Msk | USBD_INTENCLR_ENDISOOUT_Msk | USBD_INTENCLR_ENDISOIN_Msk;
+ NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_OneDir;
+
+ NRF_USBD->TASKS_STARTISOIN = 0;
+ NRF_USBD->TASKS_STARTISOOUT = 0;
+
+ tu_memclr(_dcd.xfer[EP_ISO_NUM], 2*sizeof(xfer_td_t));
+
+ // de-activate all non-control
+ NRF_USBD->EPOUTEN = 1UL;
+ NRF_USBD->EPINEN = 1UL;
+
+ dcd_int_enable(rhport);
+}
+
void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr)
{
(void) rhport;
@@ -407,29 +465,25 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
if ( control_status )
{
- // Status Phase also requires Easy DMA has to be available as well !!!!
- // However TASKS_EP0STATUS doesn't trigger any DMA transfer and got ENDED event subsequently
- // Therefore dma_running state will be corrected right away
- edpt_dma_start(&NRF_USBD->TASKS_EP0STATUS);
- if (_dcd.dma_pending) _dcd.dma_pending--; // correct the dma_running++ in dma start
+ // Status Phase also requires EasyDMA has to be available as well !!!!
+ start_ep0_task(&NRF_USBD->TASKS_EP0STATUS);
// The nRF doesn't interrupt on status transmit so we queue up a success response.
- dcd_event_xfer_complete(0, ep_addr, 0, XFER_RESULT_SUCCESS, false);
+ dcd_event_xfer_complete(0, ep_addr, 0, XFER_RESULT_SUCCESS, is_in_isr());
}
else if ( dir == TUSB_DIR_OUT )
{
if ( epnum == 0 )
{
- // Accept next Control Out packet
- NRF_USBD->TASKS_EP0RCVOUT = 1;
+ // Accept next Control Out packet. TASKS_EP0RCVOUT also require EasyDMA
+ start_ep0_task(&NRF_USBD->TASKS_EP0RCVOUT);
}else
{
if ( xfer->data_received )
{
- // Data may already be received previously
- xfer->data_received = false;
-
+ // Data is already received previously
// start DMA to copy to SRAM
+ xfer->data_received = false;
xact_out_dma(epnum);
}
else
@@ -451,7 +505,11 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr)
{
(void) rhport;
+
uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
+
+ xfer_td_t* xfer = get_td(epnum, dir);
if ( epnum == 0 )
{
@@ -459,6 +517,15 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr)
}else if (epnum != EP_ISO_NUM)
{
NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_Stall << USBD_EPSTALL_STALL_Pos) | ep_addr;
+
+ // Note: nRF can auto ACK packet OUT before get stalled.
+ // There maybe data in endpoint fifo already, we need to pull it out
+ if ( (dir == TUSB_DIR_OUT) && xfer->data_received )
+ {
+ TU_LOG_LOCATION();
+ xfer->data_received = false;
+ xact_out_dma(epnum);
+ }
}
__ISB(); __DSB();
@@ -472,14 +539,16 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
if ( epnum != 0 && epnum != EP_ISO_NUM )
{
- // clear stall
- NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_UnStall << USBD_EPSTALL_STALL_Pos) | ep_addr;
-
// reset data toggle to DATA0
+ // First write this register with VALUE=Nop to select the endpoint, then either read it to get the status from
+ // VALUE, or write it again with VALUE=Data0 or Data1
+ NRF_USBD->DTOGGLE = ep_addr;
NRF_USBD->DTOGGLE = (USBD_DTOGGLE_VALUE_Data0 << USBD_DTOGGLE_VALUE_Pos) | ep_addr;
+ // clear stall
+ NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_UnStall << USBD_EPSTALL_STALL_Pos) | ep_addr;
+
// Write any value to SIZE register will allow nRF to ACK/accept data
- // Drop any pending data
if (dir == TUSB_DIR_OUT) NRF_USBD->SIZE.EPOUT[epnum] = 0;
__ISB(); __DSB();
@@ -491,6 +560,10 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
*------------------------------------------------------------------*/
void bus_reset(void)
{
+ // 6.35.6 USB controller automatically disabled all endpoints (except control)
+ NRF_USBD->EPOUTEN = 1UL;
+ NRF_USBD->EPINEN = 1UL;
+
for(int i=0; i<8; i++)
{
NRF_USBD->TASKS_STARTEPIN[i] = 0;
@@ -500,6 +573,15 @@ void bus_reset(void)
NRF_USBD->TASKS_STARTISOIN = 0;
NRF_USBD->TASKS_STARTISOOUT = 0;
+ // Clear USB Event Interrupt
+ NRF_USBD->EVENTS_USBEVENT = 0;
+ NRF_USBD->EVENTCAUSE |= NRF_USBD->EVENTCAUSE;
+
+ // Reset interrupt
+ NRF_USBD->INTENCLR = NRF_USBD->INTEN;
+ NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_USBEVENT_Msk | USBD_INTEN_EPDATA_Msk |
+ USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPIN0_Msk | USBD_INTEN_ENDEPOUT0_Msk;
+
tu_varclr(&_dcd);
_dcd.xfer[0][TUSB_DIR_IN].mps = MAX_PACKET_SIZE;
_dcd.xfer[0][TUSB_DIR_OUT].mps = MAX_PACKET_SIZE;
@@ -545,48 +627,74 @@ void dcd_int_handler(uint8_t rhport)
if ( int_status & USBD_INTEN_SOF_Msk )
{
+ bool iso_enabled = false;
+
// ISOOUT: Transfer data gathered in previous frame from buffer to RAM
if (NRF_USBD->EPOUTEN & USBD_EPOUTEN_ISOOUT_Msk)
{
+ iso_enabled = true;
xact_out_dma(EP_ISO_NUM);
}
+
// ISOIN: Notify client that data was transferred
- xfer_td_t* xfer = get_td(EP_ISO_NUM, TUSB_DIR_IN);
- if ( xfer->iso_in_transfer_ready )
+ if (NRF_USBD->EPINEN & USBD_EPINEN_ISOIN_Msk)
+ {
+ iso_enabled = true;
+
+ xfer_td_t* xfer = get_td(EP_ISO_NUM, TUSB_DIR_IN);
+ if ( xfer->iso_in_transfer_ready )
+ {
+ xfer->iso_in_transfer_ready = false;
+ dcd_event_xfer_complete(0, EP_ISO_NUM | TUSB_DIR_IN_MASK, xfer->actual_len, XFER_RESULT_SUCCESS, true);
+ }
+ }
+
+ if ( !iso_enabled )
{
- xfer->iso_in_transfer_ready = false;
- dcd_event_xfer_complete(0, EP_ISO_NUM | TUSB_DIR_IN_MASK, xfer->actual_len, XFER_RESULT_SUCCESS, true);
+ // ISO endpoint is not used, SOF is only enabled one-time for remote wakeup
+ // so we disable it now
+ NRF_USBD->INTENCLR = USBD_INTENSET_SOF_Msk;
}
+
dcd_event_bus_signal(0, DCD_EVENT_SOF, true);
}
if ( int_status & USBD_INTEN_USBEVENT_Msk )
{
- uint32_t const evt_cause = NRF_USBD->EVENTCAUSE & (USBD_EVENTCAUSE_SUSPEND_Msk | USBD_EVENTCAUSE_RESUME_Msk);
+ TU_LOG(2, "EVENTCAUSE = 0x%04lX\r\n", NRF_USBD->EVENTCAUSE);
+
+ enum { EVT_CAUSE_MASK = USBD_EVENTCAUSE_SUSPEND_Msk | USBD_EVENTCAUSE_RESUME_Msk | USBD_EVENTCAUSE_USBWUALLOWED_Msk };
+ uint32_t const evt_cause = NRF_USBD->EVENTCAUSE & EVT_CAUSE_MASK;
NRF_USBD->EVENTCAUSE = evt_cause; // clear interrupt
if ( evt_cause & USBD_EVENTCAUSE_SUSPEND_Msk )
{
- dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true);
-
// Put controller into low power mode
+ // Leave HFXO disable to application, since it may be used by other peripherals
NRF_USBD->LOWPOWER = 1;
- // Leave HFXO disable to application, since it may be used by other
+ dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true);
}
- if ( evt_cause & USBD_EVENTCAUSE_RESUME_Msk )
+ if ( evt_cause & USBD_EVENTCAUSE_USBWUALLOWED_Msk )
{
- dcd_event_bus_signal(0, DCD_EVENT_RESUME , true);
+ // USB is out of low power mode, and wakeup is allowed
+ // Initiate RESUME signal
+ NRF_USBD->DPDMVALUE = USBD_DPDMVALUE_STATE_Resume;
+ NRF_USBD->TASKS_DPDMDRIVE = 1;
+
+ // There is no Resume interrupt for remote wakeup, enable SOF for to report bus ready state
+ // Clear SOF event in case interrupt was not enabled yet.
+ if ((NRF_USBD->INTEN & USBD_INTEN_SOF_Msk) == 0) NRF_USBD->EVENTS_SOF = 0;
+ NRF_USBD->INTENSET = USBD_INTENSET_SOF_Msk;
}
- }
- if ( int_status & EDPT_END_ALL_MASK )
- {
- // DMA complete move data from SRAM -> Endpoint
- edpt_dma_end();
+ if ( evt_cause & USBD_EVENTCAUSE_RESUME_Msk )
+ {
+ dcd_event_bus_signal(0, DCD_EVENT_RESUME, true);
+ }
}
-
+
// Setup tokens are specific to the Control endpoint.
if ( int_status & USBD_INTEN_EP0SETUP_Msk )
{
@@ -607,6 +715,12 @@ void dcd_int_handler(uint8_t rhport)
}
}
+ if ( int_status & EDPT_END_ALL_MASK )
+ {
+ // DMA complete move data from SRAM -> Endpoint
+ edpt_dma_end();
+ }
+
//--------------------------------------------------------------------+
/* Control/Bulk/Interrupt (CBI) Transfer
*
@@ -655,8 +769,15 @@ void dcd_int_handler(uint8_t rhport)
{
if ( epnum == 0 )
{
- // Accept next Control Out packet
- NRF_USBD->TASKS_EP0RCVOUT = 1;
+ // Accept next Control Out packet. TASKS_EP0RCVOUT also require EasyDMA
+ if ( _dcd.dma_pending )
+ {
+ // use usbd task to defer later
+ usbd_defer_func( (osal_task_func_t) start_ep0_task, (void*) &NRF_USBD->TASKS_EP0RCVOUT, true );
+ }else
+ {
+ start_ep0_task(&NRF_USBD->TASKS_EP0RCVOUT);
+ }
}else
{
// nRF auto accept next Bulk/Interrupt OUT packet
@@ -764,7 +885,7 @@ static bool hfclk_running(void)
#ifdef SOFTDEVICE_PRESENT
if ( is_sd_enabled() )
{
- uint32_t is_running;
+ uint32_t is_running = 0;
(void) sd_clock_hfclk_is_running(&is_running);
return (is_running ? true : false);
}
@@ -822,18 +943,22 @@ void tusb_hal_nrf_power_event (uint32_t event)
USB_EVT_READY = 2
};
+#if CFG_TUSB_DEBUG >= 2
+ const char* const power_evt_str[] = { "Detected", "Removed", "Ready" };
+ TU_LOG(2, "Power USB event: %s\r\n", power_evt_str[event]);
+#endif
+
switch ( event )
{
case USB_EVT_DETECTED:
- TU_LOG2("Power USB Detect\r\n");
-
if ( !NRF_USBD->ENABLE )
{
- /* Prepare for READY event receiving */
+ // Prepare for receiving READY event: disable interrupt since we will blocking wait
+ NRF_USBD->INTENCLR = USBD_INTEN_USBEVENT_Msk;
NRF_USBD->EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk;
__ISB(); __DSB(); // for sync
-#ifdef NRF52_SERIES
+#ifdef NRF52_SERIES // NRF53 does not need this errata
// ERRATA 171, 187, 166
if ( nrfx_usbd_errata_187() )
{
@@ -868,7 +993,7 @@ void tusb_hal_nrf_power_event (uint32_t event)
}
#endif
- /* Enable the peripheral */
+ // Enable the peripheral (will cause Ready event)
NRF_USBD->ENABLE = 1;
__ISB(); __DSB(); // for sync
@@ -878,13 +1003,11 @@ void tusb_hal_nrf_power_event (uint32_t event)
break;
case USB_EVT_READY:
- TU_LOG2("Power USB Ready\r\n");
-
// Skip if pull-up is enabled and HCLK is already running.
// Application probably call this more than necessary.
if ( NRF_USBD->USBPULLUP && hfclk_running() ) break;
- /* Waiting for USBD peripheral enabled */
+ // Waiting for USBD peripheral enabled
while ( !(USBD_EVENTCAUSE_READY_Msk & NRF_USBD->EVENTCAUSE) ) { }
NRF_USBD->EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk;
@@ -936,9 +1059,8 @@ void tusb_hal_nrf_power_event (uint32_t event)
// ISO buffer Lower half for IN, upper half for OUT
NRF_USBD->ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN;
- // Enable interrupt
- NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_EPDATA_Msk |
- USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPIN0_Msk | USBD_INTEN_ENDEPOUT0_Msk;
+ // Enable bus-reset interrupt
+ NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk;
// Enable interrupt, priorities should be set by application
NVIC_ClearPendingIRQ(USBD_IRQn);
@@ -953,7 +1075,6 @@ void tusb_hal_nrf_power_event (uint32_t event)
break;
case USB_EVT_REMOVED:
- TU_LOG2("Power USB Removed\r\n");
if ( NRF_USBD->ENABLE )
{
// Abort all transfers
@@ -973,7 +1094,7 @@ void tusb_hal_nrf_power_event (uint32_t event)
hfclk_disable();
- dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) ? true : false);
+ dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, is_in_isr());
}
break;
diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c
index 047fa3fa6..7618f288d 100644
--- a/src/portable/nuvoton/nuc120/dcd_nuc120.c
+++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c
@@ -99,6 +99,11 @@ static void usb_detach(void)
USBD->DRVSE0 |= USBD_DRVSE0_DRVSE0_Msk;
}
+static inline void usb_memcpy(uint8_t *dest, uint8_t *src, uint16_t size)
+{
+ while(size--) *dest++ = *src++;
+}
+
static void usb_control_send_zlp(void)
{
USBD->EP[PERIPH_EP0].CFG |= USBD_CFG_DSQ_SYNC_Msk;
@@ -151,7 +156,8 @@ static void dcd_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep)
else
#endif
{
- memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now);
+ // USB SRAM seems to only support byte access and memcpy could possibly do it by words
+ usb_memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now);
}
ep->MXPLD = bytes_now;
@@ -246,7 +252,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
/* mine the data for the information we need */
int const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress);
int const size = p_endpoint_desc->wMaxPacketSize.size;
- tusb_xfer_type_t const type = p_endpoint_desc->bmAttributes.xfer;
+ tusb_xfer_type_t const type = (tusb_xfer_type_t) p_endpoint_desc->bmAttributes.xfer;
struct xfer_ctl_t *xfer = &xfer_table[ep - USBD->EP];
/* allocate buffer from USB RAM */
@@ -267,6 +273,12 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
return true;
}
+void dcd_edpt_close_all (uint8_t rhport)
+{
+ (void) rhport;
+ // TODO implement dcd_edpt_close_all()
+}
+
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
{
(void) rhport;
@@ -439,7 +451,8 @@ void dcd_int_handler(uint8_t rhport)
else
#endif
{
- memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes);
+ // USB SRAM seems to only support byte access and memcpy could possibly do it by words
+ usb_memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes);
xfer->data_ptr += available_bytes;
}
diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c
index 37b7b0106..dbc5cd18a 100644
--- a/src/portable/nuvoton/nuc121/dcd_nuc121.c
+++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c
@@ -40,6 +40,12 @@
#include "device/dcd.h"
#include "NuMicro.h"
+// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval)
+// We disable SOF for now until needed later on
+#ifndef USE_SOF
+# define USE_SOF 0
+#endif
+
/* allocation of USBD RAM for Setup, EP0_IN, and and EP_OUT */
#define PERIPH_SETUP_BUF_BASE 0
#define PERIPH_SETUP_BUF_LEN 8
@@ -65,9 +71,6 @@ enum ep_enum
PERIPH_MAX_EP,
};
-/* set by dcd_set_address() */
-static volatile uint8_t assigned_address;
-
/* reset by dcd_init(), this is used by dcd_edpt_open() to assign USBD peripheral buffer addresses */
static uint32_t bufseg_addr;
@@ -101,6 +104,11 @@ static void usb_detach(void)
USBD->SE0 |= USBD_SE0_SE0_Msk;
}
+static inline void usb_memcpy(uint8_t *dest, uint8_t *src, uint16_t size)
+{
+ while(size--) *dest++ = *src++;
+}
+
static void usb_control_send_zlp(void)
{
USBD->EP[PERIPH_EP0].CFG |= USBD_CFG_DSQSYNC_Msk;
@@ -153,7 +161,8 @@ static void dcd_in_xfer(struct xfer_ctl_t *xfer, USBD_EP_T *ep)
else
#endif
{
- memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now);
+ // USB SRAM seems to only support byte access and memcpy could possibly do it by words
+ usb_memcpy((uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), xfer->data_ptr, bytes_now);
}
ep->MXPLD = bytes_now;
@@ -191,7 +200,10 @@ static void bus_reset(void)
}
/* centralized location for USBD interrupt enable bit mask */
-static const uint32_t enabled_irqs = USBD_INTSTS_VBDETIF_Msk | USBD_INTSTS_BUSIF_Msk | USBD_INTSTS_SETUP_Msk | USBD_INTSTS_USBIF_Msk | USBD_INTSTS_SOFIF_Msk;
+enum {
+ ENABLED_IRQS = USBD_INTSTS_VBDETIF_Msk | USBD_INTSTS_BUSIF_Msk | USBD_INTSTS_SETUP_Msk |
+ USBD_INTSTS_USBIF_Msk | (USE_SOF ? USBD_INTSTS_SOFIF_Msk : 0)
+};
/*
NUC121/NUC125/NUC126 TinyUSB API driver implementation
@@ -213,8 +225,8 @@ void dcd_init(uint8_t rhport)
usb_attach();
- USBD->INTSTS = enabled_irqs;
- USBD->INTEN = enabled_irqs;
+ USBD->INTSTS = ENABLED_IRQS;
+ USBD->INTEN = ENABLED_IRQS;
}
void dcd_int_enable(uint8_t rhport)
@@ -232,14 +244,30 @@ void dcd_int_disable(uint8_t rhport)
void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
{
(void) rhport;
+ (void) dev_addr;
usb_control_send_zlp(); /* SET_ADDRESS is the one exception where TinyUSB doesn't use dcd_edpt_xfer() to generate a ZLP */
- assigned_address = dev_addr;
+
+ // DCD can only set address after status for this request is complete.
+ // do it at dcd_edpt0_status_complete()
+}
+
+static void remote_wakeup_delay(void)
+{
+ // try to delay for 1 ms
+ uint32_t count = SystemCoreClock / 1000;
+ while(count--) __NOP();
}
void dcd_remote_wakeup(uint8_t rhport)
{
(void) rhport;
- USBD->ATTR = USBD_ATTR_RWAKEUP_Msk;
+ // Enable PHY before sending Resume('K') state
+ USBD->ATTR |= USBD_ATTR_PHYEN_Msk;
+ USBD->ATTR |= USBD_ATTR_RWAKEUP_Msk;
+
+ // Per specs: remote wakeup signal bit must be clear within 1-15ms
+ remote_wakeup_delay();
+ USBD->ATTR &=~USBD_ATTR_RWAKEUP_Msk;
}
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
@@ -252,7 +280,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
/* mine the data for the information we need */
int const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress);
int const size = p_endpoint_desc->wMaxPacketSize.size;
- tusb_xfer_type_t const type = p_endpoint_desc->bmAttributes.xfer;
+ tusb_xfer_type_t const type = (tusb_xfer_type_t) p_endpoint_desc->bmAttributes.xfer;
struct xfer_ctl_t *xfer = &xfer_table[ep - USBD->EP];
/* allocate buffer from USB RAM */
@@ -273,6 +301,12 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
return true;
}
+void dcd_edpt_close_all (uint8_t rhport)
+{
+ (void) rhport;
+ // TODO implement dcd_edpt_close_all()
+}
+
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
{
(void) rhport;
@@ -345,14 +379,16 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
{
(void) rhport;
USBD_EP_T *ep = ep_entry(ep_addr, false);
- ep->CFG |= USBD_CFG_CSTALL_Msk;
+ ep->CFG = (ep->CFG & ~USBD_CFG_DSQSYNC_Msk) | USBD_CFG_CSTALL_Msk;
}
void dcd_int_handler(uint8_t rhport)
{
(void) rhport;
- uint32_t status = USBD->INTSTS;
+ // Mask non-enabled irqs, ex. SOF
+ uint32_t status = USBD->INTSTS & (ENABLED_IRQS | 0xffffff00);
+
#ifdef SUPPORT_LPM
uint32_t state = USBD->ATTR & 0x300f;
#else
@@ -414,9 +450,6 @@ void dcd_int_handler(uint8_t rhport)
{
if (status & USBD_INTSTS_EPEVT0_Msk) /* PERIPH_EP0 (EP0_IN) event: this is treated separately from the rest */
{
- /* given ACK from host has happened, we can now set the address (if not already done) */
- if((USBD->FADDR != assigned_address) && (USBD->FADDR == 0)) USBD->FADDR = assigned_address;
-
uint16_t const available_bytes = USBD->EP[PERIPH_EP0].MXPLD;
active_ep0_xfer = (available_bytes == xfer_table[PERIPH_EP0].max_packet_size);
@@ -450,7 +483,8 @@ void dcd_int_handler(uint8_t rhport)
else
#endif
{
- memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes);
+ // USB SRAM seems to only support byte access and memcpy could possibly do it by words
+ usb_memcpy(xfer->data_ptr, (uint8_t *)(USBD_BUF_BASE + ep->BUFSEG), available_bytes);
xfer->data_ptr += available_bytes;
}
@@ -485,7 +519,24 @@ void dcd_int_handler(uint8_t rhport)
}
/* acknowledge all interrupts */
- USBD->INTSTS = status & enabled_irqs;
+ USBD->INTSTS = status & ENABLED_IRQS;
+}
+
+// Invoked when a control transfer's status stage is complete.
+// May help DCD to prepare for next control transfer, this API is optional.
+void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request)
+{
+ (void) rhport;
+
+ if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE &&
+ request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD &&
+ request->bRequest == TUSB_REQ_SET_ADDRESS )
+ {
+ uint8_t const dev_addr = (uint8_t) request->wValue;
+
+ // Setting new address after the whole request is complete
+ USBD->FADDR = dev_addr;
+ }
}
void dcd_disconnect(uint8_t rhport)
diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c
index 4e633086d..ea5a8bea5 100644
--- a/src/portable/nuvoton/nuc505/dcd_nuc505.c
+++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c
@@ -353,6 +353,12 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
return true;
}
+void dcd_edpt_close_all (uint8_t rhport)
+{
+ (void) rhport;
+ // TODO implement dcd_edpt_close_all()
+}
+
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
{
(void) rhport;
diff --git a/src/portable/nxp/khci/dcd_khci.c b/src/portable/nxp/khci/dcd_khci.c
index 519b8fb7b..ff1997440 100644
--- a/src/portable/nxp/khci/dcd_khci.c
+++ b/src/portable/nxp/khci/dcd_khci.c
@@ -26,7 +26,9 @@
#include "tusb_option.h"
-#if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_MKL25ZXX )
+#if TUSB_OPT_DEVICE_ENABLED && ( \
+ ( CFG_TUSB_MCU == OPT_MCU_MKL25ZXX ) || ( CFG_TUSB_MCU == OPT_MCU_K32L2BXX ) \
+ )
#include "fsl_device_registers.h"
#define KHCI USB0
@@ -50,23 +52,23 @@ typedef struct TU_ATTR_PACKED
struct {
union {
struct {
- uint16_t : 2;
- uint16_t tok_pid : 4;
- uint16_t data : 1;
- uint16_t own : 1;
- uint16_t : 8;
+ uint16_t : 2;
+ __IO uint16_t tok_pid : 4;
+ uint16_t data : 1;
+ __IO uint16_t own : 1;
+ uint16_t : 8;
};
struct {
- uint16_t : 2;
- uint16_t bdt_stall: 1;
- uint16_t dts : 1;
- uint16_t ninc : 1;
- uint16_t keep : 1;
- uint16_t : 10;
+ uint16_t : 2;
+ uint16_t bdt_stall : 1;
+ uint16_t dts : 1;
+ uint16_t ninc : 1;
+ uint16_t keep : 1;
+ uint16_t : 10;
};
};
- uint16_t bc : 10;
- uint16_t : 6;
+ __IO uint16_t bc : 10;
+ uint16_t : 6;
};
};
uint8_t *addr;
@@ -118,10 +120,8 @@ static void prepare_next_setup_packet(uint8_t rhport)
{
const unsigned out_odd = _dcd.endpoint[0][0].odd;
const unsigned in_odd = _dcd.endpoint[0][1].odd;
- if (_dcd.bdt[0][0][out_odd].own) {
- TU_LOG1("DCD fail to prepare the next SETUP %d %d\r\n", out_odd, in_odd);
- return;
- }
+ TU_ASSERT(0 == _dcd.bdt[0][0][out_odd].own, );
+
_dcd.bdt[0][0][out_odd].data = 0;
_dcd.bdt[0][0][out_odd ^ 1].data = 1;
_dcd.bdt[0][1][in_odd].data = 1;
@@ -132,10 +132,16 @@ static void prepare_next_setup_packet(uint8_t rhport)
static void process_stall(uint8_t rhport)
{
- if (KHCI->ENDPOINT[0].ENDPT & USB_ENDPT_EPSTALL_MASK) {
- /* clear stall condition of the control pipe */
- prepare_next_setup_packet(rhport);
- KHCI->ENDPOINT[0].ENDPT &= ~USB_ENDPT_EPSTALL_MASK;
+ for (int i = 0; i < 16; ++i) {
+ unsigned const endpt = KHCI->ENDPOINT[i].ENDPT;
+
+ if (endpt & USB_ENDPT_EPSTALL_MASK) {
+ // prepare next setup if endpoint0
+ if ( i == 0 ) prepare_next_setup_packet(rhport);
+
+ // clear stall bit
+ KHCI->ENDPOINT[i].ENDPT = endpt & ~USB_ENDPT_EPSTALL_MASK;
+ }
}
}
@@ -143,12 +149,17 @@ static void process_tokdne(uint8_t rhport)
{
const unsigned s = KHCI->STAT;
KHCI->ISTAT = USB_ISTAT_TOKDNE_MASK; /* fetch the next token if received */
+
+ uint8_t const epnum = (s >> USB_STAT_ENDP_SHIFT);
+ uint8_t const dir = (s & USB_STAT_TX_MASK) >> USB_STAT_TX_SHIFT;
+ unsigned const odd = (s & USB_STAT_ODD_MASK) ? 1 : 0;
+
buffer_descriptor_t *bd = (buffer_descriptor_t *)&_dcd.bda[s];
endpoint_state_t *ep = &_dcd.endpoint_unified[s >> 3];
- unsigned odd = (s & USB_STAT_ODD_MASK) ? 1 : 0;
/* fetch pid before discarded by the next steps */
const unsigned pid = bd->tok_pid;
+
/* reset values for a next transfer */
bd->bdt_stall = 0;
bd->dts = 1;
@@ -161,9 +172,6 @@ static void process_tokdne(uint8_t rhport)
KHCI->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
return;
}
- if (s >> 4) {
- TU_LOG1("TKDNE %x\r\n", s);
- }
const unsigned bc = bd->bc;
const unsigned remaining = ep->remaining - bc;
@@ -182,9 +190,9 @@ static void process_tokdne(uint8_t rhport)
}
const unsigned length = ep->length;
dcd_event_xfer_complete(rhport,
- ((s & USB_STAT_TX_MASK) << 4) | (s >> USB_STAT_ENDP_SHIFT),
+ tu_edpt_addr(epnum, dir),
length - remaining, XFER_RESULT_SUCCESS, true);
- if (0 == (s & USB_STAT_ENDP_MASK) && 0 == length) {
+ if (0 == epnum && 0 == length) {
/* After completion a ZLP of control transfer,
* it prepares for the next steup transfer. */
if (_dcd.addr) {
@@ -202,7 +210,8 @@ static void process_bus_reset(uint8_t rhport)
KHCI->USBCTRL &= ~USB_USBCTRL_SUSP_MASK;
KHCI->CTL |= USB_CTL_ODDRST_MASK;
KHCI->ADDR = 0;
- KHCI->INTEN = (KHCI->INTEN & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK;
+ KHCI->INTEN = USB_INTEN_USBRSTEN_MASK | USB_INTEN_TOKDNEEN_MASK | USB_INTEN_SLEEPEN_MASK |
+ USB_INTEN_ERROREN_MASK | USB_INTEN_STALLEN_MASK;
KHCI->ENDPOINT[0].ENDPT = USB_ENDPT_EPHSHK_MASK | USB_ENDPT_EPRXEN_MASK | USB_ENDPT_EPTXEN_MASK;
for (unsigned i = 1; i < 16; ++i) {
@@ -227,21 +236,27 @@ static void process_bus_reset(uint8_t rhport)
dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true);
}
-static void process_bus_inactive(uint8_t rhport)
+static void process_bus_sleep(uint8_t rhport)
{
- (void) rhport;
+ // Enable resume & disable suspend interrupt
const unsigned inten = KHCI->INTEN;
+
KHCI->INTEN = (inten & ~USB_INTEN_SLEEPEN_MASK) | USB_INTEN_RESUMEEN_MASK;
+ KHCI->USBTRC0 |= USB_USBTRC0_USBRESMEN_MASK;
KHCI->USBCTRL |= USB_USBCTRL_SUSP_MASK;
+
dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true);
}
-static void process_bus_active(uint8_t rhport)
+static void process_bus_resume(uint8_t rhport)
{
- (void) rhport;
- KHCI->USBCTRL &= ~USB_USBCTRL_SUSP_MASK;
+ // Enable suspend & disable resume interrupt
const unsigned inten = KHCI->INTEN;
+
+ KHCI->USBCTRL &= ~USB_USBCTRL_SUSP_MASK; // will also clear USB_USBTRC0_USB_RESUME_INT_MASK
+ KHCI->USBTRC0 &= ~USB_USBTRC0_USBRESMEN_MASK;
KHCI->INTEN = (inten & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK;
+
dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true);
}
@@ -254,12 +269,15 @@ void dcd_init(uint8_t rhport)
KHCI->USBTRC0 |= USB_USBTRC0_USBRESET_MASK;
while (KHCI->USBTRC0 & USB_USBTRC0_USBRESET_MASK);
+
tu_memclr(&_dcd, sizeof(_dcd));
KHCI->USBTRC0 |= TU_BIT(6); /* software must set this bit to 1 */
KHCI->BDTPAGE1 = (uint8_t)((uintptr_t)_dcd.bdt >> 8);
KHCI->BDTPAGE2 = (uint8_t)((uintptr_t)_dcd.bdt >> 16);
KHCI->BDTPAGE3 = (uint8_t)((uintptr_t)_dcd.bdt >> 24);
+ KHCI->INTEN = USB_INTEN_USBRSTEN_MASK;
+
dcd_connect(rhport);
NVIC_ClearPendingIRQ(USB0_IRQn);
}
@@ -267,8 +285,6 @@ void dcd_init(uint8_t rhport)
void dcd_int_enable(uint8_t rhport)
{
(void) rhport;
- KHCI->INTEN = USB_INTEN_USBRSTEN_MASK | USB_INTEN_TOKDNEEN_MASK |
- USB_INTEN_SLEEPEN_MASK | USB_INTEN_ERROREN_MASK | USB_INTEN_STALLEN_MASK;
NVIC_EnableIRQ(USB0_IRQn);
}
@@ -276,13 +292,11 @@ void dcd_int_disable(uint8_t rhport)
{
(void) rhport;
NVIC_DisableIRQ(USB0_IRQn);
- KHCI->INTEN = 0;
}
void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
{
- (void) rhport;
- _dcd.addr = dev_addr & 0x7F;
+ _dcd.addr = dev_addr & 0x7F;
/* Response with status first before changing device address */
dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0);
}
@@ -290,9 +304,12 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
void dcd_remote_wakeup(uint8_t rhport)
{
(void) rhport;
- unsigned cnt = SystemCoreClock / 100;
+
KHCI->CTL |= USB_CTL_RESUME_MASK;
+
+ unsigned cnt = SystemCoreClock / 1000;
while (cnt--) __NOP();
+
KHCI->CTL &= ~USB_CTL_RESUME_MASK;
}
@@ -319,12 +336,12 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
(void) rhport;
const unsigned ep_addr = ep_desc->bEndpointAddress;
- const unsigned epn = ep_addr & 0xFu;
- const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT;
+ const unsigned epn = tu_edpt_number(ep_addr);
+ const unsigned dir = tu_edpt_dir(ep_addr);
const unsigned xfer = ep_desc->bmAttributes.xfer;
endpoint_state_t *ep = &_dcd.endpoint[epn][dir];
const unsigned odd = ep->odd;
- buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0];
+ buffer_descriptor_t *bd = _dcd.bdt[epn][dir];
/* No support for control transfer */
TU_ASSERT(epn && (xfer != TUSB_XFER_CONTROL));
@@ -345,35 +362,60 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
return true;
}
+void dcd_edpt_close_all(uint8_t rhport)
+{
+ (void) rhport;
+ const unsigned ie = NVIC_GetEnableIRQ(USB0_IRQn);
+ NVIC_DisableIRQ(USB0_IRQn);
+ for (unsigned i = 1; i < 16; ++i) {
+ KHCI->ENDPOINT[i].ENDPT = 0;
+ }
+ if (ie) NVIC_EnableIRQ(USB0_IRQn);
+ buffer_descriptor_t *bd = _dcd.bdt[1][0];
+ for (unsigned i = 2; i < sizeof(_dcd.bdt)/sizeof(*bd); ++i, ++bd) {
+ bd->head = 0;
+ }
+ endpoint_state_t *ep = &_dcd.endpoint[1][0];
+ for (unsigned i = 2; i < sizeof(_dcd.endpoint)/sizeof(*ep); ++i, ++ep) {
+ /* Clear except the odd */
+ ep->max_packet_size = 0;
+ ep->length = 0;
+ ep->remaining = 0;
+ }
+}
+
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
{
(void) rhport;
- const unsigned epn = ep_addr & 0xFu;
- const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT;
+ const unsigned epn = tu_edpt_number(ep_addr);
+ const unsigned dir = tu_edpt_dir(ep_addr);
endpoint_state_t *ep = &_dcd.endpoint[epn][dir];
- buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0];
+ buffer_descriptor_t *bd = _dcd.bdt[epn][dir];
const unsigned msk = dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK;
+ const unsigned ie = NVIC_GetEnableIRQ(USB0_IRQn);
+ NVIC_DisableIRQ(USB0_IRQn);
KHCI->ENDPOINT[epn].ENDPT &= ~msk;
ep->max_packet_size = 0;
ep->length = 0;
ep->remaining = 0;
- bd->head = 0;
+ bd[0].head = 0;
+ bd[1].head = 0;
+ if (ie) NVIC_EnableIRQ(USB0_IRQn);
}
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes)
{
(void) rhport;
- NVIC_DisableIRQ(USB0_IRQn);
- const unsigned epn = ep_addr & 0xFu;
- const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT;
+ const unsigned epn = tu_edpt_number(ep_addr);
+ const unsigned dir = tu_edpt_dir(ep_addr);
endpoint_state_t *ep = &_dcd.endpoint[epn][dir];
buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][ep->odd];
+ TU_ASSERT(0 == bd->own);
+
+ const unsigned ie = NVIC_GetEnableIRQ(USB0_IRQn);
+ NVIC_DisableIRQ(USB0_IRQn);
- if (bd->own) {
- TU_LOG1("DCD XFER fail %x %d %lx %lx\r\n", ep_addr, total_bytes, ep->state, bd->head);
- return false; /* The last transfer has not completed */
- }
ep->length = total_bytes;
ep->remaining = total_bytes;
@@ -386,42 +428,69 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to
next->addr = buffer + mps;
next->own = 1;
}
- bd->bc = total_bytes >= mps ? mps: total_bytes;
- bd->addr = buffer;
+ bd->bc = total_bytes >= mps ? mps: total_bytes;
+ bd->addr = buffer;
__DSB();
- bd->own = 1; /* the own bit must set after addr */
- NVIC_EnableIRQ(USB0_IRQn);
+ bd->own = 1; /* This bit must be set last */
+
+ if (ie) NVIC_EnableIRQ(USB0_IRQn);
return true;
}
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
{
(void) rhport;
- const unsigned epn = ep_addr & 0xFu;
+ const unsigned epn = tu_edpt_number(ep_addr);
+
if (0 == epn) {
KHCI->ENDPOINT[epn].ENDPT |= USB_ENDPT_EPSTALL_MASK;
} else {
- const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT;
- buffer_descriptor_t *bd = _dcd.bdt[epn][dir];
- bd[0].bdt_stall = 1;
- bd[1].bdt_stall = 1;
+ const unsigned dir = tu_edpt_dir(ep_addr);
+ const unsigned odd = _dcd.endpoint[epn][dir].odd;
+ buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][odd];
+ TU_ASSERT(0 == bd->own,);
+
+ const unsigned ie = NVIC_GetEnableIRQ(USB0_IRQn);
+ NVIC_DisableIRQ(USB0_IRQn);
+
+ bd->bdt_stall = 1;
+ __DSB();
+ bd->own = 1; /* This bit must be set last */
+
+ if (ie) NVIC_EnableIRQ(USB0_IRQn);
}
}
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
{
(void) rhport;
- const unsigned epn = ep_addr & 0xFu;
- const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT;
+ const unsigned epn = tu_edpt_number(ep_addr);
+ TU_VERIFY(epn,);
+ const unsigned dir = tu_edpt_dir(ep_addr);
const unsigned odd = _dcd.endpoint[epn][dir].odd;
buffer_descriptor_t *bd = _dcd.bdt[epn][dir];
+ TU_VERIFY(bd[odd].own,);
- bd[odd ^ 1].own = 0;
- bd[odd ^ 1].data = 1;
- bd[odd ^ 1].bdt_stall = 0;
- bd[odd].own = 0;
- bd[odd].data = 0;
- bd[odd].bdt_stall = 0;
+ const unsigned ie = NVIC_GetEnableIRQ(USB0_IRQn);
+ NVIC_DisableIRQ(USB0_IRQn);
+
+ bd[odd].own = 0;
+ __DSB();
+
+ // clear stall
+ bd[odd].bdt_stall = 0;
+
+ // Reset data toggle
+ bd[odd ].data = 0;
+ bd[odd ^ 1].data = 1;
+
+ // We already cleared this in ISR, but just clear it here to be safe
+ const unsigned endpt = KHCI->ENDPOINT[epn].ENDPT;
+ if (endpt & USB_ENDPT_EPSTALL_MASK) {
+ KHCI->ENDPOINT[epn].ENDPT = endpt & ~USB_ENDPT_EPSTALL_MASK;
+ }
+
+ if (ie) NVIC_EnableIRQ(USB0_IRQn);
}
//--------------------------------------------------------------------+
@@ -429,48 +498,59 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
//--------------------------------------------------------------------+
void dcd_int_handler(uint8_t rhport)
{
- (void) rhport;
-
uint32_t is = KHCI->ISTAT;
uint32_t msk = KHCI->INTEN;
+
+ // clear non-enabled interrupts
KHCI->ISTAT = is & ~msk;
is &= msk;
+
if (is & USB_ISTAT_ERROR_MASK) {
/* TODO: */
uint32_t es = KHCI->ERRSTAT;
KHCI->ERRSTAT = es;
KHCI->ISTAT = is; /* discard any pending events */
- return;
}
if (is & USB_ISTAT_USBRST_MASK) {
KHCI->ISTAT = is; /* discard any pending events */
process_bus_reset(rhport);
- return;
}
+
if (is & USB_ISTAT_SLEEP_MASK) {
+ // TU_LOG2("Suspend: "); TU_LOG2_HEX(is);
+
+ // Note Host usually has extra delay after bus reset (without SOF), which could falsely
+ // detected as Sleep event. Though usbd has debouncing logic so we are good
KHCI->ISTAT = USB_ISTAT_SLEEP_MASK;
- process_bus_inactive(rhport);
- return;
+ process_bus_sleep(rhport);
}
+
+#if 0 // ISTAT_RESUME never trigger, probably for host mode ?
if (is & USB_ISTAT_RESUME_MASK) {
+ // TU_LOG2("ISTAT Resume: "); TU_LOG2_HEX(is);
KHCI->ISTAT = USB_ISTAT_RESUME_MASK;
- process_bus_active(rhport);
- return;
+ process_bus_resume(rhport);
}
+#endif
+
+ if (KHCI->USBTRC0 & USB_USBTRC0_USB_RESUME_INT_MASK) {
+ // TU_LOG2("USBTRC0 Resume: "); TU_LOG2_HEX(is); TU_LOG2_HEX(KHCI->USBTRC0);
+ process_bus_resume(rhport);
+ }
+
if (is & USB_ISTAT_SOFTOK_MASK) {
KHCI->ISTAT = USB_ISTAT_SOFTOK_MASK;
dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true);
- return;
}
+
if (is & USB_ISTAT_STALL_MASK) {
KHCI->ISTAT = USB_ISTAT_STALL_MASK;
process_stall(rhport);
- return;
}
+
if (is & USB_ISTAT_TOKDNE_MASK) {
process_tokdne(rhport);
- return;
}
}
diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c
index 519d09151..2eae6d0f7 100644
--- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c
+++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c
@@ -326,6 +326,12 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
return true;
}
+void dcd_edpt_close_all (uint8_t rhport)
+{
+ (void) rhport;
+ // TODO implement dcd_edpt_close_all()
+}
+
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
{
(void) rhport;
diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c
index 4392d1882..1bdf72d6d 100644
--- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c
+++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c
@@ -323,6 +323,12 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
return true;
}
+void dcd_edpt_close_all (uint8_t rhport)
+{
+ (void) rhport;
+ // TODO implement dcd_edpt_close_all()
+}
+
static void prepare_setup_packet(uint8_t rhport)
{
if (_dcd_controller[rhport].max_speed == TUSB_SPEED_FULL )
diff --git a/src/portable/nxp/transdimension/common_transdimension.h b/src/portable/nxp/transdimension/common_transdimension.h
index 7b94dac34..69074de41 100644
--- a/src/portable/nxp/transdimension/common_transdimension.h
+++ b/src/portable/nxp/transdimension/common_transdimension.h
@@ -127,7 +127,7 @@ typedef struct
__I uint32_t ENDPTSTAT; ///< Endpoint Status
__IO uint32_t ENDPTCOMPLETE; ///< Endpoint Complete
__IO uint32_t ENDPTCTRL[8]; ///< Endpoint Control 0 - 7
-} dcd_registers_t;
+} dcd_registers_t, hcd_registers_t;
#ifdef __cplusplus
}
diff --git a/src/portable/nxp/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c
index eeab3f487..a7c4545c2 100644
--- a/src/portable/nxp/transdimension/dcd_transdimension.c
+++ b/src/portable/nxp/transdimension/dcd_transdimension.c
@@ -57,11 +57,15 @@
// ENDPTCTRL
enum {
ENDPTCTRL_STALL = TU_BIT(0),
- ENDPTCTRL_TOGGLE_INHIBIT = TU_BIT(5), ///< used for test only
+ ENDPTCTRL_TOGGLE_INHIBIT = TU_BIT(5), // used for test only
ENDPTCTRL_TOGGLE_RESET = TU_BIT(6),
ENDPTCTRL_ENABLE = TU_BIT(7)
};
+enum {
+ ENDPTCTRL_TYPE_POS = 2, // Endpoint type is 2-bit field
+};
+
// USBSTS, USBINTR
enum {
INTR_USB = TU_BIT(0),
@@ -91,12 +95,15 @@ typedef struct
uint32_t : 3 ;
uint32_t int_on_complete : 1 ;
volatile uint32_t total_bytes : 15 ;
- uint32_t : 0 ;
+ uint32_t : 1 ;
// Word 2-6: Buffer Page Pointer List, Each element in the list is a 4K page aligned, physical memory address. The lower 12 bits in each pointer are reserved (except for the first one) as each memory pointer must reference the start of a 4K page
uint32_t buffer[5]; ///< buffer1 has frame_n for TODO Isochronous
- //------------- DCD Area -------------//
+ //--------------------------------------------------------------------+
+ // TD is 32 bytes aligned but occupies only 28 bytes
+ // Therefore there are 4 bytes padding that we can use.
+ //--------------------------------------------------------------------+
uint16_t expected_bytes;
uint8_t reserved[2];
} dcd_qtd_t;
@@ -109,11 +116,10 @@ typedef struct
// Word 0: Capabilities and Characteristics
uint32_t : 15 ; ///< Number of packets executed per transaction descriptor 00 - Execute N transactions as demonstrated by the USB variable length protocol where N is computed using Max_packet_length and the Total_bytes field in the dTD. 01 - Execute one transaction 10 - Execute two transactions 11 - Execute three transactions Remark: Non-isochronous endpoints must set MULT = 00. Remark: Isochronous endpoints must set MULT = 01, 10, or 11 as needed.
uint32_t int_on_setup : 1 ; ///< Interrupt on setup This bit is used on control type endpoints to indicate if USBINT is set in response to a setup being received.
- uint32_t max_package_size : 11 ; ///< This directly corresponds to the maximum packet size of the associated endpoint (wMaxPacketSize)
+ uint32_t max_packet_size : 11 ; ///< Endpoint's wMaxPacketSize
uint32_t : 2 ;
uint32_t zero_length_termination : 1 ; ///< This bit is used for non-isochronous endpoints to indicate when a zero-length packet is received to terminate transfers in case the total transfer length is “multiple”. 0 - Enable zero-length packet to terminate transfers equal to a multiple of Max_packet_length (default). 1 - Disable zero-length packet on transfers that are equal in length to a multiple Max_packet_length.
uint32_t iso_mult : 2 ; ///<
- uint32_t : 0 ;
// Word 1: Current qTD Pointer
volatile uint32_t qtd_addr;
@@ -125,10 +131,11 @@ typedef struct
volatile tusb_control_request_t setup_request;
//--------------------------------------------------------------------+
- /// Due to the fact QHD is 64 bytes aligned but occupies only 48 bytes
- /// thus there are 16 bytes padding free that we can make use of.
+ // QHD is 64 bytes aligned but occupies only 48 bytes
+ // Therefore there are 16 bytes padding that we can use.
//--------------------------------------------------------------------+
- uint8_t reserved[16];
+ tu_fifo_t * ff;
+ uint8_t reserved[12];
} dcd_qhd_t;
TU_VERIFY_STATIC( sizeof(dcd_qhd_t) == 64, "size is not correct");
@@ -145,10 +152,6 @@ typedef struct
}dcd_controller_t;
#if CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX
- // Each endpoint with direction (IN/OUT) occupies a queue head
- // Therefore QHD_MAX is 2 x max endpoint count
- #define QHD_MAX (8*2)
-
static const dcd_controller_t _dcd_controller[] =
{
// RT1010 and RT1020 only has 1 USB controller
@@ -161,8 +164,6 @@ typedef struct
};
#else
- #define QHD_MAX (6*2)
-
static const dcd_controller_t _dcd_controller[] =
{
{ .regs = (dcd_registers_t*) LPC_USB0_BASE, .irqnum = USB0_IRQn, .ep_count = 6 },
@@ -174,8 +175,10 @@ typedef struct
typedef struct {
// Must be at 2K alignment
- dcd_qhd_t qhd[QHD_MAX] TU_ATTR_ALIGNED(64);
- dcd_qtd_t qtd[QHD_MAX] TU_ATTR_ALIGNED(32); // for portability, TinyUSB only queue 1 TD for each Qhd
+ // Each endpoint with direction (IN/OUT) occupies a queue head
+ // for portability, TinyUSB only queue 1 TD for each Qhd
+ dcd_qhd_t qhd[DCD_ATTR_ENDPOINT_MAX][2] TU_ATTR_ALIGNED(64);
+ dcd_qtd_t qtd[DCD_ATTR_ENDPOINT_MAX][2] TU_ATTR_ALIGNED(32);
}dcd_data_t;
CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(2048)
@@ -195,9 +198,9 @@ static void bus_reset(uint8_t rhport)
// endpoint type of the unused direction must be changed from the control type to any other
// type (e.g. bulk). Leaving an un-configured endpoint control will cause undefined behavior
// for the data PID tracking on the active endpoint.
- for( int i=1; i < _dcd_controller[rhport].ep_count; i++)
+ for( uint8_t i=1; i < _dcd_controller[rhport].ep_count; i++)
{
- dcd_reg->ENDPTCTRL[i] = (TUSB_XFER_BULK << 2) | (TUSB_XFER_BULK << 18);
+ dcd_reg->ENDPTCTRL[i] = (TUSB_XFER_BULK << ENDPTCTRL_TYPE_POS) | (TUSB_XFER_BULK << (16+ENDPTCTRL_TYPE_POS));
}
//------------- Clear All Registers -------------//
@@ -217,11 +220,11 @@ static void bus_reset(uint8_t rhport)
tu_memclr(&_dcd_data, sizeof(dcd_data_t));
//------------- Set up Control Endpoints (0 OUT, 1 IN) -------------//
- _dcd_data.qhd[0].zero_length_termination = _dcd_data.qhd[1].zero_length_termination = 1;
- _dcd_data.qhd[0].max_package_size = _dcd_data.qhd[1].max_package_size = CFG_TUD_ENDPOINT0_SIZE;
- _dcd_data.qhd[0].qtd_overlay.next = _dcd_data.qhd[1].qtd_overlay.next = QTD_NEXT_INVALID;
+ _dcd_data.qhd[0][0].zero_length_termination = _dcd_data.qhd[0][1].zero_length_termination = 1;
+ _dcd_data.qhd[0][0].max_packet_size = _dcd_data.qhd[0][1].max_packet_size = CFG_TUD_ENDPOINT0_SIZE;
+ _dcd_data.qhd[0][0].qtd_overlay.next = _dcd_data.qhd[0][1].qtd_overlay.next = QTD_NEXT_INVALID;
- _dcd_data.qhd[0].int_on_setup = 1; // OUT only
+ _dcd_data.qhd[0][0].int_on_setup = 1; // OUT only
}
void dcd_init(uint8_t rhport)
@@ -238,14 +241,15 @@ void dcd_init(uint8_t rhport)
dcd_reg->USBMODE = USBMODE_CM_DEVICE;
dcd_reg->OTGSC = OTGSC_VBUS_DISCHARGE | OTGSC_OTG_TERMINATION;
- // TODO Force fullspeed on non-highspeed port
- // dcd_reg->PORTSC1 = PORTSC1_FORCE_FULL_SPEED;
+#if !TUD_OPT_HIGH_SPEED
+ dcd_reg->PORTSC1 = PORTSC1_FORCE_FULL_SPEED;
+#endif
CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
dcd_reg->ENDPTLISTADDR = (uint32_t) _dcd_data.qhd; // Endpoint List Address has to be 2K alignment
dcd_reg->USBSTS = dcd_reg->USBSTS;
- dcd_reg->USBINTR = INTR_USB | INTR_ERROR | INTR_PORT_CHANGE | INTR_RESET | INTR_SUSPEND /*| INTR_SOF*/;
+ dcd_reg->USBINTR = INTR_USB | INTR_ERROR | INTR_PORT_CHANGE | INTR_SUSPEND;
dcd_reg->USBCMD &= ~0x00FF0000; // Interrupt Threshold Interval = 0
dcd_reg->USBCMD |= USBCMD_RUN_STOP; // Connect
@@ -272,7 +276,8 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
void dcd_remote_wakeup(uint8_t rhport)
{
- (void) rhport;
+ dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
+ dcd_reg->PORTSC1 |= PORTSC1_FORCE_PORT_RESUME;
}
void dcd_connect(uint8_t rhport)
@@ -290,26 +295,33 @@ void dcd_disconnect(uint8_t rhport)
//--------------------------------------------------------------------+
// HELPER
//--------------------------------------------------------------------+
-// index to bit position in register
-static inline uint8_t ep_idx2bit(uint8_t ep_idx)
-{
- return ep_idx/2 + ( (ep_idx%2) ? 16 : 0);
-}
static void qtd_init(dcd_qtd_t* p_qtd, void * data_ptr, uint16_t total_bytes)
{
+ // Force the CPU to flush the buffer. We increase the size by 31 because the call aligns the
+ // address to 32-byte boundaries. Buffer must be word aligned
+ CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) data_ptr, 4), total_bytes + 31);
+
tu_memclr(p_qtd, sizeof(dcd_qtd_t));
- p_qtd->next = QTD_NEXT_INVALID;
- p_qtd->active = 1;
- p_qtd->total_bytes = p_qtd->expected_bytes = total_bytes;
+ p_qtd->next = QTD_NEXT_INVALID;
+ p_qtd->active = 1;
+ p_qtd->total_bytes = p_qtd->expected_bytes = total_bytes;
+ p_qtd->int_on_complete = true;
if (data_ptr != NULL)
{
- p_qtd->buffer[0] = (uint32_t) data_ptr;
+ p_qtd->buffer[0] = (uint32_t) data_ptr;
+
+ uint32_t const bufend = p_qtd->buffer[0] + total_bytes;
for(uint8_t i=1; i<5; i++)
{
- p_qtd->buffer[i] |= tu_align4k( p_qtd->buffer[i-1] ) + 4096;
+ uint32_t const next_page = tu_align4k( p_qtd->buffer[i-1] ) + 4096;
+ if ( bufend <= next_page ) break;
+
+ p_qtd->buffer[i] = next_page;
+
+ // TODO page[1] FRAME_N for ISO transfer
}
}
}
@@ -324,12 +336,15 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
dcd_reg->ENDPTCTRL[epnum] |= ENDPTCTRL_STALL << (dir ? 16 : 0);
+
+ // flush to abort any primed buffer
+ dcd_reg->ENDPTFLUSH = TU_BIT(epnum + (dir ? 16 : 0));
}
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
{
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
// data toggle also need to be reset
dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
@@ -339,39 +354,87 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
{
- // TODO not support ISO yet
- TU_VERIFY ( p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS);
-
- uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress);
- uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress);
- uint8_t const ep_idx = 2*epnum + dir;
+ uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress);
+ uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress);
// Must not exceed max endpoint number
TU_ASSERT( epnum < _dcd_controller[rhport].ep_count );
//------------- Prepare Queue Head -------------//
- dcd_qhd_t * p_qhd = &_dcd_data.qhd[ep_idx];
+ dcd_qhd_t * p_qhd = &_dcd_data.qhd[epnum][dir];
tu_memclr(p_qhd, sizeof(dcd_qhd_t));
p_qhd->zero_length_termination = 1;
- p_qhd->max_package_size = p_endpoint_desc->wMaxPacketSize.size;
+ p_qhd->max_packet_size = p_endpoint_desc->wMaxPacketSize.size;
+ if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS)
+ {
+ p_qhd->iso_mult = 1;
+ }
+
p_qhd->qtd_overlay.next = QTD_NEXT_INVALID;
CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
// Enable EP Control
dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
- dcd_reg->ENDPTCTRL[epnum] |= ((p_endpoint_desc->bmAttributes.xfer << 2) | ENDPTCTRL_ENABLE | ENDPTCTRL_TOGGLE_RESET) << (dir ? 16 : 0);
+
+ uint32_t const epctrl = (p_endpoint_desc->bmAttributes.xfer << ENDPTCTRL_TYPE_POS) | ENDPTCTRL_ENABLE | ENDPTCTRL_TOGGLE_RESET;
+
+ if ( dir == TUSB_DIR_OUT )
+ {
+ dcd_reg->ENDPTCTRL[epnum] = (dcd_reg->ENDPTCTRL[epnum] & 0xFFFF0000u) | epctrl;
+ }else
+ {
+ dcd_reg->ENDPTCTRL[epnum] = (dcd_reg->ENDPTCTRL[epnum] & 0x0000FFFFu) | (epctrl << 16);
+ }
return true;
}
-bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
+void dcd_edpt_close_all (uint8_t rhport)
{
dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
- uint8_t const ep_idx = 2*epnum + dir;
+
+ // Disable all non-control endpoints
+ for( uint8_t epnum=1; epnum < _dcd_controller[rhport].ep_count; epnum++)
+ {
+ _dcd_data.qhd[epnum][TUSB_DIR_OUT].qtd_overlay.halted = 1;
+ _dcd_data.qhd[epnum][TUSB_DIR_IN ].qtd_overlay.halted = 1;
+
+ dcd_reg->ENDPTFLUSH = TU_BIT(epnum) | TU_BIT(epnum+16);
+ dcd_reg->ENDPTCTRL[epnum] = (TUSB_XFER_BULK << ENDPTCTRL_TYPE_POS) | (TUSB_XFER_BULK << (16+ENDPTCTRL_TYPE_POS));
+ }
+}
+
+void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
+{
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
+
+ dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
+
+ _dcd_data.qhd[epnum][dir].qtd_overlay.halted = 1;
+
+ // Flush EP
+ uint32_t const flush_mask = TU_BIT(epnum + (dir ? 16 : 0));
+ dcd_reg->ENDPTFLUSH = flush_mask;
+ while(dcd_reg->ENDPTFLUSH & flush_mask);
+
+ // Clear EP enable
+ dcd_reg->ENDPTCTRL[epnum] &=~(ENDPTCTRL_ENABLE << (dir ? 16 : 0));
+}
+
+static void qhd_start_xfer(uint8_t rhport, uint8_t epnum, uint8_t dir)
+{
+ dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
+ dcd_qhd_t* p_qhd = &_dcd_data.qhd[epnum][dir];
+ dcd_qtd_t* p_qtd = &_dcd_data.qtd[epnum][dir];
+
+ p_qhd->qtd_overlay.halted = false; // clear any previous error
+ p_qhd->qtd_overlay.next = (uint32_t) p_qtd; // link qtd to qhd
+
+ // flush cache
+ CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
if ( epnum == 0 )
{
@@ -380,23 +443,87 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t
while(dcd_reg->ENDPTSETUPSTAT & TU_BIT(0)) {}
}
- dcd_qhd_t * p_qhd = &_dcd_data.qhd[ep_idx];
- dcd_qtd_t * p_qtd = &_dcd_data.qtd[ep_idx];
+ // start transfer
+ dcd_reg->ENDPTPRIME = TU_BIT(epnum + (dir ? 16 : 0));
+}
+
+bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
+{
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
- // Force the CPU to flush the buffer. We increase the size by 32 because the call aligns the
- // address to 32-byte boundaries.
- // void* cast to suppress cast-align warning, buffer must be
- CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) buffer, 4), total_bytes + 31);
+ dcd_qhd_t* p_qhd = &_dcd_data.qhd[epnum][dir];
+ dcd_qtd_t* p_qtd = &_dcd_data.qtd[epnum][dir];
- //------------- Prepare qtd -------------//
+ // Prepare qtd
qtd_init(p_qtd, buffer, total_bytes);
- p_qtd->int_on_complete = true;
- p_qhd->qtd_overlay.next = (uint32_t) p_qtd; // link qtd to qhd
- CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
+ // Start qhd transfer
+ p_qhd->ff = NULL;
+ qhd_start_xfer(rhport, epnum, dir);
- // start transfer
- dcd_reg->ENDPTPRIME = TU_BIT( ep_idx2bit(ep_idx) ) ;
+ return true;
+}
+
+// fifo has to be aligned to 4k boundary
+bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
+{
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
+
+ dcd_qhd_t * p_qhd = &_dcd_data.qhd[epnum][dir];
+ dcd_qtd_t * p_qtd = &_dcd_data.qtd[epnum][dir];
+
+ tu_fifo_buffer_info_t fifo_info;
+
+ if (dir)
+ {
+ tu_fifo_get_read_info(ff, &fifo_info);
+ } else
+ {
+ tu_fifo_get_write_info(ff, &fifo_info);
+ }
+
+ if ( fifo_info.len_lin >= total_bytes )
+ {
+ // Linear length is enough for this transfer
+ qtd_init(p_qtd, fifo_info.ptr_lin, total_bytes);
+ }
+ else
+ {
+ // linear part is not enough
+
+ // prepare TD up to linear length
+ qtd_init(p_qtd, fifo_info.ptr_lin, fifo_info.len_lin);
+
+ if ( !tu_offset4k((uint32_t) fifo_info.ptr_wrap) && !tu_offset4k(tu_fifo_depth(ff)) )
+ {
+ // If buffer is aligned to 4K & buffer size is multiple of 4K
+ // We can make use of buffer page array to also combine the linear + wrapped length
+ p_qtd->total_bytes = p_qtd->expected_bytes = total_bytes;
+
+ for(uint8_t i = 1, page = 0; i < 5; i++)
+ {
+ // pick up buffer array where linear ends
+ if (p_qtd->buffer[i] == 0)
+ {
+ p_qtd->buffer[i] = (uint32_t) fifo_info.ptr_wrap + 4096 * page;
+ page++;
+ }
+ }
+
+ CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) fifo_info.ptr_wrap, 4), total_bytes - fifo_info.len_wrap + 31);
+ }
+ else
+ {
+ // TODO we may need to carry the wrapped length after the linear part complete
+ // for now only transfer up to linear part
+ }
+ }
+
+ // Start qhd transfer
+ p_qhd->ff = ff;
+ qhd_start_xfer(rhport, epnum, dir);
return true;
}
@@ -404,9 +531,42 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t
//--------------------------------------------------------------------+
// ISR
//--------------------------------------------------------------------+
+
+static void process_edpt_complete_isr(uint8_t rhport, uint8_t epnum, uint8_t dir)
+{
+ dcd_qhd_t * p_qhd = &_dcd_data.qhd[epnum][dir];
+ dcd_qtd_t * p_qtd = &_dcd_data.qtd[epnum][dir];
+
+ uint8_t result = p_qtd->halted ? XFER_RESULT_STALLED :
+ ( p_qtd->xact_err || p_qtd->buffer_err ) ? XFER_RESULT_FAILED : XFER_RESULT_SUCCESS;
+
+ if ( result != XFER_RESULT_SUCCESS )
+ {
+ dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
+ // flush to abort error buffer
+ dcd_reg->ENDPTFLUSH = TU_BIT(epnum + (dir ? 16 : 0));
+ }
+
+ uint16_t const xferred_bytes = p_qtd->expected_bytes - p_qtd->total_bytes;
+
+ if (p_qhd->ff)
+ {
+ if (dir == TUSB_DIR_IN)
+ {
+ tu_fifo_advance_read_pointer(p_qhd->ff, xferred_bytes);
+ } else
+ {
+ tu_fifo_advance_write_pointer(p_qhd->ff, xferred_bytes);
+ }
+ }
+
+ // only number of bytes in the IOC qtd
+ dcd_event_xfer_complete(rhport, tu_edpt_addr(epnum, dir), xferred_bytes, result, true);
+}
+
void dcd_int_handler(uint8_t rhport)
{
- dcd_registers_t* const dcd_reg = _dcd_controller[rhport].regs;
+ dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs;
uint32_t const int_enable = dcd_reg->USBINTR;
uint32_t const int_status = dcd_reg->USBSTS & int_enable;
@@ -415,18 +575,46 @@ void dcd_int_handler(uint8_t rhport)
// disabled interrupt sources
if (int_status == 0) return;
- if (int_status & INTR_RESET)
- {
- bus_reset(rhport);
- uint32_t speed = (dcd_reg->PORTSC1 & PORTSC1_PORT_SPEED) >> PORTSC1_PORT_SPEED_POS;
- dcd_event_bus_reset(rhport, (tusb_speed_t) speed, true);
- }
+ // Set if the port controller enters the full or high-speed operational state.
+ // either from Bus Reset or Suspended state
+ if (int_status & INTR_PORT_CHANGE)
+ {
+ // TU_LOG2("PortChange %08lx\r\n", dcd_reg->PORTSC1);
+
+ // Reset interrupt is not enabled, we manually check if Port Change is due
+ // to connection / disconnection
+ if ( dcd_reg->USBSTS & INTR_RESET )
+ {
+ dcd_reg->USBSTS = INTR_RESET;
+
+ if (dcd_reg->PORTSC1 & PORTSC1_CURRENT_CONNECT_STATUS)
+ {
+ uint32_t const speed = (dcd_reg->PORTSC1 & PORTSC1_PORT_SPEED) >> PORTSC1_PORT_SPEED_POS;
+ bus_reset(rhport);
+ dcd_event_bus_reset(rhport, (tusb_speed_t) speed, true);
+ }else
+ {
+ dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true);
+ }
+ }
+ else
+ {
+ // Triggered by resuming from suspended state
+ if ( !(dcd_reg->PORTSC1 & PORTSC1_SUSPEND) )
+ {
+ dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true);
+ }
+ }
+ }
if (int_status & INTR_SUSPEND)
{
+ // TU_LOG2("Suspend %08lx\r\n", dcd_reg->PORTSC1);
+
if (dcd_reg->PORTSC1 & PORTSC1_SUSPEND)
{
// Note: Host may delay more than 3 ms before and/or after bus reset before doing enumeration.
+ // Skip suspend event if we are not addressed
if ((dcd_reg->DEVICEADDR >> 25) & 0x0f)
{
dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true);
@@ -434,21 +622,11 @@ void dcd_int_handler(uint8_t rhport)
}
}
- // Make sure we read the latest version of _dcd_data.
- CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
-
- // TODO disconnection does not generate interrupt !!!!!!
-// if (int_status & INTR_PORT_CHANGE)
-// {
-// if ( !(dcd_reg->PORTSC1 & PORTSC1_CURRENT_CONNECT_STATUS) )
-// {
-// dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_UNPLUGGED };
-// dcd_event_handler(&event, true);
-// }
-// }
-
if (int_status & INTR_USB)
{
+ // Make sure we read the latest version of _dcd_data.
+ CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
+
uint32_t const edpt_complete = dcd_reg->ENDPTCOMPLETE;
dcd_reg->ENDPTCOMPLETE = edpt_complete; // acknowledge
@@ -456,26 +634,21 @@ void dcd_int_handler(uint8_t rhport)
{
//------------- Set up Received -------------//
// 23.10.10.2 Operational model for setup transfers
- dcd_reg->ENDPTSETUPSTAT = dcd_reg->ENDPTSETUPSTAT;// acknowledge
+ dcd_reg->ENDPTSETUPSTAT = dcd_reg->ENDPTSETUPSTAT;
- dcd_event_setup_received(rhport, (uint8_t*) &_dcd_data.qhd[0].setup_request, true);
+ dcd_event_setup_received(rhport, (uint8_t*) &_dcd_data.qhd[0][0].setup_request, true);
}
+ // 23.10.12.3 Failed QTD also get ENDPTCOMPLETE set
+ // nothing to do, we will submit xfer as error to usbd
+ // if (int_status & INTR_ERROR) { }
+
if ( edpt_complete )
{
- for(uint8_t ep_idx = 0; ep_idx < QHD_MAX; ep_idx++)
+ for(uint8_t epnum = 0; epnum < DCD_ATTR_ENDPOINT_MAX; epnum++)
{
- if ( tu_bit_test(edpt_complete, ep_idx2bit(ep_idx)) )
- {
- // 23.10.12.3 Failed QTD also get ENDPTCOMPLETE set
- dcd_qtd_t * p_qtd = &_dcd_data.qtd[ep_idx];
-
- uint8_t result = p_qtd->halted ? XFER_RESULT_STALLED :
- ( p_qtd->xact_err ||p_qtd->buffer_err ) ? XFER_RESULT_FAILED : XFER_RESULT_SUCCESS;
-
- uint8_t const ep_addr = (ep_idx/2) | ( (ep_idx & 0x01) ? TUSB_DIR_IN_MASK : 0 );
- dcd_event_xfer_complete(rhport, ep_addr, p_qtd->expected_bytes - p_qtd->total_bytes, result, true); // only number of bytes in the IOC qtd
- }
+ if ( tu_bit_test(edpt_complete, epnum) ) process_edpt_complete_isr(rhport, epnum, TUSB_DIR_OUT);
+ if ( tu_bit_test(edpt_complete, epnum+16) ) process_edpt_complete_isr(rhport, epnum, TUSB_DIR_IN);
}
}
}
@@ -484,9 +657,6 @@ void dcd_int_handler(uint8_t rhport)
{
dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true);
}
-
- if (int_status & INTR_NAK) {}
- if (int_status & INTR_ERROR) TU_ASSERT(false, );
}
#endif
diff --git a/src/portable/nxp/transdimension/hcd_transdimension.c b/src/portable/nxp/transdimension/hcd_transdimension.c
index db447ef23..d216f0728 100644
--- a/src/portable/nxp/transdimension/hcd_transdimension.c
+++ b/src/portable/nxp/transdimension/hcd_transdimension.c
@@ -43,7 +43,7 @@
#include "common/tusb_common.h"
#include "common_transdimension.h"
-#include "portable/ehci/hcd_ehci.h"
+#include "portable/ehci/ehci_api.h"
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
@@ -82,26 +82,26 @@ typedef struct
bool hcd_init(uint8_t rhport)
{
- dcd_registers_t* dcd_reg = (dcd_registers_t*) _hcd_controller[rhport].regs_base;
+ hcd_registers_t* hcd_reg = (hcd_registers_t*) _hcd_controller[rhport].regs_base;
// Reset controller
- dcd_reg->USBCMD |= USBCMD_RESET;
- while( dcd_reg->USBCMD & USBCMD_RESET ) {}
+ hcd_reg->USBCMD |= USBCMD_RESET;
+ while( hcd_reg->USBCMD & USBCMD_RESET ) {}
// Set mode to device, must be set immediately after reset
#if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX
// LPC18XX/43XX need to set VBUS Power Select to HIGH
// RHPORT1 is fullspeed only (need external PHY for Highspeed)
- dcd_reg->USBMODE = USBMODE_CM_HOST | USBMODE_VBUS_POWER_SELECT;
- if (rhport == 1) dcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED;
+ hcd_reg->USBMODE = USBMODE_CM_HOST | USBMODE_VBUS_POWER_SELECT;
+ if (rhport == 1) hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED;
#else
- dcd_reg->USBMODE = USBMODE_CM_HOST;
+ hcd_reg->USBMODE = USBMODE_CM_HOST;
#endif
// FIXME force full speed, still have issue with Highspeed enumeration
- dcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED;
+ hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED;
- return hcd_ehci_init(rhport);
+ return ehci_init(rhport, (uint32_t) &hcd_reg->CAPLENGTH, (uint32_t) &hcd_reg->USBCMD);
}
void hcd_int_enable(uint8_t rhport)
@@ -114,12 +114,4 @@ void hcd_int_disable(uint8_t rhport)
NVIC_DisableIRQ(_hcd_controller[rhport].irqnum);
}
-uint32_t hcd_ehci_register_addr(uint8_t rhport)
-{
- dcd_registers_t* hcd_reg = (dcd_registers_t*) _hcd_controller[rhport].regs_base;
-
- // EHCI USBCMD has same address within dcd_register_t
- return (uint32_t) &hcd_reg->USBCMD;
-}
-
#endif
diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c
index 73489c764..bcee34938 100644
--- a/src/portable/ohci/ohci.c
+++ b/src/portable/ohci/ohci.c
@@ -24,10 +24,9 @@
* This file is part of the TinyUSB stack.
*/
-#include <common/tusb_common.h>
+#include "host/hcd_attr.h"
-#if TUSB_OPT_HOST_ENABLED && \
- (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX)
+#if TUSB_OPT_HOST_ENABLED && defined(HCD_ATTR_OHCI)
//--------------------------------------------------------------------+
// INCLUDE
@@ -35,7 +34,6 @@
#include "osal/osal.h"
#include "host/hcd.h"
-#include "host/usbh_hcd.h"
#include "ohci.h"
// TODO remove
@@ -280,10 +278,13 @@ static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t ep_size, uint8_t
tu_memclr(p_ed, sizeof(ohci_ed_t));
}
+ hcd_devtree_info_t devtree_info;
+ hcd_devtree_get_info(dev_addr, &devtree_info);
+
p_ed->dev_addr = dev_addr;
p_ed->ep_number = ep_addr & 0x0F;
p_ed->pid = (xfer_type == TUSB_XFER_CONTROL) ? PID_FROM_TD : (tu_edpt_dir(ep_addr) ? PID_IN : PID_OUT);
- p_ed->speed = _usbh_devices[dev_addr].speed;
+ p_ed->speed = devtree_info.speed;
p_ed->is_iso = (xfer_type == TUSB_XFER_ISOCHRONOUS) ? 1 : 0;
p_ed->max_packet_size = ep_size;
diff --git a/src/portable/ohci/ohci.h b/src/portable/ohci/ohci.h
index 6a634592a..cd90aa45a 100644
--- a/src/portable/ohci/ohci.h
+++ b/src/portable/ohci/ohci.h
@@ -159,7 +159,7 @@ typedef struct TU_ATTR_ALIGNED(256)
struct {
ohci_ed_t ed;
ohci_gtd_t gtd;
- }control[CFG_TUSB_HOST_DEVICE_MAX+1];
+ }control[CFG_TUH_DEVICE_MAX+1];
// ochi_itd_t itd[OHCI_MAX_ITD]; // itd requires alignment of 32
ohci_ed_t ed_pool[HCD_MAX_ENDPOINT];
diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c
index 0048270a6..a710bd557 100644
--- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c
+++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c
@@ -37,6 +37,11 @@
#include "device/dcd.h"
+// Current implementation force vbus detection as always present, causing device think it is always plugged into host.
+// Therefore it cannot detect disconnect event, mistaken it as suspend.
+// Note: won't work if change to 0 (for now)
+#define FORCE_VBUS_DETECT 1
+
/*------------------------------------------------------------------*/
/* Low level controller
*------------------------------------------------------------------*/
@@ -48,129 +53,44 @@
static uint8_t *next_buffer_ptr;
// USB_MAX_ENDPOINTS Endpoints, direction TUSB_DIR_OUT for out and TUSB_DIR_IN for in.
-static struct hw_endpoint hw_endpoints[USB_MAX_ENDPOINTS][2] = {0};
+static struct hw_endpoint hw_endpoints[USB_MAX_ENDPOINTS][2];
static inline struct hw_endpoint *hw_endpoint_get_by_num(uint8_t num, tusb_dir_t dir)
{
- return &hw_endpoints[num][dir];
+ return &hw_endpoints[num][dir];
}
static struct hw_endpoint *hw_endpoint_get_by_addr(uint8_t ep_addr)
{
- uint8_t num = tu_edpt_number(ep_addr);
- tusb_dir_t dir = tu_edpt_dir(ep_addr);
- return hw_endpoint_get_by_num(num, dir);
+ uint8_t num = tu_edpt_number(ep_addr);
+ tusb_dir_t dir = tu_edpt_dir(ep_addr);
+ return hw_endpoint_get_by_num(num, dir);
}
-static void _hw_endpoint_alloc(struct hw_endpoint *ep)
+static void _hw_endpoint_alloc(struct hw_endpoint *ep, uint8_t transfer_type)
{
- uint16_t size = tu_min16(64, ep->wMaxPacketSize);
-
- // Assumes single buffered for now
- ep->hw_data_buf = next_buffer_ptr;
- next_buffer_ptr += size;
- // Bits 0-5 are ignored by the controller so make sure these are 0
- if ((uintptr_t)next_buffer_ptr & 0b111111u)
- {
- // Round up to the next 64
- uint32_t fixptr = (uintptr_t)next_buffer_ptr;
- fixptr &= ~0b111111u;
- fixptr += 64;
- pico_info("Rounding non 64 byte boundary buffer up from %x to %x\n", (uintptr_t)next_buffer_ptr, fixptr);
- next_buffer_ptr = (uint8_t*)fixptr;
- }
- assert(((uintptr_t)next_buffer_ptr & 0b111111u) == 0);
- uint dpram_offset = hw_data_offset(ep->hw_data_buf);
- assert(hw_data_offset(next_buffer_ptr) <= USB_DPRAM_MAX);
+ // size must be multiple of 64
+ uint16_t size = tu_div_ceil(ep->wMaxPacketSize, 64) * 64u;
- pico_info("Alloced %d bytes at offset 0x%x (0x%p) for ep %d %s\n",
- size,
- dpram_offset,
- ep->hw_data_buf,
- ep->num,
- ep_dir_string[ep->in]);
+ // double buffered Bulk endpoint
+ if ( transfer_type == TUSB_XFER_BULK )
+ {
+ size *= 2u;
+ }
- // Fill in endpoint control register with buffer offset
- uint32_t reg = EP_CTRL_ENABLE_BITS
- | EP_CTRL_INTERRUPT_PER_BUFFER
- | (ep->transfer_type << EP_CTRL_BUFFER_TYPE_LSB)
- | dpram_offset;
+ ep->hw_data_buf = next_buffer_ptr;
+ next_buffer_ptr += size;
- *ep->endpoint_control = reg;
-}
+ assert(((uintptr_t )next_buffer_ptr & 0b111111u) == 0);
+ uint dpram_offset = hw_data_offset(ep->hw_data_buf);
+ assert(hw_data_offset(next_buffer_ptr) <= USB_DPRAM_MAX);
-static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type)
-{
- const uint8_t num = tu_edpt_number(ep_addr);
- const tusb_dir_t dir = tu_edpt_dir(ep_addr);
- ep->ep_addr = ep_addr;
- // For device, IN is a tx transfer and OUT is an rx transfer
- ep->rx = (dir == TUSB_DIR_OUT);
- // Response to a setup packet on EP0 starts with pid of 1
- ep->next_pid = num == 0 ? 1u : 0u;
+ pico_info(" Alloced %d bytes at offset 0x%x (0x%p)\r\n", size, dpram_offset, ep->hw_data_buf);
- // Add some checks around the max packet size
- if (transfer_type == TUSB_XFER_ISOCHRONOUS)
- {
- if (wMaxPacketSize > USB_MAX_ISO_PACKET_SIZE)
- {
- panic("Isochronous wMaxPacketSize %d too large", wMaxPacketSize);
- }
- }
- else
- {
- if (wMaxPacketSize > USB_MAX_PACKET_SIZE)
- {
- panic("Isochronous wMaxPacketSize %d too large", wMaxPacketSize);
- }
- }
+ // Fill in endpoint control register with buffer offset
+ uint32_t const reg = EP_CTRL_ENABLE_BITS | (transfer_type << EP_CTRL_BUFFER_TYPE_LSB) | dpram_offset;
- ep->wMaxPacketSize = wMaxPacketSize;
- ep->transfer_type = transfer_type;
-
- // Every endpoint has a buffer control register in dpram
- if (dir == TUSB_DIR_IN)
- {
- ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].in;
- }
- else
- {
- ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].out;
- }
-
- // Clear existing buffer control state
- *ep->buffer_control = 0;
-
- if (num == 0)
- {
- // EP0 has no endpoint control register because
- // the buffer offsets are fixed
- ep->endpoint_control = NULL;
-
- // Buffer offset is fixed
- ep->hw_data_buf = (uint8_t*)&usb_dpram->ep0_buf_a[0];
- }
- else
- {
- // Set the endpoint control register (starts at EP1, hence num-1)
- if (dir == TUSB_DIR_IN)
- {
- ep->endpoint_control = &usb_dpram->ep_ctrl[num-1].in;
- }
- else
- {
- ep->endpoint_control = &usb_dpram->ep_ctrl[num-1].out;
- }
-
- // Now if it hasn't already been done
- //alloc a buffer and fill in endpoint control register
- if(!(ep->configured))
- {
- _hw_endpoint_alloc(ep);
- }
- }
-
- ep->configured = true;
+ *ep->endpoint_control = reg;
}
#if 0 // todo unused
@@ -192,40 +112,87 @@ static void hw_endpoint_close(uint8_t ep_addr)
}
#endif
-static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t bmAttributes)
+static void hw_endpoint_init(uint8_t ep_addr, uint16_t wMaxPacketSize, uint8_t transfer_type)
{
- struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr);
- _hw_endpoint_init(ep, ep_addr, wMaxPacketSize, bmAttributes);
+ struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr);
+
+ const uint8_t num = tu_edpt_number(ep_addr);
+ const tusb_dir_t dir = tu_edpt_dir(ep_addr);
+
+ ep->ep_addr = ep_addr;
+
+ // For device, IN is a tx transfer and OUT is an rx transfer
+ ep->rx = (dir == TUSB_DIR_OUT);
+
+ ep->next_pid = 0u;
+ ep->wMaxPacketSize = wMaxPacketSize;
+ ep->transfer_type = transfer_type;
+
+ // Every endpoint has a buffer control register in dpram
+ if ( dir == TUSB_DIR_IN )
+ {
+ ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].in;
+ }
+ else
+ {
+ ep->buffer_control = &usb_dpram->ep_buf_ctrl[num].out;
+ }
+
+ // Clear existing buffer control state
+ *ep->buffer_control = 0;
+
+ if ( num == 0 )
+ {
+ // EP0 has no endpoint control register because the buffer offsets are fixed
+ ep->endpoint_control = NULL;
+
+ // Buffer offset is fixed (also double buffered)
+ ep->hw_data_buf = (uint8_t*) &usb_dpram->ep0_buf_a[0];
+ }
+ else
+ {
+ // Set the endpoint control register (starts at EP1, hence num-1)
+ if ( dir == TUSB_DIR_IN )
+ {
+ ep->endpoint_control = &usb_dpram->ep_ctrl[num - 1].in;
+ }
+ else
+ {
+ ep->endpoint_control = &usb_dpram->ep_ctrl[num - 1].out;
+ }
+
+ // alloc a buffer and fill in endpoint control register
+ _hw_endpoint_alloc(ep, transfer_type);
+ }
}
-static void hw_endpoint_xfer(uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes, bool start)
+static void hw_endpoint_xfer(uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
{
struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr);
- _hw_endpoint_xfer(ep, buffer, total_bytes, start);
+ hw_endpoint_xfer_start(ep, buffer, total_bytes);
}
static void hw_handle_buff_status(void)
{
uint32_t remaining_buffers = usb_hw->buf_status;
- pico_trace("buf_status 0x%08x\n", remaining_buffers);
+ pico_trace("buf_status = 0x%08x\n", remaining_buffers);
uint bit = 1u;
for (uint i = 0; remaining_buffers && i < USB_MAX_ENDPOINTS * 2; i++)
{
if (remaining_buffers & bit)
{
- uint __unused which = (usb_hw->buf_cpu_should_handle & bit) ? 1 : 0;
- // Should be single buffered
- assert(which == 0);
// clear this in advance
usb_hw_clear->buf_status = bit;
+
// IN transfer for even i, OUT transfer for odd i
struct hw_endpoint *ep = hw_endpoint_get_by_num(i >> 1u, !(i & 1u));
+
// Continue xfer
- bool done = _hw_endpoint_xfer_continue(ep);
+ bool done = hw_endpoint_xfer_continue(ep);
if (done)
{
// Notify
- dcd_event_xfer_complete(0, ep->ep_addr, ep->len, XFER_RESULT_SUCCESS, true);
+ dcd_event_xfer_complete(0, ep->ep_addr, ep->xferred_len, XFER_RESULT_SUCCESS, true);
hw_endpoint_reset_transfer(ep);
}
remaining_buffers &= ~bit;
@@ -234,7 +201,7 @@ static void hw_handle_buff_status(void)
}
}
-static void reset_ep0(void)
+static void reset_ep0_pid(void)
{
// If we have finished this transfer on EP0 set pid back to 1 for next
// setup transfer. Also clear a stall in case
@@ -243,63 +210,36 @@ static void reset_ep0(void)
{
struct hw_endpoint *ep = hw_endpoint_get_by_addr(addrs[i]);
ep->next_pid = 1u;
- ep->stalled = 0;
- }
-}
-
-static void ep0_0len_status(void)
-{
- // Send 0len complete response on EP0 IN
- reset_ep0();
- hw_endpoint_xfer(0x80, NULL, 0, true);
-}
-
-static void _hw_endpoint_stall(struct hw_endpoint *ep)
-{
- assert(!ep->stalled);
- if (tu_edpt_number(ep->ep_addr) == 0)
- {
- // A stall on EP0 has to be armed so it can be cleared on the next setup packet
- usb_hw_set->ep_stall_arm = (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN) ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS;
}
- _hw_endpoint_buffer_control_set_mask32(ep, USB_BUF_CTRL_STALL);
- ep->stalled = true;
}
-static void hw_endpoint_stall(uint8_t ep_addr)
+static void reset_non_control_endpoints(void)
{
- struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr);
- _hw_endpoint_stall(ep);
-}
+ // Disable all non-control
+ for ( uint8_t i = 0; i < USB_MAX_ENDPOINTS-1; i++ )
+ {
+ usb_dpram->ep_ctrl[i].in = 0;
+ usb_dpram->ep_ctrl[i].out = 0;
+ }
-static void _hw_endpoint_clear_stall(struct hw_endpoint *ep)
-{
- if (tu_edpt_number(ep->ep_addr) == 0)
- {
- // Probably already been cleared but no harm
- usb_hw_clear->ep_stall_arm = (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN) ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS;
- }
- _hw_endpoint_buffer_control_clear_mask32(ep, USB_BUF_CTRL_STALL);
- ep->stalled = false;
-}
-
-static void hw_endpoint_clear_stall(uint8_t ep_addr)
-{
- struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr);
- _hw_endpoint_clear_stall(ep);
+ // clear non-control hw endpoints
+ tu_memclr(hw_endpoints[1], sizeof(hw_endpoints) - 2*sizeof(hw_endpoint_t));
+ next_buffer_ptr = &usb_dpram->epx_data[0];
}
static void dcd_rp2040_irq(void)
{
- uint32_t status = usb_hw->ints;
+ uint32_t const status = usb_hw->ints;
uint32_t handled = 0;
if (status & USB_INTS_SETUP_REQ_BITS)
{
handled |= USB_INTS_SETUP_REQ_BITS;
uint8_t const *setup = (uint8_t const *)&usb_dpram->setup_packet;
- // Clear stall bits and reset pid
- reset_ep0();
+
+ // reset pid to both 1 (data and ack)
+ reset_ep0_pid();
+
// Pass setup packet to tiny usb
dcd_event_setup_received(0, setup, true);
usb_hw_clear->sie_status = USB_SIE_STATUS_SETUP_REC_BITS;
@@ -311,7 +251,9 @@ static void dcd_rp2040_irq(void)
hw_handle_buff_status();
}
- // SE0 for 2 us or more, usually together with Bus Reset
+#if FORCE_VBUS_DETECT == 0
+ // Since we force VBUS detect On, device will always think it is connected and
+ // couldn't distinguish between disconnect and suspend
if (status & USB_INTS_DEV_CONN_DIS_BITS)
{
handled |= USB_INTS_DEV_CONN_DIS_BITS;
@@ -327,28 +269,26 @@ static void dcd_rp2040_irq(void)
usb_hw_clear->sie_status = USB_SIE_STATUS_CONNECTED_BITS;
}
+#endif
- // SE0 for 2.5 us or more
+ // SE0 for 2.5 us or more (will last at least 10ms)
if (status & USB_INTS_BUS_RESET_BITS)
{
pico_trace("BUS RESET\n");
- usb_hw->dev_addr_ctrl = 0;
+
handled |= USB_INTS_BUS_RESET_BITS;
+
+ usb_hw->dev_addr_ctrl = 0;
+ reset_non_control_endpoints();
dcd_event_bus_reset(0, TUSB_SPEED_FULL, true);
usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS;
#if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX
// Only run enumeration walk-around if pull up is enabled
- if ( usb_hw->sie_ctrl & USB_SIE_CTRL_PULLUP_EN_BITS )
- {
- rp2040_usb_device_enumeration_fix();
- }
+ if ( usb_hw->sie_ctrl & USB_SIE_CTRL_PULLUP_EN_BITS ) rp2040_usb_device_enumeration_fix();
#endif
}
-#if 0
- // TODO Enable SUSPEND & RESUME interrupt and test later on with/without VBUS detection
-
/* Note from pico datasheet 4.1.2.6.4 (v1.2)
* If you enable the suspend interrupt, it is likely you will see a suspend interrupt when
* the device is first connected but the bus is idle. The bus can be idle for a few ms before
@@ -370,7 +310,6 @@ static void dcd_rp2040_irq(void)
dcd_event_bus_signal(0, DCD_EVENT_RESUME, true);
usb_hw_clear->sie_status = USB_SIE_STATUS_RESUME_BITS;
}
-#endif
if (status ^ handled)
{
@@ -388,36 +327,42 @@ static void dcd_rp2040_irq(void)
/*------------------------------------------------------------------*/
/* Controller API
*------------------------------------------------------------------*/
+
void dcd_init (uint8_t rhport)
{
- pico_trace("dcd_init %d\n", rhport);
- assert(rhport == 0);
+ assert(rhport == 0);
- // Reset hardware to default state
- rp2040_usb_init();
+ // Reset hardware to default state
+ rp2040_usb_init();
- irq_set_exclusive_handler(USBCTRL_IRQ, dcd_rp2040_irq);
- memset(hw_endpoints, 0, sizeof(hw_endpoints));
- next_buffer_ptr = &usb_dpram->epx_data[0];
+#if FORCE_VBUS_DETECT
+ // Force VBUS detect so the device thinks it is plugged into a host
+ usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS;
+#endif
+
+ irq_set_exclusive_handler(USBCTRL_IRQ, dcd_rp2040_irq);
- // EP0 always exists so init it now
- // EP0 OUT
- hw_endpoint_init(0x0, 64, 0);
- // EP0 IN
- hw_endpoint_init(0x80, 64, 0);
+ // Init control endpoints
+ tu_memclr(hw_endpoints[0], 2*sizeof(hw_endpoint_t));
+ hw_endpoint_init(0x0, 64, TUSB_XFER_CONTROL);
+ hw_endpoint_init(0x80, 64, TUSB_XFER_CONTROL);
- // Initializes the USB peripheral for device mode and enables it.
- // Don't need to enable the pull up here. Force VBUS
- usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS;
+ // Init non-control endpoints
+ reset_non_control_endpoints();
- // Enable individual controller IRQS here. Processor interrupt enable will be used
- // for the global interrupt enable...
- // TODO Enable SUSPEND & RESUME interrupt
- usb_hw->sie_ctrl = USB_SIE_CTRL_EP0_INT_1BUF_BITS;
- usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS |
- USB_INTS_DEV_CONN_DIS_BITS /* | USB_INTS_DEV_SUSPEND_BITS | USB_INTS_DEV_RESUME_FROM_HOST_BITS */ ;
+ // Initializes the USB peripheral for device mode and enables it.
+ // Don't need to enable the pull up here. Force VBUS
+ usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS;
- dcd_connect(rhport);
+ // Enable individual controller IRQS here. Processor interrupt enable will be used
+ // for the global interrupt enable...
+ // Note: Force VBUS detect cause disconnection not detectable
+ usb_hw->sie_ctrl = USB_SIE_CTRL_EP0_INT_1BUF_BITS;
+ usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS |
+ USB_INTS_DEV_SUSPEND_BITS | USB_INTS_DEV_RESUME_FROM_HOST_BITS |
+ (FORCE_VBUS_DETECT ? 0 : USB_INTS_DEV_CONN_DIS_BITS);
+
+ dcd_connect(rhport);
}
void dcd_int_enable(uint8_t rhport)
@@ -434,11 +379,11 @@ void dcd_int_disable(uint8_t rhport)
void dcd_set_address (uint8_t rhport, uint8_t dev_addr)
{
- pico_trace("dcd_set_address %d %d\n", rhport, dev_addr);
- assert(rhport == 0);
+ assert(rhport == 0);
- // Can't set device address in hardware until status xfer has complete
- ep0_0len_status();
+ // Can't set device address in hardware until status xfer has complete
+ // Send 0len complete response on EP0 IN
+ hw_endpoint_xfer(0x80, NULL, 0);
}
void dcd_remote_wakeup(uint8_t rhport)
@@ -451,17 +396,15 @@ void dcd_remote_wakeup(uint8_t rhport)
// disconnect by disabling internal pull-up resistor on D+/D-
void dcd_disconnect(uint8_t rhport)
{
- pico_info("dcd_disconnect %d\n", rhport);
- assert(rhport == 0);
- usb_hw_clear->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
+ (void) rhport;
+ usb_hw_clear->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
}
// connect by enabling internal pull-up resistor on D+/D-
void dcd_connect(uint8_t rhport)
{
- pico_info("dcd_connect %d\n", rhport);
- assert(rhport == 0);
- usb_hw_set->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
+ (void) rhport;
+ usb_hw_set->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
}
/*------------------------------------------------------------------*/
@@ -470,62 +413,82 @@ void dcd_connect(uint8_t rhport)
void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request)
{
- pico_trace("dcd_edpt0_status_complete %d\n", rhport);
- assert(rhport == 0);
+ (void) rhport;
- if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE &&
- request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD &&
- request->bRequest == TUSB_REQ_SET_ADDRESS)
- {
- pico_trace("Set HW address %d\n", assigned_address);
- usb_hw->dev_addr_ctrl = (uint8_t) request->wValue;
- }
-
- reset_ep0();
+ if ( request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE &&
+ request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD &&
+ request->bRequest == TUSB_REQ_SET_ADDRESS )
+ {
+ usb_hw->dev_addr_ctrl = (uint8_t) request->wValue;
+ }
}
bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
{
- pico_info("dcd_edpt_open %d %02x\n", rhport, desc_edpt->bEndpointAddress);
assert(rhport == 0);
hw_endpoint_init(desc_edpt->bEndpointAddress, desc_edpt->wMaxPacketSize.size, desc_edpt->bmAttributes.xfer);
return true;
}
+void dcd_edpt_close_all (uint8_t rhport)
+{
+ (void) rhport;
+
+ // may need to use EP Abort
+ reset_non_control_endpoints();
+}
+
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
{
assert(rhport == 0);
- // True means start new xfer
- hw_endpoint_xfer(ep_addr, buffer, total_bytes, true);
+ hw_endpoint_xfer(ep_addr, buffer, total_bytes);
return true;
}
-void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr)
+void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
{
- pico_trace("dcd_edpt_stall %d %02x\n", rhport, ep_addr);
- assert(rhport == 0);
- hw_endpoint_stall(ep_addr);
+ (void) rhport;
+
+ if ( tu_edpt_number(ep_addr) == 0 )
+ {
+ // A stall on EP0 has to be armed so it can be cleared on the next setup packet
+ usb_hw_set->ep_stall_arm = (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) ? USB_EP_STALL_ARM_EP0_IN_BITS : USB_EP_STALL_ARM_EP0_OUT_BITS;
+ }
+
+ struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr);
+
+ // stall and clear current pending buffer
+ // may need to use EP_ABORT
+ _hw_endpoint_buffer_control_set_value32(ep, USB_BUF_CTRL_STALL);
}
-void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
+void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
{
- pico_trace("dcd_edpt_clear_stall %d %02x\n", rhport, ep_addr);
- assert(rhport == 0);
- hw_endpoint_clear_stall(ep_addr);
-}
+ (void) rhport;
+
+ if (tu_edpt_number(ep_addr))
+ {
+ struct hw_endpoint *ep = hw_endpoint_get_by_addr(ep_addr);
+ // clear stall also reset toggle to DATA0, ready for next transfer
+ ep->next_pid = 0;
+ _hw_endpoint_buffer_control_clear_mask32(ep, USB_BUF_CTRL_STALL);
+ }
+}
void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr)
{
- // usbd.c says: In progress transfers on this EP may be delivered after this call
- pico_trace("dcd_edpt_close %d %02x\n", rhport, ep_addr);
+ (void) rhport;
+ (void) ep_addr;
+ // usbd.c says: In progress transfers on this EP may be delivered after this call
+ pico_trace("dcd_edpt_close %02x\n", ep_addr);
}
void dcd_int_handler(uint8_t rhport)
{
- (void) rhport;
- dcd_rp2040_irq();
+ (void) rhport;
+ dcd_rp2040_irq();
}
#endif
diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c
index b575c6afc..5e5bb4906 100644
--- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c
+++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c
@@ -2,6 +2,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ * Copyright (c) 2021 Ha Thach (tinyusb.org) for Double Buffered
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -38,7 +39,6 @@
#include "host/hcd.h"
#include "host/usbh.h"
-#include "host/usbh_hcd.h"
#define ROOT_PORT 0
@@ -52,46 +52,30 @@
static_assert(PICO_USB_HOST_INTERRUPT_ENDPOINTS <= USB_MAX_ENDPOINTS, "");
// Host mode uses one shared endpoint register for non-interrupt endpoint
-struct hw_endpoint eps[1 + PICO_USB_HOST_INTERRUPT_ENDPOINTS];
-#define epx (eps[0])
+static struct hw_endpoint ep_pool[1 + PICO_USB_HOST_INTERRUPT_ENDPOINTS];
+#define epx (ep_pool[0])
-#define usb_hw_set hw_set_alias(usb_hw)
+#define usb_hw_set hw_set_alias(usb_hw)
#define usb_hw_clear hw_clear_alias(usb_hw)
-// Used for hcd pipe busy.
-// todo still a bit wasteful
-// top bit set if valid
-uint8_t dev_ep_map[CFG_TUSB_HOST_DEVICE_MAX][1 + PICO_USB_HOST_INTERRUPT_ENDPOINTS][2];
-
// Flags we set by default in sie_ctrl (we add other bits on top)
-static uint32_t sie_ctrl_base = USB_SIE_CTRL_SOF_EN_BITS |
- USB_SIE_CTRL_KEEP_ALIVE_EN_BITS |
- USB_SIE_CTRL_PULLDOWN_EN_BITS |
- USB_SIE_CTRL_EP0_INT_1BUF_BITS;
+enum {
+ SIE_CTRL_BASE = USB_SIE_CTRL_SOF_EN_BITS | USB_SIE_CTRL_KEEP_ALIVE_EN_BITS |
+ USB_SIE_CTRL_PULLDOWN_EN_BITS | USB_SIE_CTRL_EP0_INT_1BUF_BITS
+};
static struct hw_endpoint *get_dev_ep(uint8_t dev_addr, uint8_t ep_addr)
{
- uint8_t num = tu_edpt_number(ep_addr);
- if (num == 0) {
- return &epx;
- }
- uint8_t in = (ep_addr & TUSB_DIR_IN_MASK) ? 1 : 0;
- uint mapping = dev_ep_map[dev_addr-1][num][in];
- pico_trace("Get dev addr %d ep %d = %d\n", dev_addr, ep_addr, mapping);
- return mapping >= 128 ? eps + (mapping & 0x7fu) : NULL;
-}
+ uint8_t num = tu_edpt_number(ep_addr);
+ if ( num == 0 ) return &epx;
-static void set_dev_ep(uint8_t dev_addr, uint8_t ep_addr, struct hw_endpoint *ep)
-{
- uint8_t num = tu_edpt_number(ep_addr);
- uint8_t in = (ep_addr & TUSB_DIR_IN_MASK) ? 1 : 0;
- uint32_t index = ep - eps;
- hard_assert(index < TU_ARRAY_SIZE(eps));
- // todo revisit why dev_addr can be 0 here
- if (dev_addr) {
- dev_ep_map[dev_addr-1][num][in] = 128u | index;
- }
- pico_trace("Set dev addr %d ep %d = %d\n", dev_addr, ep_addr, index);
+ for ( uint32_t i = 1; i < TU_ARRAY_SIZE(ep_pool); i++ )
+ {
+ struct hw_endpoint *ep = &ep_pool[i];
+ if ( ep->configured && (ep->dev_addr == dev_addr) && (ep->ep_addr == ep_addr) ) return ep;
+ }
+
+ return NULL;
}
static inline uint8_t dev_speed(void)
@@ -103,7 +87,7 @@ static bool need_pre(uint8_t dev_addr)
{
// If this device is different to the speed of the root device
// (i.e. is a low speed device on a full speed hub) then need pre
- return hcd_port_speed_get(0) != tuh_device_get_speed(dev_addr);
+ return hcd_port_speed_get(0) != tuh_speed_get(dev_addr);
}
static void hw_xfer_complete(struct hw_endpoint *ep, xfer_result_t xfer_result)
@@ -111,15 +95,15 @@ static void hw_xfer_complete(struct hw_endpoint *ep, xfer_result_t xfer_result)
// Mark transfer as done before we tell the tinyusb stack
uint8_t dev_addr = ep->dev_addr;
uint8_t ep_addr = ep->ep_addr;
- uint total_len = ep->total_len;
+ uint xferred_len = ep->xferred_len;
hw_endpoint_reset_transfer(ep);
- hcd_event_xfer_complete(dev_addr, ep_addr, total_len, xfer_result, true);
+ hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, xfer_result, true);
}
static void _handle_buff_status_bit(uint bit, struct hw_endpoint *ep)
{
usb_hw_clear->buf_status = bit;
- bool done = _hw_endpoint_xfer_continue(ep);
+ bool done = hw_endpoint_xfer_continue(ep);
if (done)
{
hw_xfer_complete(ep, XFER_RESULT_SUCCESS);
@@ -137,6 +121,17 @@ static void hw_handle_buff_status(void)
{
remaining_buffers &= ~bit;
struct hw_endpoint *ep = &epx;
+
+ uint32_t ep_ctrl = *ep->endpoint_control;
+ if (ep_ctrl & EP_CTRL_DOUBLE_BUFFERED_BITS)
+ {
+ TU_LOG(3, "Double Buffered: ");
+ }else
+ {
+ TU_LOG(3, "Single Buffered: ");
+ }
+ TU_LOG_HEX(3, ep_ctrl);
+
_handle_buff_status_bit(bit, ep);
}
@@ -153,7 +148,7 @@ static void hw_handle_buff_status(void)
if (remaining_buffers & bit)
{
remaining_buffers &= ~bit;
- _handle_buff_status_bit(bit, &eps[i]);
+ _handle_buff_status_bit(bit, &ep_pool[i]);
}
}
@@ -165,19 +160,19 @@ static void hw_handle_buff_status(void)
static void hw_trans_complete(void)
{
- struct hw_endpoint *ep = &epx;
- assert(ep->active);
+ struct hw_endpoint *ep = &epx;
+ assert(ep->active);
- if (ep->sent_setup)
- {
- pico_trace("Sent setup packet\n");
- hw_xfer_complete(ep, XFER_RESULT_SUCCESS);
- }
- else
- {
- // Don't care. Will handle this in buff status
- return;
- }
+ if (usb_hw->sie_ctrl & USB_SIE_CTRL_SEND_SETUP_BITS)
+ {
+ pico_trace("Sent setup packet\n");
+ hw_xfer_complete(ep, XFER_RESULT_SUCCESS);
+ }
+ else
+ {
+ // Don't care. Will handle this in buff status
+ return;
+ }
}
static void hcd_rp2040_irq(void)
@@ -202,20 +197,21 @@ static void hcd_rp2040_irq(void)
usb_hw_clear->sie_status = USB_SIE_STATUS_SPEED_BITS;
}
+ if (status & USB_INTS_BUFF_STATUS_BITS)
+ {
+ handled |= USB_INTS_BUFF_STATUS_BITS;
+ TU_LOG(2, "Buffer complete\n");
+ hw_handle_buff_status();
+ }
+
if (status & USB_INTS_TRANS_COMPLETE_BITS)
{
handled |= USB_INTS_TRANS_COMPLETE_BITS;
usb_hw_clear->sie_status = USB_SIE_STATUS_TRANS_COMPLETE_BITS;
+ TU_LOG(2, "Transfer complete\n");
hw_trans_complete();
}
- if (status & USB_INTS_BUFF_STATUS_BITS)
- {
- handled |= USB_INTS_BUFF_STATUS_BITS;
- // print_bufctrl32(*epx.buffer_control);
- hw_handle_buff_status();
- }
-
if (status & USB_INTS_STALL_BITS)
{
// We have rx'd a stall from the device
@@ -234,7 +230,7 @@ static void hcd_rp2040_irq(void)
if (status & USB_INTS_ERROR_DATA_SEQ_BITS)
{
usb_hw_clear->sie_status = USB_SIE_STATUS_DATA_SEQ_ERROR_BITS;
- // print_bufctrl32(*epx.buffer_control);
+ TU_LOG(3, " Seq Error: [0] = 0x%04u [1] = 0x%04x\r\n", tu_u32_low16(*epx.buffer_control), tu_u32_high16(*epx.buffer_control));
panic("Data Seq Error \n");
}
@@ -247,9 +243,9 @@ static void hcd_rp2040_irq(void)
static struct hw_endpoint *_next_free_interrupt_ep(void)
{
struct hw_endpoint *ep = NULL;
- for (uint i = 1; i < TU_ARRAY_SIZE(eps); i++)
+ for (uint i = 1; i < TU_ARRAY_SIZE(ep_pool); i++)
{
- ep = &eps[i];
+ ep = &ep_pool[i];
if (!ep->configured)
{
// Will be configured by _hw_endpoint_init / _hw_endpoint_allocate
@@ -263,6 +259,7 @@ static struct hw_endpoint *_next_free_interrupt_ep(void)
static struct hw_endpoint *_hw_endpoint_allocate(uint8_t transfer_type)
{
struct hw_endpoint *ep = NULL;
+
if (transfer_type == TUSB_XFER_INTERRUPT)
{
ep = _next_free_interrupt_ep();
@@ -270,11 +267,11 @@ static struct hw_endpoint *_hw_endpoint_allocate(uint8_t transfer_type)
assert(ep);
ep->buffer_control = &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num].ctrl;
ep->endpoint_control = &usbh_dpram->int_ep_ctrl[ep->interrupt_num].ctrl;
- // 0x180 for epx
- // 0x1c0 for intep0
- // 0x200 for intep1
+ // 0 for epx (double buffered): TODO increase to 1024 for ISO
+ // 2x64 for intep0
+ // 3x64 for intep1
// etc
- ep->hw_data_buf = &usbh_dpram->epx_data[64 * (ep->interrupt_num + 1)];
+ ep->hw_data_buf = &usbh_dpram->epx_data[64 * (ep->interrupt_num + 2)];
}
else
{
@@ -283,6 +280,7 @@ static struct hw_endpoint *_hw_endpoint_allocate(uint8_t transfer_type)
ep->endpoint_control = &usbh_dpram->epx_ctrl;
ep->hw_data_buf = &usbh_dpram->epx_data[0];
}
+
return ep;
}
@@ -303,7 +301,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t
ep->rx = (dir == TUSB_DIR_IN);
// Response to a setup packet on EP0 starts with pid of 1
- ep->next_pid = num == 0 ? 1u : 0u;
+ ep->next_pid = (num == 0 ? 1u : 0u);
ep->wMaxPacketSize = wMaxPacketSize;
ep->transfer_type = transfer_type;
@@ -332,6 +330,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t
// preamble
uint32_t reg = dev_addr | (num << USB_ADDR_ENDP1_ENDPOINT_LSB);
// Assert the interrupt endpoint is IN_TO_HOST
+ // TODO Interrupt can also be OUT
assert(dir == TUSB_DIR_IN);
if (need_pre(dev_addr))
@@ -345,24 +344,9 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t
// If it's an interrupt endpoint we need to set up the buffer control
// register
-
}
}
-static void hw_endpoint_init(uint8_t dev_addr, const tusb_desc_endpoint_t *ep_desc)
-{
- // Allocated differently based on if it's an interrupt endpoint or not
- struct hw_endpoint *ep = _hw_endpoint_allocate(ep_desc->bmAttributes.xfer);
- _hw_endpoint_init(ep,
- dev_addr,
- ep_desc->bEndpointAddress,
- ep_desc->wMaxPacketSize.size,
- ep_desc->bmAttributes.xfer,
- ep_desc->bInterval);
- // Map this struct to ep@device address
- set_dev_ep(dev_addr, ep_desc->bEndpointAddress, ep);
-}
-
//--------------------------------------------------------------------+
// HCD API
//--------------------------------------------------------------------+
@@ -374,14 +358,17 @@ bool hcd_init(uint8_t rhport)
// Reset any previous state
rp2040_usb_init();
+ // Force VBUS detect to always present, for now we assume vbus is always provided (without using VBUS En)
+ usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS;
+
irq_set_exclusive_handler(USBCTRL_IRQ, hcd_rp2040_irq);
// clear epx and interrupt eps
- memset(&eps, 0, sizeof(eps));
+ memset(&ep_pool, 0, sizeof(ep_pool));
// Enable in host mode with SOF / Keep alive on
usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS | USB_MAIN_CTRL_HOST_NDEVICE_BITS;
- usb_hw->sie_ctrl = sie_ctrl_base;
+ usb_hw->sie_ctrl = SIE_CTRL_BASE;
usb_hw->inte = USB_INTE_BUFF_STATUS_BITS |
USB_INTE_HOST_CONN_DIS_BITS |
USB_INTE_HOST_RESUME_BITS |
@@ -409,7 +396,6 @@ bool hcd_port_connect_status(uint8_t rhport)
tusb_speed_t hcd_port_speed_get(uint8_t rhport)
{
- pico_trace("hcd_port_speed_get\n");
assert(rhport == 0);
// TODO: Should enumval this register
switch (dev_speed())
@@ -420,15 +406,25 @@ tusb_speed_t hcd_port_speed_get(uint8_t rhport)
return TUSB_SPEED_FULL;
default:
panic("Invalid speed\n");
+ return TUSB_SPEED_INVALID;
}
}
// Close all opened endpoint belong to this device
void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
{
+ (void) rhport;
+ (void) dev_addr;
+
pico_trace("hcd_device_close %d\n", dev_addr);
}
+uint32_t hcd_frame_number(uint8_t rhport)
+{
+ (void) rhport;
+ return usb_hw->sof_rd;
+}
+
void hcd_int_enable(uint8_t rhport)
{
assert(rhport == 0);
@@ -442,36 +438,70 @@ void hcd_int_disable(uint8_t rhport)
irq_set_enabled(USBCTRL_IRQ, false);
}
+//--------------------------------------------------------------------+
+// Endpoint API
+//--------------------------------------------------------------------+
+
+bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc)
+{
+ (void) rhport;
+
+ pico_trace("hcd_edpt_open dev_addr %d, ep_addr %d\n", dev_addr, ep_desc->bEndpointAddress);
+
+ // Allocated differently based on if it's an interrupt endpoint or not
+ struct hw_endpoint *ep = _hw_endpoint_allocate(ep_desc->bmAttributes.xfer);
+
+ _hw_endpoint_init(ep,
+ dev_addr,
+ ep_desc->bEndpointAddress,
+ ep_desc->wMaxPacketSize.size,
+ ep_desc->bmAttributes.xfer,
+ ep_desc->bInterval);
+
+ return true;
+}
+
bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen)
{
- pico_info("hcd_edpt_xfer dev_addr %d, ep_addr 0x%x, len %d\n", dev_addr, ep_addr, buflen);
+ (void) rhport;
+
+ pico_trace("hcd_edpt_xfer dev_addr %d, ep_addr 0x%x, len %d\n", dev_addr, ep_addr, buflen);
+ uint8_t const ep_num = tu_edpt_number(ep_addr);
+ tusb_dir_t const ep_dir = tu_edpt_dir(ep_addr);
+
// Get appropriate ep. Either EPX or interrupt endpoint
struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr);
assert(ep);
- if (ep_addr != ep->ep_addr)
+ // Control endpoint can change direction 0x00 <-> 0x80
+ if ( ep_addr != ep->ep_addr )
{
- // Direction has flipped so re init it but with same properties
- // TODO treat IN and OUT as invidual endpoints
- _hw_endpoint_init(ep, dev_addr, ep_addr, ep->wMaxPacketSize, ep->transfer_type, 0);
- }
+ assert(ep_num == 0);
- // True indicates this is the start of the transfer
- _hw_endpoint_xfer(ep, buffer, buflen, true);
+ // Direction has flipped on endpoint control so re init it but with same properties
+ _hw_endpoint_init(ep, dev_addr, ep_addr, ep->wMaxPacketSize, ep->transfer_type, 0);
+ }
// If a normal transfer (non-interrupt) then initiate using
// sie ctrl registers. Otherwise interrupt ep registers should
// already be configured
if (ep == &epx) {
+ hw_endpoint_xfer_start(ep, buffer, buflen);
+
// That has set up buffer control, endpoint control etc
// for host we have to initiate the transfer
- usb_hw->dev_addr_ctrl = dev_addr | (tu_edpt_number(ep_addr) << USB_ADDR_ENDP_ENDPOINT_LSB);
- uint32_t flags = USB_SIE_CTRL_START_TRANS_BITS | sie_ctrl_base;
- flags |= ep->rx ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS;
+ usb_hw->dev_addr_ctrl = dev_addr | (ep_num << USB_ADDR_ENDP_ENDPOINT_LSB);
+
+ uint32_t flags = USB_SIE_CTRL_START_TRANS_BITS | SIE_CTRL_BASE |
+ (ep_dir ? USB_SIE_CTRL_RECEIVE_DATA_BITS : USB_SIE_CTRL_SEND_DATA_BITS);
// Set pre if we are a low speed device on full speed hub
flags |= need_pre(dev_addr) ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0;
+
usb_hw->sie_ctrl = flags;
+ }else
+ {
+ hw_endpoint_xfer_start(ep, buffer, buflen);
}
return true;
@@ -479,42 +509,34 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8])
{
- pico_info("hcd_setup_send dev_addr %d\n", dev_addr);
-
+ (void) rhport;
+
// Copy data into setup packet buffer
memcpy((void*)&usbh_dpram->setup_packet[0], setup_packet, 8);
// Configure EP0 struct with setup info for the trans complete
struct hw_endpoint *ep = _hw_endpoint_allocate(0);
+
// EP0 out
_hw_endpoint_init(ep, dev_addr, 0x00, ep->wMaxPacketSize, 0, 0);
assert(ep->configured);
- ep->total_len = 8;
- ep->transfer_size = 8;
- ep->active = true;
- ep->sent_setup = true;
+
+ ep->remaining_len = 8;
+ ep->active = true;
// Set device address
usb_hw->dev_addr_ctrl = dev_addr;
+
// Set pre if we are a low speed device on full speed hub
- uint32_t flags = sie_ctrl_base | USB_SIE_CTRL_SEND_SETUP_BITS | USB_SIE_CTRL_START_TRANS_BITS;
- flags |= need_pre(dev_addr) ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0;
- usb_hw->sie_ctrl = flags;
- return true;
-}
+ uint32_t const flags = SIE_CTRL_BASE | USB_SIE_CTRL_SEND_SETUP_BITS | USB_SIE_CTRL_START_TRANS_BITS |
+ (need_pre(dev_addr) ? USB_SIE_CTRL_PREAMBLE_EN_BITS : 0);
-uint32_t hcd_frame_number(uint8_t rhport)
-{
- return usb_hw->sof_rd;
-}
+ usb_hw->sie_ctrl = flags;
-bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc)
-{
- pico_trace("hcd_edpt_open dev_addr %d, ep_addr %d\n", dev_addr, ep_desc->bEndpointAddress);
- hw_endpoint_init(dev_addr, ep_desc);
return true;
}
+
//bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr)
//{
// // EPX is shared, so multiple device addresses and endpoint addresses share that
@@ -531,6 +553,9 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr)
{
+ (void) dev_addr;
+ (void) ep_addr;
+
panic("hcd_clear_stall");
return true;
}
diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c
index 31381e6c2..f9b4d9b17 100644
--- a/src/portable/raspberrypi/rp2040/rp2040_usb.c
+++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c
@@ -2,6 +2,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ * Copyright (c) 2021 Ha Thach (tinyusb.org) for Double Buffered
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -43,42 +44,33 @@ static inline void _hw_endpoint_lock_update(struct hw_endpoint *ep, int delta) {
// sense to have worker and IRQ on same core, however I think using critsec is about equivalent.
}
-#if TUSB_OPT_HOST_ENABLED
-static inline void _hw_endpoint_update_last_buf(struct hw_endpoint *ep)
-{
- ep->last_buf = (ep->len + ep->transfer_size == ep->total_len);
-}
-#endif
+static void _hw_endpoint_xfer_sync(struct hw_endpoint *ep);
+static void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep);
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
void rp2040_usb_init(void)
{
- // Reset usb controller
- reset_block(RESETS_RESET_USBCTRL_BITS);
- unreset_block_wait(RESETS_RESET_USBCTRL_BITS);
-
- // Clear any previous state just in case
- memset(usb_hw, 0, sizeof(*usb_hw));
- memset(usb_dpram, 0, sizeof(*usb_dpram));
+ // Reset usb controller
+ reset_block(RESETS_RESET_USBCTRL_BITS);
+ unreset_block_wait(RESETS_RESET_USBCTRL_BITS);
- // Mux the controller to the onboard usb phy
- usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS;
+ // Clear any previous state just in case
+ memset(usb_hw, 0, sizeof(*usb_hw));
+ memset(usb_dpram, 0, sizeof(*usb_dpram));
- // Force VBUS detect so the device thinks it is plugged into a host
- // TODO support VBUs detect
- usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS;
+ // Mux the controller to the onboard usb phy
+ usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS;
}
void hw_endpoint_reset_transfer(struct hw_endpoint *ep)
{
- ep->stalled = false;
- ep->active = false;
-#if TUSB_OPT_HOST_ENABLED
- ep->sent_setup = false;
-#endif
- ep->total_len = 0;
- ep->len = 0;
- ep->transfer_size = 0;
- ep->user_buf = 0;
+ ep->active = false;
+ ep->remaining_len = 0;
+ ep->xferred_len = 0;
+ ep->user_buf = 0;
}
void _hw_endpoint_buffer_control_update32(struct hw_endpoint *ep, uint32_t and_mask, uint32_t or_mask) {
@@ -111,215 +103,221 @@ void _hw_endpoint_buffer_control_update32(struct hw_endpoint *ep, uint32_t and_m
*ep->buffer_control = value;
}
-void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep)
+// prepare buffer, return buffer control
+static uint32_t prepare_ep_buffer(struct hw_endpoint *ep, uint8_t buf_id)
{
- // Prepare buffer control register value
- uint32_t val = ep->transfer_size | USB_BUF_CTRL_AVAIL;
+ uint16_t const buflen = tu_min16(ep->remaining_len, ep->wMaxPacketSize);
+ ep->remaining_len -= buflen;
- if (!ep->rx)
- {
- // Copy data from user buffer to hw buffer
- memcpy(ep->hw_data_buf, &ep->user_buf[ep->len], ep->transfer_size);
- // Mark as full
- val |= USB_BUF_CTRL_FULL;
- }
+ uint32_t buf_ctrl = buflen | USB_BUF_CTRL_AVAIL;
- // PID
- val |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID;
+ // PID
+ buf_ctrl |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID;
+ ep->next_pid ^= 1u;
-#if TUSB_OPT_DEVICE_ENABLED
- ep->next_pid ^= 1u;
+ if ( !ep->rx )
+ {
+ // Copy data from user buffer to hw buffer
+ memcpy(ep->hw_data_buf + buf_id*64, ep->user_buf, buflen);
+ ep->user_buf += buflen;
-#else
- // For Host (also device but since we dictate the endpoint size, following scenario does not occur)
- // Next PID depends on the number of packet in case wMaxPacketSize < 64 (e.g Interrupt Endpoint 8, or 12)
- // Special case with control status stage where PID is always DATA1
- if ( ep->transfer_size == 0 )
- {
- // ZLP also toggle data
- ep->next_pid ^= 1u;
- }else
- {
- uint32_t packet_count = 1 + ((ep->transfer_size - 1) / ep->wMaxPacketSize);
-
- if ( packet_count & 0x01 )
- {
- ep->next_pid ^= 1u;
- }
- }
-#endif
+ // Mark as full
+ buf_ctrl |= USB_BUF_CTRL_FULL;
+ }
+ // Is this the last buffer? Only really matters for host mode. Will trigger
+ // the trans complete irq but also stop it polling. We only really care about
+ // trans complete for setup packets being sent
+ if (ep->remaining_len == 0)
+ {
+ buf_ctrl |= USB_BUF_CTRL_LAST;
+ }
-#if TUSB_OPT_HOST_ENABLED
- // Is this the last buffer? Only really matters for host mode. Will trigger
- // the trans complete irq but also stop it polling. We only really care about
- // trans complete for setup packets being sent
- if (ep->last_buf)
- {
- pico_trace("Last buf (%d bytes left)\n", ep->transfer_size);
- val |= USB_BUF_CTRL_LAST;
- }
-#endif
+ if (buf_id) buf_ctrl = buf_ctrl << 16;
- // Finally, write to buffer_control which will trigger the transfer
- // the next time the controller polls this dpram address
- _hw_endpoint_buffer_control_set_value32(ep, val);
- pico_trace("buffer control (0x%p) <- 0x%x\n", ep->buffer_control, val);
- //print_bufctrl16(val);
+ return buf_ctrl;
}
-
-void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len)
+// Prepare buffer control register value
+static void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep)
{
- _hw_endpoint_lock_update(ep, 1);
- pico_trace("Start transfer of total len %d on ep %d %s\n", total_len, tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]);
- if (ep->active)
- {
- // TODO: Is this acceptable for interrupt packets?
- pico_warn("WARN: starting new transfer on already active ep %d %s\n", tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]);
+ uint32_t ep_ctrl = *ep->endpoint_control;
- hw_endpoint_reset_transfer(ep);
- }
+ // always compute and start with buffer 0
+ uint32_t buf_ctrl = prepare_ep_buffer(ep, 0) | USB_BUF_CTRL_SEL;
- // Fill in info now that we're kicking off the hw
- ep->total_len = total_len;
- ep->len = 0;
+ // For now: skip double buffered for Device mode, OUT endpoint since
+ // host could send < 64 bytes and cause short packet on buffer0
+ // NOTE this could happen to Host mode IN endpoint
+ bool const force_single = !(usb_hw->main_ctrl & USB_MAIN_CTRL_HOST_NDEVICE_BITS) && !tu_edpt_dir(ep->ep_addr);
- // Limit by packet size but not less 64 (i.e low speed 8 bytes EP0)
- ep->transfer_size = tu_min16(total_len, tu_max16(64, ep->wMaxPacketSize));
+ if(ep->remaining_len && !force_single)
+ {
+ // Use buffer 1 (double buffered) if there is still data
+ // TODO: Isochronous for buffer1 bit-field is different than CBI (control bulk, interrupt)
- ep->active = true;
- ep->user_buf = buffer;
-#if TUSB_OPT_HOST_ENABLED
- // Recalculate if this is the last buffer
- _hw_endpoint_update_last_buf(ep);
- ep->buf_sel = 0;
-#endif
+ buf_ctrl |= prepare_ep_buffer(ep, 1);
- _hw_endpoint_start_next_buffer(ep);
- _hw_endpoint_lock_update(ep, -1);
+ // Set endpoint control double buffered bit if needed
+ ep_ctrl &= ~EP_CTRL_INTERRUPT_PER_BUFFER;
+ ep_ctrl |= EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER;
+ }else
+ {
+ // Single buffered since 1 is enough
+ ep_ctrl &= ~(EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER);
+ ep_ctrl |= EP_CTRL_INTERRUPT_PER_BUFFER;
+ }
+
+ *ep->endpoint_control = ep_ctrl;
+
+ TU_LOG(3, " Prepare BufCtrl: [0] = 0x%04u [1] = 0x%04x\r\n", tu_u32_low16(buf_ctrl), tu_u32_high16(buf_ctrl));
+
+ // Finally, write to buffer_control which will trigger the transfer
+ // the next time the controller polls this dpram address
+ _hw_endpoint_buffer_control_set_value32(ep, buf_ctrl);
}
-void _hw_endpoint_xfer_sync(struct hw_endpoint *ep)
+void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len)
{
- // Update hw endpoint struct with info from hardware
- // after a buff status interrupt
+ _hw_endpoint_lock_update(ep, 1);
- uint32_t buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep);
+ if ( ep->active )
+ {
+ // TODO: Is this acceptable for interrupt packets?
+ TU_LOG(1, "WARN: starting new transfer on already active ep %d %s\n", tu_edpt_number(ep->ep_addr),
+ ep_dir_string[tu_edpt_dir(ep->ep_addr)]);
-#if TUSB_OPT_HOST_ENABLED
- // RP2040-E4
- // tag::host_buf_sel_fix[]
- // TODO need changes to support double buffering
- if (ep->buf_sel == 1)
- {
- // Host can erroneously write status to top half of buf_ctrl register
- buf_ctrl = buf_ctrl >> 16;
+ hw_endpoint_reset_transfer(ep);
+ }
- // update buf1 -> buf0 to prevent panic with "already available"
- *ep->buffer_control = buf_ctrl;
- }
- // Flip buf sel for host
- ep->buf_sel ^= 1u;
- // end::host_buf_sel_fix[]
-#endif
+ // Fill in info now that we're kicking off the hw
+ ep->remaining_len = total_len;
+ ep->xferred_len = 0;
+ ep->active = true;
+ ep->user_buf = buffer;
+
+ _hw_endpoint_start_next_buffer(ep);
+ _hw_endpoint_lock_update(ep, -1);
+}
+
+// sync endpoint buffer and return transferred bytes
+static uint16_t sync_ep_buffer(struct hw_endpoint *ep, uint8_t buf_id)
+{
+ uint32_t buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep);
+ if (buf_id) buf_ctrl = buf_ctrl >> 16;
- // Get tranferred bytes after adjusted buf sel
- uint16_t const transferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK;
+ uint16_t xferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK;
- // We are continuing a transfer here. If we are TX, we have successfullly
+ if ( !ep->rx )
+ {
+ // We are continuing a transfer here. If we are TX, we have successfully
// sent some data can increase the length we have sent
- if (!ep->rx)
- {
- assert(!(buf_ctrl & USB_BUF_CTRL_FULL));
- pico_trace("tx %d bytes (buf_ctrl 0x%08x)\n", transferred_bytes, buf_ctrl);
- ep->len += transferred_bytes;
- }
- else
- {
- // If we are OUT we have recieved some data, so can increase the length
- // we have recieved AFTER we have copied it to the user buffer at the appropriate
- // offset
- pico_trace("rx %d bytes (buf_ctrl 0x%08x)\n", transferred_bytes, buf_ctrl);
- assert(buf_ctrl & USB_BUF_CTRL_FULL);
- memcpy(&ep->user_buf[ep->len], ep->hw_data_buf, transferred_bytes);
- ep->len += transferred_bytes;
- }
+ assert(!(buf_ctrl & USB_BUF_CTRL_FULL));
- // Sometimes the host will send less data than we expect...
- // If this is a short out transfer update the total length of the transfer
- // to be the current length
- if ((ep->rx) && (transferred_bytes < ep->wMaxPacketSize))
- {
- pico_trace("Short rx transfer\n");
- // Reduce total length as this is last packet
- ep->total_len = ep->len;
- }
+ ep->xferred_len += xferred_bytes;
+ }else
+ {
+ // If we have received some data, so can increase the length
+ // we have received AFTER we have copied it to the user buffer at the appropriate offset
+ assert(buf_ctrl & USB_BUF_CTRL_FULL);
+
+ memcpy(ep->user_buf, ep->hw_data_buf + buf_id*64, xferred_bytes);
+ ep->xferred_len += xferred_bytes;
+ ep->user_buf += xferred_bytes;
+ }
+
+ // Short packet
+ if (xferred_bytes < ep->wMaxPacketSize)
+ {
+ pico_trace(" Short packet on buffer %d with %u bytes\n", buf_id, xferred_bytes);
+ // Reduce total length as this is last packet
+ ep->remaining_len = 0;
+ }
+
+ return xferred_bytes;
}
-// Returns true if transfer is complete
-bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep)
+static void _hw_endpoint_xfer_sync (struct hw_endpoint *ep)
{
- _hw_endpoint_lock_update(ep, 1);
- // Part way through a transfer
- if (!ep->active)
- {
- panic("Can't continue xfer on inactive ep %d %s", tu_edpt_number(ep->ep_addr), ep_dir_string);
- }
+ // Update hw endpoint struct with info from hardware
+ // after a buff status interrupt
- // Update EP struct from hardware state
- _hw_endpoint_xfer_sync(ep);
-
- // Now we have synced our state with the hardware. Is there more data to transfer?
- // Limit by packet size but not less 64 (i.e low speed 8 bytes EP0)
- uint16_t remaining_bytes = ep->total_len - ep->len;
- ep->transfer_size = tu_min16(remaining_bytes, tu_max16(64, ep->wMaxPacketSize));
-#if TUSB_OPT_HOST_ENABLED
- _hw_endpoint_update_last_buf(ep);
-#endif
+ uint32_t buf_ctrl = _hw_endpoint_buffer_control_get_value32(ep);
+ TU_LOG(3, " Sync BufCtrl: [0] = 0x%04u [1] = 0x%04x\r\n", tu_u32_low16(buf_ctrl), tu_u32_high16(buf_ctrl));
- // Can happen because of programmer error so check for it
- if (ep->len > ep->total_len)
- {
- panic("Transferred more data than expected");
- }
+ // always sync buffer 0
+ uint16_t buf0_bytes = sync_ep_buffer(ep, 0);
- // If we are done then notify tinyusb
- if (ep->len == ep->total_len)
+ // sync buffer 1 if double buffered
+ if ( (*ep->endpoint_control) & EP_CTRL_DOUBLE_BUFFERED_BITS )
+ {
+ if (buf0_bytes == ep->wMaxPacketSize)
{
- pico_trace("Completed transfer of %d bytes on ep %d %s\n",
- ep->len, tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]);
- // Notify caller we are done so it can notify the tinyusb stack
- _hw_endpoint_lock_update(ep, -1);
- return true;
- }
- else
+ // sync buffer 1 if not short packet
+ sync_ep_buffer(ep, 1);
+ }else
{
- _hw_endpoint_start_next_buffer(ep);
- }
+ // short packet on buffer 0
+ // TODO couldn't figure out how to handle this case which happen with net_lwip_webserver example
+ // At this time (currently trigger per 2 buffer), the buffer1 is probably filled with data from
+ // the next transfer (not current one). For now we disable double buffered for device OUT
+ // NOTE this could happen to Host IN
+#if 0
+ uint8_t const ep_num = tu_edpt_number(ep->ep_addr);
+ uint8_t const dir = (uint8_t) tu_edpt_dir(ep->ep_addr);
+ uint8_t const ep_id = 2*ep_num + (dir ? 0 : 1);
- _hw_endpoint_lock_update(ep, -1);
- // More work to do
- return false;
+ // abort queued transfer on buffer 1
+ usb_hw->abort |= TU_BIT(ep_id);
+
+ while ( !(usb_hw->abort_done & TU_BIT(ep_id)) ) {}
+
+ uint32_t ep_ctrl = *ep->endpoint_control;
+ ep_ctrl &= ~(EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER);
+ ep_ctrl |= EP_CTRL_INTERRUPT_PER_BUFFER;
+
+ _hw_endpoint_buffer_control_set_value32(ep, 0);
+
+ usb_hw->abort &= ~TU_BIT(ep_id);
+
+ TU_LOG(3, "----SHORT PACKET buffer0 on EP %02X:\r\n", ep->ep_addr);
+ TU_LOG(3, " BufCtrl: [0] = 0x%04u [1] = 0x%04x\r\n", tu_u32_low16(buf_ctrl), tu_u32_high16(buf_ctrl));
+#endif
+ }
+ }
}
-void _hw_endpoint_xfer(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len, bool start)
+// Returns true if transfer is complete
+bool hw_endpoint_xfer_continue(struct hw_endpoint *ep)
{
- // Trace
- pico_trace("hw_endpoint_xfer ep %d %s", tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]);
- pico_trace(" total_len %d, start=%d\n", total_len, start);
+ _hw_endpoint_lock_update(ep, 1);
+ // Part way through a transfer
+ if (!ep->active)
+ {
+ panic("Can't continue xfer on inactive ep %d %s", tu_edpt_number(ep->ep_addr), ep_dir_string);
+ }
- assert(ep->configured);
+ // Update EP struct from hardware state
+ _hw_endpoint_xfer_sync(ep);
+ // Now we have synced our state with the hardware. Is there more data to transfer?
+ // If we are done then notify tinyusb
+ if (ep->remaining_len == 0)
+ {
+ pico_trace("Completed transfer of %d bytes on ep %d %s\n",
+ ep->xferred_len, tu_edpt_number(ep->ep_addr), ep_dir_string[tu_edpt_dir(ep->ep_addr)]);
+ // Notify caller we are done so it can notify the tinyusb stack
+ _hw_endpoint_lock_update(ep, -1);
+ return true;
+ }
+ else
+ {
+ _hw_endpoint_start_next_buffer(ep);
+ }
- if (start)
- {
- _hw_endpoint_xfer_start(ep, buffer, total_len);
- }
- else
- {
- _hw_endpoint_xfer_continue(ep);
- }
+ _hw_endpoint_lock_update(ep, -1);
+ // More work to do
+ return false;
}
#endif
diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h
index 33f3ecd41..a9cf1dd07 100644
--- a/src/portable/raspberrypi/rp2040/rp2040_usb.h
+++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h
@@ -17,26 +17,11 @@
#endif
-#if false && !defined(NDEBUG)
-#define pico_trace(format,args...) printf(format, ## args)
-#else
-#define pico_trace(format,...) ((void)0)
-#endif
-
-#if false && !defined(NDEBUG)
-#define pico_info(format,args...) printf(format, ## args)
-#else
-#define pico_info(format,...) ((void)0)
-#endif
-
-#if false && !defined(NDEBUG)
-#define pico_warn(format,args...) printf(format, ## args)
-#else
-#define pico_warn(format,...) ((void)0)
-#endif
+#define pico_info(...) TU_LOG(2, __VA_ARGS__)
+#define pico_trace(...) TU_LOG(3, __VA_ARGS__)
// Hardware information per endpoint
-struct hw_endpoint
+typedef struct hw_endpoint
{
// Is this a valid struct
bool configured;
@@ -50,51 +35,42 @@ struct hw_endpoint
// Endpoint control register
io_rw_32 *endpoint_control;
+
// Buffer control register
io_rw_32 *buffer_control;
// Buffer pointer in usb dpram
uint8_t *hw_data_buf;
- // Have we been stalled
- bool stalled;
-
// Current transfer information
bool active;
- uint16_t total_len;
- uint16_t len;
- // Amount of data with the hardware
- uint16_t transfer_size;
+ uint16_t remaining_len;
+ uint16_t xferred_len;
+
// User buffer in main memory
uint8_t *user_buf;
// Data needed from EP descriptor
uint16_t wMaxPacketSize;
+
// Interrupt, bulk, etc
uint8_t transfer_type;
#if TUSB_OPT_HOST_ENABLED
- // Only needed for host mode
- bool last_buf;
- // RP2040-E4: HOST BUG. Host will incorrect write status to top half of buffer
- // control register when doing transfers > 1 packet
- uint8_t buf_sel;
// Only needed for host
uint8_t dev_addr;
- bool sent_setup;
+
// If interrupt endpoint
uint8_t interrupt_num;
#endif
-};
+} hw_endpoint_t;
void rp2040_usb_init(void);
+void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len);
+bool hw_endpoint_xfer_continue(struct hw_endpoint *ep);
void hw_endpoint_reset_transfer(struct hw_endpoint *ep);
-void _hw_endpoint_xfer(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len, bool start);
-void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep);
-void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len);
-void _hw_endpoint_xfer_sync(struct hw_endpoint *ep);
-bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep);
+
void _hw_endpoint_buffer_control_update32(struct hw_endpoint *ep, uint32_t and_mask, uint32_t or_mask);
static inline uint32_t _hw_endpoint_buffer_control_get_value32(struct hw_endpoint *ep) {
return *ep->buffer_control;
@@ -117,44 +93,4 @@ static inline uintptr_t hw_data_offset(uint8_t *buf)
extern const char *ep_dir_string[];
-typedef union TU_ATTR_PACKED
-{
- uint16_t u16;
- struct TU_ATTR_PACKED
- {
- uint16_t xfer_len : 10;
- uint16_t available : 1;
- uint16_t stall : 1;
- uint16_t reset_bufsel : 1;
- uint16_t data_toggle : 1;
- uint16_t last_buf : 1;
- uint16_t full : 1;
- };
-} rp2040_buffer_control_t;
-
-TU_VERIFY_STATIC(sizeof(rp2040_buffer_control_t) == 2, "size is not correct");
-
-static inline void print_bufctrl16(uint32_t __unused u16)
-{
- rp2040_buffer_control_t __unused bufctrl = {
- .u16 = u16
- };
-
- TU_LOG(2, "len = %u, available = %u, stall = %u, reset = %u, toggle = %u, last = %u, full = %u\r\n",
- bufctrl.xfer_len, bufctrl.available, bufctrl.stall, bufctrl.reset_bufsel, bufctrl.data_toggle, bufctrl.last_buf, bufctrl.full);
-}
-
-static inline void print_bufctrl32(uint32_t u32)
-{
- uint16_t u16;
-
- u16 = u32 >> 16;
- TU_LOG(2, "Buffer Control 1 0x%x: ", u16);
- print_bufctrl16(u16);
-
- u16 = u32 & 0x0000ffff;
- TU_LOG(2, "Buffer Control 0 0x%x: ", u16);
- print_bufctrl16(u16);
-}
-
#endif
diff --git a/src/portable/renesas/usba/dcd_usba.c b/src/portable/renesas/usba/dcd_usba.c
index 06ea1a3f9..92e29f9bf 100644
--- a/src/portable/renesas/usba/dcd_usba.c
+++ b/src/portable/renesas/usba/dcd_usba.c
@@ -2,6 +2,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2020 Koji Kitayama
+ * Portions copyrighted (c) 2021 Roland Winistoerfer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -26,8 +27,13 @@
#include "tusb_option.h"
-#if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_RX63X )
+// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval)
+// We disable SOF for now until needed later on
+#define USE_SOF 0
+#if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_RX63X || \
+ CFG_TUSB_MCU == OPT_MCU_RX65X || \
+ CFG_TUSB_MCU == OPT_MCU_RX72N )
#include "device/dcd.h"
#include "iodefine.h"
@@ -38,6 +44,7 @@
#define SYSTEM_PRCR_PRKEY (0xA5u<<8)
#define USB_FIFOSEL_TX ((uint16_t)(1u<<5))
+#define USB_FIFOSEL_BIGEND ((uint16_t)(1u<<8))
#define USB_FIFOSEL_MBW_8 ((uint16_t)(0u<<10))
#define USB_FIFOSEL_MBW_16 ((uint16_t)(1u<<10))
#define USB_IS0_CTSQ ((uint16_t)(7u))
@@ -63,7 +70,10 @@
#define USB_IS0_CTSQ_SETUP (1u)
#define USB_IS0_DVSQ_DEF (1u<<4)
#define USB_IS0_DVSQ_ADDR (2u<<4)
-#define USB_IS0_DVSQ_SUSP (4u<<4)
+#define USB_IS0_DVSQ_SUSP0 (4u<<4)
+#define USB_IS0_DVSQ_SUSP1 (5u<<4)
+#define USB_IS0_DVSQ_SUSP2 (6u<<4)
+#define USB_IS0_DVSQ_SUSP3 (7u<<4)
#define USB_PIPECTR_PID_NAK (0u)
#define USB_PIPECTR_PID_BUF (1u)
@@ -89,6 +99,10 @@
#define FIFO_REQ_CLR (1u)
#define FIFO_COMPLETE (1u<<1)
+// Start of definition of packed structs (used by the CCRX toolchain)
+TU_ATTR_PACKED_BEGIN
+TU_ATTR_BIT_FIELD_ORDER_BEGIN
+
typedef struct {
union {
struct {
@@ -112,37 +126,50 @@ typedef union {
typedef struct TU_ATTR_PACKED
{
- uintptr_t addr; /* the start address of a transfer data buffer */
+ void *buf; /* the start address of a transfer data buffer */
uint16_t length; /* the number of bytes in the buffer */
uint16_t remaining; /* the number of bytes remaining in the buffer */
struct {
uint32_t ep : 8; /* an assigned endpoint address */
+ uint32_t ff : 1; /* `buf` is TU_FUFO or POD */
uint32_t : 0;
};
} pipe_state_t;
+TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain)
+TU_ATTR_BIT_FIELD_ORDER_END
+
typedef struct
{
- pipe_state_t pipe[9];
+ pipe_state_t pipe[10];
uint8_t ep[2][16]; /* a lookup table for a pipe index from an endpoint address */
} dcd_data_t;
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-CFG_TUSB_MEM_SECTION static dcd_data_t _dcd;
+static dcd_data_t _dcd;
static uint32_t disable_interrupt(void)
{
uint32_t pswi;
+#if defined(__CCRX__)
+ pswi = get_psw() & 0x010000;
+ clrpsw_i();
+#else
pswi = __builtin_rx_mvfc(0) & 0x010000;
__builtin_rx_clrpsw('I');
+#endif
return pswi;
}
static void enable_interrupt(uint32_t pswi)
{
+#if defined(__CCRX__)
+ set_psw(get_psw() | pswi);
+#else
__builtin_rx_mvtc(0, __builtin_rx_mvfc(0) | pswi);
+#endif
}
static unsigned find_pipe(unsigned xfer)
@@ -213,40 +240,27 @@ static volatile uint16_t* ep_addr_to_pipectr(uint8_t rhport, unsigned ep_addr)
return ctr;
}
-static unsigned wait_for_pipe_ready(void)
+static unsigned edpt0_max_packet_size(void)
{
- unsigned ctr;
- do {
- ctr = USB0.D0FIFOCTR.WORD;
- } while (!(ctr & USB_FIFOCTR_FRDY));
- return ctr;
+ return USB0.DCPMAXP.BIT.MXPS;
}
-static unsigned select_pipe(unsigned num, unsigned attr)
+static unsigned edpt_max_packet_size(unsigned num)
{
- USB0.PIPESEL.WORD = num;
- USB0.D0FIFOSEL.WORD = num | attr;
- while (!(USB0.D0FIFOSEL.BIT.CURPIPE != num)) ;
- return wait_for_pipe_ready();
+ USB0.PIPESEL.WORD = num;
+ return USB0.PIPEMAXP.WORD;
}
-/* 1 less than mps bytes were written to FIFO
- * 2 no bytes were written to FIFO
- * 0 mps bytes were written to FIFO */
-static int fifo_write(volatile void *fifo, pipe_state_t* pipe, unsigned mps)
+static inline void pipe_wait_for_ready(unsigned num)
{
- unsigned rem = pipe->remaining;
- if (!rem) return 2;
- unsigned len = TU_MIN(rem, mps);
+ while (USB0.D0FIFOSEL.BIT.CURPIPE != num) ;
+ while (!USB0.D0FIFOCTR.BIT.FRDY) ;
+}
+static void pipe_write_packet(void *buf, volatile void *fifo, unsigned len)
+{
hw_fifo_t *reg = (hw_fifo_t*)fifo;
- uintptr_t addr = pipe->addr + pipe->length - rem;
- if (addr & 1u) {
- /* addr is not 2-byte aligned */
- reg->u8 = *(const uint8_t *)addr;
- ++addr;
- --len;
- }
+ uintptr_t addr = (uintptr_t)buf;
while (len >= 2) {
reg->u16 = *(const uint16_t *)addr;
addr += 2;
@@ -256,31 +270,147 @@ static int fifo_write(volatile void *fifo, pipe_state_t* pipe, unsigned mps)
reg->u8 = *(const uint8_t *)addr;
++addr;
}
- if (rem < mps) return 1;
- return 0;
}
-/* 1 less than mps bytes were read from FIFO
- * 2 the end of the buffer reached.
- * 0 mps bytes were read from FIFO */
-static int fifo_read(volatile void *fifo, pipe_state_t* pipe, unsigned mps, size_t len)
+static void pipe_read_packet(void *buf, volatile void *fifo, unsigned len)
+{
+ uint8_t *p = (uint8_t*)buf;
+ uint8_t *reg = (uint8_t*)fifo; /* byte access is always at base register address */
+ while (len--) *p++ = *reg;
+}
+
+static void pipe_read_write_packet_ff(tu_fifo_t *f, volatile void *fifo, unsigned len, unsigned dir)
+{
+ static const struct {
+ void (*tu_fifo_get_info)(tu_fifo_t *f, tu_fifo_buffer_info_t *info);
+ void (*tu_fifo_advance)(tu_fifo_t *f, uint16_t n);
+ void (*pipe_read_write)(void *buf, volatile void *fifo, unsigned len);
+ } ops[] = {
+ /* OUT */ {tu_fifo_get_write_info,tu_fifo_advance_write_pointer,pipe_read_packet},
+ /* IN */ {tu_fifo_get_read_info, tu_fifo_advance_read_pointer, pipe_write_packet},
+ };
+ tu_fifo_buffer_info_t info;
+ ops[dir].tu_fifo_get_info(f, &info);
+ unsigned total_len = len;
+ len = TU_MIN(total_len, info.len_lin);
+ ops[dir].pipe_read_write(info.ptr_lin, fifo, len);
+ unsigned rem = total_len - len;
+ if (rem) {
+ len = TU_MIN(rem, info.len_wrap);
+ ops[dir].pipe_read_write(info.ptr_wrap, fifo, len);
+ rem -= len;
+ }
+ ops[dir].tu_fifo_advance(f, total_len - rem);
+}
+
+static bool pipe0_xfer_in(void)
{
- unsigned rem = pipe->remaining;
- if (!rem) return 2;
- if (rem < len) len = rem;
+ pipe_state_t *pipe = &_dcd.pipe[0];
+ const unsigned rem = pipe->remaining;
+ if (!rem) {
+ pipe->buf = NULL;
+ return true;
+ }
+ const unsigned mps = edpt0_max_packet_size();
+ const unsigned len = TU_MIN(mps, rem);
+ void *buf = pipe->buf;
+ if (len) {
+ if (pipe->ff) {
+ pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&USB0.CFIFO.WORD, len, TUSB_DIR_IN);
+ } else {
+ pipe_write_packet(buf, (volatile void*)&USB0.CFIFO.WORD, len);
+ pipe->buf = (uint8_t*)buf + len;
+ }
+ }
+ if (len < mps) USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL;
pipe->remaining = rem - len;
+ return false;
+}
- hw_fifo_t *reg = (hw_fifo_t*)fifo;
- uintptr_t addr = pipe->addr;
- unsigned loop = len;
- while (loop--) {
- *(uint8_t *)addr = reg->u8;
- ++addr;
+static bool pipe0_xfer_out(void)
+{
+ pipe_state_t *pipe = &_dcd.pipe[0];
+ const unsigned rem = pipe->remaining;
+
+ const unsigned mps = edpt0_max_packet_size();
+ const unsigned vld = USB0.CFIFOCTR.BIT.DTLN;
+ const unsigned len = TU_MIN(TU_MIN(rem, mps), vld);
+ void *buf = pipe->buf;
+ if (len) {
+ if (pipe->ff) {
+ pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&USB0.CFIFO.WORD, len, TUSB_DIR_OUT);
+ } else {
+ pipe_read_packet(buf, (volatile void*)&USB0.CFIFO.WORD, len);
+ pipe->buf = (uint8_t*)buf + len;
+ }
}
- pipe->addr = addr;
- if (rem < mps) return 1;
- if (rem == len) return 2;
- return 0;
+ if (len < mps) USB0.CFIFOCTR.WORD = USB_FIFOCTR_BCLR;
+ pipe->remaining = rem - len;
+ if ((len < mps) || (rem == len)) {
+ pipe->buf = NULL;
+ return true;
+ }
+ return false;
+}
+
+static bool pipe_xfer_in(unsigned num)
+{
+ pipe_state_t *pipe = &_dcd.pipe[num];
+ const unsigned rem = pipe->remaining;
+
+ if (!rem) {
+ pipe->buf = NULL;
+ return true;
+ }
+
+ USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16 | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? USB_FIFOSEL_BIGEND : 0);
+ const unsigned mps = edpt_max_packet_size(num);
+ pipe_wait_for_ready(num);
+ const unsigned len = TU_MIN(rem, mps);
+ void *buf = pipe->buf;
+ if (len) {
+ if (pipe->ff) {
+ pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&USB0.D0FIFO.WORD, len, TUSB_DIR_IN);
+ } else {
+ pipe_write_packet(buf, (volatile void*)&USB0.D0FIFO.WORD, len);
+ pipe->buf = (uint8_t*)buf + len;
+ }
+ }
+ if (len < mps) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL;
+ USB0.D0FIFOSEL.WORD = 0;
+ while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */
+ pipe->remaining = rem - len;
+ return false;
+}
+
+static bool pipe_xfer_out(unsigned num)
+{
+ pipe_state_t *pipe = &_dcd.pipe[num];
+ const unsigned rem = pipe->remaining;
+
+ USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_8;
+ const unsigned mps = edpt_max_packet_size(num);
+ pipe_wait_for_ready(num);
+ const unsigned vld = USB0.D0FIFOCTR.BIT.DTLN;
+ const unsigned len = TU_MIN(TU_MIN(rem, mps), vld);
+ void *buf = pipe->buf;
+ if (len) {
+ if (pipe->ff) {
+ pipe_read_write_packet_ff((tu_fifo_t*)buf, (volatile void*)&USB0.D0FIFO.WORD, len, TUSB_DIR_OUT);
+ } else {
+ pipe_read_packet(buf, (volatile void*)&USB0.D0FIFO.WORD, len);
+ pipe->buf = (uint8_t*)buf + len;
+ }
+ }
+ if (len < mps) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BCLR;
+ USB0.D0FIFOSEL.WORD = 0;
+ while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */
+ pipe->remaining = rem - len;
+ if ((len < mps) || (rem == len)) {
+ pipe->buf = NULL;
+ return NULL != buf;
+ }
+ return false;
}
static void process_setup_packet(uint8_t rhport)
@@ -288,7 +418,7 @@ static void process_setup_packet(uint8_t rhport)
uint16_t setup_packet[4];
if (0 == (USB0.INTSTS0.WORD & USB_IS0_VALID)) return;
USB0.CFIFOCTR.WORD = USB_FIFOCTR_BCLR;
- setup_packet[0] = USB0.USBREQ.WORD;
+ setup_packet[0] = tu_le16toh(USB0.USBREQ.WORD);
setup_packet[1] = USB0.USBVAL;
setup_packet[2] = USB0.USBINDX;
setup_packet[3] = USB0.USBLENG;
@@ -310,96 +440,63 @@ static void process_status_completion(uint8_t rhport)
dcd_event_xfer_complete(rhport, ep_addr, 0, XFER_RESULT_SUCCESS, true);
}
-static bool process_edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes)
+static bool process_pipe0_xfer(int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes)
{
- (void)rhport;
-
- pipe_state_t *pipe = &_dcd.pipe[0];
/* configure fifo direction and access unit settings */
if (ep_addr) { /* IN, 2 bytes */
- USB0.CFIFOSEL.WORD = USB_FIFOSEL_TX | USB_FIFOSEL_MBW_16;
+ USB0.CFIFOSEL.WORD = USB_FIFOSEL_TX | USB_FIFOSEL_MBW_16 | (TU_BYTE_ORDER == TU_BIG_ENDIAN ? USB_FIFOSEL_BIGEND : 0);
while (!(USB0.CFIFOSEL.WORD & USB_FIFOSEL_TX)) ;
} else { /* OUT, a byte */
USB0.CFIFOSEL.WORD = USB_FIFOSEL_MBW_8;
while (USB0.CFIFOSEL.WORD & USB_FIFOSEL_TX) ;
}
+
+ pipe_state_t *pipe = &_dcd.pipe[0];
+ pipe->ff = buffer_type;
+ pipe->length = total_bytes;
+ pipe->remaining = total_bytes;
if (total_bytes) {
- pipe->addr = (uintptr_t)buffer;
- pipe->length = total_bytes;
- pipe->remaining = total_bytes;
+ pipe->buf = buffer;
if (ep_addr) { /* IN */
TU_ASSERT(USB0.DCPCTR.BIT.BSTS && (USB0.USBREQ.WORD & 0x80));
- if (fifo_write(&USB0.CFIFO.WORD, pipe, 64)) {
- USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL;
- }
+ pipe0_xfer_in();
}
USB0.DCPCTR.WORD = USB_PIPECTR_PID_BUF;
} else {
/* ZLP */
- pipe->addr = 0;
- pipe->length = 0;
- pipe->remaining = 0;
+ pipe->buf = NULL;
USB0.DCPCTR.WORD = USB_PIPECTR_CCPL | USB_PIPECTR_PID_BUF;
}
return true;
}
-static void process_edpt0_bemp(uint8_t rhport)
+static bool process_pipe_xfer(int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes)
{
- pipe_state_t *pipe = &_dcd.pipe[0];
- const unsigned rem = pipe->remaining;
- if (rem > 64) {
- pipe->remaining = rem - 64;
- int r = fifo_write(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64);
- if (r) USB0.CFIFOCTR.WORD = USB_FIFOCTR_BVAL;
- return;
- }
- pipe->addr = 0;
- pipe->remaining = 0;
- dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_IN),
- pipe->length, XFER_RESULT_SUCCESS, true);
-}
-
-static void process_edpt0_brdy(uint8_t rhport)
-{
- size_t len = USB0.CFIFOCTR.BIT.DTLN;
- int cplt = fifo_read(&USB0.CFIFO.WORD, &_dcd.pipe[0], 64, len);
- if (cplt || (len < 64)) {
- if (2 != cplt) {
- USB0.CFIFOCTR.WORD = USB_FIFOCTR_BCLR;
- }
- dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_OUT),
- _dcd.pipe[0].length - _dcd.pipe[0].remaining,
- XFER_RESULT_SUCCESS, true);
- }
-}
-
-static bool process_pipe_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes)
-{
- (void)rhport;
-
const unsigned epn = tu_edpt_number(ep_addr);
const unsigned dir = tu_edpt_dir(ep_addr);
const unsigned num = _dcd.ep[dir][epn];
TU_ASSERT(num);
- pipe_state_t *pipe = &_dcd.pipe[num];
- pipe->addr = (uintptr_t)buffer;
+ pipe_state_t *pipe = &_dcd.pipe[num];
+ pipe->ff = buffer_type;
+ pipe->buf = buffer;
pipe->length = total_bytes;
pipe->remaining = total_bytes;
-
- USB0.PIPESEL.WORD = num;
- const unsigned mps = USB0.PIPEMAXP.WORD;
if (dir) { /* IN */
- USB0.D0FIFOSEL.WORD = num | USB_FIFOSEL_MBW_16;
- while (!(USB0.D0FIFOSEL.BIT.CURPIPE != num)) ;
- int r = fifo_write(&USB0.D0FIFO.WORD, pipe, mps);
- if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL;
- USB0.D0FIFOSEL.WORD = 0;
+ if (total_bytes) {
+ pipe_xfer_in(num);
+ } else { /* ZLP */
+ USB0.D0FIFOSEL.WORD = num;
+ pipe_wait_for_ready(num);
+ USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL;
+ USB0.D0FIFOSEL.WORD = 0;
+ while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */
+ }
} else {
volatile reg_pipetre_t *pt = get_pipetre(num);
if (pt) {
+ const unsigned mps = edpt_max_packet_size(num);
volatile uint16_t *ctr = get_pipectr(num);
if (*ctr & 0x3) *ctr = USB_PIPECTR_PID_NAK;
pt->TRE = TU_BIT(8);
@@ -408,47 +505,50 @@ static bool process_pipe_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer,
*ctr = USB_PIPECTR_PID_BUF;
}
}
- // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes);
+ // TU_LOG1("X %x %d %d\r\n", ep_addr, total_bytes, buffer_type);
return true;
}
+static bool process_edpt_xfer(int buffer_type, uint8_t ep_addr, void* buffer, uint16_t total_bytes)
+{
+ const unsigned epn = tu_edpt_number(ep_addr);
+ if (0 == epn) {
+ return process_pipe0_xfer(buffer_type, ep_addr, buffer, total_bytes);
+ } else {
+ return process_pipe_xfer(buffer_type, ep_addr, buffer, total_bytes);
+ }
+}
+
+static void process_pipe0_bemp(uint8_t rhport)
+{
+ bool completed = pipe0_xfer_in();
+ if (completed) {
+ pipe_state_t *pipe = &_dcd.pipe[0];
+ dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_IN),
+ pipe->length, XFER_RESULT_SUCCESS, true);
+ }
+}
+
static void process_pipe_brdy(uint8_t rhport, unsigned num)
{
- pipe_state_t *pipe = &_dcd.pipe[num];
- if (tu_edpt_dir(pipe->ep)) { /* IN */
- select_pipe(num, USB_FIFOSEL_MBW_16);
- const unsigned mps = USB0.PIPEMAXP.WORD;
- unsigned rem = pipe->remaining;
- rem -= TU_MIN(rem, mps);
- pipe->remaining = rem;
- if (rem) {
- int r = 0;
- r = fifo_write(&USB0.D0FIFO.WORD, pipe, mps);
- if (r) USB0.D0FIFOCTR.WORD = USB_FIFOCTR_BVAL;
- USB0.D0FIFOSEL.WORD = 0;
- return;
- }
- USB0.D0FIFOSEL.WORD = 0;
- pipe->addr = 0;
- pipe->remaining = 0;
- dcd_event_xfer_complete(rhport, pipe->ep, pipe->length,
- XFER_RESULT_SUCCESS, true);
+ pipe_state_t *pipe = &_dcd.pipe[num];
+ const unsigned dir = tu_edpt_dir(pipe->ep);
+ bool completed;
+
+ if (dir) { /* IN */
+ completed = pipe_xfer_in(num);
} else {
- const unsigned ctr = select_pipe(num, USB_FIFOSEL_MBW_8);
- const unsigned len = ctr & USB_FIFOCTR_DTLN;
- const unsigned mps = USB0.PIPEMAXP.WORD;
- int cplt = fifo_read(&USB0.D0FIFO.WORD, pipe, mps, len);
- if (cplt || (len < mps)) {
- if (2 != cplt) {
- USB0.D0FIFO.WORD = USB_FIFOCTR_BCLR;
- }
- USB0.D0FIFOSEL.WORD = 0;
- dcd_event_xfer_complete(rhport, pipe->ep,
- pipe->length - pipe->remaining,
- XFER_RESULT_SUCCESS, true);
- return;
+ if (num) {
+ completed = pipe_xfer_out(num);
+ } else {
+ completed = pipe0_xfer_out();
}
- USB0.D0FIFOSEL.WORD = 0;
+ }
+ if (completed) {
+ dcd_event_xfer_complete(rhport, pipe->ep,
+ pipe->length - pipe->remaining,
+ XFER_RESULT_SUCCESS, true);
+ // TU_LOG1("C %d %d\r\n", num, pipe->length - pipe->remaining);
}
}
@@ -458,7 +558,9 @@ static void process_bus_reset(uint8_t rhport)
USB0.BRDYENB.WORD = 1;
USB0.CFIFOCTR.WORD = USB_FIFOCTR_BCLR;
USB0.D0FIFOSEL.WORD = 0;
+ while (USB0.D0FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */
USB0.D1FIFOSEL.WORD = 0;
+ while (USB0.D1FIFOSEL.BIT.CURPIPE) ; /* if CURPIPE bits changes, check written value */
volatile uint16_t *ctr = (volatile uint16_t*)((uintptr_t)(&USB0.PIPE1CTR.WORD));
volatile uint16_t *tre = (volatile uint16_t*)((uintptr_t)(&USB0.PIPE1TRE.WORD));
for (int i = 1; i <= 5; ++i) {
@@ -486,12 +588,16 @@ static void process_set_address(uint8_t rhport)
const uint32_t addr = USB0.USBADDR.BIT.USBADDR;
if (!addr) return;
const tusb_control_request_t setup_packet = {
- .bmRequestType = 0,
- .bRequest = 5,
- .wValue = addr,
- .wIndex = 0,
- .wLength = 0,
- };
+#if defined(__CCRX__)
+ .bmRequestType = { 0 }, /* Note: CCRX needs the braces over this struct member */
+#else
+ .bmRequestType = 0,
+#endif
+ .bRequest = TUSB_REQ_SET_ADDRESS,
+ .wValue = addr,
+ .wIndex = 0,
+ .wLength = 0,
+ };
dcd_event_setup_received(rhport, (const uint8_t*)&setup_packet, true);
}
@@ -513,11 +619,18 @@ void dcd_init(uint8_t rhport)
USB0.SYSCFG.BIT.DCFM = 0;
USB0.SYSCFG.BIT.USBE = 1;
+ USB.DPUSR0R.BIT.FIXPHY0 = 0u; /* USB0 Transceiver Output fixed */
+#if ( CFG_TUSB_MCU == OPT_MCU_RX72N )
+ USB0.PHYSLEW.LONG = 0x5;
+ IR(PERIB, INTB185) = 0;
+#else
IR(USB0, USBI0) = 0;
+#endif
/* Setup default control pipe */
USB0.DCPMAXP.BIT.MXPS = 64;
- USB0.INTENB0.WORD = USB_IS0_VBINT | USB_IS0_BRDY | USB_IS0_BEMP | USB_IS0_DVST | USB_IS0_CTRT;
+ USB0.INTENB0.WORD = USB_IS0_VBINT | USB_IS0_BRDY | USB_IS0_BEMP |
+ USB_IS0_DVST | USB_IS0_CTRT | (USE_SOF ? USB_IS0_SOFR: 0) | USB_IS0_RESM;
USB0.BEMPENB.WORD = 1;
USB0.BRDYENB.WORD = 1;
@@ -529,13 +642,21 @@ void dcd_init(uint8_t rhport)
void dcd_int_enable(uint8_t rhport)
{
(void)rhport;
+#if ( CFG_TUSB_MCU == OPT_MCU_RX72N )
+ IEN(PERIB, INTB185) = 1;
+#else
IEN(USB0, USBI0) = 1;
+#endif
}
void dcd_int_disable(uint8_t rhport)
{
(void)rhport;
+#if ( CFG_TUSB_MCU == OPT_MCU_RX72N )
+ IEN(PERIB, INTB185) = 0;
+#else
IEN(USB0, USBI0) = 0;
+#endif
}
void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
@@ -547,7 +668,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
void dcd_remote_wakeup(uint8_t rhport)
{
(void)rhport;
- /* TODO */
+ USB0.DVSTCTR0.BIT.WKUP = 1;
}
void dcd_connect(uint8_t rhport)
@@ -574,7 +695,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
const unsigned dir = tu_edpt_dir(ep_addr);
const unsigned xfer = ep_desc->bmAttributes.xfer;
- const unsigned mps = ep_desc->wMaxPacketSize.size;
+ const unsigned mps = tu_le16toh(ep_desc->wMaxPacketSize.size);
if (xfer == TUSB_XFER_ISOCHRONOUS && mps > 256) {
/* USBa supports up to 256 bytes */
return false;
@@ -590,7 +711,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
USB0.PIPESEL.WORD = num;
USB0.PIPEMAXP.WORD = mps;
volatile uint16_t *ctr = get_pipectr(num);
- *ctr = USB_PIPECTR_ACLRM;
+ *ctr = USB_PIPECTR_ACLRM | USB_PIPECTR_SQCLR;
*ctr = 0;
unsigned cfg = (dir << 4) | epn;
if (xfer == TUSB_XFER_BULK) {
@@ -606,12 +727,24 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
if (dir || (xfer != TUSB_XFER_BULK)) {
*ctr = USB_PIPECTR_PID_BUF;
}
- // TU_LOG1("O %d %x %x\r\n", USB0.PIPESEL.WORD, USB0.PIPECFG.WORD, USB0.PIPEMAXP.WORD);
+ // TU_LOG1("O %d %x %x\r\n", USB0.PIPESEL.WORD, USB0.PIPECFG.WORD, USB0.PIPEMAXP.WORD);
dcd_int_enable(rhport);
return true;
}
+void dcd_edpt_close_all(uint8_t rhport)
+{
+ unsigned i = TU_ARRAY_SIZE(_dcd.pipe);
+ dcd_int_disable(rhport);
+ while (--i) { /* Close all pipes except 0 */
+ const unsigned ep_addr = _dcd.pipe[i].ep;
+ if (!ep_addr) continue;
+ dcd_edpt_close(rhport, ep_addr);
+ }
+ dcd_int_enable(rhport);
+}
+
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
{
(void)rhport;
@@ -631,13 +764,19 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes)
{
bool r;
- const unsigned epn = tu_edpt_number(ep_addr);
dcd_int_disable(rhport);
- if (0 == epn) {
- r = process_edpt0_xfer(rhport, ep_addr, buffer, total_bytes);
- } else {
- r = process_pipe_xfer(rhport, ep_addr, buffer, total_bytes);
- }
+ r = process_edpt_xfer(0, ep_addr, buffer, total_bytes);
+ dcd_int_enable(rhport);
+ return r;
+}
+
+bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
+{
+ // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1
+ TU_ASSERT(ff->item_size == 1);
+ bool r;
+ dcd_int_disable(rhport);
+ r = process_edpt_xfer(1, ep_addr, ff, total_bytes);
dcd_int_enable(rhport);
return r;
}
@@ -680,8 +819,8 @@ void dcd_int_handler(uint8_t rhport)
(void)rhport;
unsigned is0 = USB0.INTSTS0.WORD;
- /* clear bits except VALID */
- USB0.INTSTS0.WORD = USB_IS0_VALID;
+ /* clear active bits except VALID (don't write 0 to already cleared bits according to the HW manual) */
+ USB0.INTSTS0.WORD = ~((USB_IS0_CTRT | USB_IS0_DVST | USB_IS0_SOFR | USB_IS0_RESM | USB_IS0_VBINT) & is0) | USB_IS0_VALID;
if (is0 & USB_IS0_VBINT) {
if (USB0.INTSTS0.BIT.VBSTS) {
dcd_connect(rhport);
@@ -689,6 +828,19 @@ void dcd_int_handler(uint8_t rhport)
dcd_disconnect(rhport);
}
}
+ if (is0 & USB_IS0_RESM) {
+ dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true);
+#if (0==USE_SOF)
+ USB0.INTENB0.BIT.SOFE = 0;
+#endif
+ }
+ if ((is0 & USB_IS0_SOFR) && USB0.INTENB0.BIT.SOFE) {
+ // USBD will exit suspended mode when SOF event is received
+ dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true);
+#if (0==USE_SOF)
+ USB0.INTENB0.BIT.SOFE = 0;
+#endif
+ }
if (is0 & USB_IS0_DVST) {
switch (is0 & USB_IS0_DVSQ) {
case USB_IS0_DVSQ_DEF:
@@ -697,6 +849,14 @@ void dcd_int_handler(uint8_t rhport)
case USB_IS0_DVSQ_ADDR:
process_set_address(rhport);
break;
+ case USB_IS0_DVSQ_SUSP0:
+ case USB_IS0_DVSQ_SUSP1:
+ case USB_IS0_DVSQ_SUSP2:
+ case USB_IS0_DVSQ_SUSP3:
+ dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true);
+#if (0==USE_SOF)
+ USB0.INTENB0.BIT.SOFE = 1;
+#endif
default:
break;
}
@@ -714,19 +874,26 @@ void dcd_int_handler(uint8_t rhport)
const unsigned s = USB0.BEMPSTS.WORD;
USB0.BEMPSTS.WORD = 0;
if (s & 1) {
- process_edpt0_bemp(rhport);
+ process_pipe0_bemp(rhport);
}
}
if (is0 & USB_IS0_BRDY) {
const unsigned m = USB0.BRDYENB.WORD;
unsigned s = USB0.BRDYSTS.WORD & m;
- USB0.BRDYSTS.WORD = 0;
- if (s & 1) {
- process_edpt0_brdy(rhport);
- s &= ~1;
- }
+ /* clear active bits (don't write 0 to already cleared bits according to the HW manual) */
+ USB0.BRDYSTS.WORD = ~s;
while (s) {
+#if defined(__CCRX__)
+ static const int Mod37BitPosition[] = {
+ -1, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, 4,
+ 7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5,
+ 20, 8, 19, 18
+ };
+
+ const unsigned num = Mod37BitPosition[(-s & s) % 37];
+#else
const unsigned num = __builtin_ctz(s);
+#endif
process_pipe_brdy(rhport, num);
s &= ~TU_BIT(num);
}
diff --git a/src/portable/silabs/efm32/dcd_efm32.c b/src/portable/silabs/efm32/dcd_efm32.c
index bd1f32e6b..3bef83408 100644
--- a/src/portable/silabs/efm32/dcd_efm32.c
+++ b/src/portable/silabs/efm32/dcd_efm32.c
@@ -434,6 +434,12 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
return true;
}
+void dcd_edpt_close_all (uint8_t rhport)
+{
+ (void) rhport;
+ // TODO implement dcd_edpt_close_all()
+}
+
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes)
{
(void)rhport;
diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c
index 834976468..cfd74330f 100644
--- a/src/portable/sony/cxd56/dcd_cxd56.c
+++ b/src/portable/sony/cxd56/dcd_cxd56.c
@@ -312,6 +312,12 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoint_desc)
return true;
}
+void dcd_edpt_close_all (uint8_t rhport)
+{
+ (void) rhport;
+ // TODO implement dcd_edpt_close_all()
+}
+
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
{
(void) rhport;
diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
index 74c144107..ccffa42d7 100644
--- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
@@ -113,7 +113,8 @@
(CFG_TUSB_MCU == OPT_MCU_STM32F0 ) || \
(CFG_TUSB_MCU == OPT_MCU_STM32F1 && defined(STM32F1_FSDEV)) || \
(CFG_TUSB_MCU == OPT_MCU_STM32F3 ) || \
- (CFG_TUSB_MCU == OPT_MCU_STM32L0 ) \
+ (CFG_TUSB_MCU == OPT_MCU_STM32L0 ) || \
+ (CFG_TUSB_MCU == OPT_MCU_STM32L1 ) \
)
// In order to reduce the dependance on HAL, we undefine this.
@@ -273,6 +274,20 @@ void dcd_connect(uint8_t rhport)
USB->BCDR |= USB_BCDR_DPPU;
}
+#elif defined(SYSCFG_PMC_USB_PU) // works e.g. on STM32L151
+// Disable internal D+ PU
+void dcd_disconnect(uint8_t rhport)
+{
+ (void) rhport;
+ SYSCFG->PMC &= ~(SYSCFG_PMC_USB_PU);
+}
+
+// Enable internal D+ PU
+void dcd_connect(uint8_t rhport)
+{
+ (void) rhport;
+ SYSCFG->PMC |= SYSCFG_PMC_USB_PU;
+}
#endif
// Enable device interrupt
@@ -284,6 +299,8 @@ void dcd_int_enable (uint8_t rhport)
__ISB();
#if CFG_TUSB_MCU == OPT_MCU_STM32F0 || CFG_TUSB_MCU == OPT_MCU_STM32L0
NVIC_EnableIRQ(USB_IRQn);
+#elif CFG_TUSB_MCU == OPT_MCU_STM32L1
+ NVIC_EnableIRQ(USB_LP_IRQn);
#elif CFG_TUSB_MCU == OPT_MCU_STM32F3
// Some STM32F302/F303 devices allow to remap the USB interrupt vectors from
// shared USB/CAN IRQs to separate CAN and USB IRQs.
@@ -318,6 +335,8 @@ void dcd_int_disable(uint8_t rhport)
#if CFG_TUSB_MCU == OPT_MCU_STM32F0 || CFG_TUSB_MCU == OPT_MCU_STM32L0
NVIC_DisableIRQ(USB_IRQn);
+#elif CFG_TUSB_MCU == OPT_MCU_STM32L1
+ NVIC_DisableIRQ(USB_LP_IRQn);
#elif CFG_TUSB_MCU == OPT_MCU_STM32F3
// Some STM32F302/F303 devices allow to remap the USB interrupt vectors from
// shared USB/CAN IRQs to separate CAN and USB IRQs.
@@ -781,6 +800,12 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc
return true;
}
+void dcd_edpt_close_all (uint8_t rhport)
+{
+ (void) rhport;
+ // TODO implement dcd_edpt_close_all()
+}
+
/**
* Close an endpoint.
*
diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h
index d26c700d2..eca8bf575 100644
--- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h
+++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h
@@ -83,6 +83,10 @@
#include "stm32l0xx.h"
#define PMA_LENGTH (1024u)
+#elif CFG_TUSB_MCU == OPT_MCU_STM32L1
+ #include "stm32l1xx.h"
+ #define PMA_LENGTH (512u)
+
#else
#error You are using an untested or unimplemented STM32 variant. Please update the driver.
// This includes L1x0, L1x1, L1x2, L4x2 and L4x3, G1x1, G1x3, and G1x4
diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c
index 8a196e061..85abf940e 100644
--- a/src/portable/st/synopsys/dcd_synopsys.c
+++ b/src/portable/st/synopsys/dcd_synopsys.c
@@ -51,7 +51,8 @@
CFG_TUSB_MCU == OPT_MCU_STM32F4 || \
CFG_TUSB_MCU == OPT_MCU_STM32F7 || \
CFG_TUSB_MCU == OPT_MCU_STM32H7 || \
- (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS)) \
+ (CFG_TUSB_MCU == OPT_MCU_STM32L4 && defined(STM32L4_SYNOPSYS) || \
+ CFG_TUSB_MCU == OPT_MCU_GD32VF103 ) \
)
// EP_MAX : Max number of bi-directional endpoints including EP0
@@ -92,6 +93,33 @@
#define EP_MAX_FS 6
#define EP_FIFO_SIZE_FS 1280
+#elif CFG_TUSB_MCU == OPT_MCU_GD32VF103
+#include "synopsys_common.h"
+
+// for remote wakeup delay
+#define __NOP() __asm volatile ("nop")
+
+// These numbers are the same for the whole GD32VF103 family.
+#define OTG_FS_IRQn 86
+#define EP_MAX_FS 4
+#define EP_FIFO_SIZE_FS 1280
+
+// The GD32VF103 is a RISC-V MCU, which implements the ECLIC Core-Local
+// Interrupt Controller by Nuclei. It is nearly API compatible to the
+// NVIC used by ARM MCUs.
+#define ECLIC_INTERRUPT_ENABLE_BASE 0xD2001001UL
+
+#define NVIC_EnableIRQ __eclic_enable_interrupt
+#define NVIC_DisableIRQ __eclic_disable_interrupt
+
+static inline void __eclic_enable_interrupt (uint32_t irq) {
+ *(volatile uint8_t*)(ECLIC_INTERRUPT_ENABLE_BASE + (irq * 4)) = 1;
+}
+
+static inline void __eclic_disable_interrupt (uint32_t irq){
+ *(volatile uint8_t*)(ECLIC_INTERRUPT_ENABLE_BASE + (irq * 4)) = 0;
+}
+
#else
#error "Unsupported MCUs"
#endif
@@ -188,13 +216,18 @@ static void bus_reset(uint8_t rhport)
tu_memclr(xfer_status, sizeof(xfer_status));
_out_ep_closed = false;
+ // clear device address
+ dev->DCFG &= ~USB_OTG_DCFG_DAD_Msk;
+
+ // 1. NAK for all OUT endpoints
for(uint8_t n = 0; n < EP_MAX; n++) {
out_ep[n].DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
}
- dev->DAINTMSK |= (1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos);
- dev->DOEPMSK |= USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM;
- dev->DIEPMSK |= USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM;
+ // 2. Un-mask interrupt bits
+ dev->DAINTMSK = (1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos);
+ dev->DOEPMSK = USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM;
+ dev->DIEPMSK = USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM;
// "USB Data FIFOs" section in reference manual
// Peripheral FIFO architecture
@@ -519,19 +552,40 @@ void dcd_int_disable (uint8_t rhport)
void dcd_set_address (uint8_t rhport, uint8_t dev_addr)
{
USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport);
- dev->DCFG |= (dev_addr << USB_OTG_DCFG_DAD_Pos) & USB_OTG_DCFG_DAD_Msk;
+ dev->DCFG = (dev->DCFG & ~USB_OTG_DCFG_DAD_Msk) | (dev_addr << USB_OTG_DCFG_DAD_Pos);
// Response with status after changing device address
dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0);
}
+static void remote_wakeup_delay(void)
+{
+ // try to delay for 1 ms
+ uint32_t count = SystemCoreClock / 1000;
+ while ( count-- )
+ {
+ __NOP();
+ }
+}
+
void dcd_remote_wakeup(uint8_t rhport)
{
(void) rhport;
- // TODO must manually clear this bit after 1-15 ms
- // USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport);
- // dev->DCTL |= USB_OTG_DCTL_RWUSIG;
+ USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport);
+ USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport);
+
+ // set remote wakeup
+ dev->DCTL |= USB_OTG_DCTL_RWUSIG;
+
+ // enable SOF to detect bus resume
+ usb_otg->GINTSTS = USB_OTG_GINTSTS_SOF;
+ usb_otg->GINTMSK |= USB_OTG_GINTMSK_SOFM;
+
+ // Per specs: remote wakeup signal bit must be clear within 1-15ms
+ remote_wakeup_delay();
+
+ dev->DCTL &= ~USB_OTG_DCTL_RWUSIG;
}
void dcd_connect(uint8_t rhport)
@@ -587,8 +641,9 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
usb_otg->GRXFSIZ = sz;
}
- out_ep[epnum].DOEPCTL |= (1 << USB_OTG_DOEPCTL_USBAEP_Pos) |
- (desc_edpt->bmAttributes.xfer << USB_OTG_DOEPCTL_EPTYP_Pos) |
+ out_ep[epnum].DOEPCTL |= (1 << USB_OTG_DOEPCTL_USBAEP_Pos) |
+ (desc_edpt->bmAttributes.xfer << USB_OTG_DOEPCTL_EPTYP_Pos) |
+ (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM : 0) |
(desc_edpt->wMaxPacketSize.size << USB_OTG_DOEPCTL_MPSIZ_Pos);
dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_OEPM_Pos + epnum));
@@ -621,6 +676,8 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
_allocated_fifo_words_tx += fifo_size;
+ TU_LOG(2, " Allocated %u bytes at offset %u", fifo_size*4, EP_FIFO_SIZE-_allocated_fifo_words_tx*4);
+
// DIEPTXF starts at FIFO #1.
// Both TXFD and TXSA are in unit of 32-bit words.
usb_otg->DIEPTXF[epnum - 1] = (fifo_size << USB_OTG_DIEPTXF_INEPTXFD_Pos) | (EP_FIFO_SIZE/4 - _allocated_fifo_words_tx);
@@ -628,7 +685,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
in_ep[epnum].DIEPCTL |= (1 << USB_OTG_DIEPCTL_USBAEP_Pos) |
(epnum << USB_OTG_DIEPCTL_TXFNUM_Pos) |
(desc_edpt->bmAttributes.xfer << USB_OTG_DIEPCTL_EPTYP_Pos) |
- (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DOEPCTL_SD0PID_SEVNFRM : 0) |
+ (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_OTG_DIEPCTL_SD0PID_SEVNFRM : 0) |
(desc_edpt->wMaxPacketSize.size << USB_OTG_DIEPCTL_MPSIZ_Pos);
dev->DAINTMSK |= (1 << (USB_OTG_DAINTMSK_IEPM_Pos + epnum));
@@ -637,6 +694,34 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
return true;
}
+// Close all non-control endpoints, cancel all pending transfers if any.
+void dcd_edpt_close_all (uint8_t rhport)
+{
+ (void) rhport;
+
+// USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport);
+ USB_OTG_DeviceTypeDef * dev = DEVICE_BASE(rhport);
+ USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport);
+ USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport);
+
+ // Disable non-control interrupt
+ dev->DAINTMSK = (1 << USB_OTG_DAINTMSK_OEPM_Pos) | (1 << USB_OTG_DAINTMSK_IEPM_Pos);
+
+ for(uint8_t n = 1; n < EP_MAX; n++)
+ {
+ // disable OUT endpoint
+ out_ep[n].DOEPCTL = 0;
+ xfer_status[n][TUSB_DIR_OUT].max_size = 0;
+
+ // disable IN endpoint
+ in_ep[n].DIEPCTL = 0;
+ xfer_status[n][TUSB_DIR_IN].max_size = 0;
+ }
+
+ // reset allocated fifo IN
+ _allocated_fifo_words_tx = 16;
+}
+
bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
{
uint8_t const epnum = tu_edpt_number(ep_addr);
@@ -656,7 +741,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
}
uint16_t num_packets = (total_bytes / xfer->max_size);
- uint8_t const short_packet_size = total_bytes % xfer->max_size;
+ uint16_t const short_packet_size = total_bytes % xfer->max_size;
// Zero-size packet is special case.
if(short_packet_size > 0 || (total_bytes == 0)) {
@@ -687,7 +772,7 @@ bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16
xfer->total_len = total_bytes;
uint16_t num_packets = (total_bytes / xfer->max_size);
- uint8_t const short_packet_size = total_bytes % xfer->max_size;
+ uint16_t const short_packet_size = total_bytes % xfer->max_size;
// Zero-size packet is special case.
if(short_packet_size > 0 || (total_bytes == 0)) num_packets++;
@@ -796,22 +881,13 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const dir = tu_edpt_dir(ep_addr);
+ // Clear stall and reset data toggle
if(dir == TUSB_DIR_IN) {
in_ep[epnum].DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;
-
- uint8_t eptype = (in_ep[epnum].DIEPCTL & USB_OTG_DIEPCTL_EPTYP_Msk) >> USB_OTG_DIEPCTL_EPTYP_Pos;
- // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt and bulk endpoints.
- if(eptype == 2 || eptype == 3) {
- in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM;
- }
+ in_ep[epnum].DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM;
} else {
out_ep[epnum].DOEPCTL &= ~USB_OTG_DOEPCTL_STALL;
-
- uint8_t eptype = (out_ep[epnum].DOEPCTL & USB_OTG_DOEPCTL_EPTYP_Msk) >> USB_OTG_DOEPCTL_EPTYP_Pos;
- // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt and bulk endpoints.
- if(eptype == 2 || eptype == 3) {
- out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM;
- }
+ out_ep[epnum].DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM;
}
}
@@ -1048,7 +1124,7 @@ void dcd_int_handler(uint8_t rhport)
USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE(rhport);
USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE(rhport);
- uint32_t int_status = usb_otg->GINTSTS;
+ uint32_t const int_status = usb_otg->GINTSTS & usb_otg->GINTMSK;
if(int_status & USB_OTG_GINTSTS_USBRST)
{
@@ -1081,6 +1157,9 @@ void dcd_int_handler(uint8_t rhport)
dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true);
}
+ // TODO check USB_OTG_GINTSTS_DISCINT for disconnect detection
+ // if(int_status & USB_OTG_GINTSTS_DISCINT)
+
if(int_status & USB_OTG_GINTSTS_OTGINT)
{
// OTG INT bit is read-only
@@ -1094,13 +1173,15 @@ void dcd_int_handler(uint8_t rhport)
usb_otg->GOTGINT = otg_int;
}
-#if USE_SOF
if(int_status & USB_OTG_GINTSTS_SOF)
{
usb_otg->GINTSTS = USB_OTG_GINTSTS_SOF;
+
+ // Disable SOF interrupt since currently only used for remote wakeup detection
+ usb_otg->GINTMSK &= ~USB_OTG_GINTMSK_SOFM;
+
dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true);
}
-#endif
// RxFIFO non-empty interrupt handling.
if(int_status & USB_OTG_GINTSTS_RXFLVL)
@@ -1114,8 +1195,7 @@ void dcd_int_handler(uint8_t rhport)
do
{
handle_rxflvl_ints(rhport, out_ep);
- int_status = usb_otg->GINTSTS;
- } while(int_status & USB_OTG_GINTSTS_RXFLVL);
+ } while(usb_otg->GINTSTS & USB_OTG_GINTSTS_RXFLVL);
// Manage RX FIFO size
if (_out_ep_closed)
diff --git a/src/portable/st/synopsys/synopsys_common.h b/src/portable/st/synopsys/synopsys_common.h
new file mode 100644
index 000000000..6f0602fe9
--- /dev/null
+++ b/src/portable/st/synopsys/synopsys_common.h
@@ -0,0 +1,1465 @@
+/**
+ ******************************************************************************
+ * @file synopsys_common.h
+ * @author MCD Application Team
+ * @brief CMSIS Cortex-M3 Device USB OTG peripheral Header File.
+ * This file contains the USB OTG peripheral register's definitions, bits
+ * definitions and memory mapping for STM32F1xx devices.
+ *
+ * This file contains:
+ * - Data structures and the address mapping for the USB OTG peripheral
+ * - The Peripheral's registers declarations and bits definition
+ * - Macros to access the peripheral's registers hardware
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+#include "stdint.h"
+
+#pragma once
+
+#ifdef __cplusplus
+ #define __I volatile
+#else
+ #define __I volatile const
+#endif
+#define __O volatile
+#define __IO volatile
+#define __IM volatile const
+#define __OM volatile
+#define __IOM volatile
+
+/**
+ * @brief __USB_OTG_Core_register
+ */
+
+typedef struct
+{
+ __IO uint32_t GOTGCTL; /*!< USB_OTG Control and Status Register Address offset: 000h */
+ __IO uint32_t GOTGINT; /*!< USB_OTG Interrupt Register Address offset: 004h */
+ __IO uint32_t GAHBCFG; /*!< Core AHB Configuration Register Address offset: 008h */
+ __IO uint32_t GUSBCFG; /*!< Core USB Configuration Register Address offset: 00Ch */
+ __IO uint32_t GRSTCTL; /*!< Core Reset Register Address offset: 010h */
+ __IO uint32_t GINTSTS; /*!< Core Interrupt Register Address offset: 014h */
+ __IO uint32_t GINTMSK; /*!< Core Interrupt Mask Register Address offset: 018h */
+ __IO uint32_t GRXSTSR; /*!< Receive Sts Q Read Register Address offset: 01Ch */
+ __IO uint32_t GRXSTSP; /*!< Receive Sts Q Read & POP Register Address offset: 020h */
+ __IO uint32_t GRXFSIZ; /*!< Receive FIFO Size Register Address offset: 024h */
+ __IO uint32_t DIEPTXF0_HNPTXFSIZ; /*!< EP0 / Non Periodic Tx FIFO Size Register Address offset: 028h */
+ __IO uint32_t HNPTXSTS; /*!< Non Periodic Tx FIFO/Queue Sts reg Address offset: 02Ch */
+ uint32_t Reserved30[2]; /*!< Reserved 030h*/
+ __IO uint32_t GCCFG; /*!< General Purpose IO Register Address offset: 038h */
+ __IO uint32_t CID; /*!< User ID Register Address offset: 03Ch */
+ uint32_t Reserved40[48]; /*!< Reserved 040h-0FFh */
+ __IO uint32_t HPTXFSIZ; /*!< Host Periodic Tx FIFO Size Reg Address offset: 100h */
+ __IO uint32_t DIEPTXF[0x0F]; /*!< dev Periodic Transmit FIFO Address offset: 0x104 */
+} USB_OTG_GlobalTypeDef;
+
+/**
+ * @brief __device_Registers
+ */
+
+typedef struct
+{
+ __IO uint32_t DCFG; /*!< dev Configuration Register Address offset: 800h*/
+ __IO uint32_t DCTL; /*!< dev Control Register Address offset: 804h*/
+ __IO uint32_t DSTS; /*!< dev Status Register (RO) Address offset: 808h*/
+ uint32_t Reserved0C; /*!< Reserved 80Ch*/
+ __IO uint32_t DIEPMSK; /*!< dev IN Endpoint Mask Address offset: 810h*/
+ __IO uint32_t DOEPMSK; /*!< dev OUT Endpoint Mask Address offset: 814h*/
+ __IO uint32_t DAINT; /*!< dev All Endpoints Itr Reg Address offset: 818h*/
+ __IO uint32_t DAINTMSK; /*!< dev All Endpoints Itr Mask Address offset: 81Ch*/
+ uint32_t Reserved20; /*!< Reserved 820h*/
+ uint32_t Reserved9; /*!< Reserved 824h*/
+ __IO uint32_t DVBUSDIS; /*!< dev VBUS discharge Register Address offset: 828h*/
+ __IO uint32_t DVBUSPULSE; /*!< dev VBUS Pulse Register Address offset: 82Ch*/
+ __IO uint32_t DTHRCTL; /*!< dev thr Address offset: 830h*/
+ __IO uint32_t DIEPEMPMSK; /*!< dev empty msk Address offset: 834h*/
+ __IO uint32_t DEACHINT; /*!< dedicated EP interrupt Address offset: 838h*/
+ __IO uint32_t DEACHMSK; /*!< dedicated EP msk Address offset: 83Ch*/
+ uint32_t Reserved40; /*!< dedicated EP mask Address offset: 840h*/
+ __IO uint32_t DINEP1MSK; /*!< dedicated EP mask Address offset: 844h*/
+ uint32_t Reserved44[15]; /*!< Reserved 844-87Ch*/
+ __IO uint32_t DOUTEP1MSK; /*!< dedicated EP msk Address offset: 884h*/
+} USB_OTG_DeviceTypeDef;
+
+/**
+ * @brief __IN_Endpoint-Specific_Register
+ */
+
+typedef struct
+{
+ __IO uint32_t DIEPCTL; /*!< dev IN Endpoint Control Reg 900h + (ep_num * 20h) + 00h*/
+ uint32_t Reserved04; /*!< Reserved 900h + (ep_num * 20h) + 04h*/
+ __IO uint32_t DIEPINT; /*!< dev IN Endpoint Itr Reg 900h + (ep_num * 20h) + 08h*/
+ uint32_t Reserved0C; /*!< Reserved 900h + (ep_num * 20h) + 0Ch*/
+ __IO uint32_t DIEPTSIZ; /*!< IN Endpoint Txfer Size 900h + (ep_num * 20h) + 10h*/
+ __IO uint32_t DIEPDMA; /*!< IN Endpoint DMA Address Reg 900h + (ep_num * 20h) + 14h*/
+ __IO uint32_t DTXFSTS; /*!< IN Endpoint Tx FIFO Status Reg 900h + (ep_num * 20h) + 18h*/
+ uint32_t Reserved18; /*!< Reserved 900h+(ep_num*20h)+1Ch-900h+ (ep_num * 20h) + 1Ch*/
+} USB_OTG_INEndpointTypeDef;
+
+/**
+ * @brief __OUT_Endpoint-Specific_Registers
+ */
+
+typedef struct
+{
+ __IO uint32_t DOEPCTL; /*!< dev OUT Endpoint Control Reg B00h + (ep_num * 20h) + 00h*/
+ uint32_t Reserved04; /*!< Reserved B00h + (ep_num * 20h) + 04h*/
+ __IO uint32_t DOEPINT; /*!< dev OUT Endpoint Itr Reg B00h + (ep_num * 20h) + 08h*/
+ uint32_t Reserved0C; /*!< Reserved B00h + (ep_num * 20h) + 0Ch*/
+ __IO uint32_t DOEPTSIZ; /*!< dev OUT Endpoint Txfer Size B00h + (ep_num * 20h) + 10h*/
+ __IO uint32_t DOEPDMA; /*!< dev OUT Endpoint DMA Address B00h + (ep_num * 20h) + 14h*/
+ uint32_t Reserved18[2]; /*!< Reserved B00h + (ep_num * 20h) + 18h - B00h + (ep_num * 20h) + 1Ch*/
+} USB_OTG_OUTEndpointTypeDef;
+
+/**
+ * @brief __Host_Mode_Register_Structures
+ */
+
+typedef struct
+{
+ __IO uint32_t HCFG; /*!< Host Configuration Register 400h*/
+ __IO uint32_t HFIR; /*!< Host Frame Interval Register 404h*/
+ __IO uint32_t HFNUM; /*!< Host Frame Nbr/Frame Remaining 408h*/
+ uint32_t Reserved40C; /*!< Reserved 40Ch*/
+ __IO uint32_t HPTXSTS; /*!< Host Periodic Tx FIFO/ Queue Status 410h*/
+ __IO uint32_t HAINT; /*!< Host All Channels Interrupt Register 414h*/
+ __IO uint32_t HAINTMSK; /*!< Host All Channels Interrupt Mask 418h*/
+} USB_OTG_HostTypeDef;
+
+/**
+ * @brief __Host_Channel_Specific_Registers
+ */
+
+typedef struct
+{
+ __IO uint32_t HCCHAR;
+ __IO uint32_t HCSPLT;
+ __IO uint32_t HCINT;
+ __IO uint32_t HCINTMSK;
+ __IO uint32_t HCTSIZ;
+ __IO uint32_t HCDMA;
+ uint32_t Reserved[2];
+} USB_OTG_HostChannelTypeDef;
+
+/*!< USB registers base address */
+#define USB_OTG_FS_PERIPH_BASE 0x50000000UL
+
+#define USB_OTG_GLOBAL_BASE 0x00000000UL
+#define USB_OTG_DEVICE_BASE 0x00000800UL
+#define USB_OTG_IN_ENDPOINT_BASE 0x00000900UL
+#define USB_OTG_OUT_ENDPOINT_BASE 0x00000B00UL
+#define USB_OTG_EP_REG_SIZE 0x00000020UL
+#define USB_OTG_HOST_BASE 0x00000400UL
+#define USB_OTG_HOST_PORT_BASE 0x00000440UL
+#define USB_OTG_HOST_CHANNEL_BASE 0x00000500UL
+#define USB_OTG_HOST_CHANNEL_SIZE 0x00000020UL
+#define USB_OTG_PCGCCTL_BASE 0x00000E00UL
+#define USB_OTG_FIFO_BASE 0x00001000UL
+#define USB_OTG_FIFO_SIZE 0x00001000UL
+
+/******************************************************************************/
+/* */
+/* USB_OTG */
+/* */
+/******************************************************************************/
+/******************** Bit definition for USB_OTG_GOTGCTL register ***********/
+#define USB_OTG_GOTGCTL_SRQSCS_Pos (0U)
+#define USB_OTG_GOTGCTL_SRQSCS_Msk (0x1UL << USB_OTG_GOTGCTL_SRQSCS_Pos) /*!< 0x00000001 */
+#define USB_OTG_GOTGCTL_SRQSCS USB_OTG_GOTGCTL_SRQSCS_Msk /*!< Session request success */
+#define USB_OTG_GOTGCTL_SRQ_Pos (1U)
+#define USB_OTG_GOTGCTL_SRQ_Msk (0x1UL << USB_OTG_GOTGCTL_SRQ_Pos) /*!< 0x00000002 */
+#define USB_OTG_GOTGCTL_SRQ USB_OTG_GOTGCTL_SRQ_Msk /*!< Session request */
+#define USB_OTG_GOTGCTL_HNGSCS_Pos (8U)
+#define USB_OTG_GOTGCTL_HNGSCS_Msk (0x1UL << USB_OTG_GOTGCTL_HNGSCS_Pos) /*!< 0x00000100 */
+#define USB_OTG_GOTGCTL_HNGSCS USB_OTG_GOTGCTL_HNGSCS_Msk /*!< Host set HNP enable */
+#define USB_OTG_GOTGCTL_HNPRQ_Pos (9U)
+#define USB_OTG_GOTGCTL_HNPRQ_Msk (0x1UL << USB_OTG_GOTGCTL_HNPRQ_Pos) /*!< 0x00000200 */
+#define USB_OTG_GOTGCTL_HNPRQ USB_OTG_GOTGCTL_HNPRQ_Msk /*!< HNP request */
+#define USB_OTG_GOTGCTL_HSHNPEN_Pos (10U)
+#define USB_OTG_GOTGCTL_HSHNPEN_Msk (0x1UL << USB_OTG_GOTGCTL_HSHNPEN_Pos) /*!< 0x00000400 */
+#define USB_OTG_GOTGCTL_HSHNPEN USB_OTG_GOTGCTL_HSHNPEN_Msk /*!< Host set HNP enable */
+#define USB_OTG_GOTGCTL_DHNPEN_Pos (11U)
+#define USB_OTG_GOTGCTL_DHNPEN_Msk (0x1UL << USB_OTG_GOTGCTL_DHNPEN_Pos) /*!< 0x00000800 */
+#define USB_OTG_GOTGCTL_DHNPEN USB_OTG_GOTGCTL_DHNPEN_Msk /*!< Device HNP enabled */
+#define USB_OTG_GOTGCTL_CIDSTS_Pos (16U)
+#define USB_OTG_GOTGCTL_CIDSTS_Msk (0x1UL << USB_OTG_GOTGCTL_CIDSTS_Pos) /*!< 0x00010000 */
+#define USB_OTG_GOTGCTL_CIDSTS USB_OTG_GOTGCTL_CIDSTS_Msk /*!< Connector ID status */
+#define USB_OTG_GOTGCTL_DBCT_Pos (17U)
+#define USB_OTG_GOTGCTL_DBCT_Msk (0x1UL << USB_OTG_GOTGCTL_DBCT_Pos) /*!< 0x00020000 */
+#define USB_OTG_GOTGCTL_DBCT USB_OTG_GOTGCTL_DBCT_Msk /*!< Long/short debounce time */
+#define USB_OTG_GOTGCTL_ASVLD_Pos (18U)
+#define USB_OTG_GOTGCTL_ASVLD_Msk (0x1UL << USB_OTG_GOTGCTL_ASVLD_Pos) /*!< 0x00040000 */
+#define USB_OTG_GOTGCTL_ASVLD USB_OTG_GOTGCTL_ASVLD_Msk /*!< A-session valid */
+#define USB_OTG_GOTGCTL_BSVLD_Pos (19U)
+#define USB_OTG_GOTGCTL_BSVLD_Msk (0x1UL << USB_OTG_GOTGCTL_BSVLD_Pos) /*!< 0x00080000 */
+#define USB_OTG_GOTGCTL_BSVLD USB_OTG_GOTGCTL_BSVLD_Msk /*!< B-session valid */
+
+/******************** Bit definition for USB_OTG_HCFG register ********************/
+
+#define USB_OTG_HCFG_FSLSPCS_Pos (0U)
+#define USB_OTG_HCFG_FSLSPCS_Msk (0x3UL << USB_OTG_HCFG_FSLSPCS_Pos) /*!< 0x00000003 */
+#define USB_OTG_HCFG_FSLSPCS USB_OTG_HCFG_FSLSPCS_Msk /*!< FS/LS PHY clock select */
+#define USB_OTG_HCFG_FSLSPCS_0 (0x1UL << USB_OTG_HCFG_FSLSPCS_Pos) /*!< 0x00000001 */
+#define USB_OTG_HCFG_FSLSPCS_1 (0x2UL << USB_OTG_HCFG_FSLSPCS_Pos) /*!< 0x00000002 */
+#define USB_OTG_HCFG_FSLSS_Pos (2U)
+#define USB_OTG_HCFG_FSLSS_Msk (0x1UL << USB_OTG_HCFG_FSLSS_Pos) /*!< 0x00000004 */
+#define USB_OTG_HCFG_FSLSS USB_OTG_HCFG_FSLSS_Msk /*!< FS- and LS-only support */
+
+/******************** Bit definition for USB_OTG_DCFG register ********************/
+
+#define USB_OTG_DCFG_DSPD_Pos (0U)
+#define USB_OTG_DCFG_DSPD_Msk (0x3UL << USB_OTG_DCFG_DSPD_Pos) /*!< 0x00000003 */
+#define USB_OTG_DCFG_DSPD USB_OTG_DCFG_DSPD_Msk /*!< Device speed */
+#define USB_OTG_DCFG_DSPD_0 (0x1UL << USB_OTG_DCFG_DSPD_Pos) /*!< 0x00000001 */
+#define USB_OTG_DCFG_DSPD_1 (0x2UL << USB_OTG_DCFG_DSPD_Pos) /*!< 0x00000002 */
+#define USB_OTG_DCFG_NZLSOHSK_Pos (2U)
+#define USB_OTG_DCFG_NZLSOHSK_Msk (0x1UL << USB_OTG_DCFG_NZLSOHSK_Pos) /*!< 0x00000004 */
+#define USB_OTG_DCFG_NZLSOHSK USB_OTG_DCFG_NZLSOHSK_Msk /*!< Nonzero-length status OUT handshake */
+
+#define USB_OTG_DCFG_DAD_Pos (4U)
+#define USB_OTG_DCFG_DAD_Msk (0x7FUL << USB_OTG_DCFG_DAD_Pos) /*!< 0x000007F0 */
+#define USB_OTG_DCFG_DAD USB_OTG_DCFG_DAD_Msk /*!< Device address */
+#define USB_OTG_DCFG_DAD_0 (0x01UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000010 */
+#define USB_OTG_DCFG_DAD_1 (0x02UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000020 */
+#define USB_OTG_DCFG_DAD_2 (0x04UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000040 */
+#define USB_OTG_DCFG_DAD_3 (0x08UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000080 */
+#define USB_OTG_DCFG_DAD_4 (0x10UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000100 */
+#define USB_OTG_DCFG_DAD_5 (0x20UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000200 */
+#define USB_OTG_DCFG_DAD_6 (0x40UL << USB_OTG_DCFG_DAD_Pos) /*!< 0x00000400 */
+
+#define USB_OTG_DCFG_PFIVL_Pos (11U)
+#define USB_OTG_DCFG_PFIVL_Msk (0x3UL << USB_OTG_DCFG_PFIVL_Pos) /*!< 0x00001800 */
+#define USB_OTG_DCFG_PFIVL USB_OTG_DCFG_PFIVL_Msk /*!< Periodic (micro)frame interval */
+#define USB_OTG_DCFG_PFIVL_0 (0x1UL << USB_OTG_DCFG_PFIVL_Pos) /*!< 0x00000800 */
+#define USB_OTG_DCFG_PFIVL_1 (0x2UL << USB_OTG_DCFG_PFIVL_Pos) /*!< 0x00001000 */
+
+#define USB_OTG_DCFG_PERSCHIVL_Pos (24U)
+#define USB_OTG_DCFG_PERSCHIVL_Msk (0x3UL << USB_OTG_DCFG_PERSCHIVL_Pos) /*!< 0x03000000 */
+#define USB_OTG_DCFG_PERSCHIVL USB_OTG_DCFG_PERSCHIVL_Msk /*!< Periodic scheduling interval */
+#define USB_OTG_DCFG_PERSCHIVL_0 (0x1UL << USB_OTG_DCFG_PERSCHIVL_Pos) /*!< 0x01000000 */
+#define USB_OTG_DCFG_PERSCHIVL_1 (0x2UL << USB_OTG_DCFG_PERSCHIVL_Pos) /*!< 0x02000000 */
+
+/******************** Bit definition for USB_OTG_PCGCR register ********************/
+#define USB_OTG_PCGCR_STPPCLK_Pos (0U)
+#define USB_OTG_PCGCR_STPPCLK_Msk (0x1UL << USB_OTG_PCGCR_STPPCLK_Pos) /*!< 0x00000001 */
+#define USB_OTG_PCGCR_STPPCLK USB_OTG_PCGCR_STPPCLK_Msk /*!< Stop PHY clock */
+#define USB_OTG_PCGCR_GATEHCLK_Pos (1U)
+#define USB_OTG_PCGCR_GATEHCLK_Msk (0x1UL << USB_OTG_PCGCR_GATEHCLK_Pos) /*!< 0x00000002 */
+#define USB_OTG_PCGCR_GATEHCLK USB_OTG_PCGCR_GATEHCLK_Msk /*!< Gate HCLK */
+#define USB_OTG_PCGCR_PHYSUSP_Pos (4U)
+#define USB_OTG_PCGCR_PHYSUSP_Msk (0x1UL << USB_OTG_PCGCR_PHYSUSP_Pos) /*!< 0x00000010 */
+#define USB_OTG_PCGCR_PHYSUSP USB_OTG_PCGCR_PHYSUSP_Msk /*!< PHY suspended */
+
+/******************** Bit definition for USB_OTG_GOTGINT register ********************/
+#define USB_OTG_GOTGINT_SEDET_Pos (2U)
+#define USB_OTG_GOTGINT_SEDET_Msk (0x1UL << USB_OTG_GOTGINT_SEDET_Pos) /*!< 0x00000004 */
+#define USB_OTG_GOTGINT_SEDET USB_OTG_GOTGINT_SEDET_Msk /*!< Session end detected */
+#define USB_OTG_GOTGINT_SRSSCHG_Pos (8U)
+#define USB_OTG_GOTGINT_SRSSCHG_Msk (0x1UL << USB_OTG_GOTGINT_SRSSCHG_Pos) /*!< 0x00000100 */
+#define USB_OTG_GOTGINT_SRSSCHG USB_OTG_GOTGINT_SRSSCHG_Msk /*!< Session request success status change */
+#define USB_OTG_GOTGINT_HNSSCHG_Pos (9U)
+#define USB_OTG_GOTGINT_HNSSCHG_Msk (0x1UL << USB_OTG_GOTGINT_HNSSCHG_Pos) /*!< 0x00000200 */
+#define USB_OTG_GOTGINT_HNSSCHG USB_OTG_GOTGINT_HNSSCHG_Msk /*!< Host negotiation success status change */
+#define USB_OTG_GOTGINT_HNGDET_Pos (17U)
+#define USB_OTG_GOTGINT_HNGDET_Msk (0x1UL << USB_OTG_GOTGINT_HNGDET_Pos) /*!< 0x00020000 */
+#define USB_OTG_GOTGINT_HNGDET USB_OTG_GOTGINT_HNGDET_Msk /*!< Host negotiation detected */
+#define USB_OTG_GOTGINT_ADTOCHG_Pos (18U)
+#define USB_OTG_GOTGINT_ADTOCHG_Msk (0x1UL << USB_OTG_GOTGINT_ADTOCHG_Pos) /*!< 0x00040000 */
+#define USB_OTG_GOTGINT_ADTOCHG USB_OTG_GOTGINT_ADTOCHG_Msk /*!< A-device timeout change */
+#define USB_OTG_GOTGINT_DBCDNE_Pos (19U)
+#define USB_OTG_GOTGINT_DBCDNE_Msk (0x1UL << USB_OTG_GOTGINT_DBCDNE_Pos) /*!< 0x00080000 */
+#define USB_OTG_GOTGINT_DBCDNE USB_OTG_GOTGINT_DBCDNE_Msk /*!< Debounce done */
+
+/******************** Bit definition for USB_OTG_DCTL register ********************/
+#define USB_OTG_DCTL_RWUSIG_Pos (0U)
+#define USB_OTG_DCTL_RWUSIG_Msk (0x1UL << USB_OTG_DCTL_RWUSIG_Pos) /*!< 0x00000001 */
+#define USB_OTG_DCTL_RWUSIG USB_OTG_DCTL_RWUSIG_Msk /*!< Remote wakeup signaling */
+#define USB_OTG_DCTL_SDIS_Pos (1U)
+#define USB_OTG_DCTL_SDIS_Msk (0x1UL << USB_OTG_DCTL_SDIS_Pos) /*!< 0x00000002 */
+#define USB_OTG_DCTL_SDIS USB_OTG_DCTL_SDIS_Msk /*!< Soft disconnect */
+#define USB_OTG_DCTL_GINSTS_Pos (2U)
+#define USB_OTG_DCTL_GINSTS_Msk (0x1UL << USB_OTG_DCTL_GINSTS_Pos) /*!< 0x00000004 */
+#define USB_OTG_DCTL_GINSTS USB_OTG_DCTL_GINSTS_Msk /*!< Global IN NAK status */
+#define USB_OTG_DCTL_GONSTS_Pos (3U)
+#define USB_OTG_DCTL_GONSTS_Msk (0x1UL << USB_OTG_DCTL_GONSTS_Pos) /*!< 0x00000008 */
+#define USB_OTG_DCTL_GONSTS USB_OTG_DCTL_GONSTS_Msk /*!< Global OUT NAK status */
+
+#define USB_OTG_DCTL_TCTL_Pos (4U)
+#define USB_OTG_DCTL_TCTL_Msk (0x7UL << USB_OTG_DCTL_TCTL_Pos) /*!< 0x00000070 */
+#define USB_OTG_DCTL_TCTL USB_OTG_DCTL_TCTL_Msk /*!< Test control */
+#define USB_OTG_DCTL_TCTL_0 (0x1UL << USB_OTG_DCTL_TCTL_Pos) /*!< 0x00000010 */
+#define USB_OTG_DCTL_TCTL_1 (0x2UL << USB_OTG_DCTL_TCTL_Pos) /*!< 0x00000020 */
+#define USB_OTG_DCTL_TCTL_2 (0x4UL << USB_OTG_DCTL_TCTL_Pos) /*!< 0x00000040 */
+#define USB_OTG_DCTL_SGINAK_Pos (7U)
+#define USB_OTG_DCTL_SGINAK_Msk (0x1UL << USB_OTG_DCTL_SGINAK_Pos) /*!< 0x00000080 */
+#define USB_OTG_DCTL_SGINAK USB_OTG_DCTL_SGINAK_Msk /*!< Set global IN NAK */
+#define USB_OTG_DCTL_CGINAK_Pos (8U)
+#define USB_OTG_DCTL_CGINAK_Msk (0x1UL << USB_OTG_DCTL_CGINAK_Pos) /*!< 0x00000100 */
+#define USB_OTG_DCTL_CGINAK USB_OTG_DCTL_CGINAK_Msk /*!< Clear global IN NAK */
+#define USB_OTG_DCTL_SGONAK_Pos (9U)
+#define USB_OTG_DCTL_SGONAK_Msk (0x1UL << USB_OTG_DCTL_SGONAK_Pos) /*!< 0x00000200 */
+#define USB_OTG_DCTL_SGONAK USB_OTG_DCTL_SGONAK_Msk /*!< Set global OUT NAK */
+#define USB_OTG_DCTL_CGONAK_Pos (10U)
+#define USB_OTG_DCTL_CGONAK_Msk (0x1UL << USB_OTG_DCTL_CGONAK_Pos) /*!< 0x00000400 */
+#define USB_OTG_DCTL_CGONAK USB_OTG_DCTL_CGONAK_Msk /*!< Clear global OUT NAK */
+#define USB_OTG_DCTL_POPRGDNE_Pos (11U)
+#define USB_OTG_DCTL_POPRGDNE_Msk (0x1UL << USB_OTG_DCTL_POPRGDNE_Pos) /*!< 0x00000800 */
+#define USB_OTG_DCTL_POPRGDNE USB_OTG_DCTL_POPRGDNE_Msk /*!< Power-on programming done */
+
+/******************** Bit definition for USB_OTG_HFIR register ********************/
+#define USB_OTG_HFIR_FRIVL_Pos (0U)
+#define USB_OTG_HFIR_FRIVL_Msk (0xFFFFUL << USB_OTG_HFIR_FRIVL_Pos) /*!< 0x0000FFFF */
+#define USB_OTG_HFIR_FRIVL USB_OTG_HFIR_FRIVL_Msk /*!< Frame interval */
+
+/******************** Bit definition for USB_OTG_HFNUM register ********************/
+#define USB_OTG_HFNUM_FRNUM_Pos (0U)
+#define USB_OTG_HFNUM_FRNUM_Msk (0xFFFFUL << USB_OTG_HFNUM_FRNUM_Pos) /*!< 0x0000FFFF */
+#define USB_OTG_HFNUM_FRNUM USB_OTG_HFNUM_FRNUM_Msk /*!< Frame number */
+#define USB_OTG_HFNUM_FTREM_Pos (16U)
+#define USB_OTG_HFNUM_FTREM_Msk (0xFFFFUL << USB_OTG_HFNUM_FTREM_Pos) /*!< 0xFFFF0000 */
+#define USB_OTG_HFNUM_FTREM USB_OTG_HFNUM_FTREM_Msk /*!< Frame time remaining */
+
+/******************** Bit definition for USB_OTG_DSTS register ********************/
+#define USB_OTG_DSTS_SUSPSTS_Pos (0U)
+#define USB_OTG_DSTS_SUSPSTS_Msk (0x1UL << USB_OTG_DSTS_SUSPSTS_Pos) /*!< 0x00000001 */
+#define USB_OTG_DSTS_SUSPSTS USB_OTG_DSTS_SUSPSTS_Msk /*!< Suspend status */
+
+#define USB_OTG_DSTS_ENUMSPD_Pos (1U)
+#define USB_OTG_DSTS_ENUMSPD_Msk (0x3UL << USB_OTG_DSTS_ENUMSPD_Pos) /*!< 0x00000006 */
+#define USB_OTG_DSTS_ENUMSPD USB_OTG_DSTS_ENUMSPD_Msk /*!< Enumerated speed */
+#define USB_OTG_DSTS_ENUMSPD_0 (0x1UL << USB_OTG_DSTS_ENUMSPD_Pos) /*!< 0x00000002 */
+#define USB_OTG_DSTS_ENUMSPD_1 (0x2UL << USB_OTG_DSTS_ENUMSPD_Pos) /*!< 0x00000004 */
+#define USB_OTG_DSTS_EERR_Pos (3U)
+#define USB_OTG_DSTS_EERR_Msk (0x1UL << USB_OTG_DSTS_EERR_Pos) /*!< 0x00000008 */
+#define USB_OTG_DSTS_EERR USB_OTG_DSTS_EERR_Msk /*!< Erratic error */
+#define USB_OTG_DSTS_FNSOF_Pos (8U)
+#define USB_OTG_DSTS_FNSOF_Msk (0x3FFFUL << USB_OTG_DSTS_FNSOF_Pos) /*!< 0x003FFF00 */
+#define USB_OTG_DSTS_FNSOF USB_OTG_DSTS_FNSOF_Msk /*!< Frame number of the received SOF */
+
+/******************** Bit definition for USB_OTG_GAHBCFG register ********************/
+#define USB_OTG_GAHBCFG_GINT_Pos (0U)
+#define USB_OTG_GAHBCFG_GINT_Msk (0x1UL << USB_OTG_GAHBCFG_GINT_Pos) /*!< 0x00000001 */
+#define USB_OTG_GAHBCFG_GINT USB_OTG_GAHBCFG_GINT_Msk /*!< Global interrupt mask */
+#define USB_OTG_GAHBCFG_HBSTLEN_Pos (1U)
+#define USB_OTG_GAHBCFG_HBSTLEN_Msk (0xFUL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< 0x0000001E */
+#define USB_OTG_GAHBCFG_HBSTLEN USB_OTG_GAHBCFG_HBSTLEN_Msk /*!< Burst length/type */
+#define USB_OTG_GAHBCFG_HBSTLEN_0 (0x0UL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< Single */
+#define USB_OTG_GAHBCFG_HBSTLEN_1 (0x1UL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< INCR */
+#define USB_OTG_GAHBCFG_HBSTLEN_2 (0x3UL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< INCR4 */
+#define USB_OTG_GAHBCFG_HBSTLEN_3 (0x5UL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< INCR8 */
+#define USB_OTG_GAHBCFG_HBSTLEN_4 (0x7UL << USB_OTG_GAHBCFG_HBSTLEN_Pos) /*!< INCR16 */
+#define USB_OTG_GAHBCFG_DMAEN_Pos (5U)
+#define USB_OTG_GAHBCFG_DMAEN_Msk (0x1UL << USB_OTG_GAHBCFG_DMAEN_Pos) /*!< 0x00000020 */
+#define USB_OTG_GAHBCFG_DMAEN USB_OTG_GAHBCFG_DMAEN_Msk /*!< DMA enable */
+#define USB_OTG_GAHBCFG_TXFELVL_Pos (7U)
+#define USB_OTG_GAHBCFG_TXFELVL_Msk (0x1UL << USB_OTG_GAHBCFG_TXFELVL_Pos) /*!< 0x00000080 */
+#define USB_OTG_GAHBCFG_TXFELVL USB_OTG_GAHBCFG_TXFELVL_Msk /*!< TxFIFO empty level */
+#define USB_OTG_GAHBCFG_PTXFELVL_Pos (8U)
+#define USB_OTG_GAHBCFG_PTXFELVL_Msk (0x1UL << USB_OTG_GAHBCFG_PTXFELVL_Pos) /*!< 0x00000100 */
+#define USB_OTG_GAHBCFG_PTXFELVL USB_OTG_GAHBCFG_PTXFELVL_Msk /*!< Periodic TxFIFO empty level */
+
+/******************** Bit definition for USB_OTG_GUSBCFG register ********************/
+
+#define USB_OTG_GUSBCFG_TOCAL_Pos (0U)
+#define USB_OTG_GUSBCFG_TOCAL_Msk (0x7UL << USB_OTG_GUSBCFG_TOCAL_Pos) /*!< 0x00000007 */
+#define USB_OTG_GUSBCFG_TOCAL USB_OTG_GUSBCFG_TOCAL_Msk /*!< FS timeout calibration */
+#define USB_OTG_GUSBCFG_TOCAL_0 (0x1UL << USB_OTG_GUSBCFG_TOCAL_Pos) /*!< 0x00000001 */
+#define USB_OTG_GUSBCFG_TOCAL_1 (0x2UL << USB_OTG_GUSBCFG_TOCAL_Pos) /*!< 0x00000002 */
+#define USB_OTG_GUSBCFG_TOCAL_2 (0x4UL << USB_OTG_GUSBCFG_TOCAL_Pos) /*!< 0x00000004 */
+#define USB_OTG_GUSBCFG_PHYSEL_Pos (6U)
+#define USB_OTG_GUSBCFG_PHYSEL_Msk (0x1UL << USB_OTG_GUSBCFG_PHYSEL_Pos) /*!< 0x00000040 */
+#define USB_OTG_GUSBCFG_PHYSEL USB_OTG_GUSBCFG_PHYSEL_Msk /*!< USB 2.0 high-speed ULPI PHY or USB 1.1 full-speed serial transceiver select */
+#define USB_OTG_GUSBCFG_SRPCAP_Pos (8U)
+#define USB_OTG_GUSBCFG_SRPCAP_Msk (0x1UL << USB_OTG_GUSBCFG_SRPCAP_Pos) /*!< 0x00000100 */
+#define USB_OTG_GUSBCFG_SRPCAP USB_OTG_GUSBCFG_SRPCAP_Msk /*!< SRP-capable */
+#define USB_OTG_GUSBCFG_HNPCAP_Pos (9U)
+#define USB_OTG_GUSBCFG_HNPCAP_Msk (0x1UL << USB_OTG_GUSBCFG_HNPCAP_Pos) /*!< 0x00000200 */
+#define USB_OTG_GUSBCFG_HNPCAP USB_OTG_GUSBCFG_HNPCAP_Msk /*!< HNP-capable */
+#define USB_OTG_GUSBCFG_TRDT_Pos (10U)
+#define USB_OTG_GUSBCFG_TRDT_Msk (0xFUL << USB_OTG_GUSBCFG_TRDT_Pos) /*!< 0x00003C00 */
+#define USB_OTG_GUSBCFG_TRDT USB_OTG_GUSBCFG_TRDT_Msk /*!< USB turnaround time */
+#define USB_OTG_GUSBCFG_TRDT_0 (0x1UL << USB_OTG_GUSBCFG_TRDT_Pos) /*!< 0x00000400 */
+#define USB_OTG_GUSBCFG_TRDT_1 (0x2UL << USB_OTG_GUSBCFG_TRDT_Pos) /*!< 0x00000800 */
+#define USB_OTG_GUSBCFG_TRDT_2 (0x4UL << USB_OTG_GUSBCFG_TRDT_Pos) /*!< 0x00001000 */
+#define USB_OTG_GUSBCFG_TRDT_3 (0x8UL << USB_OTG_GUSBCFG_TRDT_Pos) /*!< 0x00002000 */
+#define USB_OTG_GUSBCFG_PHYLPCS_Pos (15U)
+#define USB_OTG_GUSBCFG_PHYLPCS_Msk (0x1UL << USB_OTG_GUSBCFG_PHYLPCS_Pos) /*!< 0x00008000 */
+#define USB_OTG_GUSBCFG_PHYLPCS USB_OTG_GUSBCFG_PHYLPCS_Msk /*!< PHY Low-power clock select */
+#define USB_OTG_GUSBCFG_ULPIFSLS_Pos (17U)
+#define USB_OTG_GUSBCFG_ULPIFSLS_Msk (0x1UL << USB_OTG_GUSBCFG_ULPIFSLS_Pos) /*!< 0x00020000 */
+#define USB_OTG_GUSBCFG_ULPIFSLS USB_OTG_GUSBCFG_ULPIFSLS_Msk /*!< ULPI FS/LS select */
+#define USB_OTG_GUSBCFG_ULPIAR_Pos (18U)
+#define USB_OTG_GUSBCFG_ULPIAR_Msk (0x1UL << USB_OTG_GUSBCFG_ULPIAR_Pos) /*!< 0x00040000 */
+#define USB_OTG_GUSBCFG_ULPIAR USB_OTG_GUSBCFG_ULPIAR_Msk /*!< ULPI Auto-resume */
+#define USB_OTG_GUSBCFG_ULPICSM_Pos (19U)
+#define USB_OTG_GUSBCFG_ULPICSM_Msk (0x1UL << USB_OTG_GUSBCFG_ULPICSM_Pos) /*!< 0x00080000 */
+#define USB_OTG_GUSBCFG_ULPICSM USB_OTG_GUSBCFG_ULPICSM_Msk /*!< ULPI Clock SuspendM */
+#define USB_OTG_GUSBCFG_ULPIEVBUSD_Pos (20U)
+#define USB_OTG_GUSBCFG_ULPIEVBUSD_Msk (0x1UL << USB_OTG_GUSBCFG_ULPIEVBUSD_Pos) /*!< 0x00100000 */
+#define USB_OTG_GUSBCFG_ULPIEVBUSD USB_OTG_GUSBCFG_ULPIEVBUSD_Msk /*!< ULPI External VBUS Drive */
+#define USB_OTG_GUSBCFG_ULPIEVBUSI_Pos (21U)
+#define USB_OTG_GUSBCFG_ULPIEVBUSI_Msk (0x1UL << USB_OTG_GUSBCFG_ULPIEVBUSI_Pos) /*!< 0x00200000 */
+#define USB_OTG_GUSBCFG_ULPIEVBUSI USB_OTG_GUSBCFG_ULPIEVBUSI_Msk /*!< ULPI external VBUS indicator */
+#define USB_OTG_GUSBCFG_TSDPS_Pos (22U)
+#define USB_OTG_GUSBCFG_TSDPS_Msk (0x1UL << USB_OTG_GUSBCFG_TSDPS_Pos) /*!< 0x00400000 */
+#define USB_OTG_GUSBCFG_TSDPS USB_OTG_GUSBCFG_TSDPS_Msk /*!< TermSel DLine pulsing selection */
+#define USB_OTG_GUSBCFG_PCCI_Pos (23U)
+#define USB_OTG_GUSBCFG_PCCI_Msk (0x1UL << USB_OTG_GUSBCFG_PCCI_Pos) /*!< 0x00800000 */
+#define USB_OTG_GUSBCFG_PCCI USB_OTG_GUSBCFG_PCCI_Msk /*!< Indicator complement */
+#define USB_OTG_GUSBCFG_PTCI_Pos (24U)
+#define USB_OTG_GUSBCFG_PTCI_Msk (0x1UL << USB_OTG_GUSBCFG_PTCI_Pos) /*!< 0x01000000 */
+#define USB_OTG_GUSBCFG_PTCI USB_OTG_GUSBCFG_PTCI_Msk /*!< Indicator pass through */
+#define USB_OTG_GUSBCFG_ULPIIPD_Pos (25U)
+#define USB_OTG_GUSBCFG_ULPIIPD_Msk (0x1UL << USB_OTG_GUSBCFG_ULPIIPD_Pos) /*!< 0x02000000 */
+#define USB_OTG_GUSBCFG_ULPIIPD USB_OTG_GUSBCFG_ULPIIPD_Msk /*!< ULPI interface protect disable */
+#define USB_OTG_GUSBCFG_FHMOD_Pos (29U)
+#define USB_OTG_GUSBCFG_FHMOD_Msk (0x1UL << USB_OTG_GUSBCFG_FHMOD_Pos) /*!< 0x20000000 */
+#define USB_OTG_GUSBCFG_FHMOD USB_OTG_GUSBCFG_FHMOD_Msk /*!< Forced host mode */
+#define USB_OTG_GUSBCFG_FDMOD_Pos (30U)
+#define USB_OTG_GUSBCFG_FDMOD_Msk (0x1UL << USB_OTG_GUSBCFG_FDMOD_Pos) /*!< 0x40000000 */
+#define USB_OTG_GUSBCFG_FDMOD USB_OTG_GUSBCFG_FDMOD_Msk /*!< Forced peripheral mode */
+#define USB_OTG_GUSBCFG_CTXPKT_Pos (31U)
+#define USB_OTG_GUSBCFG_CTXPKT_Msk (0x1UL << USB_OTG_GUSBCFG_CTXPKT_Pos) /*!< 0x80000000 */
+#define USB_OTG_GUSBCFG_CTXPKT USB_OTG_GUSBCFG_CTXPKT_Msk /*!< Corrupt Tx packet */
+
+/******************** Bit definition for USB_OTG_GRSTCTL register ********************/
+#define USB_OTG_GRSTCTL_CSRST_Pos (0U)
+#define USB_OTG_GRSTCTL_CSRST_Msk (0x1UL << USB_OTG_GRSTCTL_CSRST_Pos) /*!< 0x00000001 */
+#define USB_OTG_GRSTCTL_CSRST USB_OTG_GRSTCTL_CSRST_Msk /*!< Core soft reset */
+#define USB_OTG_GRSTCTL_HSRST_Pos (1U)
+#define USB_OTG_GRSTCTL_HSRST_Msk (0x1UL << USB_OTG_GRSTCTL_HSRST_Pos) /*!< 0x00000002 */
+#define USB_OTG_GRSTCTL_HSRST USB_OTG_GRSTCTL_HSRST_Msk /*!< HCLK soft reset */
+#define USB_OTG_GRSTCTL_FCRST_Pos (2U)
+#define USB_OTG_GRSTCTL_FCRST_Msk (0x1UL << USB_OTG_GRSTCTL_FCRST_Pos) /*!< 0x00000004 */
+#define USB_OTG_GRSTCTL_FCRST USB_OTG_GRSTCTL_FCRST_Msk /*!< Host frame counter reset */
+#define USB_OTG_GRSTCTL_RXFFLSH_Pos (4U)
+#define USB_OTG_GRSTCTL_RXFFLSH_Msk (0x1UL << USB_OTG_GRSTCTL_RXFFLSH_Pos) /*!< 0x00000010 */
+#define USB_OTG_GRSTCTL_RXFFLSH USB_OTG_GRSTCTL_RXFFLSH_Msk /*!< RxFIFO flush */
+#define USB_OTG_GRSTCTL_TXFFLSH_Pos (5U)
+#define USB_OTG_GRSTCTL_TXFFLSH_Msk (0x1UL << USB_OTG_GRSTCTL_TXFFLSH_Pos) /*!< 0x00000020 */
+#define USB_OTG_GRSTCTL_TXFFLSH USB_OTG_GRSTCTL_TXFFLSH_Msk /*!< TxFIFO flush */
+
+
+#define USB_OTG_GRSTCTL_TXFNUM_Pos (6U)
+#define USB_OTG_GRSTCTL_TXFNUM_Msk (0x1FUL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x000007C0 */
+#define USB_OTG_GRSTCTL_TXFNUM USB_OTG_GRSTCTL_TXFNUM_Msk /*!< TxFIFO number */
+#define USB_OTG_GRSTCTL_TXFNUM_0 (0x01UL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x00000040 */
+#define USB_OTG_GRSTCTL_TXFNUM_1 (0x02UL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x00000080 */
+#define USB_OTG_GRSTCTL_TXFNUM_2 (0x04UL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x00000100 */
+#define USB_OTG_GRSTCTL_TXFNUM_3 (0x08UL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x00000200 */
+#define USB_OTG_GRSTCTL_TXFNUM_4 (0x10UL << USB_OTG_GRSTCTL_TXFNUM_Pos) /*!< 0x00000400 */
+#define USB_OTG_GRSTCTL_DMAREQ_Pos (30U)
+#define USB_OTG_GRSTCTL_DMAREQ_Msk (0x1UL << USB_OTG_GRSTCTL_DMAREQ_Pos) /*!< 0x40000000 */
+#define USB_OTG_GRSTCTL_DMAREQ USB_OTG_GRSTCTL_DMAREQ_Msk /*!< DMA request signal */
+#define USB_OTG_GRSTCTL_AHBIDL_Pos (31U)
+#define USB_OTG_GRSTCTL_AHBIDL_Msk (0x1UL << USB_OTG_GRSTCTL_AHBIDL_Pos) /*!< 0x80000000 */
+#define USB_OTG_GRSTCTL_AHBIDL USB_OTG_GRSTCTL_AHBIDL_Msk /*!< AHB master idle */
+
+/******************** Bit definition for USB_OTG_DIEPMSK register ********************/
+#define USB_OTG_DIEPMSK_XFRCM_Pos (0U)
+#define USB_OTG_DIEPMSK_XFRCM_Msk (0x1UL << USB_OTG_DIEPMSK_XFRCM_Pos) /*!< 0x00000001 */
+#define USB_OTG_DIEPMSK_XFRCM USB_OTG_DIEPMSK_XFRCM_Msk /*!< Transfer completed interrupt mask */
+#define USB_OTG_DIEPMSK_EPDM_Pos (1U)
+#define USB_OTG_DIEPMSK_EPDM_Msk (0x1UL << USB_OTG_DIEPMSK_EPDM_Pos) /*!< 0x00000002 */
+#define USB_OTG_DIEPMSK_EPDM USB_OTG_DIEPMSK_EPDM_Msk /*!< Endpoint disabled interrupt mask */
+#define USB_OTG_DIEPMSK_TOM_Pos (3U)
+#define USB_OTG_DIEPMSK_TOM_Msk (0x1UL << USB_OTG_DIEPMSK_TOM_Pos) /*!< 0x00000008 */
+#define USB_OTG_DIEPMSK_TOM USB_OTG_DIEPMSK_TOM_Msk /*!< Timeout condition mask (nonisochronous endpoints) */
+#define USB_OTG_DIEPMSK_ITTXFEMSK_Pos (4U)
+#define USB_OTG_DIEPMSK_ITTXFEMSK_Msk (0x1UL << USB_OTG_DIEPMSK_ITTXFEMSK_Pos) /*!< 0x00000010 */
+#define USB_OTG_DIEPMSK_ITTXFEMSK USB_OTG_DIEPMSK_ITTXFEMSK_Msk /*!< IN token received when TxFIFO empty mask */
+#define USB_OTG_DIEPMSK_INEPNMM_Pos (5U)
+#define USB_OTG_DIEPMSK_INEPNMM_Msk (0x1UL << USB_OTG_DIEPMSK_INEPNMM_Pos) /*!< 0x00000020 */
+#define USB_OTG_DIEPMSK_INEPNMM USB_OTG_DIEPMSK_INEPNMM_Msk /*!< IN token received with EP mismatch mask */
+#define USB_OTG_DIEPMSK_INEPNEM_Pos (6U)
+#define USB_OTG_DIEPMSK_INEPNEM_Msk (0x1UL << USB_OTG_DIEPMSK_INEPNEM_Pos) /*!< 0x00000040 */
+#define USB_OTG_DIEPMSK_INEPNEM USB_OTG_DIEPMSK_INEPNEM_Msk /*!< IN endpoint NAK effective mask */
+#define USB_OTG_DIEPMSK_TXFURM_Pos (8U)
+#define USB_OTG_DIEPMSK_TXFURM_Msk (0x1UL << USB_OTG_DIEPMSK_TXFURM_Pos) /*!< 0x00000100 */
+#define USB_OTG_DIEPMSK_TXFURM USB_OTG_DIEPMSK_TXFURM_Msk /*!< FIFO underrun mask */
+#define USB_OTG_DIEPMSK_BIM_Pos (9U)
+#define USB_OTG_DIEPMSK_BIM_Msk (0x1UL << USB_OTG_DIEPMSK_BIM_Pos) /*!< 0x00000200 */
+#define USB_OTG_DIEPMSK_BIM USB_OTG_DIEPMSK_BIM_Msk /*!< BNA interrupt mask */
+
+/******************** Bit definition for USB_OTG_HPTXSTS register ********************/
+#define USB_OTG_HPTXSTS_PTXFSAVL_Pos (0U)
+#define USB_OTG_HPTXSTS_PTXFSAVL_Msk (0xFFFFUL << USB_OTG_HPTXSTS_PTXFSAVL_Pos) /*!< 0x0000FFFF */
+#define USB_OTG_HPTXSTS_PTXFSAVL USB_OTG_HPTXSTS_PTXFSAVL_Msk /*!< Periodic transmit data FIFO space available */
+#define USB_OTG_HPTXSTS_PTXQSAV_Pos (16U)
+#define USB_OTG_HPTXSTS_PTXQSAV_Msk (0xFFUL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00FF0000 */
+#define USB_OTG_HPTXSTS_PTXQSAV USB_OTG_HPTXSTS_PTXQSAV_Msk /*!< Periodic transmit request queue space available */
+#define USB_OTG_HPTXSTS_PTXQSAV_0 (0x01UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00010000 */
+#define USB_OTG_HPTXSTS_PTXQSAV_1 (0x02UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00020000 */
+#define USB_OTG_HPTXSTS_PTXQSAV_2 (0x04UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00040000 */
+#define USB_OTG_HPTXSTS_PTXQSAV_3 (0x08UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00080000 */
+#define USB_OTG_HPTXSTS_PTXQSAV_4 (0x10UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00100000 */
+#define USB_OTG_HPTXSTS_PTXQSAV_5 (0x20UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00200000 */
+#define USB_OTG_HPTXSTS_PTXQSAV_6 (0x40UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00400000 */
+#define USB_OTG_HPTXSTS_PTXQSAV_7 (0x80UL << USB_OTG_HPTXSTS_PTXQSAV_Pos) /*!< 0x00800000 */
+
+#define USB_OTG_HPTXSTS_PTXQTOP_Pos (24U)
+#define USB_OTG_HPTXSTS_PTXQTOP_Msk (0xFFUL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0xFF000000 */
+#define USB_OTG_HPTXSTS_PTXQTOP USB_OTG_HPTXSTS_PTXQTOP_Msk /*!< Top of the periodic transmit request queue */
+#define USB_OTG_HPTXSTS_PTXQTOP_0 (0x01UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x01000000 */
+#define USB_OTG_HPTXSTS_PTXQTOP_1 (0x02UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x02000000 */
+#define USB_OTG_HPTXSTS_PTXQTOP_2 (0x04UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x04000000 */
+#define USB_OTG_HPTXSTS_PTXQTOP_3 (0x08UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x08000000 */
+#define USB_OTG_HPTXSTS_PTXQTOP_4 (0x10UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x10000000 */
+#define USB_OTG_HPTXSTS_PTXQTOP_5 (0x20UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x20000000 */
+#define USB_OTG_HPTXSTS_PTXQTOP_6 (0x40UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x40000000 */
+#define USB_OTG_HPTXSTS_PTXQTOP_7 (0x80UL << USB_OTG_HPTXSTS_PTXQTOP_Pos) /*!< 0x80000000 */
+
+/******************** Bit definition for USB_OTG_HAINT register ********************/
+#define USB_OTG_HAINT_HAINT_Pos (0U)
+#define USB_OTG_HAINT_HAINT_Msk (0xFFFFUL << USB_OTG_HAINT_HAINT_Pos) /*!< 0x0000FFFF */
+#define USB_OTG_HAINT_HAINT USB_OTG_HAINT_HAINT_Msk /*!< Channel interrupts */
+
+/******************** Bit definition for USB_OTG_DOEPMSK register ********************/
+#define USB_OTG_DOEPMSK_XFRCM_Pos (0U)
+#define USB_OTG_DOEPMSK_XFRCM_Msk (0x1UL << USB_OTG_DOEPMSK_XFRCM_Pos) /*!< 0x00000001 */
+#define USB_OTG_DOEPMSK_XFRCM USB_OTG_DOEPMSK_XFRCM_Msk /*!< Transfer completed interrupt mask */
+#define USB_OTG_DOEPMSK_EPDM_Pos (1U)
+#define USB_OTG_DOEPMSK_EPDM_Msk (0x1UL << USB_OTG_DOEPMSK_EPDM_Pos) /*!< 0x00000002 */
+#define USB_OTG_DOEPMSK_EPDM USB_OTG_DOEPMSK_EPDM_Msk /*!< Endpoint disabled interrupt mask */
+#define USB_OTG_DOEPMSK_AHBERRM_Pos (2U)
+#define USB_OTG_DOEPMSK_AHBERRM_Msk (0x1UL << USB_OTG_DOEPMSK_AHBERRM_Pos) /*!< 0x00000004 */
+#define USB_OTG_DOEPMSK_AHBERRM USB_OTG_DOEPMSK_AHBERRM_Msk /*!< OUT transaction AHB Error interrupt mask */
+#define USB_OTG_DOEPMSK_STUPM_Pos (3U)
+#define USB_OTG_DOEPMSK_STUPM_Msk (0x1UL << USB_OTG_DOEPMSK_STUPM_Pos) /*!< 0x00000008 */
+#define USB_OTG_DOEPMSK_STUPM USB_OTG_DOEPMSK_STUPM_Msk /*!< SETUP phase done mask */
+#define USB_OTG_DOEPMSK_OTEPDM_Pos (4U)
+#define USB_OTG_DOEPMSK_OTEPDM_Msk (0x1UL << USB_OTG_DOEPMSK_OTEPDM_Pos) /*!< 0x00000010 */
+#define USB_OTG_DOEPMSK_OTEPDM USB_OTG_DOEPMSK_OTEPDM_Msk /*!< OUT token received when endpoint disabled mask */
+#define USB_OTG_DOEPMSK_OTEPSPRM_Pos (5U)
+#define USB_OTG_DOEPMSK_OTEPSPRM_Msk (0x1UL << USB_OTG_DOEPMSK_OTEPSPRM_Pos) /*!< 0x00000020 */
+#define USB_OTG_DOEPMSK_OTEPSPRM USB_OTG_DOEPMSK_OTEPSPRM_Msk /*!< Status Phase Received mask */
+#define USB_OTG_DOEPMSK_B2BSTUP_Pos (6U)
+#define USB_OTG_DOEPMSK_B2BSTUP_Msk (0x1UL << USB_OTG_DOEPMSK_B2BSTUP_Pos) /*!< 0x00000040 */
+#define USB_OTG_DOEPMSK_B2BSTUP USB_OTG_DOEPMSK_B2BSTUP_Msk /*!< Back-to-back SETUP packets received mask */
+#define USB_OTG_DOEPMSK_OPEM_Pos (8U)
+#define USB_OTG_DOEPMSK_OPEM_Msk (0x1UL << USB_OTG_DOEPMSK_OPEM_Pos) /*!< 0x00000100 */
+#define USB_OTG_DOEPMSK_OPEM USB_OTG_DOEPMSK_OPEM_Msk /*!< OUT packet error mask */
+#define USB_OTG_DOEPMSK_BOIM_Pos (9U)
+#define USB_OTG_DOEPMSK_BOIM_Msk (0x1UL << USB_OTG_DOEPMSK_BOIM_Pos) /*!< 0x00000200 */
+#define USB_OTG_DOEPMSK_BOIM USB_OTG_DOEPMSK_BOIM_Msk /*!< BNA interrupt mask */
+#define USB_OTG_DOEPMSK_BERRM_Pos (12U)
+#define USB_OTG_DOEPMSK_BERRM_Msk (0x1UL << USB_OTG_DOEPMSK_BERRM_Pos) /*!< 0x00001000 */
+#define USB_OTG_DOEPMSK_BERRM USB_OTG_DOEPMSK_BERRM_Msk /*!< Babble error interrupt mask */
+#define USB_OTG_DOEPMSK_NAKM_Pos (13U)
+#define USB_OTG_DOEPMSK_NAKM_Msk (0x1UL << USB_OTG_DOEPMSK_NAKM_Pos) /*!< 0x00002000 */
+#define USB_OTG_DOEPMSK_NAKM USB_OTG_DOEPMSK_NAKM_Msk /*!< OUT Packet NAK interrupt mask */
+#define USB_OTG_DOEPMSK_NYETM_Pos (14U)
+#define USB_OTG_DOEPMSK_NYETM_Msk (0x1UL << USB_OTG_DOEPMSK_NYETM_Pos) /*!< 0x00004000 */
+#define USB_OTG_DOEPMSK_NYETM USB_OTG_DOEPMSK_NYETM_Msk /*!< NYET interrupt mask */
+/******************** Bit definition for USB_OTG_GINTSTS register ********************/
+#define USB_OTG_GINTSTS_CMOD_Pos (0U)
+#define USB_OTG_GINTSTS_CMOD_Msk (0x1UL << USB_OTG_GINTSTS_CMOD_Pos) /*!< 0x00000001 */
+#define USB_OTG_GINTSTS_CMOD USB_OTG_GINTSTS_CMOD_Msk /*!< Current mode of operation */
+#define USB_OTG_GINTSTS_MMIS_Pos (1U)
+#define USB_OTG_GINTSTS_MMIS_Msk (0x1UL << USB_OTG_GINTSTS_MMIS_Pos) /*!< 0x00000002 */
+#define USB_OTG_GINTSTS_MMIS USB_OTG_GINTSTS_MMIS_Msk /*!< Mode mismatch interrupt */
+#define USB_OTG_GINTSTS_OTGINT_Pos (2U)
+#define USB_OTG_GINTSTS_OTGINT_Msk (0x1UL << USB_OTG_GINTSTS_OTGINT_Pos) /*!< 0x00000004 */
+#define USB_OTG_GINTSTS_OTGINT USB_OTG_GINTSTS_OTGINT_Msk /*!< OTG interrupt */
+#define USB_OTG_GINTSTS_SOF_Pos (3U)
+#define USB_OTG_GINTSTS_SOF_Msk (0x1UL << USB_OTG_GINTSTS_SOF_Pos) /*!< 0x00000008 */
+#define USB_OTG_GINTSTS_SOF USB_OTG_GINTSTS_SOF_Msk /*!< Start of frame */
+#define USB_OTG_GINTSTS_RXFLVL_Pos (4U)
+#define USB_OTG_GINTSTS_RXFLVL_Msk (0x1UL << USB_OTG_GINTSTS_RXFLVL_Pos) /*!< 0x00000010 */
+#define USB_OTG_GINTSTS_RXFLVL USB_OTG_GINTSTS_RXFLVL_Msk /*!< RxFIFO nonempty */
+#define USB_OTG_GINTSTS_NPTXFE_Pos (5U)
+#define USB_OTG_GINTSTS_NPTXFE_Msk (0x1UL << USB_OTG_GINTSTS_NPTXFE_Pos) /*!< 0x00000020 */
+#define USB_OTG_GINTSTS_NPTXFE USB_OTG_GINTSTS_NPTXFE_Msk /*!< Nonperiodic TxFIFO empty */
+#define USB_OTG_GINTSTS_GINAKEFF_Pos (6U)
+#define USB_OTG_GINTSTS_GINAKEFF_Msk (0x1UL << USB_OTG_GINTSTS_GINAKEFF_Pos) /*!< 0x00000040 */
+#define USB_OTG_GINTSTS_GINAKEFF USB_OTG_GINTSTS_GINAKEFF_Msk /*!< Global IN nonperiodic NAK effective */
+#define USB_OTG_GINTSTS_BOUTNAKEFF_Pos (7U)
+#define USB_OTG_GINTSTS_BOUTNAKEFF_Msk (0x1UL << USB_OTG_GINTSTS_BOUTNAKEFF_Pos) /*!< 0x00000080 */
+#define USB_OTG_GINTSTS_BOUTNAKEFF USB_OTG_GINTSTS_BOUTNAKEFF_Msk /*!< Global OUT NAK effective */
+#define USB_OTG_GINTSTS_ESUSP_Pos (10U)
+#define USB_OTG_GINTSTS_ESUSP_Msk (0x1UL << USB_OTG_GINTSTS_ESUSP_Pos) /*!< 0x00000400 */
+#define USB_OTG_GINTSTS_ESUSP USB_OTG_GINTSTS_ESUSP_Msk /*!< Early suspend */
+#define USB_OTG_GINTSTS_USBSUSP_Pos (11U)
+#define USB_OTG_GINTSTS_USBSUSP_Msk (0x1UL << USB_OTG_GINTSTS_USBSUSP_Pos) /*!< 0x00000800 */
+#define USB_OTG_GINTSTS_USBSUSP USB_OTG_GINTSTS_USBSUSP_Msk /*!< USB suspend */
+#define USB_OTG_GINTSTS_USBRST_Pos (12U)
+#define USB_OTG_GINTSTS_USBRST_Msk (0x1UL << USB_OTG_GINTSTS_USBRST_Pos) /*!< 0x00001000 */
+#define USB_OTG_GINTSTS_USBRST USB_OTG_GINTSTS_USBRST_Msk /*!< USB reset */
+#define USB_OTG_GINTSTS_ENUMDNE_Pos (13U)
+#define USB_OTG_GINTSTS_ENUMDNE_Msk (0x1UL << USB_OTG_GINTSTS_ENUMDNE_Pos) /*!< 0x00002000 */
+#define USB_OTG_GINTSTS_ENUMDNE USB_OTG_GINTSTS_ENUMDNE_Msk /*!< Enumeration done */
+#define USB_OTG_GINTSTS_ISOODRP_Pos (14U)
+#define USB_OTG_GINTSTS_ISOODRP_Msk (0x1UL << USB_OTG_GINTSTS_ISOODRP_Pos) /*!< 0x00004000 */
+#define USB_OTG_GINTSTS_ISOODRP USB_OTG_GINTSTS_ISOODRP_Msk /*!< Isochronous OUT packet dropped interrupt */
+#define USB_OTG_GINTSTS_EOPF_Pos (15U)
+#define USB_OTG_GINTSTS_EOPF_Msk (0x1UL << USB_OTG_GINTSTS_EOPF_Pos) /*!< 0x00008000 */
+#define USB_OTG_GINTSTS_EOPF USB_OTG_GINTSTS_EOPF_Msk /*!< End of periodic frame interrupt */
+#define USB_OTG_GINTSTS_IEPINT_Pos (18U)
+#define USB_OTG_GINTSTS_IEPINT_Msk (0x1UL << USB_OTG_GINTSTS_IEPINT_Pos) /*!< 0x00040000 */
+#define USB_OTG_GINTSTS_IEPINT USB_OTG_GINTSTS_IEPINT_Msk /*!< IN endpoint interrupt */
+#define USB_OTG_GINTSTS_OEPINT_Pos (19U)
+#define USB_OTG_GINTSTS_OEPINT_Msk (0x1UL << USB_OTG_GINTSTS_OEPINT_Pos) /*!< 0x00080000 */
+#define USB_OTG_GINTSTS_OEPINT USB_OTG_GINTSTS_OEPINT_Msk /*!< OUT endpoint interrupt */
+#define USB_OTG_GINTSTS_IISOIXFR_Pos (20U)
+#define USB_OTG_GINTSTS_IISOIXFR_Msk (0x1UL << USB_OTG_GINTSTS_IISOIXFR_Pos) /*!< 0x00100000 */
+#define USB_OTG_GINTSTS_IISOIXFR USB_OTG_GINTSTS_IISOIXFR_Msk /*!< Incomplete isochronous IN transfer */
+#define USB_OTG_GINTSTS_PXFR_INCOMPISOOUT_Pos (21U)
+#define USB_OTG_GINTSTS_PXFR_INCOMPISOOUT_Msk (0x1UL << USB_OTG_GINTSTS_PXFR_INCOMPISOOUT_Pos) /*!< 0x00200000 */
+#define USB_OTG_GINTSTS_PXFR_INCOMPISOOUT USB_OTG_GINTSTS_PXFR_INCOMPISOOUT_Msk /*!< Incomplete periodic transfer */
+#define USB_OTG_GINTSTS_DATAFSUSP_Pos (22U)
+#define USB_OTG_GINTSTS_DATAFSUSP_Msk (0x1UL << USB_OTG_GINTSTS_DATAFSUSP_Pos) /*!< 0x00400000 */
+#define USB_OTG_GINTSTS_DATAFSUSP USB_OTG_GINTSTS_DATAFSUSP_Msk /*!< Data fetch suspended */
+#define USB_OTG_GINTSTS_HPRTINT_Pos (24U)
+#define USB_OTG_GINTSTS_HPRTINT_Msk (0x1UL << USB_OTG_GINTSTS_HPRTINT_Pos) /*!< 0x01000000 */
+#define USB_OTG_GINTSTS_HPRTINT USB_OTG_GINTSTS_HPRTINT_Msk /*!< Host port interrupt */
+#define USB_OTG_GINTSTS_HCINT_Pos (25U)
+#define USB_OTG_GINTSTS_HCINT_Msk (0x1UL << USB_OTG_GINTSTS_HCINT_Pos) /*!< 0x02000000 */
+#define USB_OTG_GINTSTS_HCINT USB_OTG_GINTSTS_HCINT_Msk /*!< Host channels interrupt */
+#define USB_OTG_GINTSTS_PTXFE_Pos (26U)
+#define USB_OTG_GINTSTS_PTXFE_Msk (0x1UL << USB_OTG_GINTSTS_PTXFE_Pos) /*!< 0x04000000 */
+#define USB_OTG_GINTSTS_PTXFE USB_OTG_GINTSTS_PTXFE_Msk /*!< Periodic TxFIFO empty */
+#define USB_OTG_GINTSTS_CIDSCHG_Pos (28U)
+#define USB_OTG_GINTSTS_CIDSCHG_Msk (0x1UL << USB_OTG_GINTSTS_CIDSCHG_Pos) /*!< 0x10000000 */
+#define USB_OTG_GINTSTS_CIDSCHG USB_OTG_GINTSTS_CIDSCHG_Msk /*!< Connector ID status change */
+#define USB_OTG_GINTSTS_DISCINT_Pos (29U)
+#define USB_OTG_GINTSTS_DISCINT_Msk (0x1UL << USB_OTG_GINTSTS_DISCINT_Pos) /*!< 0x20000000 */
+#define USB_OTG_GINTSTS_DISCINT USB_OTG_GINTSTS_DISCINT_Msk /*!< Disconnect detected interrupt */
+#define USB_OTG_GINTSTS_SRQINT_Pos (30U)
+#define USB_OTG_GINTSTS_SRQINT_Msk (0x1UL << USB_OTG_GINTSTS_SRQINT_Pos) /*!< 0x40000000 */
+#define USB_OTG_GINTSTS_SRQINT USB_OTG_GINTSTS_SRQINT_Msk /*!< Session request/new session detected interrupt */
+#define USB_OTG_GINTSTS_WKUINT_Pos (31U)
+#define USB_OTG_GINTSTS_WKUINT_Msk (0x1UL << USB_OTG_GINTSTS_WKUINT_Pos) /*!< 0x80000000 */
+#define USB_OTG_GINTSTS_WKUINT USB_OTG_GINTSTS_WKUINT_Msk /*!< Resume/remote wakeup detected interrupt */
+
+/******************** Bit definition for USB_OTG_GINTMSK register ********************/
+#define USB_OTG_GINTMSK_MMISM_Pos (1U)
+#define USB_OTG_GINTMSK_MMISM_Msk (0x1UL << USB_OTG_GINTMSK_MMISM_Pos) /*!< 0x00000002 */
+#define USB_OTG_GINTMSK_MMISM USB_OTG_GINTMSK_MMISM_Msk /*!< Mode mismatch interrupt mask */
+#define USB_OTG_GINTMSK_OTGINT_Pos (2U)
+#define USB_OTG_GINTMSK_OTGINT_Msk (0x1UL << USB_OTG_GINTMSK_OTGINT_Pos) /*!< 0x00000004 */
+#define USB_OTG_GINTMSK_OTGINT USB_OTG_GINTMSK_OTGINT_Msk /*!< OTG interrupt mask */
+#define USB_OTG_GINTMSK_SOFM_Pos (3U)
+#define USB_OTG_GINTMSK_SOFM_Msk (0x1UL << USB_OTG_GINTMSK_SOFM_Pos) /*!< 0x00000008 */
+#define USB_OTG_GINTMSK_SOFM USB_OTG_GINTMSK_SOFM_Msk /*!< Start of frame mask */
+#define USB_OTG_GINTMSK_RXFLVLM_Pos (4U)
+#define USB_OTG_GINTMSK_RXFLVLM_Msk (0x1UL << USB_OTG_GINTMSK_RXFLVLM_Pos) /*!< 0x00000010 */
+#define USB_OTG_GINTMSK_RXFLVLM USB_OTG_GINTMSK_RXFLVLM_Msk /*!< Receive FIFO nonempty mask */
+#define USB_OTG_GINTMSK_NPTXFEM_Pos (5U)
+#define USB_OTG_GINTMSK_NPTXFEM_Msk (0x1UL << USB_OTG_GINTMSK_NPTXFEM_Pos) /*!< 0x00000020 */
+#define USB_OTG_GINTMSK_NPTXFEM USB_OTG_GINTMSK_NPTXFEM_Msk /*!< Nonperiodic TxFIFO empty mask */
+#define USB_OTG_GINTMSK_GINAKEFFM_Pos (6U)
+#define USB_OTG_GINTMSK_GINAKEFFM_Msk (0x1UL << USB_OTG_GINTMSK_GINAKEFFM_Pos) /*!< 0x00000040 */
+#define USB_OTG_GINTMSK_GINAKEFFM USB_OTG_GINTMSK_GINAKEFFM_Msk /*!< Global nonperiodic IN NAK effective mask */
+#define USB_OTG_GINTMSK_GONAKEFFM_Pos (7U)
+#define USB_OTG_GINTMSK_GONAKEFFM_Msk (0x1UL << USB_OTG_GINTMSK_GONAKEFFM_Pos) /*!< 0x00000080 */
+#define USB_OTG_GINTMSK_GONAKEFFM USB_OTG_GINTMSK_GONAKEFFM_Msk /*!< Global OUT NAK effective mask */
+#define USB_OTG_GINTMSK_ESUSPM_Pos (10U)
+#define USB_OTG_GINTMSK_ESUSPM_Msk (0x1UL << USB_OTG_GINTMSK_ESUSPM_Pos) /*!< 0x00000400 */
+#define USB_OTG_GINTMSK_ESUSPM USB_OTG_GINTMSK_ESUSPM_Msk /*!< Early suspend mask */
+#define USB_OTG_GINTMSK_USBSUSPM_Pos (11U)
+#define USB_OTG_GINTMSK_USBSUSPM_Msk (0x1UL << USB_OTG_GINTMSK_USBSUSPM_Pos) /*!< 0x00000800 */
+#define USB_OTG_GINTMSK_USBSUSPM USB_OTG_GINTMSK_USBSUSPM_Msk /*!< USB suspend mask */
+#define USB_OTG_GINTMSK_USBRST_Pos (12U)
+#define USB_OTG_GINTMSK_USBRST_Msk (0x1UL << USB_OTG_GINTMSK_USBRST_Pos) /*!< 0x00001000 */
+#define USB_OTG_GINTMSK_USBRST USB_OTG_GINTMSK_USBRST_Msk /*!< USB reset mask */
+#define USB_OTG_GINTMSK_ENUMDNEM_Pos (13U)
+#define USB_OTG_GINTMSK_ENUMDNEM_Msk (0x1UL << USB_OTG_GINTMSK_ENUMDNEM_Pos) /*!< 0x00002000 */
+#define USB_OTG_GINTMSK_ENUMDNEM USB_OTG_GINTMSK_ENUMDNEM_Msk /*!< Enumeration done mask */
+#define USB_OTG_GINTMSK_ISOODRPM_Pos (14U)
+#define USB_OTG_GINTMSK_ISOODRPM_Msk (0x1UL << USB_OTG_GINTMSK_ISOODRPM_Pos) /*!< 0x00004000 */
+#define USB_OTG_GINTMSK_ISOODRPM USB_OTG_GINTMSK_ISOODRPM_Msk /*!< Isochronous OUT packet dropped interrupt mask */
+#define USB_OTG_GINTMSK_EOPFM_Pos (15U)
+#define USB_OTG_GINTMSK_EOPFM_Msk (0x1UL << USB_OTG_GINTMSK_EOPFM_Pos) /*!< 0x00008000 */
+#define USB_OTG_GINTMSK_EOPFM USB_OTG_GINTMSK_EOPFM_Msk /*!< End of periodic frame interrupt mask */
+#define USB_OTG_GINTMSK_EPMISM_Pos (17U)
+#define USB_OTG_GINTMSK_EPMISM_Msk (0x1UL << USB_OTG_GINTMSK_EPMISM_Pos) /*!< 0x00020000 */
+#define USB_OTG_GINTMSK_EPMISM USB_OTG_GINTMSK_EPMISM_Msk /*!< Endpoint mismatch interrupt mask */
+#define USB_OTG_GINTMSK_IEPINT_Pos (18U)
+#define USB_OTG_GINTMSK_IEPINT_Msk (0x1UL << USB_OTG_GINTMSK_IEPINT_Pos) /*!< 0x00040000 */
+#define USB_OTG_GINTMSK_IEPINT USB_OTG_GINTMSK_IEPINT_Msk /*!< IN endpoints interrupt mask */
+#define USB_OTG_GINTMSK_OEPINT_Pos (19U)
+#define USB_OTG_GINTMSK_OEPINT_Msk (0x1UL << USB_OTG_GINTMSK_OEPINT_Pos) /*!< 0x00080000 */
+#define USB_OTG_GINTMSK_OEPINT USB_OTG_GINTMSK_OEPINT_Msk /*!< OUT endpoints interrupt mask */
+#define USB_OTG_GINTMSK_IISOIXFRM_Pos (20U)
+#define USB_OTG_GINTMSK_IISOIXFRM_Msk (0x1UL << USB_OTG_GINTMSK_IISOIXFRM_Pos) /*!< 0x00100000 */
+#define USB_OTG_GINTMSK_IISOIXFRM USB_OTG_GINTMSK_IISOIXFRM_Msk /*!< Incomplete isochronous IN transfer mask */
+#define USB_OTG_GINTMSK_PXFRM_IISOOXFRM_Pos (21U)
+#define USB_OTG_GINTMSK_PXFRM_IISOOXFRM_Msk (0x1UL << USB_OTG_GINTMSK_PXFRM_IISOOXFRM_Pos) /*!< 0x00200000 */
+#define USB_OTG_GINTMSK_PXFRM_IISOOXFRM USB_OTG_GINTMSK_PXFRM_IISOOXFRM_Msk /*!< Incomplete periodic transfer mask */
+#define USB_OTG_GINTMSK_FSUSPM_Pos (22U)
+#define USB_OTG_GINTMSK_FSUSPM_Msk (0x1UL << USB_OTG_GINTMSK_FSUSPM_Pos) /*!< 0x00400000 */
+#define USB_OTG_GINTMSK_FSUSPM USB_OTG_GINTMSK_FSUSPM_Msk /*!< Data fetch suspended mask */
+#define USB_OTG_GINTMSK_PRTIM_Pos (24U)
+#define USB_OTG_GINTMSK_PRTIM_Msk (0x1UL << USB_OTG_GINTMSK_PRTIM_Pos) /*!< 0x01000000 */
+#define USB_OTG_GINTMSK_PRTIM USB_OTG_GINTMSK_PRTIM_Msk /*!< Host port interrupt mask */
+#define USB_OTG_GINTMSK_HCIM_Pos (25U)
+#define USB_OTG_GINTMSK_HCIM_Msk (0x1UL << USB_OTG_GINTMSK_HCIM_Pos) /*!< 0x02000000 */
+#define USB_OTG_GINTMSK_HCIM USB_OTG_GINTMSK_HCIM_Msk /*!< Host channels interrupt mask */
+#define USB_OTG_GINTMSK_PTXFEM_Pos (26U)
+#define USB_OTG_GINTMSK_PTXFEM_Msk (0x1UL << USB_OTG_GINTMSK_PTXFEM_Pos) /*!< 0x04000000 */
+#define USB_OTG_GINTMSK_PTXFEM USB_OTG_GINTMSK_PTXFEM_Msk /*!< Periodic TxFIFO empty mask */
+#define USB_OTG_GINTMSK_CIDSCHGM_Pos (28U)
+#define USB_OTG_GINTMSK_CIDSCHGM_Msk (0x1UL << USB_OTG_GINTMSK_CIDSCHGM_Pos) /*!< 0x10000000 */
+#define USB_OTG_GINTMSK_CIDSCHGM USB_OTG_GINTMSK_CIDSCHGM_Msk /*!< Connector ID status change mask */
+#define USB_OTG_GINTMSK_DISCINT_Pos (29U)
+#define USB_OTG_GINTMSK_DISCINT_Msk (0x1UL << USB_OTG_GINTMSK_DISCINT_Pos) /*!< 0x20000000 */
+#define USB_OTG_GINTMSK_DISCINT USB_OTG_GINTMSK_DISCINT_Msk /*!< Disconnect detected interrupt mask */
+#define USB_OTG_GINTMSK_SRQIM_Pos (30U)
+#define USB_OTG_GINTMSK_SRQIM_Msk (0x1UL << USB_OTG_GINTMSK_SRQIM_Pos) /*!< 0x40000000 */
+#define USB_OTG_GINTMSK_SRQIM USB_OTG_GINTMSK_SRQIM_Msk /*!< Session request/new session detected interrupt mask */
+#define USB_OTG_GINTMSK_WUIM_Pos (31U)
+#define USB_OTG_GINTMSK_WUIM_Msk (0x1UL << USB_OTG_GINTMSK_WUIM_Pos) /*!< 0x80000000 */
+#define USB_OTG_GINTMSK_WUIM USB_OTG_GINTMSK_WUIM_Msk /*!< Resume/remote wakeup detected interrupt mask */
+
+/******************** Bit definition for USB_OTG_DAINT register ********************/
+#define USB_OTG_DAINT_IEPINT_Pos (0U)
+#define USB_OTG_DAINT_IEPINT_Msk (0xFFFFUL << USB_OTG_DAINT_IEPINT_Pos) /*!< 0x0000FFFF */
+#define USB_OTG_DAINT_IEPINT USB_OTG_DAINT_IEPINT_Msk /*!< IN endpoint interrupt bits */
+#define USB_OTG_DAINT_OEPINT_Pos (16U)
+#define USB_OTG_DAINT_OEPINT_Msk (0xFFFFUL << USB_OTG_DAINT_OEPINT_Pos) /*!< 0xFFFF0000 */
+#define USB_OTG_DAINT_OEPINT USB_OTG_DAINT_OEPINT_Msk /*!< OUT endpoint interrupt bits */
+
+/******************** Bit definition for USB_OTG_HAINTMSK register ********************/
+#define USB_OTG_HAINTMSK_HAINTM_Pos (0U)
+#define USB_OTG_HAINTMSK_HAINTM_Msk (0xFFFFUL << USB_OTG_HAINTMSK_HAINTM_Pos) /*!< 0x0000FFFF */
+#define USB_OTG_HAINTMSK_HAINTM USB_OTG_HAINTMSK_HAINTM_Msk /*!< Channel interrupt mask */
+
+/******************** Bit definition for USB_OTG_GRXSTSP register ********************/
+#define USB_OTG_GRXSTSP_EPNUM_Pos (0U)
+#define USB_OTG_GRXSTSP_EPNUM_Msk (0xFUL << USB_OTG_GRXSTSP_EPNUM_Pos) /*!< 0x0000000F */
+#define USB_OTG_GRXSTSP_EPNUM USB_OTG_GRXSTSP_EPNUM_Msk /*!< IN EP interrupt mask bits */
+#define USB_OTG_GRXSTSP_BCNT_Pos (4U)
+#define USB_OTG_GRXSTSP_BCNT_Msk (0x7FFUL << USB_OTG_GRXSTSP_BCNT_Pos) /*!< 0x00007FF0 */
+#define USB_OTG_GRXSTSP_BCNT USB_OTG_GRXSTSP_BCNT_Msk /*!< OUT EP interrupt mask bits */
+#define USB_OTG_GRXSTSP_DPID_Pos (15U)
+#define USB_OTG_GRXSTSP_DPID_Msk (0x3UL << USB_OTG_GRXSTSP_DPID_Pos) /*!< 0x00018000 */
+#define USB_OTG_GRXSTSP_DPID USB_OTG_GRXSTSP_DPID_Msk /*!< OUT EP interrupt mask bits */
+#define USB_OTG_GRXSTSP_PKTSTS_Pos (17U)
+#define USB_OTG_GRXSTSP_PKTSTS_Msk (0xFUL << USB_OTG_GRXSTSP_PKTSTS_Pos) /*!< 0x001E0000 */
+#define USB_OTG_GRXSTSP_PKTSTS USB_OTG_GRXSTSP_PKTSTS_Msk /*!< OUT EP interrupt mask bits */
+
+/******************** Bit definition for USB_OTG_DAINTMSK register ********************/
+#define USB_OTG_DAINTMSK_IEPM_Pos (0U)
+#define USB_OTG_DAINTMSK_IEPM_Msk (0xFFFFUL << USB_OTG_DAINTMSK_IEPM_Pos) /*!< 0x0000FFFF */
+#define USB_OTG_DAINTMSK_IEPM USB_OTG_DAINTMSK_IEPM_Msk /*!< IN EP interrupt mask bits */
+#define USB_OTG_DAINTMSK_OEPM_Pos (16U)
+#define USB_OTG_DAINTMSK_OEPM_Msk (0xFFFFUL << USB_OTG_DAINTMSK_OEPM_Pos) /*!< 0xFFFF0000 */
+#define USB_OTG_DAINTMSK_OEPM USB_OTG_DAINTMSK_OEPM_Msk /*!< OUT EP interrupt mask bits */
+
+/******************** Bit definition for USB_OTG_GRXFSIZ register ********************/
+#define USB_OTG_GRXFSIZ_RXFD_Pos (0U)
+#define USB_OTG_GRXFSIZ_RXFD_Msk (0xFFFFUL << USB_OTG_GRXFSIZ_RXFD_Pos) /*!< 0x0000FFFF */
+#define USB_OTG_GRXFSIZ_RXFD USB_OTG_GRXFSIZ_RXFD_Msk /*!< RxFIFO depth */
+
+/******************** Bit definition for USB_OTG_DVBUSDIS register ********************/
+#define USB_OTG_DVBUSDIS_VBUSDT_Pos (0U)
+#define USB_OTG_DVBUSDIS_VBUSDT_Msk (0xFFFFUL << USB_OTG_DVBUSDIS_VBUSDT_Pos) /*!< 0x0000FFFF */
+#define USB_OTG_DVBUSDIS_VBUSDT USB_OTG_DVBUSDIS_VBUSDT_Msk /*!< Device VBUS discharge time */
+
+/******************** Bit definition for OTG register ********************/
+#define USB_OTG_NPTXFSA_Pos (0U)
+#define USB_OTG_NPTXFSA_Msk (0xFFFFUL << USB_OTG_NPTXFSA_Pos) /*!< 0x0000FFFF */
+#define USB_OTG_NPTXFSA USB_OTG_NPTXFSA_Msk /*!< Nonperiodic transmit RAM start address */
+#define USB_OTG_NPTXFD_Pos (16U)
+#define USB_OTG_NPTXFD_Msk (0xFFFFUL << USB_OTG_NPTXFD_Pos) /*!< 0xFFFF0000 */
+#define USB_OTG_NPTXFD USB_OTG_NPTXFD_Msk /*!< Nonperiodic TxFIFO depth */
+#define USB_OTG_TX0FSA_Pos (0U)
+#define USB_OTG_TX0FSA_Msk (0xFFFFUL << USB_OTG_TX0FSA_Pos) /*!< 0x0000FFFF */
+#define USB_OTG_TX0FSA USB_OTG_TX0FSA_Msk /*!< Endpoint 0 transmit RAM start address */
+#define USB_OTG_TX0FD_Pos (16U)
+#define USB_OTG_TX0FD_Msk (0xFFFFUL << USB_OTG_TX0FD_Pos) /*!< 0xFFFF0000 */
+#define USB_OTG_TX0FD USB_OTG_TX0FD_Msk /*!< Endpoint 0 TxFIFO depth */
+
+/******************** Bit definition for USB_OTG_DVBUSPULSE register ********************/
+#define USB_OTG_DVBUSPULSE_DVBUSP_Pos (0U)
+#define USB_OTG_DVBUSPULSE_DVBUSP_Msk (0xFFFUL << USB_OTG_DVBUSPULSE_DVBUSP_Pos) /*!< 0x00000FFF */
+#define USB_OTG_DVBUSPULSE_DVBUSP USB_OTG_DVBUSPULSE_DVBUSP_Msk /*!< Device VBUS pulsing time */
+
+/******************** Bit definition for USB_OTG_GNPTXSTS register ********************/
+#define USB_OTG_GNPTXSTS_NPTXFSAV_Pos (0U)
+#define USB_OTG_GNPTXSTS_NPTXFSAV_Msk (0xFFFFUL << USB_OTG_GNPTXSTS_NPTXFSAV_Pos) /*!< 0x0000FFFF */
+#define USB_OTG_GNPTXSTS_NPTXFSAV USB_OTG_GNPTXSTS_NPTXFSAV_Msk /*!< Nonperiodic TxFIFO space available */
+
+#define USB_OTG_GNPTXSTS_NPTQXSAV_Pos (16U)
+#define USB_OTG_GNPTXSTS_NPTQXSAV_Msk (0xFFUL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00FF0000 */
+#define USB_OTG_GNPTXSTS_NPTQXSAV USB_OTG_GNPTXSTS_NPTQXSAV_Msk /*!< Nonperiodic transmit request queue space available */
+#define USB_OTG_GNPTXSTS_NPTQXSAV_0 (0x01UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00010000 */
+#define USB_OTG_GNPTXSTS_NPTQXSAV_1 (0x02UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00020000 */
+#define USB_OTG_GNPTXSTS_NPTQXSAV_2 (0x04UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00040000 */
+#define USB_OTG_GNPTXSTS_NPTQXSAV_3 (0x08UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00080000 */
+#define USB_OTG_GNPTXSTS_NPTQXSAV_4 (0x10UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00100000 */
+#define USB_OTG_GNPTXSTS_NPTQXSAV_5 (0x20UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00200000 */
+#define USB_OTG_GNPTXSTS_NPTQXSAV_6 (0x40UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00400000 */
+#define USB_OTG_GNPTXSTS_NPTQXSAV_7 (0x80UL << USB_OTG_GNPTXSTS_NPTQXSAV_Pos) /*!< 0x00800000 */
+
+#define USB_OTG_GNPTXSTS_NPTXQTOP_Pos (24U)
+#define USB_OTG_GNPTXSTS_NPTXQTOP_Msk (0x7FUL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x7F000000 */
+#define USB_OTG_GNPTXSTS_NPTXQTOP USB_OTG_GNPTXSTS_NPTXQTOP_Msk /*!< Top of the nonperiodic transmit request queue */
+#define USB_OTG_GNPTXSTS_NPTXQTOP_0 (0x01UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x01000000 */
+#define USB_OTG_GNPTXSTS_NPTXQTOP_1 (0x02UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x02000000 */
+#define USB_OTG_GNPTXSTS_NPTXQTOP_2 (0x04UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x04000000 */
+#define USB_OTG_GNPTXSTS_NPTXQTOP_3 (0x08UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x08000000 */
+#define USB_OTG_GNPTXSTS_NPTXQTOP_4 (0x10UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x10000000 */
+#define USB_OTG_GNPTXSTS_NPTXQTOP_5 (0x20UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x20000000 */
+#define USB_OTG_GNPTXSTS_NPTXQTOP_6 (0x40UL << USB_OTG_GNPTXSTS_NPTXQTOP_Pos) /*!< 0x40000000 */
+
+/******************** Bit definition for USB_OTG_DTHRCTL register ********************/
+#define USB_OTG_DTHRCTL_NONISOTHREN_Pos (0U)
+#define USB_OTG_DTHRCTL_NONISOTHREN_Msk (0x1UL << USB_OTG_DTHRCTL_NONISOTHREN_Pos) /*!< 0x00000001 */
+#define USB_OTG_DTHRCTL_NONISOTHREN USB_OTG_DTHRCTL_NONISOTHREN_Msk /*!< Nonisochronous IN endpoints threshold enable */
+#define USB_OTG_DTHRCTL_ISOTHREN_Pos (1U)
+#define USB_OTG_DTHRCTL_ISOTHREN_Msk (0x1UL << USB_OTG_DTHRCTL_ISOTHREN_Pos) /*!< 0x00000002 */
+#define USB_OTG_DTHRCTL_ISOTHREN USB_OTG_DTHRCTL_ISOTHREN_Msk /*!< ISO IN endpoint threshold enable */
+
+#define USB_OTG_DTHRCTL_TXTHRLEN_Pos (2U)
+#define USB_OTG_DTHRCTL_TXTHRLEN_Msk (0x1FFUL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x000007FC */
+#define USB_OTG_DTHRCTL_TXTHRLEN USB_OTG_DTHRCTL_TXTHRLEN_Msk /*!< Transmit threshold length */
+#define USB_OTG_DTHRCTL_TXTHRLEN_0 (0x001UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000004 */
+#define USB_OTG_DTHRCTL_TXTHRLEN_1 (0x002UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000008 */
+#define USB_OTG_DTHRCTL_TXTHRLEN_2 (0x004UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000010 */
+#define USB_OTG_DTHRCTL_TXTHRLEN_3 (0x008UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000020 */
+#define USB_OTG_DTHRCTL_TXTHRLEN_4 (0x010UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000040 */
+#define USB_OTG_DTHRCTL_TXTHRLEN_5 (0x020UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000080 */
+#define USB_OTG_DTHRCTL_TXTHRLEN_6 (0x040UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000100 */
+#define USB_OTG_DTHRCTL_TXTHRLEN_7 (0x080UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000200 */
+#define USB_OTG_DTHRCTL_TXTHRLEN_8 (0x100UL << USB_OTG_DTHRCTL_TXTHRLEN_Pos) /*!< 0x00000400 */
+#define USB_OTG_DTHRCTL_RXTHREN_Pos (16U)
+#define USB_OTG_DTHRCTL_RXTHREN_Msk (0x1UL << USB_OTG_DTHRCTL_RXTHREN_Pos) /*!< 0x00010000 */
+#define USB_OTG_DTHRCTL_RXTHREN USB_OTG_DTHRCTL_RXTHREN_Msk /*!< Receive threshold enable */
+
+#define USB_OTG_DTHRCTL_RXTHRLEN_Pos (17U)
+#define USB_OTG_DTHRCTL_RXTHRLEN_Msk (0x1FFUL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x03FE0000 */
+#define USB_OTG_DTHRCTL_RXTHRLEN USB_OTG_DTHRCTL_RXTHRLEN_Msk /*!< Receive threshold length */
+#define USB_OTG_DTHRCTL_RXTHRLEN_0 (0x001UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00020000 */
+#define USB_OTG_DTHRCTL_RXTHRLEN_1 (0x002UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00040000 */
+#define USB_OTG_DTHRCTL_RXTHRLEN_2 (0x004UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00080000 */
+#define USB_OTG_DTHRCTL_RXTHRLEN_3 (0x008UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00100000 */
+#define USB_OTG_DTHRCTL_RXTHRLEN_4 (0x010UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00200000 */
+#define USB_OTG_DTHRCTL_RXTHRLEN_5 (0x020UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00400000 */
+#define USB_OTG_DTHRCTL_RXTHRLEN_6 (0x040UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x00800000 */
+#define USB_OTG_DTHRCTL_RXTHRLEN_7 (0x080UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x01000000 */
+#define USB_OTG_DTHRCTL_RXTHRLEN_8 (0x100UL << USB_OTG_DTHRCTL_RXTHRLEN_Pos) /*!< 0x02000000 */
+#define USB_OTG_DTHRCTL_ARPEN_Pos (27U)
+#define USB_OTG_DTHRCTL_ARPEN_Msk (0x1UL << USB_OTG_DTHRCTL_ARPEN_Pos) /*!< 0x08000000 */
+#define USB_OTG_DTHRCTL_ARPEN USB_OTG_DTHRCTL_ARPEN_Msk /*!< Arbiter parking enable */
+
+/******************** Bit definition for USB_OTG_DIEPEMPMSK register ********************/
+#define USB_OTG_DIEPEMPMSK_INEPTXFEM_Pos (0U)
+#define USB_OTG_DIEPEMPMSK_INEPTXFEM_Msk (0xFFFFUL << USB_OTG_DIEPEMPMSK_INEPTXFEM_Pos) /*!< 0x0000FFFF */
+#define USB_OTG_DIEPEMPMSK_INEPTXFEM USB_OTG_DIEPEMPMSK_INEPTXFEM_Msk /*!< IN EP Tx FIFO empty interrupt mask bits */
+
+/******************** Bit definition for USB_OTG_DEACHINT register ********************/
+#define USB_OTG_DEACHINT_IEP1INT_Pos (1U)
+#define USB_OTG_DEACHINT_IEP1INT_Msk (0x1UL << USB_OTG_DEACHINT_IEP1INT_Pos) /*!< 0x00000002 */
+#define USB_OTG_DEACHINT_IEP1INT USB_OTG_DEACHINT_IEP1INT_Msk /*!< IN endpoint 1interrupt bit */
+#define USB_OTG_DEACHINT_OEP1INT_Pos (17U)
+#define USB_OTG_DEACHINT_OEP1INT_Msk (0x1UL << USB_OTG_DEACHINT_OEP1INT_Pos) /*!< 0x00020000 */
+#define USB_OTG_DEACHINT_OEP1INT USB_OTG_DEACHINT_OEP1INT_Msk /*!< OUT endpoint 1 interrupt bit */
+
+/******************** Bit definition for USB_OTG_GCCFG register ********************/
+#define USB_OTG_GCCFG_PWRDWN_Pos (16U)
+#define USB_OTG_GCCFG_PWRDWN_Msk (0x1UL << USB_OTG_GCCFG_PWRDWN_Pos) /*!< 0x00010000 */
+#define USB_OTG_GCCFG_PWRDWN USB_OTG_GCCFG_PWRDWN_Msk /*!< Power down */
+#define USB_OTG_GCCFG_VBUSASEN_Pos (18U)
+#define USB_OTG_GCCFG_VBUSASEN_Msk (0x1UL << USB_OTG_GCCFG_VBUSASEN_Pos) /*!< 0x00040000 */
+#define USB_OTG_GCCFG_VBUSASEN USB_OTG_GCCFG_VBUSASEN_Msk /*!< Enable the VBUS sensing device */
+#define USB_OTG_GCCFG_VBUSBSEN_Pos (19U)
+#define USB_OTG_GCCFG_VBUSBSEN_Msk (0x1UL << USB_OTG_GCCFG_VBUSBSEN_Pos) /*!< 0x00080000 */
+#define USB_OTG_GCCFG_VBUSBSEN USB_OTG_GCCFG_VBUSBSEN_Msk /*!< Enable the VBUS sensing device */
+#define USB_OTG_GCCFG_SOFOUTEN_Pos (20U)
+#define USB_OTG_GCCFG_SOFOUTEN_Msk (0x1UL << USB_OTG_GCCFG_SOFOUTEN_Pos) /*!< 0x00100000 */
+#define USB_OTG_GCCFG_SOFOUTEN USB_OTG_GCCFG_SOFOUTEN_Msk /*!< SOF output enable */
+
+/******************** Bit definition for USB_OTG_DEACHINTMSK register ********************/
+#define USB_OTG_DEACHINTMSK_IEP1INTM_Pos (1U)
+#define USB_OTG_DEACHINTMSK_IEP1INTM_Msk (0x1UL << USB_OTG_DEACHINTMSK_IEP1INTM_Pos) /*!< 0x00000002 */
+#define USB_OTG_DEACHINTMSK_IEP1INTM USB_OTG_DEACHINTMSK_IEP1INTM_Msk /*!< IN Endpoint 1 interrupt mask bit */
+#define USB_OTG_DEACHINTMSK_OEP1INTM_Pos (17U)
+#define USB_OTG_DEACHINTMSK_OEP1INTM_Msk (0x1UL << USB_OTG_DEACHINTMSK_OEP1INTM_Pos) /*!< 0x00020000 */
+#define USB_OTG_DEACHINTMSK_OEP1INTM USB_OTG_DEACHINTMSK_OEP1INTM_Msk /*!< OUT Endpoint 1 interrupt mask bit */
+
+/******************** Bit definition for USB_OTG_CID register ********************/
+#define USB_OTG_CID_PRODUCT_ID_Pos (0U)
+#define USB_OTG_CID_PRODUCT_ID_Msk (0xFFFFFFFFUL << USB_OTG_CID_PRODUCT_ID_Pos) /*!< 0xFFFFFFFF */
+#define USB_OTG_CID_PRODUCT_ID USB_OTG_CID_PRODUCT_ID_Msk /*!< Product ID field */
+
+/******************** Bit definition for USB_OTG_DIEPEACHMSK1 register ********************/
+#define USB_OTG_DIEPEACHMSK1_XFRCM_Pos (0U)
+#define USB_OTG_DIEPEACHMSK1_XFRCM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_XFRCM_Pos) /*!< 0x00000001 */
+#define USB_OTG_DIEPEACHMSK1_XFRCM USB_OTG_DIEPEACHMSK1_XFRCM_Msk /*!< Transfer completed interrupt mask */
+#define USB_OTG_DIEPEACHMSK1_EPDM_Pos (1U)
+#define USB_OTG_DIEPEACHMSK1_EPDM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_EPDM_Pos) /*!< 0x00000002 */
+#define USB_OTG_DIEPEACHMSK1_EPDM USB_OTG_DIEPEACHMSK1_EPDM_Msk /*!< Endpoint disabled interrupt mask */
+#define USB_OTG_DIEPEACHMSK1_TOM_Pos (3U)
+#define USB_OTG_DIEPEACHMSK1_TOM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_TOM_Pos) /*!< 0x00000008 */
+#define USB_OTG_DIEPEACHMSK1_TOM USB_OTG_DIEPEACHMSK1_TOM_Msk /*!< Timeout condition mask (nonisochronous endpoints) */
+#define USB_OTG_DIEPEACHMSK1_ITTXFEMSK_Pos (4U)
+#define USB_OTG_DIEPEACHMSK1_ITTXFEMSK_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_ITTXFEMSK_Pos) /*!< 0x00000010 */
+#define USB_OTG_DIEPEACHMSK1_ITTXFEMSK USB_OTG_DIEPEACHMSK1_ITTXFEMSK_Msk /*!< IN token received when TxFIFO empty mask */
+#define USB_OTG_DIEPEACHMSK1_INEPNMM_Pos (5U)
+#define USB_OTG_DIEPEACHMSK1_INEPNMM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_INEPNMM_Pos) /*!< 0x00000020 */
+#define USB_OTG_DIEPEACHMSK1_INEPNMM USB_OTG_DIEPEACHMSK1_INEPNMM_Msk /*!< IN token received with EP mismatch mask */
+#define USB_OTG_DIEPEACHMSK1_INEPNEM_Pos (6U)
+#define USB_OTG_DIEPEACHMSK1_INEPNEM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_INEPNEM_Pos) /*!< 0x00000040 */
+#define USB_OTG_DIEPEACHMSK1_INEPNEM USB_OTG_DIEPEACHMSK1_INEPNEM_Msk /*!< IN endpoint NAK effective mask */
+#define USB_OTG_DIEPEACHMSK1_TXFURM_Pos (8U)
+#define USB_OTG_DIEPEACHMSK1_TXFURM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_TXFURM_Pos) /*!< 0x00000100 */
+#define USB_OTG_DIEPEACHMSK1_TXFURM USB_OTG_DIEPEACHMSK1_TXFURM_Msk /*!< FIFO underrun mask */
+#define USB_OTG_DIEPEACHMSK1_BIM_Pos (9U)
+#define USB_OTG_DIEPEACHMSK1_BIM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_BIM_Pos) /*!< 0x00000200 */
+#define USB_OTG_DIEPEACHMSK1_BIM USB_OTG_DIEPEACHMSK1_BIM_Msk /*!< BNA interrupt mask */
+#define USB_OTG_DIEPEACHMSK1_NAKM_Pos (13U)
+#define USB_OTG_DIEPEACHMSK1_NAKM_Msk (0x1UL << USB_OTG_DIEPEACHMSK1_NAKM_Pos) /*!< 0x00002000 */
+#define USB_OTG_DIEPEACHMSK1_NAKM USB_OTG_DIEPEACHMSK1_NAKM_Msk /*!< NAK interrupt mask */
+
+/******************** Bit definition for USB_OTG_HPRT register ********************/
+#define USB_OTG_HPRT_PCSTS_Pos (0U)
+#define USB_OTG_HPRT_PCSTS_Msk (0x1UL << USB_OTG_HPRT_PCSTS_Pos) /*!< 0x00000001 */
+#define USB_OTG_HPRT_PCSTS USB_OTG_HPRT_PCSTS_Msk /*!< Port connect status */
+#define USB_OTG_HPRT_PCDET_Pos (1U)
+#define USB_OTG_HPRT_PCDET_Msk (0x1UL << USB_OTG_HPRT_PCDET_Pos) /*!< 0x00000002 */
+#define USB_OTG_HPRT_PCDET USB_OTG_HPRT_PCDET_Msk /*!< Port connect detected */
+#define USB_OTG_HPRT_PENA_Pos (2U)
+#define USB_OTG_HPRT_PENA_Msk (0x1UL << USB_OTG_HPRT_PENA_Pos) /*!< 0x00000004 */
+#define USB_OTG_HPRT_PENA USB_OTG_HPRT_PENA_Msk /*!< Port enable */
+#define USB_OTG_HPRT_PENCHNG_Pos (3U)
+#define USB_OTG_HPRT_PENCHNG_Msk (0x1UL << USB_OTG_HPRT_PENCHNG_Pos) /*!< 0x00000008 */
+#define USB_OTG_HPRT_PENCHNG USB_OTG_HPRT_PENCHNG_Msk /*!< Port enable/disable change */
+#define USB_OTG_HPRT_POCA_Pos (4U)
+#define USB_OTG_HPRT_POCA_Msk (0x1UL << USB_OTG_HPRT_POCA_Pos) /*!< 0x00000010 */
+#define USB_OTG_HPRT_POCA USB_OTG_HPRT_POCA_Msk /*!< Port overcurrent active */
+#define USB_OTG_HPRT_POCCHNG_Pos (5U)
+#define USB_OTG_HPRT_POCCHNG_Msk (0x1UL << USB_OTG_HPRT_POCCHNG_Pos) /*!< 0x00000020 */
+#define USB_OTG_HPRT_POCCHNG USB_OTG_HPRT_POCCHNG_Msk /*!< Port overcurrent change */
+#define USB_OTG_HPRT_PRES_Pos (6U)
+#define USB_OTG_HPRT_PRES_Msk (0x1UL << USB_OTG_HPRT_PRES_Pos) /*!< 0x00000040 */
+#define USB_OTG_HPRT_PRES USB_OTG_HPRT_PRES_Msk /*!< Port resume */
+#define USB_OTG_HPRT_PSUSP_Pos (7U)
+#define USB_OTG_HPRT_PSUSP_Msk (0x1UL << USB_OTG_HPRT_PSUSP_Pos) /*!< 0x00000080 */
+#define USB_OTG_HPRT_PSUSP USB_OTG_HPRT_PSUSP_Msk /*!< Port suspend */
+#define USB_OTG_HPRT_PRST_Pos (8U)
+#define USB_OTG_HPRT_PRST_Msk (0x1UL << USB_OTG_HPRT_PRST_Pos) /*!< 0x00000100 */
+#define USB_OTG_HPRT_PRST USB_OTG_HPRT_PRST_Msk /*!< Port reset */
+
+#define USB_OTG_HPRT_PLSTS_Pos (10U)
+#define USB_OTG_HPRT_PLSTS_Msk (0x3UL << USB_OTG_HPRT_PLSTS_Pos) /*!< 0x00000C00 */
+#define USB_OTG_HPRT_PLSTS USB_OTG_HPRT_PLSTS_Msk /*!< Port line status */
+#define USB_OTG_HPRT_PLSTS_0 (0x1UL << USB_OTG_HPRT_PLSTS_Pos) /*!< 0x00000400 */
+#define USB_OTG_HPRT_PLSTS_1 (0x2UL << USB_OTG_HPRT_PLSTS_Pos) /*!< 0x00000800 */
+#define USB_OTG_HPRT_PPWR_Pos (12U)
+#define USB_OTG_HPRT_PPWR_Msk (0x1UL << USB_OTG_HPRT_PPWR_Pos) /*!< 0x00001000 */
+#define USB_OTG_HPRT_PPWR USB_OTG_HPRT_PPWR_Msk /*!< Port power */
+
+#define USB_OTG_HPRT_PTCTL_Pos (13U)
+#define USB_OTG_HPRT_PTCTL_Msk (0xFUL << USB_OTG_HPRT_PTCTL_Pos) /*!< 0x0001E000 */
+#define USB_OTG_HPRT_PTCTL USB_OTG_HPRT_PTCTL_Msk /*!< Port test control */
+#define USB_OTG_HPRT_PTCTL_0 (0x1UL << USB_OTG_HPRT_PTCTL_Pos) /*!< 0x00002000 */
+#define USB_OTG_HPRT_PTCTL_1 (0x2UL << USB_OTG_HPRT_PTCTL_Pos) /*!< 0x00004000 */
+#define USB_OTG_HPRT_PTCTL_2 (0x4UL << USB_OTG_HPRT_PTCTL_Pos) /*!< 0x00008000 */
+#define USB_OTG_HPRT_PTCTL_3 (0x8UL << USB_OTG_HPRT_PTCTL_Pos) /*!< 0x00010000 */
+
+#define USB_OTG_HPRT_PSPD_Pos (17U)
+#define USB_OTG_HPRT_PSPD_Msk (0x3UL << USB_OTG_HPRT_PSPD_Pos) /*!< 0x00060000 */
+#define USB_OTG_HPRT_PSPD USB_OTG_HPRT_PSPD_Msk /*!< Port speed */
+#define USB_OTG_HPRT_PSPD_0 (0x1UL << USB_OTG_HPRT_PSPD_Pos) /*!< 0x00020000 */
+#define USB_OTG_HPRT_PSPD_1 (0x2UL << USB_OTG_HPRT_PSPD_Pos) /*!< 0x00040000 */
+
+/******************** Bit definition for USB_OTG_DOEPEACHMSK1 register ********************/
+#define USB_OTG_DOEPEACHMSK1_XFRCM_Pos (0U)
+#define USB_OTG_DOEPEACHMSK1_XFRCM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_XFRCM_Pos) /*!< 0x00000001 */
+#define USB_OTG_DOEPEACHMSK1_XFRCM USB_OTG_DOEPEACHMSK1_XFRCM_Msk /*!< Transfer completed interrupt mask */
+#define USB_OTG_DOEPEACHMSK1_EPDM_Pos (1U)
+#define USB_OTG_DOEPEACHMSK1_EPDM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_EPDM_Pos) /*!< 0x00000002 */
+#define USB_OTG_DOEPEACHMSK1_EPDM USB_OTG_DOEPEACHMSK1_EPDM_Msk /*!< Endpoint disabled interrupt mask */
+#define USB_OTG_DOEPEACHMSK1_TOM_Pos (3U)
+#define USB_OTG_DOEPEACHMSK1_TOM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_TOM_Pos) /*!< 0x00000008 */
+#define USB_OTG_DOEPEACHMSK1_TOM USB_OTG_DOEPEACHMSK1_TOM_Msk /*!< Timeout condition mask */
+#define USB_OTG_DOEPEACHMSK1_ITTXFEMSK_Pos (4U)
+#define USB_OTG_DOEPEACHMSK1_ITTXFEMSK_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_ITTXFEMSK_Pos) /*!< 0x00000010 */
+#define USB_OTG_DOEPEACHMSK1_ITTXFEMSK USB_OTG_DOEPEACHMSK1_ITTXFEMSK_Msk /*!< IN token received when TxFIFO empty mask */
+#define USB_OTG_DOEPEACHMSK1_INEPNMM_Pos (5U)
+#define USB_OTG_DOEPEACHMSK1_INEPNMM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_INEPNMM_Pos) /*!< 0x00000020 */
+#define USB_OTG_DOEPEACHMSK1_INEPNMM USB_OTG_DOEPEACHMSK1_INEPNMM_Msk /*!< IN token received with EP mismatch mask */
+#define USB_OTG_DOEPEACHMSK1_INEPNEM_Pos (6U)
+#define USB_OTG_DOEPEACHMSK1_INEPNEM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_INEPNEM_Pos) /*!< 0x00000040 */
+#define USB_OTG_DOEPEACHMSK1_INEPNEM USB_OTG_DOEPEACHMSK1_INEPNEM_Msk /*!< IN endpoint NAK effective mask */
+#define USB_OTG_DOEPEACHMSK1_TXFURM_Pos (8U)
+#define USB_OTG_DOEPEACHMSK1_TXFURM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_TXFURM_Pos) /*!< 0x00000100 */
+#define USB_OTG_DOEPEACHMSK1_TXFURM USB_OTG_DOEPEACHMSK1_TXFURM_Msk /*!< OUT packet error mask */
+#define USB_OTG_DOEPEACHMSK1_BIM_Pos (9U)
+#define USB_OTG_DOEPEACHMSK1_BIM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_BIM_Pos) /*!< 0x00000200 */
+#define USB_OTG_DOEPEACHMSK1_BIM USB_OTG_DOEPEACHMSK1_BIM_Msk /*!< BNA interrupt mask */
+#define USB_OTG_DOEPEACHMSK1_BERRM_Pos (12U)
+#define USB_OTG_DOEPEACHMSK1_BERRM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_BERRM_Pos) /*!< 0x00001000 */
+#define USB_OTG_DOEPEACHMSK1_BERRM USB_OTG_DOEPEACHMSK1_BERRM_Msk /*!< Bubble error interrupt mask */
+#define USB_OTG_DOEPEACHMSK1_NAKM_Pos (13U)
+#define USB_OTG_DOEPEACHMSK1_NAKM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_NAKM_Pos) /*!< 0x00002000 */
+#define USB_OTG_DOEPEACHMSK1_NAKM USB_OTG_DOEPEACHMSK1_NAKM_Msk /*!< NAK interrupt mask */
+#define USB_OTG_DOEPEACHMSK1_NYETM_Pos (14U)
+#define USB_OTG_DOEPEACHMSK1_NYETM_Msk (0x1UL << USB_OTG_DOEPEACHMSK1_NYETM_Pos) /*!< 0x00004000 */
+#define USB_OTG_DOEPEACHMSK1_NYETM USB_OTG_DOEPEACHMSK1_NYETM_Msk /*!< NYET interrupt mask */
+
+/******************** Bit definition for USB_OTG_HPTXFSIZ register ********************/
+#define USB_OTG_HPTXFSIZ_PTXSA_Pos (0U)
+#define USB_OTG_HPTXFSIZ_PTXSA_Msk (0xFFFFUL << USB_OTG_HPTXFSIZ_PTXSA_Pos) /*!< 0x0000FFFF */
+#define USB_OTG_HPTXFSIZ_PTXSA USB_OTG_HPTXFSIZ_PTXSA_Msk /*!< Host periodic TxFIFO start address */
+#define USB_OTG_HPTXFSIZ_PTXFD_Pos (16U)
+#define USB_OTG_HPTXFSIZ_PTXFD_Msk (0xFFFFUL << USB_OTG_HPTXFSIZ_PTXFD_Pos) /*!< 0xFFFF0000 */
+#define USB_OTG_HPTXFSIZ_PTXFD USB_OTG_HPTXFSIZ_PTXFD_Msk /*!< Host periodic TxFIFO depth */
+
+/******************** Bit definition for USB_OTG_DIEPCTL register ********************/
+#define USB_OTG_DIEPCTL_MPSIZ_Pos (0U)
+#define USB_OTG_DIEPCTL_MPSIZ_Msk (0x7FFUL << USB_OTG_DIEPCTL_MPSIZ_Pos) /*!< 0x000007FF */
+#define USB_OTG_DIEPCTL_MPSIZ USB_OTG_DIEPCTL_MPSIZ_Msk /*!< Maximum packet size */
+#define USB_OTG_DIEPCTL_USBAEP_Pos (15U)
+#define USB_OTG_DIEPCTL_USBAEP_Msk (0x1UL << USB_OTG_DIEPCTL_USBAEP_Pos) /*!< 0x00008000 */
+#define USB_OTG_DIEPCTL_USBAEP USB_OTG_DIEPCTL_USBAEP_Msk /*!< USB active endpoint */
+#define USB_OTG_DIEPCTL_EONUM_DPID_Pos (16U)
+#define USB_OTG_DIEPCTL_EONUM_DPID_Msk (0x1UL << USB_OTG_DIEPCTL_EONUM_DPID_Pos) /*!< 0x00010000 */
+#define USB_OTG_DIEPCTL_EONUM_DPID USB_OTG_DIEPCTL_EONUM_DPID_Msk /*!< Even/odd frame */
+#define USB_OTG_DIEPCTL_NAKSTS_Pos (17U)
+#define USB_OTG_DIEPCTL_NAKSTS_Msk (0x1UL << USB_OTG_DIEPCTL_NAKSTS_Pos) /*!< 0x00020000 */
+#define USB_OTG_DIEPCTL_NAKSTS USB_OTG_DIEPCTL_NAKSTS_Msk /*!< NAK status */
+
+#define USB_OTG_DIEPCTL_EPTYP_Pos (18U)
+#define USB_OTG_DIEPCTL_EPTYP_Msk (0x3UL << USB_OTG_DIEPCTL_EPTYP_Pos) /*!< 0x000C0000 */
+#define USB_OTG_DIEPCTL_EPTYP USB_OTG_DIEPCTL_EPTYP_Msk /*!< Endpoint type */
+#define USB_OTG_DIEPCTL_EPTYP_0 (0x1UL << USB_OTG_DIEPCTL_EPTYP_Pos) /*!< 0x00040000 */
+#define USB_OTG_DIEPCTL_EPTYP_1 (0x2UL << USB_OTG_DIEPCTL_EPTYP_Pos) /*!< 0x00080000 */
+#define USB_OTG_DIEPCTL_STALL_Pos (21U)
+#define USB_OTG_DIEPCTL_STALL_Msk (0x1UL << USB_OTG_DIEPCTL_STALL_Pos) /*!< 0x00200000 */
+#define USB_OTG_DIEPCTL_STALL USB_OTG_DIEPCTL_STALL_Msk /*!< STALL handshake */
+
+#define USB_OTG_DIEPCTL_TXFNUM_Pos (22U)
+#define USB_OTG_DIEPCTL_TXFNUM_Msk (0xFUL << USB_OTG_DIEPCTL_TXFNUM_Pos) /*!< 0x03C00000 */
+#define USB_OTG_DIEPCTL_TXFNUM USB_OTG_DIEPCTL_TXFNUM_Msk /*!< TxFIFO number */
+#define USB_OTG_DIEPCTL_TXFNUM_0 (0x1UL << USB_OTG_DIEPCTL_TXFNUM_Pos) /*!< 0x00400000 */
+#define USB_OTG_DIEPCTL_TXFNUM_1 (0x2UL << USB_OTG_DIEPCTL_TXFNUM_Pos) /*!< 0x00800000 */
+#define USB_OTG_DIEPCTL_TXFNUM_2 (0x4UL << USB_OTG_DIEPCTL_TXFNUM_Pos) /*!< 0x01000000 */
+#define USB_OTG_DIEPCTL_TXFNUM_3 (0x8UL << USB_OTG_DIEPCTL_TXFNUM_Pos) /*!< 0x02000000 */
+#define USB_OTG_DIEPCTL_CNAK_Pos (26U)
+#define USB_OTG_DIEPCTL_CNAK_Msk (0x1UL << USB_OTG_DIEPCTL_CNAK_Pos) /*!< 0x04000000 */
+#define USB_OTG_DIEPCTL_CNAK USB_OTG_DIEPCTL_CNAK_Msk /*!< Clear NAK */
+#define USB_OTG_DIEPCTL_SNAK_Pos (27U)
+#define USB_OTG_DIEPCTL_SNAK_Msk (0x1UL << USB_OTG_DIEPCTL_SNAK_Pos) /*!< 0x08000000 */
+#define USB_OTG_DIEPCTL_SNAK USB_OTG_DIEPCTL_SNAK_Msk /*!< Set NAK */
+#define USB_OTG_DIEPCTL_SD0PID_SEVNFRM_Pos (28U)
+#define USB_OTG_DIEPCTL_SD0PID_SEVNFRM_Msk (0x1UL << USB_OTG_DIEPCTL_SD0PID_SEVNFRM_Pos) /*!< 0x10000000 */
+#define USB_OTG_DIEPCTL_SD0PID_SEVNFRM USB_OTG_DIEPCTL_SD0PID_SEVNFRM_Msk /*!< Set DATA0 PID */
+#define USB_OTG_DIEPCTL_SODDFRM_Pos (29U)
+#define USB_OTG_DIEPCTL_SODDFRM_Msk (0x1UL << USB_OTG_DIEPCTL_SODDFRM_Pos) /*!< 0x20000000 */
+#define USB_OTG_DIEPCTL_SODDFRM USB_OTG_DIEPCTL_SODDFRM_Msk /*!< Set odd frame */
+#define USB_OTG_DIEPCTL_EPDIS_Pos (30U)
+#define USB_OTG_DIEPCTL_EPDIS_Msk (0x1UL << USB_OTG_DIEPCTL_EPDIS_Pos) /*!< 0x40000000 */
+#define USB_OTG_DIEPCTL_EPDIS USB_OTG_DIEPCTL_EPDIS_Msk /*!< Endpoint disable */
+#define USB_OTG_DIEPCTL_EPENA_Pos (31U)
+#define USB_OTG_DIEPCTL_EPENA_Msk (0x1UL << USB_OTG_DIEPCTL_EPENA_Pos) /*!< 0x80000000 */
+#define USB_OTG_DIEPCTL_EPENA USB_OTG_DIEPCTL_EPENA_Msk /*!< Endpoint enable */
+
+/******************** Bit definition for USB_OTG_HCCHAR register ********************/
+#define USB_OTG_HCCHAR_MPSIZ_Pos (0U)
+#define USB_OTG_HCCHAR_MPSIZ_Msk (0x7FFUL << USB_OTG_HCCHAR_MPSIZ_Pos) /*!< 0x000007FF */
+#define USB_OTG_HCCHAR_MPSIZ USB_OTG_HCCHAR_MPSIZ_Msk /*!< Maximum packet size */
+
+#define USB_OTG_HCCHAR_EPNUM_Pos (11U)
+#define USB_OTG_HCCHAR_EPNUM_Msk (0xFUL << USB_OTG_HCCHAR_EPNUM_Pos) /*!< 0x00007800 */
+#define USB_OTG_HCCHAR_EPNUM USB_OTG_HCCHAR_EPNUM_Msk /*!< Endpoint number */
+#define USB_OTG_HCCHAR_EPNUM_0 (0x1UL << USB_OTG_HCCHAR_EPNUM_Pos) /*!< 0x00000800 */
+#define USB_OTG_HCCHAR_EPNUM_1 (0x2UL << USB_OTG_HCCHAR_EPNUM_Pos) /*!< 0x00001000 */
+#define USB_OTG_HCCHAR_EPNUM_2 (0x4UL << USB_OTG_HCCHAR_EPNUM_Pos) /*!< 0x00002000 */
+#define USB_OTG_HCCHAR_EPNUM_3 (0x8UL << USB_OTG_HCCHAR_EPNUM_Pos) /*!< 0x00004000 */
+#define USB_OTG_HCCHAR_EPDIR_Pos (15U)
+#define USB_OTG_HCCHAR_EPDIR_Msk (0x1UL << USB_OTG_HCCHAR_EPDIR_Pos) /*!< 0x00008000 */
+#define USB_OTG_HCCHAR_EPDIR USB_OTG_HCCHAR_EPDIR_Msk /*!< Endpoint direction */
+#define USB_OTG_HCCHAR_LSDEV_Pos (17U)
+#define USB_OTG_HCCHAR_LSDEV_Msk (0x1UL << USB_OTG_HCCHAR_LSDEV_Pos) /*!< 0x00020000 */
+#define USB_OTG_HCCHAR_LSDEV USB_OTG_HCCHAR_LSDEV_Msk /*!< Low-speed device */
+
+#define USB_OTG_HCCHAR_EPTYP_Pos (18U)
+#define USB_OTG_HCCHAR_EPTYP_Msk (0x3UL << USB_OTG_HCCHAR_EPTYP_Pos) /*!< 0x000C0000 */
+#define USB_OTG_HCCHAR_EPTYP USB_OTG_HCCHAR_EPTYP_Msk /*!< Endpoint type */
+#define USB_OTG_HCCHAR_EPTYP_0 (0x1UL << USB_OTG_HCCHAR_EPTYP_Pos) /*!< 0x00040000 */
+#define USB_OTG_HCCHAR_EPTYP_1 (0x2UL << USB_OTG_HCCHAR_EPTYP_Pos) /*!< 0x00080000 */
+
+#define USB_OTG_HCCHAR_MC_Pos (20U)
+#define USB_OTG_HCCHAR_MC_Msk (0x3UL << USB_OTG_HCCHAR_MC_Pos) /*!< 0x00300000 */
+#define USB_OTG_HCCHAR_MC USB_OTG_HCCHAR_MC_Msk /*!< Multi Count (MC) / Error Count (EC) */
+#define USB_OTG_HCCHAR_MC_0 (0x1UL << USB_OTG_HCCHAR_MC_Pos) /*!< 0x00100000 */
+#define USB_OTG_HCCHAR_MC_1 (0x2UL << USB_OTG_HCCHAR_MC_Pos) /*!< 0x00200000 */
+
+#define USB_OTG_HCCHAR_DAD_Pos (22U)
+#define USB_OTG_HCCHAR_DAD_Msk (0x7FUL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x1FC00000 */
+#define USB_OTG_HCCHAR_DAD USB_OTG_HCCHAR_DAD_Msk /*!< Device address */
+#define USB_OTG_HCCHAR_DAD_0 (0x01UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x00400000 */
+#define USB_OTG_HCCHAR_DAD_1 (0x02UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x00800000 */
+#define USB_OTG_HCCHAR_DAD_2 (0x04UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x01000000 */
+#define USB_OTG_HCCHAR_DAD_3 (0x08UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x02000000 */
+#define USB_OTG_HCCHAR_DAD_4 (0x10UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x04000000 */
+#define USB_OTG_HCCHAR_DAD_5 (0x20UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x08000000 */
+#define USB_OTG_HCCHAR_DAD_6 (0x40UL << USB_OTG_HCCHAR_DAD_Pos) /*!< 0x10000000 */
+#define USB_OTG_HCCHAR_ODDFRM_Pos (29U)
+#define USB_OTG_HCCHAR_ODDFRM_Msk (0x1UL << USB_OTG_HCCHAR_ODDFRM_Pos) /*!< 0x20000000 */
+#define USB_OTG_HCCHAR_ODDFRM USB_OTG_HCCHAR_ODDFRM_Msk /*!< Odd frame */
+#define USB_OTG_HCCHAR_CHDIS_Pos (30U)
+#define USB_OTG_HCCHAR_CHDIS_Msk (0x1UL << USB_OTG_HCCHAR_CHDIS_Pos) /*!< 0x40000000 */
+#define USB_OTG_HCCHAR_CHDIS USB_OTG_HCCHAR_CHDIS_Msk /*!< Channel disable */
+#define USB_OTG_HCCHAR_CHENA_Pos (31U)
+#define USB_OTG_HCCHAR_CHENA_Msk (0x1UL << USB_OTG_HCCHAR_CHENA_Pos) /*!< 0x80000000 */
+#define USB_OTG_HCCHAR_CHENA USB_OTG_HCCHAR_CHENA_Msk /*!< Channel enable */
+
+/******************** Bit definition for USB_OTG_HCSPLT register ********************/
+
+#define USB_OTG_HCSPLT_PRTADDR_Pos (0U)
+#define USB_OTG_HCSPLT_PRTADDR_Msk (0x7FUL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x0000007F */
+#define USB_OTG_HCSPLT_PRTADDR USB_OTG_HCSPLT_PRTADDR_Msk /*!< Port address */
+#define USB_OTG_HCSPLT_PRTADDR_0 (0x01UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000001 */
+#define USB_OTG_HCSPLT_PRTADDR_1 (0x02UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000002 */
+#define USB_OTG_HCSPLT_PRTADDR_2 (0x04UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000004 */
+#define USB_OTG_HCSPLT_PRTADDR_3 (0x08UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000008 */
+#define USB_OTG_HCSPLT_PRTADDR_4 (0x10UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000010 */
+#define USB_OTG_HCSPLT_PRTADDR_5 (0x20UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000020 */
+#define USB_OTG_HCSPLT_PRTADDR_6 (0x40UL << USB_OTG_HCSPLT_PRTADDR_Pos) /*!< 0x00000040 */
+
+#define USB_OTG_HCSPLT_HUBADDR_Pos (7U)
+#define USB_OTG_HCSPLT_HUBADDR_Msk (0x7FUL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00003F80 */
+#define USB_OTG_HCSPLT_HUBADDR USB_OTG_HCSPLT_HUBADDR_Msk /*!< Hub address */
+#define USB_OTG_HCSPLT_HUBADDR_0 (0x01UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00000080 */
+#define USB_OTG_HCSPLT_HUBADDR_1 (0x02UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00000100 */
+#define USB_OTG_HCSPLT_HUBADDR_2 (0x04UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00000200 */
+#define USB_OTG_HCSPLT_HUBADDR_3 (0x08UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00000400 */
+#define USB_OTG_HCSPLT_HUBADDR_4 (0x10UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00000800 */
+#define USB_OTG_HCSPLT_HUBADDR_5 (0x20UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00001000 */
+#define USB_OTG_HCSPLT_HUBADDR_6 (0x40UL << USB_OTG_HCSPLT_HUBADDR_Pos) /*!< 0x00002000 */
+
+#define USB_OTG_HCSPLT_XACTPOS_Pos (14U)
+#define USB_OTG_HCSPLT_XACTPOS_Msk (0x3UL << USB_OTG_HCSPLT_XACTPOS_Pos) /*!< 0x0000C000 */
+#define USB_OTG_HCSPLT_XACTPOS USB_OTG_HCSPLT_XACTPOS_Msk /*!< XACTPOS */
+#define USB_OTG_HCSPLT_XACTPOS_0 (0x1UL << USB_OTG_HCSPLT_XACTPOS_Pos) /*!< 0x00004000 */
+#define USB_OTG_HCSPLT_XACTPOS_1 (0x2UL << USB_OTG_HCSPLT_XACTPOS_Pos) /*!< 0x00008000 */
+#define USB_OTG_HCSPLT_COMPLSPLT_Pos (16U)
+#define USB_OTG_HCSPLT_COMPLSPLT_Msk (0x1UL << USB_OTG_HCSPLT_COMPLSPLT_Pos) /*!< 0x00010000 */
+#define USB_OTG_HCSPLT_COMPLSPLT USB_OTG_HCSPLT_COMPLSPLT_Msk /*!< Do complete split */
+#define USB_OTG_HCSPLT_SPLITEN_Pos (31U)
+#define USB_OTG_HCSPLT_SPLITEN_Msk (0x1UL << USB_OTG_HCSPLT_SPLITEN_Pos) /*!< 0x80000000 */
+#define USB_OTG_HCSPLT_SPLITEN USB_OTG_HCSPLT_SPLITEN_Msk /*!< Split enable */
+
+/******************** Bit definition for USB_OTG_HCINT register ********************/
+#define USB_OTG_HCINT_XFRC_Pos (0U)
+#define USB_OTG_HCINT_XFRC_Msk (0x1UL << USB_OTG_HCINT_XFRC_Pos) /*!< 0x00000001 */
+#define USB_OTG_HCINT_XFRC USB_OTG_HCINT_XFRC_Msk /*!< Transfer completed */
+#define USB_OTG_HCINT_CHH_Pos (1U)
+#define USB_OTG_HCINT_CHH_Msk (0x1UL << USB_OTG_HCINT_CHH_Pos) /*!< 0x00000002 */
+#define USB_OTG_HCINT_CHH USB_OTG_HCINT_CHH_Msk /*!< Channel halted */
+#define USB_OTG_HCINT_AHBERR_Pos (2U)
+#define USB_OTG_HCINT_AHBERR_Msk (0x1UL << USB_OTG_HCINT_AHBERR_Pos) /*!< 0x00000004 */
+#define USB_OTG_HCINT_AHBERR USB_OTG_HCINT_AHBERR_Msk /*!< AHB error */
+#define USB_OTG_HCINT_STALL_Pos (3U)
+#define USB_OTG_HCINT_STALL_Msk (0x1UL << USB_OTG_HCINT_STALL_Pos) /*!< 0x00000008 */
+#define USB_OTG_HCINT_STALL USB_OTG_HCINT_STALL_Msk /*!< STALL response received interrupt */
+#define USB_OTG_HCINT_NAK_Pos (4U)
+#define USB_OTG_HCINT_NAK_Msk (0x1UL << USB_OTG_HCINT_NAK_Pos) /*!< 0x00000010 */
+#define USB_OTG_HCINT_NAK USB_OTG_HCINT_NAK_Msk /*!< NAK response received interrupt */
+#define USB_OTG_HCINT_ACK_Pos (5U)
+#define USB_OTG_HCINT_ACK_Msk (0x1UL << USB_OTG_HCINT_ACK_Pos) /*!< 0x00000020 */
+#define USB_OTG_HCINT_ACK USB_OTG_HCINT_ACK_Msk /*!< ACK response received/transmitted interrupt */
+#define USB_OTG_HCINT_NYET_Pos (6U)
+#define USB_OTG_HCINT_NYET_Msk (0x1UL << USB_OTG_HCINT_NYET_Pos) /*!< 0x00000040 */
+#define USB_OTG_HCINT_NYET USB_OTG_HCINT_NYET_Msk /*!< Response received interrupt */
+#define USB_OTG_HCINT_TXERR_Pos (7U)
+#define USB_OTG_HCINT_TXERR_Msk (0x1UL << USB_OTG_HCINT_TXERR_Pos) /*!< 0x00000080 */
+#define USB_OTG_HCINT_TXERR USB_OTG_HCINT_TXERR_Msk /*!< Transaction error */
+#define USB_OTG_HCINT_BBERR_Pos (8U)
+#define USB_OTG_HCINT_BBERR_Msk (0x1UL << USB_OTG_HCINT_BBERR_Pos) /*!< 0x00000100 */
+#define USB_OTG_HCINT_BBERR USB_OTG_HCINT_BBERR_Msk /*!< Babble error */
+#define USB_OTG_HCINT_FRMOR_Pos (9U)
+#define USB_OTG_HCINT_FRMOR_Msk (0x1UL << USB_OTG_HCINT_FRMOR_Pos) /*!< 0x00000200 */
+#define USB_OTG_HCINT_FRMOR USB_OTG_HCINT_FRMOR_Msk /*!< Frame overrun */
+#define USB_OTG_HCINT_DTERR_Pos (10U)
+#define USB_OTG_HCINT_DTERR_Msk (0x1UL << USB_OTG_HCINT_DTERR_Pos) /*!< 0x00000400 */
+#define USB_OTG_HCINT_DTERR USB_OTG_HCINT_DTERR_Msk /*!< Data toggle error */
+
+/******************** Bit definition for USB_OTG_DIEPINT register ********************/
+#define USB_OTG_DIEPINT_XFRC_Pos (0U)
+#define USB_OTG_DIEPINT_XFRC_Msk (0x1UL << USB_OTG_DIEPINT_XFRC_Pos) /*!< 0x00000001 */
+#define USB_OTG_DIEPINT_XFRC USB_OTG_DIEPINT_XFRC_Msk /*!< Transfer completed interrupt */
+#define USB_OTG_DIEPINT_EPDISD_Pos (1U)
+#define USB_OTG_DIEPINT_EPDISD_Msk (0x1UL << USB_OTG_DIEPINT_EPDISD_Pos) /*!< 0x00000002 */
+#define USB_OTG_DIEPINT_EPDISD USB_OTG_DIEPINT_EPDISD_Msk /*!< Endpoint disabled interrupt */
+#define USB_OTG_DIEPINT_AHBERR_Pos (2U)
+#define USB_OTG_DIEPINT_AHBERR_Msk (0x1UL << USB_OTG_DIEPINT_AHBERR_Pos) /*!< 0x00000004 */
+#define USB_OTG_DIEPINT_AHBERR USB_OTG_DIEPINT_AHBERR_Msk /*!< AHB Error (AHBErr) during an IN transaction */
+#define USB_OTG_DIEPINT_TOC_Pos (3U)
+#define USB_OTG_DIEPINT_TOC_Msk (0x1UL << USB_OTG_DIEPINT_TOC_Pos) /*!< 0x00000008 */
+#define USB_OTG_DIEPINT_TOC USB_OTG_DIEPINT_TOC_Msk /*!< Timeout condition */
+#define USB_OTG_DIEPINT_ITTXFE_Pos (4U)
+#define USB_OTG_DIEPINT_ITTXFE_Msk (0x1UL << USB_OTG_DIEPINT_ITTXFE_Pos) /*!< 0x00000010 */
+#define USB_OTG_DIEPINT_ITTXFE USB_OTG_DIEPINT_ITTXFE_Msk /*!< IN token received when TxFIFO is empty */
+#define USB_OTG_DIEPINT_INEPNM_Pos (5U)
+#define USB_OTG_DIEPINT_INEPNM_Msk (0x1UL << USB_OTG_DIEPINT_INEPNM_Pos) /*!< 0x00000004 */
+#define USB_OTG_DIEPINT_INEPNM USB_OTG_DIEPINT_INEPNM_Msk /*!< IN token received with EP mismatch */
+#define USB_OTG_DIEPINT_INEPNE_Pos (6U)
+#define USB_OTG_DIEPINT_INEPNE_Msk (0x1UL << USB_OTG_DIEPINT_INEPNE_Pos) /*!< 0x00000040 */
+#define USB_OTG_DIEPINT_INEPNE USB_OTG_DIEPINT_INEPNE_Msk /*!< IN endpoint NAK effective */
+#define USB_OTG_DIEPINT_TXFE_Pos (7U)
+#define USB_OTG_DIEPINT_TXFE_Msk (0x1UL << USB_OTG_DIEPINT_TXFE_Pos) /*!< 0x00000080 */
+#define USB_OTG_DIEPINT_TXFE USB_OTG_DIEPINT_TXFE_Msk /*!< Transmit FIFO empty */
+#define USB_OTG_DIEPINT_TXFIFOUDRN_Pos (8U)
+#define USB_OTG_DIEPINT_TXFIFOUDRN_Msk (0x1UL << USB_OTG_DIEPINT_TXFIFOUDRN_Pos) /*!< 0x00000100 */
+#define USB_OTG_DIEPINT_TXFIFOUDRN USB_OTG_DIEPINT_TXFIFOUDRN_Msk /*!< Transmit Fifo Underrun */
+#define USB_OTG_DIEPINT_BNA_Pos (9U)
+#define USB_OTG_DIEPINT_BNA_Msk (0x1UL << USB_OTG_DIEPINT_BNA_Pos) /*!< 0x00000200 */
+#define USB_OTG_DIEPINT_BNA USB_OTG_DIEPINT_BNA_Msk /*!< Buffer not available interrupt */
+#define USB_OTG_DIEPINT_PKTDRPSTS_Pos (11U)
+#define USB_OTG_DIEPINT_PKTDRPSTS_Msk (0x1UL << USB_OTG_DIEPINT_PKTDRPSTS_Pos) /*!< 0x00000800 */
+#define USB_OTG_DIEPINT_PKTDRPSTS USB_OTG_DIEPINT_PKTDRPSTS_Msk /*!< Packet dropped status */
+#define USB_OTG_DIEPINT_BERR_Pos (12U)
+#define USB_OTG_DIEPINT_BERR_Msk (0x1UL << USB_OTG_DIEPINT_BERR_Pos) /*!< 0x00001000 */
+#define USB_OTG_DIEPINT_BERR USB_OTG_DIEPINT_BERR_Msk /*!< Babble error interrupt */
+#define USB_OTG_DIEPINT_NAK_Pos (13U)
+#define USB_OTG_DIEPINT_NAK_Msk (0x1UL << USB_OTG_DIEPINT_NAK_Pos) /*!< 0x00002000 */
+#define USB_OTG_DIEPINT_NAK USB_OTG_DIEPINT_NAK_Msk /*!< NAK interrupt */
+
+/******************** Bit definition for USB_OTG_HCINTMSK register ********************/
+#define USB_OTG_HCINTMSK_XFRCM_Pos (0U)
+#define USB_OTG_HCINTMSK_XFRCM_Msk (0x1UL << USB_OTG_HCINTMSK_XFRCM_Pos) /*!< 0x00000001 */
+#define USB_OTG_HCINTMSK_XFRCM USB_OTG_HCINTMSK_XFRCM_Msk /*!< Transfer completed mask */
+#define USB_OTG_HCINTMSK_CHHM_Pos (1U)
+#define USB_OTG_HCINTMSK_CHHM_Msk (0x1UL << USB_OTG_HCINTMSK_CHHM_Pos) /*!< 0x00000002 */
+#define USB_OTG_HCINTMSK_CHHM USB_OTG_HCINTMSK_CHHM_Msk /*!< Channel halted mask */
+#define USB_OTG_HCINTMSK_AHBERR_Pos (2U)
+#define USB_OTG_HCINTMSK_AHBERR_Msk (0x1UL << USB_OTG_HCINTMSK_AHBERR_Pos) /*!< 0x00000004 */
+#define USB_OTG_HCINTMSK_AHBERR USB_OTG_HCINTMSK_AHBERR_Msk /*!< AHB error */
+#define USB_OTG_HCINTMSK_STALLM_Pos (3U)
+#define USB_OTG_HCINTMSK_STALLM_Msk (0x1UL << USB_OTG_HCINTMSK_STALLM_Pos) /*!< 0x00000008 */
+#define USB_OTG_HCINTMSK_STALLM USB_OTG_HCINTMSK_STALLM_Msk /*!< STALL response received interrupt mask */
+#define USB_OTG_HCINTMSK_NAKM_Pos (4U)
+#define USB_OTG_HCINTMSK_NAKM_Msk (0x1UL << USB_OTG_HCINTMSK_NAKM_Pos) /*!< 0x00000010 */
+#define USB_OTG_HCINTMSK_NAKM USB_OTG_HCINTMSK_NAKM_Msk /*!< NAK response received interrupt mask */
+#define USB_OTG_HCINTMSK_ACKM_Pos (5U)
+#define USB_OTG_HCINTMSK_ACKM_Msk (0x1UL << USB_OTG_HCINTMSK_ACKM_Pos) /*!< 0x00000020 */
+#define USB_OTG_HCINTMSK_ACKM USB_OTG_HCINTMSK_ACKM_Msk /*!< ACK response received/transmitted interrupt mask */
+#define USB_OTG_HCINTMSK_NYET_Pos (6U)
+#define USB_OTG_HCINTMSK_NYET_Msk (0x1UL << USB_OTG_HCINTMSK_NYET_Pos) /*!< 0x00000040 */
+#define USB_OTG_HCINTMSK_NYET USB_OTG_HCINTMSK_NYET_Msk /*!< response received interrupt mask */
+#define USB_OTG_HCINTMSK_TXERRM_Pos (7U)
+#define USB_OTG_HCINTMSK_TXERRM_Msk (0x1UL << USB_OTG_HCINTMSK_TXERRM_Pos) /*!< 0x00000080 */
+#define USB_OTG_HCINTMSK_TXERRM USB_OTG_HCINTMSK_TXERRM_Msk /*!< Transaction error mask */
+#define USB_OTG_HCINTMSK_BBERRM_Pos (8U)
+#define USB_OTG_HCINTMSK_BBERRM_Msk (0x1UL << USB_OTG_HCINTMSK_BBERRM_Pos) /*!< 0x00000100 */
+#define USB_OTG_HCINTMSK_BBERRM USB_OTG_HCINTMSK_BBERRM_Msk /*!< Babble error mask */
+#define USB_OTG_HCINTMSK_FRMORM_Pos (9U)
+#define USB_OTG_HCINTMSK_FRMORM_Msk (0x1UL << USB_OTG_HCINTMSK_FRMORM_Pos) /*!< 0x00000200 */
+#define USB_OTG_HCINTMSK_FRMORM USB_OTG_HCINTMSK_FRMORM_Msk /*!< Frame overrun mask */
+#define USB_OTG_HCINTMSK_DTERRM_Pos (10U)
+#define USB_OTG_HCINTMSK_DTERRM_Msk (0x1UL << USB_OTG_HCINTMSK_DTERRM_Pos) /*!< 0x00000400 */
+#define USB_OTG_HCINTMSK_DTERRM USB_OTG_HCINTMSK_DTERRM_Msk /*!< Data toggle error mask */
+
+/******************** Bit definition for USB_OTG_DIEPTSIZ register ********************/
+
+#define USB_OTG_DIEPTSIZ_XFRSIZ_Pos (0U)
+#define USB_OTG_DIEPTSIZ_XFRSIZ_Msk (0x7FFFFUL << USB_OTG_DIEPTSIZ_XFRSIZ_Pos) /*!< 0x0007FFFF */
+#define USB_OTG_DIEPTSIZ_XFRSIZ USB_OTG_DIEPTSIZ_XFRSIZ_Msk /*!< Transfer size */
+#define USB_OTG_DIEPTSIZ_PKTCNT_Pos (19U)
+#define USB_OTG_DIEPTSIZ_PKTCNT_Msk (0x3FFUL << USB_OTG_DIEPTSIZ_PKTCNT_Pos) /*!< 0x1FF80000 */
+#define USB_OTG_DIEPTSIZ_PKTCNT USB_OTG_DIEPTSIZ_PKTCNT_Msk /*!< Packet count */
+#define USB_OTG_DIEPTSIZ_MULCNT_Pos (29U)
+#define USB_OTG_DIEPTSIZ_MULCNT_Msk (0x3UL << USB_OTG_DIEPTSIZ_MULCNT_Pos) /*!< 0x60000000 */
+#define USB_OTG_DIEPTSIZ_MULCNT USB_OTG_DIEPTSIZ_MULCNT_Msk /*!< Packet count */
+/******************** Bit definition for USB_OTG_HCTSIZ register ********************/
+#define USB_OTG_HCTSIZ_XFRSIZ_Pos (0U)
+#define USB_OTG_HCTSIZ_XFRSIZ_Msk (0x7FFFFUL << USB_OTG_HCTSIZ_XFRSIZ_Pos) /*!< 0x0007FFFF */
+#define USB_OTG_HCTSIZ_XFRSIZ USB_OTG_HCTSIZ_XFRSIZ_Msk /*!< Transfer size */
+#define USB_OTG_HCTSIZ_PKTCNT_Pos (19U)
+#define USB_OTG_HCTSIZ_PKTCNT_Msk (0x3FFUL << USB_OTG_HCTSIZ_PKTCNT_Pos) /*!< 0x1FF80000 */
+#define USB_OTG_HCTSIZ_PKTCNT USB_OTG_HCTSIZ_PKTCNT_Msk /*!< Packet count */
+#define USB_OTG_HCTSIZ_DOPING_Pos (31U)
+#define USB_OTG_HCTSIZ_DOPING_Msk (0x1UL << USB_OTG_HCTSIZ_DOPING_Pos) /*!< 0x80000000 */
+#define USB_OTG_HCTSIZ_DOPING USB_OTG_HCTSIZ_DOPING_Msk /*!< Do PING */
+#define USB_OTG_HCTSIZ_DPID_Pos (29U)
+#define USB_OTG_HCTSIZ_DPID_Msk (0x3UL << USB_OTG_HCTSIZ_DPID_Pos) /*!< 0x60000000 */
+#define USB_OTG_HCTSIZ_DPID USB_OTG_HCTSIZ_DPID_Msk /*!< Data PID */
+#define USB_OTG_HCTSIZ_DPID_0 (0x1UL << USB_OTG_HCTSIZ_DPID_Pos) /*!< 0x20000000 */
+#define USB_OTG_HCTSIZ_DPID_1 (0x2UL << USB_OTG_HCTSIZ_DPID_Pos) /*!< 0x40000000 */
+
+/******************** Bit definition for USB_OTG_DIEPDMA register ********************/
+#define USB_OTG_DIEPDMA_DMAADDR_Pos (0U)
+#define USB_OTG_DIEPDMA_DMAADDR_Msk (0xFFFFFFFFUL << USB_OTG_DIEPDMA_DMAADDR_Pos) /*!< 0xFFFFFFFF */
+#define USB_OTG_DIEPDMA_DMAADDR USB_OTG_DIEPDMA_DMAADDR_Msk /*!< DMA address */
+
+/******************** Bit definition for USB_OTG_HCDMA register ********************/
+#define USB_OTG_HCDMA_DMAADDR_Pos (0U)
+#define USB_OTG_HCDMA_DMAADDR_Msk (0xFFFFFFFFUL << USB_OTG_HCDMA_DMAADDR_Pos) /*!< 0xFFFFFFFF */
+#define USB_OTG_HCDMA_DMAADDR USB_OTG_HCDMA_DMAADDR_Msk /*!< DMA address */
+
+/******************** Bit definition for USB_OTG_DTXFSTS register ********************/
+#define USB_OTG_DTXFSTS_INEPTFSAV_Pos (0U)
+#define USB_OTG_DTXFSTS_INEPTFSAV_Msk (0xFFFFUL << USB_OTG_DTXFSTS_INEPTFSAV_Pos) /*!< 0x0000FFFF */
+#define USB_OTG_DTXFSTS_INEPTFSAV USB_OTG_DTXFSTS_INEPTFSAV_Msk /*!< IN endpoint TxFIFO space available */
+
+/******************** Bit definition for USB_OTG_DIEPTXF register ********************/
+#define USB_OTG_DIEPTXF_INEPTXSA_Pos (0U)
+#define USB_OTG_DIEPTXF_INEPTXSA_Msk (0xFFFFUL << USB_OTG_DIEPTXF_INEPTXSA_Pos) /*!< 0x0000FFFF */
+#define USB_OTG_DIEPTXF_INEPTXSA USB_OTG_DIEPTXF_INEPTXSA_Msk /*!< IN endpoint FIFOx transmit RAM start address */
+#define USB_OTG_DIEPTXF_INEPTXFD_Pos (16U)
+#define USB_OTG_DIEPTXF_INEPTXFD_Msk (0xFFFFUL << USB_OTG_DIEPTXF_INEPTXFD_Pos) /*!< 0xFFFF0000 */
+#define USB_OTG_DIEPTXF_INEPTXFD USB_OTG_DIEPTXF_INEPTXFD_Msk /*!< IN endpoint TxFIFO depth */
+
+/******************** Bit definition for USB_OTG_DOEPCTL register ********************/
+
+#define USB_OTG_DOEPCTL_MPSIZ_Pos (0U)
+#define USB_OTG_DOEPCTL_MPSIZ_Msk (0x7FFUL << USB_OTG_DOEPCTL_MPSIZ_Pos) /*!< 0x000007FF */
+#define USB_OTG_DOEPCTL_MPSIZ USB_OTG_DOEPCTL_MPSIZ_Msk /*!< Maximum packet size */ /*!<Bit 1 */
+#define USB_OTG_DOEPCTL_USBAEP_Pos (15U)
+#define USB_OTG_DOEPCTL_USBAEP_Msk (0x1UL << USB_OTG_DOEPCTL_USBAEP_Pos) /*!< 0x00008000 */
+#define USB_OTG_DOEPCTL_USBAEP USB_OTG_DOEPCTL_USBAEP_Msk /*!< USB active endpoint */
+#define USB_OTG_DOEPCTL_NAKSTS_Pos (17U)
+#define USB_OTG_DOEPCTL_NAKSTS_Msk (0x1UL << USB_OTG_DOEPCTL_NAKSTS_Pos) /*!< 0x00020000 */
+#define USB_OTG_DOEPCTL_NAKSTS USB_OTG_DOEPCTL_NAKSTS_Msk /*!< NAK status */
+#define USB_OTG_DOEPCTL_SD0PID_SEVNFRM_Pos (28U)
+#define USB_OTG_DOEPCTL_SD0PID_SEVNFRM_Msk (0x1UL << USB_OTG_DOEPCTL_SD0PID_SEVNFRM_Pos) /*!< 0x10000000 */
+#define USB_OTG_DOEPCTL_SD0PID_SEVNFRM USB_OTG_DOEPCTL_SD0PID_SEVNFRM_Msk /*!< Set DATA0 PID */
+#define USB_OTG_DOEPCTL_SODDFRM_Pos (29U)
+#define USB_OTG_DOEPCTL_SODDFRM_Msk (0x1UL << USB_OTG_DOEPCTL_SODDFRM_Pos) /*!< 0x20000000 */
+#define USB_OTG_DOEPCTL_SODDFRM USB_OTG_DOEPCTL_SODDFRM_Msk /*!< Set odd frame */
+#define USB_OTG_DOEPCTL_EPTYP_Pos (18U)
+#define USB_OTG_DOEPCTL_EPTYP_Msk (0x3UL << USB_OTG_DOEPCTL_EPTYP_Pos) /*!< 0x000C0000 */
+#define USB_OTG_DOEPCTL_EPTYP USB_OTG_DOEPCTL_EPTYP_Msk /*!< Endpoint type */
+#define USB_OTG_DOEPCTL_EPTYP_0 (0x1UL << USB_OTG_DOEPCTL_EPTYP_Pos) /*!< 0x00040000 */
+#define USB_OTG_DOEPCTL_EPTYP_1 (0x2UL << USB_OTG_DOEPCTL_EPTYP_Pos) /*!< 0x00080000 */
+#define USB_OTG_DOEPCTL_SNPM_Pos (20U)
+#define USB_OTG_DOEPCTL_SNPM_Msk (0x1UL << USB_OTG_DOEPCTL_SNPM_Pos) /*!< 0x00100000 */
+#define USB_OTG_DOEPCTL_SNPM USB_OTG_DOEPCTL_SNPM_Msk /*!< Snoop mode */
+#define USB_OTG_DOEPCTL_STALL_Pos (21U)
+#define USB_OTG_DOEPCTL_STALL_Msk (0x1UL << USB_OTG_DOEPCTL_STALL_Pos) /*!< 0x00200000 */
+#define USB_OTG_DOEPCTL_STALL USB_OTG_DOEPCTL_STALL_Msk /*!< STALL handshake */
+#define USB_OTG_DOEPCTL_CNAK_Pos (26U)
+#define USB_OTG_DOEPCTL_CNAK_Msk (0x1UL << USB_OTG_DOEPCTL_CNAK_Pos) /*!< 0x04000000 */
+#define USB_OTG_DOEPCTL_CNAK USB_OTG_DOEPCTL_CNAK_Msk /*!< Clear NAK */
+#define USB_OTG_DOEPCTL_SNAK_Pos (27U)
+#define USB_OTG_DOEPCTL_SNAK_Msk (0x1UL << USB_OTG_DOEPCTL_SNAK_Pos) /*!< 0x08000000 */
+#define USB_OTG_DOEPCTL_SNAK USB_OTG_DOEPCTL_SNAK_Msk /*!< Set NAK */
+#define USB_OTG_DOEPCTL_EPDIS_Pos (30U)
+#define USB_OTG_DOEPCTL_EPDIS_Msk (0x1UL << USB_OTG_DOEPCTL_EPDIS_Pos) /*!< 0x40000000 */
+#define USB_OTG_DOEPCTL_EPDIS USB_OTG_DOEPCTL_EPDIS_Msk /*!< Endpoint disable */
+#define USB_OTG_DOEPCTL_EPENA_Pos (31U)
+#define USB_OTG_DOEPCTL_EPENA_Msk (0x1UL << USB_OTG_DOEPCTL_EPENA_Pos) /*!< 0x80000000 */
+#define USB_OTG_DOEPCTL_EPENA USB_OTG_DOEPCTL_EPENA_Msk /*!< Endpoint enable */
+
+/******************** Bit definition for USB_OTG_DOEPINT register ********************/
+#define USB_OTG_DOEPINT_XFRC_Pos (0U)
+#define USB_OTG_DOEPINT_XFRC_Msk (0x1UL << USB_OTG_DOEPINT_XFRC_Pos) /*!< 0x00000001 */
+#define USB_OTG_DOEPINT_XFRC USB_OTG_DOEPINT_XFRC_Msk /*!< Transfer completed interrupt */
+#define USB_OTG_DOEPINT_EPDISD_Pos (1U)
+#define USB_OTG_DOEPINT_EPDISD_Msk (0x1UL << USB_OTG_DOEPINT_EPDISD_Pos) /*!< 0x00000002 */
+#define USB_OTG_DOEPINT_EPDISD USB_OTG_DOEPINT_EPDISD_Msk /*!< Endpoint disabled interrupt */
+#define USB_OTG_DOEPINT_AHBERR_Pos (2U)
+#define USB_OTG_DOEPINT_AHBERR_Msk (0x1UL << USB_OTG_DOEPINT_AHBERR_Pos) /*!< 0x00000004 */
+#define USB_OTG_DOEPINT_AHBERR USB_OTG_DOEPINT_AHBERR_Msk /*!< AHB Error (AHBErr) during an OUT transaction */
+#define USB_OTG_DOEPINT_STUP_Pos (3U)
+#define USB_OTG_DOEPINT_STUP_Msk (0x1UL << USB_OTG_DOEPINT_STUP_Pos) /*!< 0x00000008 */
+#define USB_OTG_DOEPINT_STUP USB_OTG_DOEPINT_STUP_Msk /*!< SETUP phase done */
+#define USB_OTG_DOEPINT_OTEPDIS_Pos (4U)
+#define USB_OTG_DOEPINT_OTEPDIS_Msk (0x1UL << USB_OTG_DOEPINT_OTEPDIS_Pos) /*!< 0x00000010 */
+#define USB_OTG_DOEPINT_OTEPDIS USB_OTG_DOEPINT_OTEPDIS_Msk /*!< OUT token received when endpoint disabled */
+#define USB_OTG_DOEPINT_OTEPSPR_Pos (5U)
+#define USB_OTG_DOEPINT_OTEPSPR_Msk (0x1UL << USB_OTG_DOEPINT_OTEPSPR_Pos) /*!< 0x00000020 */
+#define USB_OTG_DOEPINT_OTEPSPR USB_OTG_DOEPINT_OTEPSPR_Msk /*!< Status Phase Received For Control Write */
+#define USB_OTG_DOEPINT_B2BSTUP_Pos (6U)
+#define USB_OTG_DOEPINT_B2BSTUP_Msk (0x1UL << USB_OTG_DOEPINT_B2BSTUP_Pos) /*!< 0x00000040 */
+#define USB_OTG_DOEPINT_B2BSTUP USB_OTG_DOEPINT_B2BSTUP_Msk /*!< Back-to-back SETUP packets received */
+#define USB_OTG_DOEPINT_OUTPKTERR_Pos (8U)
+#define USB_OTG_DOEPINT_OUTPKTERR_Msk (0x1UL << USB_OTG_DOEPINT_OUTPKTERR_Pos) /*!< 0x00000100 */
+#define USB_OTG_DOEPINT_OUTPKTERR USB_OTG_DOEPINT_OUTPKTERR_Msk /*!< OUT packet error */
+#define USB_OTG_DOEPINT_NAK_Pos (13U)
+#define USB_OTG_DOEPINT_NAK_Msk (0x1UL << USB_OTG_DOEPINT_NAK_Pos) /*!< 0x00002000 */
+#define USB_OTG_DOEPINT_NAK USB_OTG_DOEPINT_NAK_Msk /*!< NAK Packet is transmitted by the device */
+#define USB_OTG_DOEPINT_NYET_Pos (14U)
+#define USB_OTG_DOEPINT_NYET_Msk (0x1UL << USB_OTG_DOEPINT_NYET_Pos) /*!< 0x00004000 */
+#define USB_OTG_DOEPINT_NYET USB_OTG_DOEPINT_NYET_Msk /*!< NYET interrupt */
+#define USB_OTG_DOEPINT_STPKTRX_Pos (15U)
+#define USB_OTG_DOEPINT_STPKTRX_Msk (0x1UL << USB_OTG_DOEPINT_STPKTRX_Pos) /*!< 0x00008000 */
+#define USB_OTG_DOEPINT_STPKTRX USB_OTG_DOEPINT_STPKTRX_Msk /*!< Setup Packet Received */
+/******************** Bit definition for USB_OTG_DOEPTSIZ register ********************/
+
+#define USB_OTG_DOEPTSIZ_XFRSIZ_Pos (0U)
+#define USB_OTG_DOEPTSIZ_XFRSIZ_Msk (0x7FFFFUL << USB_OTG_DOEPTSIZ_XFRSIZ_Pos) /*!< 0x0007FFFF */
+#define USB_OTG_DOEPTSIZ_XFRSIZ USB_OTG_DOEPTSIZ_XFRSIZ_Msk /*!< Transfer size */
+#define USB_OTG_DOEPTSIZ_PKTCNT_Pos (19U)
+#define USB_OTG_DOEPTSIZ_PKTCNT_Msk (0x3FFUL << USB_OTG_DOEPTSIZ_PKTCNT_Pos) /*!< 0x1FF80000 */
+#define USB_OTG_DOEPTSIZ_PKTCNT USB_OTG_DOEPTSIZ_PKTCNT_Msk /*!< Packet count */
+
+#define USB_OTG_DOEPTSIZ_STUPCNT_Pos (29U)
+#define USB_OTG_DOEPTSIZ_STUPCNT_Msk (0x3UL << USB_OTG_DOEPTSIZ_STUPCNT_Pos) /*!< 0x60000000 */
+#define USB_OTG_DOEPTSIZ_STUPCNT USB_OTG_DOEPTSIZ_STUPCNT_Msk /*!< SETUP packet count */
+#define USB_OTG_DOEPTSIZ_STUPCNT_0 (0x1UL << USB_OTG_DOEPTSIZ_STUPCNT_Pos) /*!< 0x20000000 */
+#define USB_OTG_DOEPTSIZ_STUPCNT_1 (0x2UL << USB_OTG_DOEPTSIZ_STUPCNT_Pos) /*!< 0x40000000 */
+
+/******************** Bit definition for PCGCCTL register ********************/
+#define USB_OTG_PCGCCTL_STOPCLK_Pos (0U)
+#define USB_OTG_PCGCCTL_STOPCLK_Msk (0x1UL << USB_OTG_PCGCCTL_STOPCLK_Pos) /*!< 0x00000001 */
+#define USB_OTG_PCGCCTL_STOPCLK USB_OTG_PCGCCTL_STOPCLK_Msk /*!< SETUP packet count */
+#define USB_OTG_PCGCCTL_GATECLK_Pos (1U)
+#define USB_OTG_PCGCCTL_GATECLK_Msk (0x1UL << USB_OTG_PCGCCTL_GATECLK_Pos) /*!< 0x00000002 */
+#define USB_OTG_PCGCCTL_GATECLK USB_OTG_PCGCCTL_GATECLK_Msk /*!<Bit 0 */
+#define USB_OTG_PCGCCTL_PHYSUSP_Pos (4U)
+#define USB_OTG_PCGCCTL_PHYSUSP_Msk (0x1UL << USB_OTG_PCGCCTL_PHYSUSP_Pos) /*!< 0x00000010 */
+#define USB_OTG_PCGCCTL_PHYSUSP USB_OTG_PCGCCTL_PHYSUSP_Msk /*!<Bit 1 */
+
+/* Legacy define */
+/******************** Bit definition for OTG register ********************/
+#define USB_OTG_CHNUM_Pos (0U)
+#define USB_OTG_CHNUM_Msk (0xFUL << USB_OTG_CHNUM_Pos) /*!< 0x0000000F */
+#define USB_OTG_CHNUM USB_OTG_CHNUM_Msk /*!< Channel number */
+#define USB_OTG_CHNUM_0 (0x1UL << USB_OTG_CHNUM_Pos) /*!< 0x00000001 */
+#define USB_OTG_CHNUM_1 (0x2UL << USB_OTG_CHNUM_Pos) /*!< 0x00000002 */
+#define USB_OTG_CHNUM_2 (0x4UL << USB_OTG_CHNUM_Pos) /*!< 0x00000004 */
+#define USB_OTG_CHNUM_3 (0x8UL << USB_OTG_CHNUM_Pos) /*!< 0x00000008 */
+#define USB_OTG_BCNT_Pos (4U)
+#define USB_OTG_BCNT_Msk (0x7FFUL << USB_OTG_BCNT_Pos) /*!< 0x00007FF0 */
+#define USB_OTG_BCNT USB_OTG_BCNT_Msk /*!< Byte count */
+
+#define USB_OTG_DPID_Pos (15U)
+#define USB_OTG_DPID_Msk (0x3UL << USB_OTG_DPID_Pos) /*!< 0x00018000 */
+#define USB_OTG_DPID USB_OTG_DPID_Msk /*!< Data PID */
+#define USB_OTG_DPID_0 (0x1UL << USB_OTG_DPID_Pos) /*!< 0x00008000 */
+#define USB_OTG_DPID_1 (0x2UL << USB_OTG_DPID_Pos) /*!< 0x00010000 */
+
+#define USB_OTG_PKTSTS_Pos (17U)
+#define USB_OTG_PKTSTS_Msk (0xFUL << USB_OTG_PKTSTS_Pos) /*!< 0x001E0000 */
+#define USB_OTG_PKTSTS USB_OTG_PKTSTS_Msk /*!< Packet status */
+#define USB_OTG_PKTSTS_0 (0x1UL << USB_OTG_PKTSTS_Pos) /*!< 0x00020000 */
+#define USB_OTG_PKTSTS_1 (0x2UL << USB_OTG_PKTSTS_Pos) /*!< 0x00040000 */
+#define USB_OTG_PKTSTS_2 (0x4UL << USB_OTG_PKTSTS_Pos) /*!< 0x00080000 */
+#define USB_OTG_PKTSTS_3 (0x8UL << USB_OTG_PKTSTS_Pos) /*!< 0x00100000 */
+
+#define USB_OTG_EPNUM_Pos (0U)
+#define USB_OTG_EPNUM_Msk (0xFUL << USB_OTG_EPNUM_Pos) /*!< 0x0000000F */
+#define USB_OTG_EPNUM USB_OTG_EPNUM_Msk /*!< Endpoint number */
+#define USB_OTG_EPNUM_0 (0x1UL << USB_OTG_EPNUM_Pos) /*!< 0x00000001 */
+#define USB_OTG_EPNUM_1 (0x2UL << USB_OTG_EPNUM_Pos) /*!< 0x00000002 */
+#define USB_OTG_EPNUM_2 (0x4UL << USB_OTG_EPNUM_Pos) /*!< 0x00000004 */
+#define USB_OTG_EPNUM_3 (0x8UL << USB_OTG_EPNUM_Pos) /*!< 0x00000008 */
+
+#define USB_OTG_FRMNUM_Pos (21U)
+#define USB_OTG_FRMNUM_Msk (0xFUL << USB_OTG_FRMNUM_Pos) /*!< 0x01E00000 */
+#define USB_OTG_FRMNUM USB_OTG_FRMNUM_Msk /*!< Frame number */
+#define USB_OTG_FRMNUM_0 (0x1UL << USB_OTG_FRMNUM_Pos) /*!< 0x00200000 */
+#define USB_OTG_FRMNUM_1 (0x2UL << USB_OTG_FRMNUM_Pos) /*!< 0x00400000 */
+#define USB_OTG_FRMNUM_2 (0x4UL << USB_OTG_FRMNUM_Pos) /*!< 0x00800000 */
+#define USB_OTG_FRMNUM_3 (0x8UL << USB_OTG_FRMNUM_Pos) /*!< 0x01000000 */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c
index 12b9144bf..977369300 100644
--- a/src/portable/template/dcd_template.c
+++ b/src/portable/template/dcd_template.c
@@ -94,6 +94,11 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc)
return false;
}
+void dcd_edpt_close_all (uint8_t rhport)
+{
+ (void) rhport;
+}
+
// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack
bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
{
diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c
index 027ed26c9..ee85f0a77 100644
--- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c
+++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c
@@ -298,6 +298,12 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
return true;
}
+void dcd_edpt_close_all (uint8_t rhport)
+{
+ (void) rhport;
+ // TODO implement dcd_edpt_close_all()
+}
+
bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
{
(void) rhport;
diff --git a/src/portable/valentyusb/eptri/dcd_eptri.c b/src/portable/valentyusb/eptri/dcd_eptri.c
index b68f04faa..89bc7a1ab 100644
--- a/src/portable/valentyusb/eptri/dcd_eptri.c
+++ b/src/portable/valentyusb/eptri/dcd_eptri.c
@@ -429,6 +429,12 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
return true;
}
+void dcd_edpt_close_all (uint8_t rhport)
+{
+ (void) rhport;
+ // TODO implement dcd_edpt_close_all()
+}
+
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
{
(void) rhport;
diff --git a/src/tusb.c b/src/tusb.c
index 0350fa1de..6494287d2 100644
--- a/src/tusb.c
+++ b/src/tusb.c
@@ -63,6 +63,99 @@ bool tusb_inited(void)
return ret;
}
+//--------------------------------------------------------------------+
+// Internal Helper for both Host and Device stack
+//--------------------------------------------------------------------+
+
+bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed)
+{
+ uint16_t const max_packet_size = tu_le16toh(desc_ep->wMaxPacketSize.size);
+ TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, max_packet_size);
+
+ switch (desc_ep->bmAttributes.xfer)
+ {
+ case TUSB_XFER_ISOCHRONOUS:
+ {
+ uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 1023);
+ TU_ASSERT(max_packet_size <= spec_size);
+ }
+ break;
+
+ case TUSB_XFER_BULK:
+ if (speed == TUSB_SPEED_HIGH)
+ {
+ // Bulk highspeed must be EXACTLY 512
+ TU_ASSERT(max_packet_size == 512);
+ }else
+ {
+ // TODO Bulk fullspeed can only be 8, 16, 32, 64
+ TU_ASSERT(max_packet_size <= 64);
+ }
+ break;
+
+ case TUSB_XFER_INTERRUPT:
+ {
+ uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 64);
+ TU_ASSERT(max_packet_size <= spec_size);
+ }
+ break;
+
+ default: return false;
+ }
+
+ return true;
+}
+
+void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_itf, uint16_t desc_len, uint8_t driver_id)
+{
+ uint8_t const* p_desc = (uint8_t const*) desc_itf;
+ uint16_t len = 0;
+
+ while( len < desc_len )
+ {
+ if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) )
+ {
+ uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress;
+
+ TU_LOG(2, " Bind EP %02x to driver id %u\r\n", ep_addr, driver_id);
+ ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id;
+ }
+
+ len = (uint16_t)(len + tu_desc_len(p_desc));
+ p_desc = tu_desc_next(p_desc);
+ }
+}
+
+uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len)
+{
+ uint8_t const* p_desc = (uint8_t const*) desc_itf;
+ uint16_t len = 0;
+
+ while (itf_count--)
+ {
+ // Next on interface desc
+ len += tu_desc_len(desc_itf);
+ p_desc = tu_desc_next(p_desc);
+
+ while (len < max_len)
+ {
+ // return on IAD regardless of itf count
+ if ( tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION ) return len;
+
+ if ( (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) &&
+ ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0 )
+ {
+ break;
+ }
+
+ len += tu_desc_len(p_desc);
+ p_desc = tu_desc_next(p_desc);
+ }
+ }
+
+ return len;
+}
+
/*------------------------------------------------------------------*/
/* Debug
*------------------------------------------------------------------*/
diff --git a/src/tusb.h b/src/tusb.h
index 2b1d7483a..b52f8839a 100644
--- a/src/tusb.h
+++ b/src/tusb.h
@@ -96,7 +96,7 @@
#include "class/dfu/dfu_rt_device.h"
#endif
- #if CFG_TUD_DFU_MODE
+ #if CFG_TUD_DFU
#include "class/dfu/dfu_device.h"
#endif
diff --git a/src/tusb_option.h b/src/tusb_option.h
index 5cfcc08e2..a00f3489f 100644
--- a/src/tusb_option.h
+++ b/src/tusb_option.h
@@ -28,13 +28,15 @@
#define _TUSB_OPTION_H_
#define TUSB_VERSION_MAJOR 0
-#define TUSB_VERSION_MINOR 10
-#define TUSB_VERSION_REVISION 1
+#define TUSB_VERSION_MINOR 11
+#define TUSB_VERSION_REVISION 0
#define TUSB_VERSION_STRING TU_STRING(TUSB_VERSION_MAJOR) "." TU_STRING(TUSB_VERSION_MINOR) "." TU_STRING(TUSB_VERSION_REVISION)
-/** \defgroup group_mcu Supported MCU
- * \ref CFG_TUSB_MCU must be defined to one of these
- * @{ */
+//--------------------------------------------------------------------+
+// Supported MCUs
+// CFG_TUSB_MCU must be defined to one of following value
+//--------------------------------------------------------------------+
+#define TU_CHECK_MCU(_m) (CFG_TUSB_MCU == OPT_MCU_##_m)
#define OPT_MCU_NONE 0
@@ -61,6 +63,8 @@
#define OPT_MCU_SAME5X 203 ///< MicroChip SAM E5x
#define OPT_MCU_SAMD11 204 ///< MicroChip SAMD11
#define OPT_MCU_SAML22 205 ///< MicroChip SAML22
+#define OPT_MCU_SAML21 206 ///< MicroChip SAML21
+#define OPT_MCU_SAMX7X 207 ///< MicroChip SAME70, S70, V70, V71 family
// STM32
#define OPT_MCU_STM32F0 300 ///< ST STM32F0
@@ -104,6 +108,7 @@
// NXP Kinetis
#define OPT_MCU_MKL25ZXX 1200 ///< NXP MKL25Zxx
+#define OPT_MCU_K32L2BXX 1201 ///< NXP K32L2Bxx
// Silabs
#define OPT_MCU_EFM32GG 1300 ///< Silabs EFM32GG
@@ -112,22 +117,25 @@
// Renesas RX
#define OPT_MCU_RX63X 1400 ///< Renesas RX63N/631
+#define OPT_MCU_RX65X 1401 ///< Renesas RX65N/RX651
+#define OPT_MCU_RX72N 1402 ///< Renesas RX72N
// Mind Motion
#define OPT_MCU_MM32F327X 1500 ///< Mind Motion MM32F327
-/** @} */
+// GigaDevice
+#define OPT_MCU_GD32VF103 1600 ///< GigaDevice GD32VF103
+
+//--------------------------------------------------------------------+
+// Supported OS
+//--------------------------------------------------------------------+
-/** \defgroup group_supported_os Supported RTOS
- * \ref CFG_TUSB_OS must be defined to one of these
- * @{ */
#define OPT_OS_NONE 1 ///< No RTOS
#define OPT_OS_FREERTOS 2 ///< FreeRTOS
#define OPT_OS_MYNEWT 3 ///< Mynewt OS
#define OPT_OS_CUSTOM 4 ///< Custom OS is implemented by application
#define OPT_OS_PICO 5 ///< Raspberry Pi Pico SDK
#define OPT_OS_RTTHREAD 6 ///< RT-Thread
-/** @} */
// Allow to use command line to change the config name/location
#ifdef CFG_TUSB_CONFIG_FILE
@@ -136,10 +144,6 @@
#include "tusb_config.h"
#endif
-/** \addtogroup group_configuration
- * @{ */
-
-
//--------------------------------------------------------------------
// RootHub Mode Configuration
// CFG_TUSB_RHPORTx_MODE contains operation mode and speed for that port
@@ -247,12 +251,8 @@
#define CFG_TUD_DFU_RUNTIME 0
#endif
-#ifndef CFG_TUD_DFU_MODE
- #define CFG_TUD_DFU_MODE 0
-#endif
-
-#ifndef CFG_TUD_DFU_TRANSFER_BUFFER_SIZE
- #define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 64
+#ifndef CFG_TUD_DFU
+ #define CFG_TUD_DFU 0
#endif
#ifndef CFG_TUD_NET
@@ -267,30 +267,23 @@
// HOST OPTIONS
//--------------------------------------------------------------------
#if TUSB_OPT_HOST_ENABLED
- #ifndef CFG_TUSB_HOST_DEVICE_MAX
- #define CFG_TUSB_HOST_DEVICE_MAX 1
- #warning CFG_TUSB_HOST_DEVICE_MAX is not defined, default value is 1
+ #ifndef CFG_TUH_DEVICE_MAX
+ #define CFG_TUH_DEVICE_MAX 1
#endif
- //------------- HUB CLASS -------------//
- #if CFG_TUH_HUB && (CFG_TUSB_HOST_DEVICE_MAX == 1)
- #error there is no benefit enable hub with max device is 1. Please disable hub or increase CFG_TUSB_HOST_DEVICE_MAX
- #endif
-
- #ifndef CFG_TUH_ENUMERATION_BUFSZIE
- #define CFG_TUH_ENUMERATION_BUFSZIE 256
+ #ifndef CFG_TUH_ENUMERATION_BUFSIZE
+ #define CFG_TUH_ENUMERATION_BUFSIZE 256
#endif
//------------- CLASS -------------//
#endif // TUSB_OPT_HOST_ENABLED
//--------------------------------------------------------------------+
-// Port Options
-// TUP for TinyUSB Port (can be renamed)
+// Port Specific
+// TUP stand for TinyUSB Port (can be renamed)
//--------------------------------------------------------------------+
-// TUP_ARCH_STRICT_ALIGN if arch cannot access unaligned memory
-
+//------------- Unaligned Memory -------------//
// ARMv7+ (M3-M7, M23-M33) can access unaligned memory
#if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7))
@@ -309,6 +302,7 @@
#define TUP_MCU_STRICT_ALIGN 0
#endif
+
//------------------------------------------------------------------
// Configuration Validation
//------------------------------------------------------------------