32#if CFG_TUD_ENABLED && defined(TUP_USBIP_DWC2)
55#define XFER_CTL_BASE(_ep, _dir) (&xfer_status[_ep][_dir])
80 if (dwc2->
gsnpsid >= DWC2_CORE_REV_3_00a) {
87 dwc2->
epout[0].
doeptsiz = (1 << DOEPTSIZ_STUPCNT_Pos) | (1 << DOEPTSIZ_PKTCNT_Pos) | (8 << DOEPTSIZ_XFRSIZ_Pos);
89 dwc2->
epout[0].
doepctl |= DOEPCTL_EPENA | DOEPCTL_USBAEP;
139TU_ATTR_ALWAYS_INLINE
static inline uint16_t
calc_device_grxfsiz(uint16_t largest_ep_size, uint8_t ep_count) {
140 return 13 + 1 + 2 * ((largest_ep_size / 4) + 1) + 2 * ep_count;
143static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) {
146 uint8_t
const ep_count = dwc2_controller->ep_count;
150 TU_ASSERT(epnum < ep_count);
165 TU_ASSERT(_allocated_ep_in_count < _dwc2_controller->ep_in_count);
170 if ((dwc2->
gahbcfg & GAHBCFG_TX_FIFO_EPMTY_LVL) == 0) {
177 TU_LOG(DWC2_DEBUG,
" TX FIFO %u: allocated %u words at offset %u\r\n", epnum, fifo_size,
_dfifo_top);
222 uint32_t epctl = (1 << DOEPCTL_USBAEP_Pos) |
223 (p_endpoint_desc->
bmAttributes.xfer << DOEPCTL_EPTYP_Pos) |
225 (
xfer->max_size << DOEPCTL_MPSIZ_Pos);
227 epctl |= (epnum << DIEPCTL_TXFNUM_Pos);
232 dwc2->
daintmsk |= TU_BIT(epnum + DAINT_SHIFT(dir));
245 if ((epnum == 0) || !(dep->
diepctl & DIEPCTL_EPENA)) {
246 dep->
diepctl |= DIEPCTL_SNAK | (stall ? DIEPCTL_STALL : 0);
250 while ((dep->
diepint & DIEPINT_INEPNE) == 0) {}
253 dep->
diepctl |= DIEPCTL_EPDIS | (stall ? DIEPCTL_STALL : 0);
254 while ((dep->
diepint & DIEPINT_EPDISD_Msk) == 0) {}
263 if ((epnum == 0) || !(dep->
doepctl & DOEPCTL_EPENA)) {
264 dep->
doepctl |= stall ? DOEPCTL_STALL : 0;
270 dwc2->
dctl |= DCTL_SGONAK;
271 while ((dwc2->
gintsts & GINTSTS_BOUTNAKEFF_Msk) == 0) {}
274 dep->
doepctl |= DOEPCTL_EPDIS | (stall ? DOEPCTL_STALL : 0);
275 while ((dep->
doepint & DOEPINT_EPDISD_Msk) == 0) {}
280 dwc2->
dctl |= DCTL_CGONAK;
296 for (uint8_t n = 0; n < ep_count; n++) {
301 for (uint8_t n = 0; n < ep_count; n++) {
303 dwc2->
epin[n].
diepctl |= DIEPCTL_SNAK | DIEPCTL_EPDIS;
311 dwc2->
daintmsk = TU_BIT(DAINTMSK_OEPM_Pos) | TU_BIT(DAINTMSK_IEPM_Pos);
312 dwc2->
doepmsk = DOEPMSK_STUPM | DOEPMSK_XFRCM;
313 dwc2->
diepmsk = DIEPMSK_TOM | DIEPMSK_XFRCM;
319 dwc2->
dcfg &= ~DCFG_DAD_Msk;
322 dwc2->
epin[0].
diepctl &= ~(0x03 << DIEPCTL_MPSIZ_Pos);
334 dwc2->
gintmsk |= GINTMSK_OEPINT | GINTMSK_IEPINT;
337static void edpt_schedule_packets(uint8_t rhport, uint8_t
const epnum, uint8_t
const dir, uint16_t
const num_packets,
352 const uint8_t is_epout = 1 - dir;
357 dep->
dieptsiz = (num_packets << DIEPTSIZ_PKTCNT_Pos) |
358 ((
total_bytes << DIEPTSIZ_XFRSIZ_Pos) & DIEPTSIZ_XFRSIZ_Msk);
364 if ((dep->
diepctl & DIEPCTL_EPTYP) == DIEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1) {
366 uint32_t
const odd_frame_now = (dwc2->
dsts & (1u << DSTS_FNSOF_Pos));
367 dep->
diepctl |= (odd_frame_now ? DIEPCTL_SD0PID_SEVNFRM_Msk : DIEPCTL_SODDFRM_Msk);
370 dep->
diepctl |= DIEPCTL_EPENA | DIEPCTL_CNAK;
372 dep->
diepctl |= DIEPCTL_EPENA | DIEPCTL_CNAK;
375 if ((dep->
diepctl & DIEPCTL_EPTYP) == DIEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1) {
377 uint32_t
const odd_frame_now = (dwc2->
dsts & (1u << DSTS_FNSOF_Pos));
378 dep->
diepctl |= (odd_frame_now ? DIEPCTL_SD0PID_SEVNFRM_Msk : DIEPCTL_SODDFRM_Msk);
387 dep->
doeptsiz &= ~(DOEPTSIZ_PKTCNT_Msk | DOEPTSIZ_XFRSIZ);
388 dep->
doeptsiz |= (num_packets << DOEPTSIZ_PKTCNT_Pos) |
389 ((
total_bytes << DOEPTSIZ_XFRSIZ_Pos) & DOEPTSIZ_XFRSIZ_Msk);
391 if ((dep->
doepctl & DOEPCTL_EPTYP) == DOEPCTL_EPTYP_0 &&
392 XFER_CTL_BASE(epnum, dir)->interval == 1) {
394 uint32_t
const odd_frame_now = (dwc2->
dsts & (1u << DSTS_FNSOF_Pos));
395 dep->
doepctl |= (odd_frame_now ? DOEPCTL_SD0PID_SEVNFRM_Msk : DOEPCTL_SODDFRM_Msk);
402 dep->
doepctl |= DOEPCTL_EPENA | DOEPCTL_CNAK;
419 dwc2->
gahbcfg |= GAHBCFG_DMAEN | GAHBCFG_HBSTLEN_2;
421 dwc2->
gintmsk |= GINTSTS_RXFLVL;
428 uint32_t dcfg = dwc2->
dcfg & ~DCFG_DSPD_Msk;
430 dcfg |= DCFG_DSPD_HS << DCFG_DSPD_Pos;
435 dcfg |= DCFG_XCVRDLY;
438 dcfg |= DCFG_DSPD_FS << DCFG_DSPD_Pos;
446 dwc2->
gotgctl = (dwc2->
gotgctl & ~GOTGCTL_AVALOEN) | GOTGCTL_BVALOEN | GOTGCTL_BVALOVAL;
449 dwc2->
dcfg |= DCFG_NZLSOHSK;
452 dwc2->
gintmsk |= GINTMSK_OTGINT | GINTMSK_USBSUSPM | GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_WUIM;
455 uint32_t gahbcfg = dwc2->
gahbcfg;
456 gahbcfg |= GAHBCFG_TX_FIFO_EPMTY_LVL;
457 gahbcfg |= GAHBCFG_GINT;
486 dwc2->
dctl |= DCTL_RWUSIG;
495 dwc2->
dctl &= ~DCTL_RWUSIG;
502#ifdef TUP_USBIP_DWC2_ESP32
503 usb_wrap_otg_conf_reg_t conf = USB_WRAP.otg_conf;
504 conf.pad_pull_override = 0;
506 conf.dp_pulldown = 0;
508 conf.dm_pulldown = 0;
509 USB_WRAP.otg_conf = conf;
512 dwc2->
dctl &= ~DCTL_SDIS;
519#ifdef TUP_USBIP_DWC2_ESP32
520 usb_wrap_otg_conf_reg_t conf = USB_WRAP.otg_conf;
521 conf.pad_pull_override = 1;
523 conf.dp_pulldown = 1;
525 conf.dm_pulldown = 1;
526 USB_WRAP.otg_conf = conf;
529 dwc2->
dctl |= DCTL_SDIS;
543 dwc2->
gintmsk &= ~GINTMSK_SOFM;
565 dwc2->
daintmsk = (1 << DAINTMSK_OEPM_Pos) | (1 << DAINTMSK_IEPM_Pos);
567 for (uint8_t n = 1; n < ep_count; n++) {
568 for (uint8_t d = 0; d < 2; d++) {
570 if (dep->
ctl & EPCTL_EPENA) {
571 dep->
ctl |= EPCTL_SNAK | EPCTL_EPDIS;
584 TU_ASSERT(
dfifo_alloc(rhport, ep_addr, largest_packet_size));
612 if (num_packets == 0) {
629 TU_ASSERT(ff->item_size == 1);
672 dep->
ctl &= ~EPCTL_STALL;;
673 dep->
ctl |= EPCTL_SD0PID_SEVNFRM;
683 const volatile uint32_t* rx_fifo = dwc2->
fifo[0];
687 const uint8_t epnum = grxstsp_bm.
ep_ch_num;
688 const uint16_t byte_count = grxstsp_bm.
byte_count;
706 epout->
doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos);
726 if (byte_count < xfer->max_size) {
754 for (uint8_t epnum = 0; epnum < ep_count; epnum++) {
755 if (dwc2->
daint & TU_BIT(DAINT_OEPINT_Pos + epnum)) {
757 const uint32_t doepint = epout->
doepint;
758 TU_ASSERT((epout->
doepint & DOEPINT_AHBERR) == 0, );
761 if (dwc2->
gsnpsid >= DWC2_CORE_REV_3_00a) {
762 if (doepint & DOEPINT_STSPHSRX) {
764 epout->
doepint = DOEPINT_STSPHSRX;
767 if (doepint & DOEPINT_STPKTRX) {
769 epout->
doepint = DOEPINT_STPKTRX;
773 if (doepint & DOEPINT_SETUP) {
774 epout->
doepint = DOEPINT_SETUP;
784 if (doepint & DOEPINT_XFRC) {
789 if (!(doepint & (DOEPINT_SETUP | DOEPINT_STPKTRX | DOEPINT_STSPHSRX))) {
798 uint16_t remain = (epout->
doeptsiz & DOEPTSIZ_XFRSIZ_Msk) >> DOEPTSIZ_XFRSIZ_Pos;
828 for (uint8_t n = 0; n < ep_count; n++) {
829 if (dwc2->
daint & TU_BIT(DAINT_IEPINT_Pos + n)) {
834 if (epin->
diepint & DIEPINT_XFRC) {
858 for (uint16_t i = 0; i < remain_packets; i++) {
862 const uint16_t xact_bytes =
tu_min16(remain_bytes,
xfer->max_size);
866 if (xact_bytes > ((epin->
dtxfsts & DTXFSTS_INEPTFSAV_Msk) << 2)) {
872 volatile uint32_t* tx_fifo = dwc2->
fifo[n];
905 uint32_t
const int_mask = dwc2->
gintmsk;
906 uint32_t
const int_status = dwc2->
gintsts & int_mask;
908 if (int_status & GINTSTS_USBRST) {
910 dwc2->
gintsts = GINTSTS_USBRST;
914 if (int_status & GINTSTS_ENUMDNE) {
916 dwc2->
gintsts = GINTSTS_ENUMDNE;
919 switch ((dwc2->
dsts & DSTS_ENUMSPD_Msk) >> DSTS_ENUMSPD_Pos) {
920 case DSTS_ENUMSPD_HS:
924 case DSTS_ENUMSPD_LS:
928 case DSTS_ENUMSPD_FS_HSPHY:
929 case DSTS_ENUMSPD_FS:
940 if (int_status & GINTSTS_USBSUSP) {
941 dwc2->
gintsts = GINTSTS_USBSUSP;
945 if (int_status & GINTSTS_WKUINT) {
946 dwc2->
gintsts = GINTSTS_WKUINT;
953 if (int_status & GINTSTS_OTGINT) {
955 uint32_t
const otg_int = dwc2->
gotgint;
957 if (otg_int & GOTGINT_SEDET) {
964 if(int_status & GINTSTS_SOF) {
966 const uint32_t frame = (dwc2->
dsts & DSTS_FNSOF) >> DSTS_FNSOF_Pos;
970 dwc2->
gintmsk &= ~GINTMSK_SOFM;
977 if (int_status & GINTSTS_RXFLVL) {
979 dwc2->
gintmsk &= ~GINTMSK_RXFLVLM;
983 }
while(dwc2->
gintsts & GINTSTS_RXFLVL);
985 dwc2->
gintmsk |= GINTMSK_RXFLVLM;
989 if (int_status & GINTSTS_OEPINT) {
995 if (int_status & GINTSTS_IEPINT) {
1007#if CFG_TUD_TEST_MODE
1012 dwc2->
dctl = (dwc2->
dctl & ~DCTL_TCTL_Msk) | (((uint8_t) test_selector) << DCTL_TCTL_Pos);
static TU_ATTR_ALWAYS_INLINE void dcd_event_bus_signal(uint8_t rhport, dcd_eventid_t eid, bool in_isr)
static TU_ATTR_ALWAYS_INLINE void dcd_event_xfer_complete(uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr)
static TU_ATTR_ALWAYS_INLINE void dcd_event_sof(uint8_t rhport, uint32_t frame_count, bool in_isr)
static TU_ATTR_ALWAYS_INLINE void dcd_event_setup_received(uint8_t rhport, uint8_t const *setup, bool in_isr)
static TU_ATTR_ALWAYS_INLINE void dcd_event_bus_reset(uint8_t rhport, tusb_speed_t speed, bool in_isr)
bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes)
static void dma_setup_prepare(uint8_t rhport)
static void handle_epin_irq(uint8_t rhport)
static uint8_t _allocated_ep_in_count
static void handle_rxflvl_irq(uint8_t rhport)
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
void dcd_enter_test_mode(uint8_t rhport, tusb_feature_test_mode_t test_selector)
static void bus_reset(uint8_t rhport)
void dcd_int_handler(uint8_t rhport)
static uint16_t _dfifo_top
static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall)
void dcd_disconnect(uint8_t rhport)
static uint16_t ep0_pending[2]
static TU_ATTR_ALWAYS_INLINE bool dma_device_enabled(const dwc2_regs_t *dwc2)
void dcd_edpt_close_all(uint8_t rhport)
static TU_ATTR_ALWAYS_INLINE uint16_t calc_device_grxfsiz(uint16_t largest_ep_size, uint8_t ep_count)
void dcd_int_disable(uint8_t rhport)
static void edpt_activate(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoint_desc)
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
static void handle_epout_irq(uint8_t rhport)
void dcd_connect(uint8_t rhport)
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt)
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size)
bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoint_desc)
static CFG_TUD_MEM_SECTION TU_ATTR_ALIGNED(4)
void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init)
static xfer_ctl_t xfer_status[DWC2_EP_MAX][2]
bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size)
static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t const dir, uint16_t const num_packets, uint16_t total_bytes)
void dcd_int_enable(uint8_t rhport)
void dcd_remote_wakeup(uint8_t rhport)
void dcd_sof_enable(uint8_t rhport, bool en)
static void dfifo_device_init(uint8_t rhport)
xfer_td_t xfer[EP_CBI_COUNT+1][2]
static void dwc2_remote_wakeup_delay(void)
static TU_ATTR_ALWAYS_INLINE void dwc2_dcd_int_enable(uint8_t rhport)
static TU_ATTR_ALWAYS_INLINE void dwc2_dcd_int_disable(uint8_t rhport)
void dfifo_read_packet(dwc2_regs_t *dwc2, uint8_t *dst, uint16_t len)
bool dwc2_core_is_highspeed(dwc2_regs_t *dwc2, tusb_role_t role)
bool dwc2_core_init(uint8_t rhport, bool is_highspeed)
void dfifo_write_packet(dwc2_regs_t *dwc2, uint8_t fifo_num, const uint8_t *src, uint16_t len)
static TU_ATTR_ALWAYS_INLINE dwc2_regs_t * DWC2_REG(uint8_t rhport)
static TU_ATTR_ALWAYS_INLINE void dfifo_flush_tx(dwc2_regs_t *dwc2, uint8_t fnum)
static TU_ATTR_ALWAYS_INLINE void dfifo_flush_rx(dwc2_regs_t *dwc2)
static const dwc2_controller_t _dwc2_controller[]
@ GRXSTS_PKTSTS_GLOBALOUTNAK
@ GRXSTS_PKTSTS_SETUPDONE
@ GHWCFG2_ARCH_INTERNAL_DMA
AUDIO Channel Cluster Descriptor (4.1)
uint8_t bmAttributes
See: audio_clock_source_attribute_t.
volatile uint32_t doeptsiz
volatile uint32_t dieptsiz
volatile uint32_t diepctl
volatile uint32_t doepint
volatile uint32_t diepdma
volatile uint32_t doepdma
volatile uint32_t doepctl
volatile uint32_t diepint
volatile dwc2_ep_tsize_t dieptsiz_bm
volatile uint32_t dtxfsts
volatile uint32_t diepctl
volatile uint32_t diepint
volatile uint32_t doeptsiz
volatile uint32_t doepctl
volatile dwc2_ep_tsize_t doeptsiz_bm
volatile uint32_t doepint
volatile uint32_t doepdma
volatile uint32_t gahbcfg
volatile uint32_t diepempmsk
volatile uint32_t daintmsk
volatile uint32_t gotgctl
volatile uint32_t gotgint
volatile uint32_t grxfsiz
volatile uint32_t gusbcfg
volatile uint32_t gsnpsid
volatile uint32_t dieptxf0
volatile dwc2_grxstsp_t grxstsp_bm
volatile uint32_t diepmsk
volatile dwc2_ghwcfg2_t ghwcfg2_bm
volatile uint32_t gintmsk
volatile uint32_t doepmsk
volatile uint32_t fifo[16][0x400]
volatile uint32_t gintsts
volatile uint32_t gdfifocfg
volatile uint32_t dieptxf[15]
static TU_ATTR_ALWAYS_INLINE uint32_t tu_div_ceil(uint32_t v, uint32_t d)
static TU_ATTR_ALWAYS_INLINE uint16_t tu_min16(uint16_t x, uint16_t y)
uint16_t tu_fifo_write_n_const_addr_full_words(tu_fifo_t *f, const void *data, uint16_t n)
This function will write n elements into the array index specified by the write pointer and increment...
uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t *f, void *buffer, uint16_t n)
This function will read n elements from the array index specified by the read pointer and increment t...
tusb_speed_t
defined base on EHCI specs value for Endpoint Speed
static TU_ATTR_ALWAYS_INLINE uint8_t tu_edpt_number(uint8_t addr)
static TU_ATTR_ALWAYS_INLINE uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const *desc_ep)
TU_ATTR_PACKED_END TU_ATTR_BIT_FIELD_ORDER_END static TU_ATTR_ALWAYS_INLINE tusb_dir_t tu_edpt_dir(uint8_t addr)
static TU_ATTR_ALWAYS_INLINE uint8_t tu_edpt_addr(uint8_t num, uint8_t dir)