move buffer and buflen to hcd_endpoint_t to support periodic endpoint
This commit is contained in:
		| @@ -224,15 +224,9 @@ bool dwc2_core_init(uint8_t rhport, bool is_highspeed) { | ||||
|   dfifo_flush_tx(dwc2, 0x10); // all tx fifo | ||||
|   dfifo_flush_rx(dwc2); | ||||
|  | ||||
|   // Clear all pending interrupts | ||||
|   uint32_t int_mask; | ||||
|  | ||||
|   int_mask = dwc2->gintsts; | ||||
|   dwc2->gintsts |= int_mask; | ||||
|  | ||||
|   int_mask = dwc2->gotgint; | ||||
|   dwc2->gotgint |= int_mask; | ||||
|  | ||||
|   // Clear pending and disable all interrupts | ||||
|   dwc2->gintsts = 0xFFFFFFFFU; | ||||
|   dwc2->gotgint = 0xFFFFFFFFU; | ||||
|   dwc2->gintmsk = 0; | ||||
|  | ||||
|   return true; | ||||
|   | ||||
| @@ -66,9 +66,13 @@ typedef struct { | ||||
|     uint32_t hcsplt; | ||||
|     dwc2_channel_split_t hcsplt_bm; | ||||
|   }; | ||||
|  | ||||
|   uint8_t next_pid; | ||||
|   uint16_t frame_interval; | ||||
|   uint16_t frame_countdown; | ||||
|  | ||||
|   uint8_t* buffer; | ||||
|   uint16_t buflen; | ||||
| } hcd_endpoint_t; | ||||
|  | ||||
| // Additional info for each channel when it is active | ||||
| @@ -83,8 +87,6 @@ typedef struct { | ||||
|  | ||||
|   uint16_t xferred_bytes;  // bytes that accumulate transferred though USB bus for the whole hcd_edpt_xfer(), which can | ||||
|                            // be composed of multiple channel_xfer_start() (retry with NAK/NYET) | ||||
|   uint16_t buf_len; | ||||
|   uint8_t* buf_start; | ||||
|   uint16_t out_fifo_bytes; // bytes written to TX FIFO (may not be transferred on USB bus). | ||||
| } hcd_xfer_t; | ||||
|  | ||||
| @@ -490,7 +492,6 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t* | ||||
| static void channel_xfer_cleanup(dwc2_regs_t* dwc2, uint8_t ch_id) { | ||||
|   hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; | ||||
|   dwc2_channel_t* channel = &dwc2->channel[ch_id]; | ||||
|   TU_ASSERT(xfer->ep_id < CFG_TUH_DWC2_ENDPOINT_MAX, ); | ||||
|   hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; | ||||
|  | ||||
|   edpt->next_pid = channel->hctsiz_bm.pid; // save PID | ||||
| @@ -500,12 +501,12 @@ static void channel_xfer_cleanup(dwc2_regs_t* dwc2, uint8_t ch_id) { | ||||
|   * was halted before its normal completion. (Can't use the hctsiz.xfersize field because that reflects the number of | ||||
|   * bytes transferred via the AHB, not the USB). */ | ||||
|   const uint16_t remain_packets = channel->hctsiz_bm.packet_count; | ||||
|   const uint16_t total_packets = cal_packet_count(xfer->buf_len, channel->hcchar_bm.ep_size); | ||||
|   const uint16_t total_packets = cal_packet_count(edpt->buflen, channel->hcchar_bm.ep_size); | ||||
|   const uint16_t actual_bytes = (total_packets - remain_packets) * channel->hcchar_bm.ep_size; | ||||
|   xfer->xferred_bytes += actual_bytes; | ||||
|   xfer->buf_start += actual_bytes; | ||||
|   xfer->buf_len -= actual_bytes; | ||||
|   xfer->out_fifo_bytes = 0; | ||||
|   edpt->buffer += actual_bytes; | ||||
|   edpt->buflen -= actual_bytes; | ||||
| } | ||||
|  | ||||
| static bool channel_xfer_start(dwc2_regs_t* dwc2, uint8_t ch_id) { | ||||
| @@ -525,8 +526,8 @@ static bool channel_xfer_start(dwc2_regs_t* dwc2, uint8_t ch_id) { | ||||
|   channel->hcchar = (edpt->hcchar & ~HCCHAR_CHENA); | ||||
|  | ||||
|   // hctsiz: zero length packet still count as 1 | ||||
|   const uint16_t packet_count = cal_packet_count(xfer->buf_len, hcchar_bm->ep_size); | ||||
|   uint32_t hctsiz = (edpt->next_pid << HCTSIZ_PID_Pos) | (packet_count << HCTSIZ_PKTCNT_Pos) | xfer->buf_len; | ||||
|   const uint16_t packet_count = cal_packet_count(edpt->buflen, hcchar_bm->ep_size); | ||||
|   uint32_t hctsiz = (edpt->next_pid << HCTSIZ_PID_Pos) | (packet_count << HCTSIZ_PKTCNT_Pos) | edpt->buflen; | ||||
|   if (xfer->do_ping && edpt->next_pid != HCTSIZ_PID_SETUP && hcchar_bm->ep_dir == TUSB_DIR_OUT) { | ||||
|     hcd_devtree_info_t devtree_info; | ||||
|     hcd_devtree_get_info(hcchar_bm->dev_addr, &devtree_info); | ||||
| @@ -547,14 +548,14 @@ static bool channel_xfer_start(dwc2_regs_t* dwc2, uint8_t ch_id) { | ||||
|   // split: TODO support later | ||||
|   channel->hcsplt = edpt->hcsplt; | ||||
|  | ||||
|   channel->hcint = 0xFFFFFFFF; // clear all channel interrupts | ||||
|   channel->hcint = 0xFFFFFFFFU; // clear all channel interrupts | ||||
|  | ||||
|   if (dma_host_enabled(dwc2)) { | ||||
|     uint32_t hcintmsk = HCINT_HALTED; | ||||
|     channel->hcintmsk = hcintmsk; | ||||
|     dwc2->haintmsk |= TU_BIT(ch_id); | ||||
|  | ||||
|     channel->hcdma = (uint32_t) xfer->buf_start; | ||||
|     channel->hcdma = (uint32_t) edpt->buffer; | ||||
|  | ||||
|     if (hcchar_bm->ep_dir == TUSB_DIR_IN) { | ||||
|       channel_send_in_token(dwc2, channel); | ||||
| @@ -580,7 +581,7 @@ static bool channel_xfer_start(dwc2_regs_t* dwc2, uint8_t ch_id) { | ||||
|       channel_send_in_token(dwc2, channel); | ||||
|     } else { | ||||
|       channel->hcchar |= HCCHAR_CHENA; | ||||
|       if (xfer->buf_len > 0) { | ||||
|       if (edpt->buflen > 0) { | ||||
|         // To prevent conflict with other channel, we will enable periodic/non-periodic FIFO empty interrupt accordingly | ||||
|         // And write packet in the interrupt handler | ||||
|         dwc2->gintmsk |= (is_period ? GINTSTS_PTX_FIFO_EMPTY : GINTSTS_NPTX_FIFO_EMPTY); | ||||
| @@ -605,9 +606,9 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * | ||||
|   TU_ASSERT(ch_id < 16); // all channel are in used | ||||
|   hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; | ||||
|   xfer->ep_id = ep_id; | ||||
|   xfer->buf_start = buffer; | ||||
|   xfer->buf_len = buflen; | ||||
|   xfer->result = XFER_RESULT_INVALID; | ||||
|   edpt->buffer = buffer; | ||||
|   edpt->buflen = buflen; | ||||
|  | ||||
|   if (ep_num == 0) { | ||||
|     // update ep_dir since control endpoint can switch direction | ||||
| @@ -681,8 +682,10 @@ static void handle_rxflvl_irq(uint8_t rhport) { | ||||
|       // In packet received | ||||
|       const uint16_t byte_count = grxstsp_bm.byte_count; | ||||
|       hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; | ||||
|       TU_ASSERT(xfer->ep_id < CFG_TUH_DWC2_ENDPOINT_MAX,); | ||||
|       hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; | ||||
|  | ||||
|       dfifo_read_packet(dwc2, xfer->buf_start + xfer->xferred_bytes, byte_count); | ||||
|       dfifo_read_packet(dwc2, edpt->buffer + xfer->xferred_bytes, byte_count); | ||||
|       xfer->xferred_bytes += byte_count; | ||||
|  | ||||
|       const uint16_t remain_bytes = (uint16_t) channel->hctsiz_bm.xfer_size; | ||||
| @@ -692,8 +695,6 @@ static void handle_rxflvl_irq(uint8_t rhport) { | ||||
|         xfer->xferred_bytes -= remain_bytes; | ||||
|  | ||||
|         // update PID based on remain packets count | ||||
|         TU_ASSERT(xfer->ep_id < CFG_TUH_DWC2_ENDPOINT_MAX,); | ||||
|         hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; // update PID | ||||
|         edpt->next_pid = cal_next_pid(edpt->next_pid, remain_packets); | ||||
|       } else { | ||||
|         if (remain_packets) { | ||||
| @@ -721,6 +722,40 @@ static void handle_rxflvl_irq(uint8_t rhport) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| // return true if there is still pending data and need more ISR | ||||
| static bool handle_txfifo_empty(dwc2_regs_t* dwc2, bool is_periodic) { | ||||
|   // Use period txsts for both p/np to get request queue space available (1-bit difference, it is small enough) | ||||
|   volatile dwc2_hptxsts_t* txsts_bm = (volatile dwc2_hptxsts_t*) (is_periodic ? &dwc2->hptxsts : &dwc2->hnptxsts); | ||||
|  | ||||
|   const uint8_t max_channel = DWC2_CHANNEL_COUNT(dwc2); | ||||
|   for (uint8_t ch_id = 0; ch_id < max_channel; ch_id++) { | ||||
|     dwc2_channel_t* channel = &dwc2->channel[ch_id]; | ||||
|     // skip writing to FIFO if channel is expecting halted. | ||||
|     if (!(channel->hcintmsk & HCINT_HALTED) && (channel->hcchar_bm.ep_dir == TUSB_DIR_OUT)) { | ||||
|       hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; | ||||
|       TU_ASSERT(xfer->ep_id < CFG_TUH_DWC2_ENDPOINT_MAX); | ||||
|       hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; | ||||
|  | ||||
|       const uint16_t remain_packets = channel->hctsiz_bm.packet_count; | ||||
|       for (uint16_t i = 0; i < remain_packets; i++) { | ||||
|         const uint16_t remain_bytes = edpt->buflen - xfer->out_fifo_bytes; | ||||
|         const uint16_t xact_bytes = tu_min16(remain_bytes, channel->hcchar_bm.ep_size); | ||||
|  | ||||
|         // skip if there is not enough space in FIFO and RequestQueue. | ||||
|         // Packet's last word written to FIFO will trigger a request queue | ||||
|         if ((xact_bytes > (txsts_bm->fifo_available << 2)) || (txsts_bm->req_queue_available == 0)) { | ||||
|           return true; | ||||
|         } | ||||
|  | ||||
|         dfifo_write_packet(dwc2, ch_id, edpt->buffer + xfer->out_fifo_bytes, xact_bytes); | ||||
|         xfer->out_fifo_bytes += xact_bytes; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return false; // all data written | ||||
| } | ||||
|  | ||||
| static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hcint) { | ||||
|   hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; | ||||
|   dwc2_channel_t* channel = &dwc2->channel[ch_id]; | ||||
| @@ -812,6 +847,8 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t | ||||
| static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hcint) { | ||||
|   hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; | ||||
|   dwc2_channel_t* channel = &dwc2->channel[ch_id]; | ||||
|   hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; | ||||
|  | ||||
|   bool is_done = false; | ||||
|  | ||||
|   if (hcint & HCINT_HALTED) { | ||||
| @@ -819,7 +856,7 @@ static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci | ||||
|       is_done = true; | ||||
|       xfer->err_count = 0; | ||||
|       const uint16_t remain_bytes = (uint16_t) channel->hctsiz_bm.xfer_size; | ||||
|       xfer->xferred_bytes += (xfer->buf_len - remain_bytes); | ||||
|       xfer->xferred_bytes += (edpt->buflen - remain_bytes); | ||||
|       if (hcint & HCINT_STALL) { | ||||
|         xfer->result = XFER_RESULT_STALLED; | ||||
|       } else if (hcint & HCINT_BABBLE_ERR) { | ||||
| @@ -838,14 +875,23 @@ static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci | ||||
|         // re-init channel | ||||
|         TU_ASSERT(false); | ||||
|       } | ||||
|     } else if (hcint & (HCINT_ACK | HCINT_NAK | HCINT_DATATOGGLE_ERR)) { | ||||
|       xfer->err_count = 0; | ||||
|       channel->hcintmsk &= ~(HCINT_ACK | HCINT_NAK | HCINT_DATATOGGLE_ERR); | ||||
|       if ((hcint & (HCINT_NAK | HCINT_DATATOGGLE_ERR))) { | ||||
|         edpt->next_pid = channel->hctsiz_bm.pid; // save PID | ||||
|  | ||||
|         if (edpt_is_periodic(channel->hcchar_bm.ep_type)){ | ||||
|           // for periodic, de-allocate channel, enable SOF set frame counter for later transfer | ||||
|           channel_dealloc(dwc2, ch_id); | ||||
|           edpt->frame_countdown = edpt->frame_interval; | ||||
|           dwc2->gintmsk |= GINTSTS_SOF; | ||||
|         } else { | ||||
|           // for control/bulk: try again immediately | ||||
|           TU_ASSERT(false); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } else if (hcint & (HCINT_ACK | HCINT_NAK | HCINT_DATATOGGLE_ERR)) { | ||||
|     xfer->err_count = 0; | ||||
|     channel->hcintmsk &= ~(HCINT_ACK | HCINT_NAK | HCINT_DATATOGGLE_ERR); | ||||
|     // if (hcint & (HCINT_NAK | HCINT_DATATOGGLE_ERR)) { | ||||
|     //   TU_ASSERT(xfer->ep_id < CFG_TUH_DWC2_ENDPOINT_MAX,); | ||||
|     //   hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; | ||||
|     // } | ||||
|   } | ||||
|  | ||||
|   return is_done; | ||||
| @@ -854,6 +900,8 @@ static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci | ||||
| static bool handle_channel_out_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hcint) { | ||||
|   hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; | ||||
|   dwc2_channel_t* channel = &dwc2->channel[ch_id]; | ||||
|   hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; | ||||
|  | ||||
|   bool is_done = false; | ||||
|  | ||||
|   if (hcint & HCINT_HALTED) { | ||||
| @@ -862,7 +910,7 @@ static bool handle_channel_out_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hc | ||||
|       xfer->err_count = 0; | ||||
|       if (hcint & HCINT_XFER_COMPLETE) { | ||||
|         xfer->result = XFER_RESULT_SUCCESS; | ||||
|         xfer->xferred_bytes += xfer->buf_len; | ||||
|         xfer->xferred_bytes += edpt->buflen; | ||||
|       } else { | ||||
|         xfer->result = XFER_RESULT_STALLED; | ||||
|         channel_xfer_cleanup(dwc2, ch_id); | ||||
| @@ -904,6 +952,7 @@ static void handle_channel_irq(uint8_t rhport, bool in_isr) { | ||||
|     if (tu_bit_test(dwc2->haint, ch_id)) { | ||||
|       dwc2_channel_t* channel = &dwc2->channel[ch_id]; | ||||
|       hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; | ||||
|       TU_ASSERT(xfer->ep_id < CFG_TUH_DWC2_ENDPOINT_MAX,); | ||||
|       dwc2_channel_char_t hcchar_bm = channel->hcchar_bm; | ||||
|  | ||||
|       uint32_t hcint = channel->hcint; | ||||
| @@ -937,35 +986,21 @@ static void handle_channel_irq(uint8_t rhport, bool in_isr) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| // return true if there is still pending data and need more ISR | ||||
| static bool handle_txfifo_empty(dwc2_regs_t* dwc2, bool is_periodic) { | ||||
|   // Use period txsts for both p/np to get request queue space available (1-bit difference, it is small enough) | ||||
|   volatile dwc2_hptxsts_t* txsts_bm = (volatile dwc2_hptxsts_t*) (is_periodic ? &dwc2->hptxsts : &dwc2->hnptxsts); | ||||
|  | ||||
|   const uint8_t max_channel = DWC2_CHANNEL_COUNT(dwc2); | ||||
|   for (uint8_t ch_id = 0; ch_id < max_channel; ch_id++) { | ||||
|     dwc2_channel_t* channel = &dwc2->channel[ch_id]; | ||||
|     // skip writing to FIFO if channel is expecting halted. | ||||
|     if (!(channel->hcintmsk & HCINT_HALTED) && (channel->hcchar_bm.ep_dir == TUSB_DIR_OUT)) { | ||||
|       hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; | ||||
|       const uint16_t remain_packets = channel->hctsiz_bm.packet_count; | ||||
|       for (uint16_t i = 0; i < remain_packets; i++) { | ||||
|         const uint16_t remain_bytes = xfer->buf_len - xfer->out_fifo_bytes; | ||||
|         const uint16_t xact_bytes = tu_min16(remain_bytes, channel->hcchar_bm.ep_size); | ||||
|  | ||||
|         // skip if there is not enough space in FIFO and RequestQueue. | ||||
|         // Packet's last word written to FIFO will trigger a request queue | ||||
|         if ((xact_bytes > (txsts_bm->fifo_available << 2)) || (txsts_bm->req_queue_available == 0)) { | ||||
|           return true; | ||||
|         } | ||||
|  | ||||
|         dfifo_write_packet(dwc2, ch_id, xfer->buf_start + xfer->out_fifo_bytes, xact_bytes); | ||||
|         xfer->out_fifo_bytes += xact_bytes; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return false; // all data written | ||||
| // SOF is enabled for scheduled periodic transfer | ||||
| static void handle_sof_irq(uint8_t rhport, bool in_isr) { | ||||
|   (void) in_isr; | ||||
|   dwc2_regs_t* dwc2 = DWC2_REG(rhport); | ||||
|   (void) dwc2; | ||||
|   // for(uint8_t ep_id; ep_id < CFG_TUH_DWC2_ENDPOINT_MAX; ep_id++) { | ||||
|   //   hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; | ||||
|   //   if (edpt->hcchar_bm.enable && edpt_is_periodic(edpt->hcchar_bm.ep_type) && edpt->frame_countdown > 0) { | ||||
|   // | ||||
|   //     edpt->frame_countdown--; | ||||
|   //     if (edpt->frame_countdown == 0) { | ||||
|   //       channel_xfer_start(dwc2, ep_id); | ||||
|   //     } | ||||
|   //   } | ||||
|   // } | ||||
| } | ||||
|  | ||||
| /* Handle Host Port interrupt, possible source are: | ||||
| @@ -1034,22 +1069,20 @@ static void handle_hprt_irq(uint8_t rhport, bool in_isr) { | ||||
| } | ||||
|  | ||||
| /* Interrupt Hierarchy | ||||
|                HCINTn         HPRT | ||||
|                  |             | | ||||
|                HAINT.CHn       | | ||||
|                  |             | | ||||
|     GINTSTS :  HCInt         PrtInt      NPTxFEmp PTxFEmpp RXFLVL | ||||
|  | ||||
|  | ||||
|                HCINTn       HPRT | ||||
|                  |           | | ||||
|                HAINT.CHn     | | ||||
|                  |           | | ||||
|     GINTSTS :  HCInt     | PrtInt | NPTxFEmp | PTxFEmpp | RXFLVL | SOF | ||||
| */ | ||||
| void hcd_int_handler(uint8_t rhport, bool in_isr) { | ||||
|   dwc2_regs_t* dwc2 = DWC2_REG(rhport); | ||||
|   const uint32_t int_mask = dwc2->gintmsk; | ||||
|   const uint32_t int_status = dwc2->gintsts & int_mask; | ||||
|   const uint32_t gintmsk = dwc2->gintmsk; | ||||
|   const uint32_t gintsts = dwc2->gintsts & gintmsk; | ||||
|  | ||||
|   // TU_LOG1_HEX(int_status); | ||||
|  | ||||
|   if (int_status & GINTSTS_CONIDSTSCHNG) { | ||||
|   if (gintsts & GINTSTS_CONIDSTSCHNG) { | ||||
|     // Connector ID status change | ||||
|     dwc2->gintsts = GINTSTS_CONIDSTSCHNG; | ||||
|  | ||||
| @@ -1059,7 +1092,11 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { | ||||
|     // TODO wait for SRP if OTG | ||||
|   } | ||||
|  | ||||
|   if (int_status & GINTSTS_HPRTINT) { | ||||
|   if (gintsts & GINTSTS_SOF) { | ||||
|     handle_sof_irq(rhport, in_isr); | ||||
|   } | ||||
|  | ||||
|   if (gintsts & GINTSTS_HPRTINT) { | ||||
|     // Host port interrupt: source is cleared in HPRT register | ||||
|     // TU_LOG1_HEX(dwc2->hprt); | ||||
|     handle_hprt_irq(rhport, in_isr); | ||||
| @@ -1067,7 +1104,7 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { | ||||
|  | ||||
| #if CFG_TUH_DWC2_SLAVE_ENABLE | ||||
|   // RxFIFO non-empty interrupt handling, must be handled before HCINT | ||||
|   if (int_status & GINTSTS_RXFLVL) { | ||||
|   if (gintsts & GINTSTS_RXFLVL) { | ||||
|     // RXFLVL bit is read-only | ||||
|     dwc2->gintmsk &= ~GINTSTS_RXFLVL; // disable RXFLVL interrupt while reading | ||||
|  | ||||
| @@ -1077,9 +1114,8 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { | ||||
|  | ||||
|     dwc2->gintmsk |= GINTSTS_RXFLVL; | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   if (int_status & GINTSTS_NPTX_FIFO_EMPTY) { | ||||
|   if (gintsts & GINTSTS_NPTX_FIFO_EMPTY) { | ||||
|     // NPTX FIFO empty interrupt, this is read-only and cleared by hardware when FIFO is written | ||||
|     const bool more_isr = handle_txfifo_empty(dwc2, false); | ||||
|     if (!more_isr) { | ||||
| @@ -1087,8 +1123,9 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { | ||||
|       dwc2->gintmsk &= ~GINTSTS_NPTX_FIFO_EMPTY; | ||||
|     } | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   if (int_status & GINTSTS_HCINT) { | ||||
|   if (gintsts & GINTSTS_HCINT) { | ||||
|     // Host Channel interrupt: source is cleared in HCINT register | ||||
|     // must bee handled after TX FIFO empty | ||||
|     handle_channel_irq(rhport, in_isr); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 hathach
					hathach