29#if CFG_TUH_ENABLED && defined(TUP_USBIP_DWC2)
38#ifndef CFG_TUH_DWC2_ENDPOINT_MAX
39#define CFG_TUH_DWC2_ENDPOINT_MAX 16
42#define DWC2_CHANNEL_COUNT_MAX 16
43#define DWC2_CHANNEL_COUNT(_dwc2) tu_min8((_dwc2)->ghwcfg2_bm.num_host_ch + 1, DWC2_CHANNEL_COUNT_MAX)
45TU_VERIFY_STATIC(CFG_TUH_DWC2_ENDPOINT_MAX <= 255,
"currently only use 8-bit for index");
48 HPRT_W1_MASK = HPRT_CONN_DETECT | HPRT_ENABLE | HPRT_ENABLE_CHANGE | HPRT_OVER_CURRENT_CHANGE | HPRT_SUSPEND
137 const uint8_t max_channel = DWC2_CHANNEL_COUNT(dwc2);
138 for (uint8_t ch_id = 0; ch_id < max_channel; ch_id++) {
140 if (!
xfer->allocated) {
142 xfer->allocated =
true;
164 xfer->allocated =
false;
172 channel->
hcchar |= HCCHAR_CHDIS | HCCHAR_CHENA;
179 channel->
hcchar |= HCCHAR_CHENA;
185 const uint8_t max_channel = DWC2_CHANNEL_COUNT(dwc2);
186 for (uint8_t ch_id = 0; ch_id < max_channel; ch_id++) {
199TU_ATTR_ALWAYS_INLINE
static inline uint8_t
edpt_alloc(
void) {
200 for (uint32_t i = 0; i < CFG_TUH_DWC2_ENDPOINT_MAX; i++) {
214 for (uint8_t i = 0; i < (uint8_t)CFG_TUH_DWC2_ENDPOINT_MAX; i++) {
217 hcchar_bm->
ep_num == ep_num && (ep_num == 0 || hcchar_bm->
ep_dir == ep_dir)) {
224TU_ATTR_ALWAYS_INLINE
static inline uint16_t
cal_packet_count(uint16_t len, uint16_t ep_size) {
232TU_ATTR_ALWAYS_INLINE
static inline uint8_t
cal_next_pid(uint8_t pid, uint8_t packet_count) {
233 if (packet_count & 0x01) {
289 uint16_t dfifo_top = dwc2_controller->ep_fifo_size/4;
300 uint16_t nptxfsiz = 2 * nptx_largest;
302 TU_ASSERT(dfifo_top >= (nptxfsiz + rxfsiz),);
303 uint16_t ptxfsiz = dfifo_top - (nptxfsiz + rxfsiz);
305 dwc2->
gdfifocfg = (dfifo_top << GDFIFOCFG_EPINFOBASE_SHIFT) | dfifo_top;
310 dfifo_top -= nptxfsiz;
313 dfifo_top -= ptxfsiz;
343 dwc2->
gahbcfg |= GAHBCFG_DMAEN | GAHBCFG_HBSTLEN_2;
345 dwc2->
gintmsk |= GINTSTS_RXFLVL;
351 dwc2->
hcfg &= ~HCFG_FSLS_ONLY;
354 if (dwc2->
gsnpsid >= DWC2_CORE_REV_2_92a) {
355 dwc2->
hfir |= HFIR_RELOAD_CTRL;
366 dwc2->
hprt = HPRT_POWER;
369 dwc2->
gintmsk |= GINTSTS_OTGINT | GINTSTS_CONIDSTSCHNG | GINTSTS_HPRTINT | GINTSTS_HCINT;
372 uint32_t gahbcfg = dwc2->
gahbcfg & ~GAHBCFG_TX_FIFO_EPMTY_LVL;
373 gahbcfg |= GAHBCFG_GINT;
392 return dwc2->
hfnum & HFNUM_FRNUM_Msk;
402 return dwc2->
hprt & HPRT_CONN_STATUS;
409 uint32_t hprt = dwc2->
hprt & ~HPRT_W1_MASK;
417 uint32_t hprt = dwc2->
hprt & ~HPRT_W1_MASK;
432 for (uint8_t i = 0; i < (uint8_t) CFG_TUH_DWC2_ENDPOINT_MAX; i++) {
454 TU_ASSERT(ep_id < CFG_TUH_DWC2_ENDPOINT_MAX);
476 edpt->speed = devtree_info.
speed;
479 edpt->uframe_interval = 1 << (desc_ep->
bInterval - 1);
481 edpt->uframe_interval <<= 3;
485 edpt->uframe_interval = 1 << (desc_ep->
bInterval - 1);
487 edpt->uframe_interval = desc_ep->
bInterval << 3;
510 const uint16_t actual_bytes = (total_packets - remain_packets) * channel->
hcchar_bm.
ep_size;
512 xfer->fifo_bytes = 0;
513 xfer->xferred_bytes += actual_bytes;
514 edpt->
buffer += actual_bytes;
515 edpt->
buflen -= actual_bytes;
526 xfer->fifo_bytes = 0;
536 uint32_t hctsiz = (edpt->next_pid << HCTSIZ_PID_Pos) | (packet_count << HCTSIZ_PKTCNT_Pos) | edpt->
buflen;
539 hctsiz |= HCTSIZ_DOPING;
545 if (hcchar_bm->
ep_num == 0) {
548 edpt->next_pid =
cal_next_pid(edpt->next_pid, packet_count);
552 channel->
hcint = 0xFFFFFFFFU;
555 uint32_t hcintmsk = HCINT_HALTED;
564 channel->
hcchar |= HCCHAR_CHENA;
567 uint32_t hcintmsk = HCINT_NAK | HCINT_XACT_ERR | HCINT_STALL | HCINT_XFER_COMPLETE | HCINT_DATATOGGLE_ERR;
569 hcintmsk |= HCINT_BABBLE_ERR | HCINT_DATATOGGLE_ERR | HCINT_ACK;
571 hcintmsk |= HCINT_NYET;
573 hcintmsk |= HCINT_ACK;
587 channel->
hcchar |= HCCHAR_CHENA;
591 dwc2->
gintmsk |= (is_period ? GINTSTS_PTX_FIFO_EMPTY : GINTSTS_NPTX_FIFO_EMPTY);
602 TU_ASSERT(ch_id < 16);
617 TU_ASSERT(ep_id < CFG_TUH_DWC2_ENDPOINT_MAX);
638 TU_VERIFY(ep_id < CFG_TUH_DWC2_ENDPOINT_MAX);
657 TU_ASSERT(ep_id < CFG_TUH_DWC2_ENDPOINT_MAX);
670 TU_VERIFY(ep_id < CFG_TUH_DWC2_ENDPOINT_MAX);
689 xfer->period_split_nyet_count++;
690 xfer->halted_nyet = 0;
697 xfer->period_split_nyet_count = 0;
706 if (hcint & HCINT_HALTED) {
711 xfer->halted_sof_schedule = 1;
721TU_ATTR_ALWAYS_INLINE
static inline void print_hcint(uint32_t hcint) {
722 const char* str[] = {
723 "XFRC",
"HALTED",
"AHBERR",
"STALL",
724 "NAK",
"ACK",
"NYET",
"XERR",
725 "BBLERR",
"FRMOR",
"DTERR",
"BNA",
729 for(uint32_t i=0; i<14; i++) {
730 if (hcint & TU_BIT(i)) {
731 TU_LOG1(
"%s ", str[i]);
738#if CFG_TUH_DWC2_SLAVE_ENABLE
744 const uint8_t ch_id = grxstsp_bm.
ep_ch_num;
749 const uint16_t byte_count = grxstsp_bm.
byte_count;
751 TU_ASSERT(
xfer->ep_id < CFG_TUH_DWC2_ENDPOINT_MAX,);
756 xfer->xferred_bytes += byte_count;
757 xfer->fifo_bytes = byte_count;
785 const uint8_t max_channel = DWC2_CHANNEL_COUNT(dwc2);
786 for (uint8_t ch_id = 0; ch_id < max_channel; ch_id++) {
791 TU_ASSERT(
xfer->ep_id < CFG_TUH_DWC2_ENDPOINT_MAX);
795 for (uint16_t i = 0; i < remain_packets; i++) {
796 const uint16_t remain_bytes = edpt->
buflen -
xfer->fifo_bytes;
806 xfer->fifo_bytes += xact_bytes;
818 bool is_done =
false;
826 if (hcint & HCINT_XFER_COMPLETE) {
840 }
else if (hcint & (HCINT_XACT_ERR | HCINT_BABBLE_ERR | HCINT_STALL)) {
841 if (hcint & HCINT_STALL) {
843 }
else if (hcint & HCINT_BABBLE_ERR) {
845 }
else if (hcint & HCINT_XACT_ERR) {
851 }
else if (hcint & HCINT_NYET) {
854 xfer->halted_nyet = 1;
856 }
else if (hcint & HCINT_NAK) {
863 }
else if (hcint & HCINT_ACK) {
878 if (remain_packets) {
884 }
else if (hcint & HCINT_HALTED) {
886 if (
xfer->halted_sof_schedule) {
898 }
else if (hcint & HCINT_DATATOGGLE_ERR) {
909 bool is_done =
false;
911 if (hcint & HCINT_XFER_COMPLETE) {
915 }
else if (hcint & HCINT_STALL) {
918 }
else if (hcint & HCINT_NYET) {
923 channel->
hcchar |= HCCHAR_CHENA;
929 }
else if (hcint & (HCINT_NAK | HCINT_XACT_ERR)) {
933 if (hcint & HCINT_XACT_ERR) {
941 }
else if (hcint & HCINT_HALTED) {
952 }
else if (hcint & HCINT_ACK) {
958 channel->
hcchar |= HCCHAR_CHENA;
963 xfer->xferred_bytes +=
xfer->fifo_bytes;
964 xfer->fifo_bytes = 0;
971#if CFG_TUH_DWC2_DMA_ENABLE
977 bool is_done =
false;
981 if (hcint & HCINT_HALTED) {
982 if (hcint & (HCINT_XFER_COMPLETE | HCINT_STALL | HCINT_BABBLE_ERR)) {
990 if (hcint & HCINT_STALL) {
992 }
else if (hcint & HCINT_BABBLE_ERR) {
1006 xfer->err_count = 0;
1008 }
else if (hcint & HCINT_XACT_ERR) {
1014 channel->
hcintmsk |= HCINT_ACK | HCINT_NAK | HCINT_DATATOGGLE_ERR;
1018 }
else if (hcint & HCINT_NYET) {
1026 }
else if (hcint & HCINT_ACK) {
1027 xfer->err_count = 0;
1038 }
else if (hcint & (HCINT_NAK | HCINT_DATATOGGLE_ERR)) {
1039 xfer->err_count = 0;
1040 channel->
hcintmsk &= ~(HCINT_NAK | HCINT_DATATOGGLE_ERR);
1043 }
else if (hcint & HCINT_FARME_OVERRUN) {
1057 bool is_done =
false;
1061 if (hcint & HCINT_HALTED) {
1062 if (hcint & (HCINT_XFER_COMPLETE | HCINT_STALL)) {
1064 xfer->err_count = 0;
1065 if (hcint & HCINT_XFER_COMPLETE) {
1073 }
else if (hcint & HCINT_XACT_ERR) {
1074 if (hcint & (HCINT_NAK | HCINT_NYET | HCINT_ACK)) {
1075 xfer->err_count = 0;
1090 }
else if (hcint & HCINT_NYET) {
1094 channel->
hcchar |= HCCHAR_CHENA;
1096 }
else if (hcint & HCINT_ACK) {
1097 xfer->err_count = 0;
1101 channel->
hcchar |= HCCHAR_CHENA;
1104 }
else if (hcint & HCINT_ACK) {
1105 xfer->err_count = 0;
1116 const uint8_t max_channel = DWC2_CHANNEL_COUNT(dwc2);
1118 for (uint8_t ch_id = 0; ch_id < max_channel; ch_id++) {
1122 TU_ASSERT(
xfer->ep_id < CFG_TUH_DWC2_ENDPOINT_MAX,);
1125 uint32_t hcint = channel->
hcint;
1126 channel->
hcint = hcint;
1130 #if CFG_TUH_DWC2_DMA_ENABLE
1138 #if CFG_TUH_DWC2_SLAVE_ENABLE
1161 bool more_isr =
false;
1166 for(uint8_t ep_id = 0; ep_id < CFG_TUH_DWC2_ENDPOINT_MAX; ep_id++) {
1185 uint32_t hcfg = dwc2->
hcfg & ~HCFG_FSLS_PHYCLK_SEL;
1193 hcfg |= HCFG_FSLS_PHYCLK_SEL_6MHZ;
1195 hcfg |= HCFG_FSLS_PHYCLK_SEL_48MHZ;
1202 phy_clock = gusbcfg_bm.
phy_if16 ? 30 : 60;
1206 dwc2->
gusbcfg &= ~GUSBCFG_PHYLPCS;
1208 dwc2->
gusbcfg |= GUSBCFG_PHYLPCS;
1212 hcfg |= HCFG_FSLS_PHYCLK_SEL_30_60MHZ;
1217 uint32_t hfir = dwc2->
hfir & ~HFIR_FRIVL_Msk;
1219 hfir |= 125*phy_clock;
1221 hfir |= 1000*phy_clock;
1234 uint32_t hprt = dwc2->
hprt & ~HPRT_W1_MASK;
1237 if (dwc2->
hprt & HPRT_CONN_DETECT) {
1239 hprt |= HPRT_CONN_DETECT;
1248 if (dwc2->
hprt & HPRT_ENABLE_CHANGE) {
1250 hprt |= HPRT_ENABLE_CHANGE;
1273 const uint32_t gintmsk = dwc2->
gintmsk;
1274 const uint32_t gintsts = dwc2->
gintsts & gintmsk;
1278 if (gintsts & GINTSTS_CONIDSTSCHNG) {
1280 dwc2->
gintsts = GINTSTS_CONIDSTSCHNG;
1288 if (gintsts & GINTSTS_SOF) {
1291 dwc2->
gintmsk &= ~GINTSTS_SOF;
1295 if (gintsts & GINTSTS_HPRTINT) {
1301 if (gintsts & GINTSTS_HCINT) {
1307#if CFG_TUH_DWC2_SLAVE_ENABLE
1309 if (gintsts & GINTSTS_RXFLVL) {
1311 dwc2->
gintmsk &= ~GINTSTS_RXFLVL;
1315 }
while(dwc2->
gintsts & GINTSTS_RXFLVL);
1317 dwc2->
gintmsk |= GINTSTS_RXFLVL;
1320 if (gintsts & GINTSTS_NPTX_FIFO_EMPTY) {
1325 dwc2->
gintmsk &= ~GINTSTS_NPTX_FIFO_EMPTY;
1329 if (gintsts & GINTSTS_PTX_FIFO_EMPTY) {
1334 dwc2->
gintmsk &= ~GINTSTS_PTX_FIFO_EMPTY;
xfer_td_t xfer[EP_CBI_COUNT+1][2]
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 dwc2_int_set(uint8_t rhport, tusb_role_t role, bool enabled)
static const dwc2_controller_t _dwc2_controller[]
@ HCCHAR_EPTYPE_INTERRUPT
@ HCCHAR_EPTYPE_ISOCHRONOUS
@ GRXSTS_PKTSTS_HOST_CHANNEL_HALTED
@ GRXSTS_PKTSTS_RX_COMPLETE
@ GRXSTS_PKTSTS_HOST_DATATOGGLE_ERR
@ GHWCFG2_ARCH_INTERNAL_DMA
static TU_ATTR_ALWAYS_INLINE void hcd_event_device_remove(uint8_t rhport, bool in_isr)
static TU_ATTR_ALWAYS_INLINE void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr)
static TU_ATTR_ALWAYS_INLINE void hcd_event_device_attach(uint8_t rhport, bool in_isr)
void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t *devtree_info)
static bool channel_xfer_start(dwc2_regs_t *dwc2, uint8_t ch_id)
static TU_ATTR_ALWAYS_INLINE uint8_t edpt_alloc(void)
static void handle_channel_irq(uint8_t rhport, bool in_isr)
void hcd_int_disable(uint8_t rhport)
static TU_ATTR_ALWAYS_INLINE bool dma_host_enabled(const dwc2_regs_t *dwc2)
bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, const uint8_t setup_packet[8])
bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t *desc_ep)
bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void *cfg_param)
static TU_ATTR_ALWAYS_INLINE uint8_t channel_find_enabled(dwc2_regs_t *dwc2, uint8_t dev_addr, uint8_t ep_num, uint8_t ep_dir)
static TU_ATTR_ALWAYS_INLINE uint8_t channel_alloc(dwc2_regs_t *dwc2)
static TU_ATTR_ALWAYS_INLINE tusb_speed_t hprt_speed_get(dwc2_regs_t *dwc2)
static TU_ATTR_ALWAYS_INLINE bool channel_disable(const dwc2_regs_t *dwc2, dwc2_channel_t *channel)
static void handle_rxflvl_irq(uint8_t rhport)
@ HCD_XFER_PERIOD_SPLIT_NYET_MAX
static TU_ATTR_ALWAYS_INLINE bool channel_send_in_token(const dwc2_regs_t *dwc2, dwc2_channel_t *channel)
static bool handle_channel_in_dma(dwc2_regs_t *dwc2, uint8_t ch_id, uint32_t hcint)
static TU_ATTR_ALWAYS_INLINE void print_hcint(uint32_t hcint)
static void channel_xfer_out_wrapup(dwc2_regs_t *dwc2, uint8_t ch_id)
static TU_ATTR_ALWAYS_INLINE uint8_t req_queue_avail(const dwc2_regs_t *dwc2, bool is_period)
bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr)
void hcd_int_enable(uint8_t rhport)
TU_VERIFY_STATIC(CFG_TUH_DWC2_ENDPOINT_MAX<=255, "currently only use 8-bit for index")
bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen)
static TU_ATTR_ALWAYS_INLINE bool edpt_is_periodic(uint8_t ep_type)
void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr)
static void port0_enable(dwc2_regs_t *dwc2, tusb_speed_t speed)
void hcd_port_reset_end(uint8_t rhport)
static void handle_hprt_irq(uint8_t rhport, bool in_isr)
static bool handle_sof_irq(uint8_t rhport, bool in_isr)
void hcd_port_reset(uint8_t rhport)
bool hcd_port_connect_status(uint8_t rhport)
static TU_ATTR_ALWAYS_INLINE uint16_t cal_packet_count(uint16_t len, uint16_t ep_size)
static bool handle_channel_out_dma(dwc2_regs_t *dwc2, uint8_t ch_id, uint32_t hcint)
uint32_t hcd_frame_number(uint8_t rhport)
static void dfifo_host_init(uint8_t rhport)
static TU_ATTR_ALWAYS_INLINE uint8_t edpt_find_opened(uint8_t dev_addr, uint8_t ep_num, uint8_t ep_dir)
static bool edpt_xfer_kickoff(dwc2_regs_t *dwc2, uint8_t ep_id)
tusb_speed_t hcd_port_speed_get(uint8_t rhport)
static TU_ATTR_ALWAYS_INLINE void channel_dealloc(dwc2_regs_t *dwc2, uint8_t ch_id)
void hcd_int_handler(uint8_t rhport, bool in_isr)
static bool handle_channel_out_slave(dwc2_regs_t *dwc2, uint8_t ch_id, uint32_t hcint)
static void channel_xfer_in_retry(dwc2_regs_t *dwc2, uint8_t ch_id, uint32_t hcint)
bool hcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init)
static bool handle_txfifo_empty(dwc2_regs_t *dwc2, bool is_periodic)
static bool handle_channel_in_slave(dwc2_regs_t *dwc2, uint8_t ch_id, uint32_t hcint)
static TU_ATTR_ALWAYS_INLINE uint8_t cal_next_pid(uint8_t pid, uint8_t packet_count)
AUDIO Channel Cluster Descriptor (4.1)
uint8_t bmAttributes
See: audio_clock_source_attribute_t.
uint32_t req_queue_available
volatile dwc2_channel_tsize_t hctsiz_bm
volatile dwc2_channel_char_t hcchar_bm
volatile uint32_t hcintmsk
volatile dwc2_channel_split_t hcsplt_bm
volatile uint32_t gahbcfg
volatile uint32_t gnptxfsiz
volatile dwc2_hptxsts_t hptxsts_bm
volatile uint32_t grxfsiz
volatile uint32_t gusbcfg
volatile uint32_t hptxfsiz
volatile dwc2_hprt_t hprt_bm
volatile uint32_t gsnpsid
volatile uint32_t haintmsk
volatile dwc2_grxstsp_t grxstsp_bm
volatile dwc2_ghwcfg2_t ghwcfg2_bm
volatile uint32_t hptxsts
dwc2_channel_t channel[16]
volatile uint32_t hnptxsts
volatile dwc2_hnptxsts_t hnptxsts_bm
volatile dwc2_gusbcfg_t gusbcfg_bm
volatile uint32_t gintmsk
volatile uint32_t gintsts
volatile uint32_t gdfifocfg
hcd_xfer_t xfer[DWC2_CHANNEL_COUNT_MAX]
hcd_endpoint_t edpt[CFG_TUH_DWC2_ENDPOINT_MAX]
dwc2_channel_split_t hcsplt_bm
uint32_t uframe_countdown
dwc2_channel_char_t hcchar_bm
uint8_t halted_sof_schedule
uint8_t period_split_nyet_count
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)
static TU_ATTR_ALWAYS_INLINE uint32_t tu_min32(uint32_t x, uint32_t y)
static TU_ATTR_ALWAYS_INLINE bool tu_bit_test(uint32_t value, uint8_t pos)
static TU_ATTR_ALWAYS_INLINE uint32_t tu_u32_from_u16(uint16_t high, uint16_t low)
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)
volatile uint16_t actual_len