enhance dwc2
This commit is contained in:
		| @@ -1,6 +1,7 @@ | ||||
| set(MCU_VARIANT XMC4500) | ||||
|  | ||||
| set(JLINK_DEVICE XMC4500-1024) | ||||
| #set(JLINK_OPTION "-USB 000551005307") | ||||
| set(LD_FILE_GNU ${SDK_DIR}/CMSIS/Infineon/COMPONENT_${MCU_VARIANT}/Source/TOOLCHAIN_GCC_ARM/XMC4500x1024.ld) | ||||
|  | ||||
| function(update_board TARGET) | ||||
|   | ||||
| @@ -398,12 +398,8 @@ static void bus_reset(uint8_t rhport) { | ||||
|   tu_memclr(xfer_status, sizeof(xfer_status)); | ||||
|  | ||||
|   _sof_en = false; | ||||
|  | ||||
|   _allocated_ep_in_count = 1; | ||||
|  | ||||
|   // clear device address | ||||
|   dwc2->dcfg &= ~DCFG_DAD_Msk; | ||||
|  | ||||
|   // 1. NAK for all OUT endpoints | ||||
|   for (uint8_t n = 0; n < ep_count; n++) { | ||||
|     dwc2->epout[n].doepctl |= DOEPCTL_SNAK; | ||||
| @@ -419,13 +415,17 @@ static void bus_reset(uint8_t rhport) { | ||||
|   dfifo_flush_tx(dwc2, 0x10); // all tx fifo | ||||
|   dfifo_flush_rx(dwc2); | ||||
|  | ||||
|   // 3. Set up interrupt mask | ||||
|   // 3. Set up interrupt mask for EP0 | ||||
|   dwc2->daintmsk = TU_BIT(DAINTMSK_OEPM_Pos) | TU_BIT(DAINTMSK_IEPM_Pos); | ||||
|   dwc2->doepmsk = DOEPMSK_STUPM | DOEPMSK_XFRCM; | ||||
|   dwc2->diepmsk = DIEPMSK_TOM | DIEPMSK_XFRCM; | ||||
|  | ||||
|   // 4. Set up DFIFO | ||||
|   dfifo_init(rhport); | ||||
|  | ||||
|   // 5. Reset device address | ||||
|   dwc2->dcfg &= ~DCFG_DAD_Msk; | ||||
|  | ||||
|   // Fixed both control EP0 size to 64 bytes | ||||
|   dwc2->epin[0].diepctl &= ~(0x03 << DIEPCTL_MPSIZ_Pos); | ||||
|   dwc2->epout[0].doepctl &= ~(0x03 << DOEPCTL_MPSIZ_Pos); | ||||
| @@ -907,7 +907,9 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t | ||||
|   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++; | ||||
|   if (short_packet_size > 0 || (total_bytes == 0)) { | ||||
|     num_packets++; | ||||
|   } | ||||
|  | ||||
|   // Schedule packets to be sent within interrupt | ||||
|   edpt_schedule_packets(rhport, epnum, dir, num_packets, total_bytes); | ||||
| @@ -941,6 +943,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { | ||||
| // Interrupt Handler | ||||
| //-------------------------------------------------------------------- | ||||
|  | ||||
| // Process shared receive FIFO, this interrupt is only used in Slave mode | ||||
| static void handle_rxflvl_irq(uint8_t rhport) { | ||||
|   dwc2_regs_t* dwc2 = DWC2_REG(rhport); | ||||
|   volatile uint32_t const* rx_fifo = dwc2->fifo[0]; | ||||
| @@ -950,20 +953,8 @@ static void handle_rxflvl_irq(uint8_t rhport) { | ||||
|   uint8_t const pktsts = (grxstsp & GRXSTSP_PKTSTS_Msk) >> GRXSTSP_PKTSTS_Pos; | ||||
|   uint8_t const epnum = (grxstsp & GRXSTSP_EPNUM_Msk) >> GRXSTSP_EPNUM_Pos; | ||||
|   uint16_t const bcnt = (grxstsp & GRXSTSP_BCNT_Msk) >> GRXSTSP_BCNT_Pos; | ||||
|  | ||||
|   dwc2_epout_t* epout = &dwc2->epout[epnum]; | ||||
|  | ||||
| //#if CFG_TUSB_DEBUG >= DWC2_DEBUG | ||||
| //  const char * pktsts_str[] = | ||||
| //  { | ||||
| //    "ASSERT", "Global NAK (ISR)", "Out Data Received", "Out Transfer Complete (ISR)", | ||||
| //    "Setup Complete (ISR)", "ASSERT", "Setup Data Received" | ||||
| //  }; | ||||
| //  TU_LOG_LOCATION(); | ||||
| //  TU_LOG(DWC2_DEBUG, "  EP %02X, Byte Count %u, %s\r\n", epnum, bcnt, pktsts_str[pktsts]); | ||||
| //  TU_LOG(DWC2_DEBUG, "  daint = %08lX, doepint = %04X\r\n", (unsigned long) dwc2->daint, (unsigned int) epout->doepint); | ||||
| //#endif | ||||
|  | ||||
|   switch (pktsts) { | ||||
|     // Global OUT NAK: do nothing | ||||
|     case GRXSTS_PKTSTS_GLOBALOUTNAK: | ||||
| @@ -971,15 +962,14 @@ static void handle_rxflvl_irq(uint8_t rhport) { | ||||
|  | ||||
|     case GRXSTS_PKTSTS_SETUPRX: | ||||
|       // Setup packet received | ||||
|  | ||||
|       // We can receive up to three setup packets in succession, but | ||||
|       // only the last one is valid. | ||||
|       // We can receive up to three setup packets in succession, but  only the last one is valid. | ||||
|       _setup_packet[0] = (*rx_fifo); | ||||
|       _setup_packet[1] = (*rx_fifo); | ||||
|       break; | ||||
|  | ||||
|     case GRXSTS_PKTSTS_SETUPDONE: | ||||
|       // Setup packet done (Interrupt) | ||||
|       // Setup packet done: | ||||
|       // After popping this out, dwc2 asserts a DOEPINT_SETUP interrupt which is handled by handle_epout_irq() | ||||
|       epout->doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); | ||||
|       break; | ||||
|  | ||||
| @@ -1011,8 +1001,8 @@ static void handle_rxflvl_irq(uint8_t rhport) { | ||||
|     } | ||||
|  | ||||
|     case GRXSTS_PKTSTS_OUTDONE: | ||||
|       /* Out packet done (Interrupt) | ||||
|          After this entry is popped from the receive FIFO, the controller asserts a Transfer Completed interrupt on | ||||
|       /* Out packet done | ||||
|          After this entry is popped from the receive FIFO, dwc2 asserts a Transfer Completed interrupt on | ||||
|          the specified OUT endpoint which will be handled by handle_epout_irq() */ | ||||
|       break; | ||||
|  | ||||
| @@ -1034,27 +1024,43 @@ static void handle_epout_irq(uint8_t rhport) { | ||||
|       const uint32_t doepint = epout->doepint; | ||||
|       TU_ASSERT((epout->doepint & DOEPINT_AHBERR) == 0, ); | ||||
|  | ||||
|       TU_LOG1_HEX(doepint); | ||||
|  | ||||
|       // Setup and/or STPKTRX/STSPHSRX (from 3.00a) can be set along with XFRC, and also set independently. | ||||
|       if (dwc2->gsnpsid >= DWC2_CORE_REV_3_00a) { | ||||
|         if (doepint & DOEPINT_STSPHSRX) { | ||||
|           // Status phase received for control write: In token received from Host | ||||
|           epout->doepint = DOEPINT_STSPHSRX; | ||||
|         } | ||||
|  | ||||
|         if (doepint & DOEPINT_STPKTRX) { | ||||
|           // New setup packet received, but wait for Setup done, since we can receive up to 3 setup consecutively | ||||
|           epout->doepint = DOEPINT_STPKTRX; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       if (doepint & DOEPINT_SETUP) { | ||||
|         epout->doepint = DOEPINT_SETUP; | ||||
|  | ||||
|         if(dma_enabled(dwc2)) { | ||||
|           dma_setup_prepare(rhport); | ||||
|         } | ||||
|  | ||||
|         dcd_event_setup_received(rhport, (uint8_t*) _setup_packet, true); | ||||
|       } | ||||
|  | ||||
|       // OUT XFER complete | ||||
|       if (doepint & DOEPINT_XFRC) { | ||||
|         epout->doepint = DOEPINT_XFRC; | ||||
|  | ||||
|         // only handle data skip if it is setup or status related | ||||
|         // Normal OUT transfer complete | ||||
|         if (!(doepint & (DOEPINT_SETUP | DOEPINT_STPKTRX | DOEPINT_STSPHSRX))) { | ||||
|           xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); | ||||
|  | ||||
|           if(dma_enabled(dwc2)) { | ||||
|           if (doepint & DOEPINT_SETUP) { | ||||
|             // STPKTRX is only available for version from 3_00a | ||||
|             if ((doepint & DOEPINT_DMA_STPKTRX) && (dwc2->gsnpsid > DWC2_CORE_REV_3_00a)) { | ||||
|               epout->doepint = DOEPINT_DMA_STPKTRX; | ||||
|             } | ||||
|           } else if (doepint & DOEPINT_STSPHSRX) { | ||||
|             epout->doepint = DOEPINT_STSPHSRX; | ||||
|           } else { | ||||
|             if ((doepint & DOEPINT_DMA_STPKTRX) && (dwc2->gsnpsid > DWC2_CORE_REV_3_00a)) { | ||||
|               epout->doepint = DOEPINT_DMA_STPKTRX; | ||||
|             } else { | ||||
|               // EP0 can only handle one packet | ||||
|             if ((epnum == 0) && ep0_pending[TUSB_DIR_OUT]) { | ||||
|                 // Schedule another packet to be received. | ||||
|               // EP0 can only handle one packet Schedule another packet to be received. | ||||
|               edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT, 1, ep0_pending[TUSB_DIR_OUT]); | ||||
|             } else { | ||||
|               // Fix packet length | ||||
| @@ -1067,18 +1073,7 @@ static void handle_epout_irq(uint8_t rhport) { | ||||
|  | ||||
|               dcd_event_xfer_complete(rhport, epnum, xfer->total_len, XFER_RESULT_SUCCESS, true); | ||||
|             } | ||||
|             } | ||||
|           } | ||||
|           } else { | ||||
|           // DMA_STPKTRX should only be set in Buffer DMA Mode. However, STM32L476 (slave-only) with v3.10a | ||||
|           // incorrectly set this along with SETUP bit. This may (or not) be STM32L476 or 3.10a specific bug | ||||
|           if ((doepint & DOEPINT_DMA_STPKTRX) && (dwc2->gsnpsid == DWC2_CORE_REV_3_10a)) { | ||||
|             epout->doepint = DOEPINT_DMA_STPKTRX; | ||||
|           } else { | ||||
|             if ((doepint & DOEPINT_STSPHSRX) && (dwc2->gsnpsid == DWC2_CORE_REV_3_10a)) { | ||||
|               epout->doepint = DOEPINT_STSPHSRX; | ||||
|             } | ||||
|  | ||||
|             // EP0 can only handle one packet | ||||
|             if ((epnum == 0) && ep0_pending[TUSB_DIR_OUT]) { | ||||
|               // Schedule another packet to be received. | ||||
| @@ -1089,19 +1084,6 @@ static void handle_epout_irq(uint8_t rhport) { | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       // SETUP packet Setup Phase done. | ||||
|       if (doepint & DOEPINT_SETUP) { | ||||
|         epout->doepint = DOEPINT_SETUP; | ||||
|         if ((doepint & DOEPINT_DMA_STPKTRX) && (dwc2->gsnpsid > DWC2_CORE_REV_3_00a)) { | ||||
|           epout->doepint = DOEPINT_DMA_STPKTRX; | ||||
|         } | ||||
|         if(dma_enabled(dwc2) && (dwc2->gsnpsid > DWC2_CORE_REV_3_00a)) { | ||||
|           dma_setup_prepare(rhport); | ||||
|         } | ||||
|  | ||||
|         dcd_event_setup_received(rhport, (uint8_t*) _setup_packet, true); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -1274,13 +1256,10 @@ void dcd_int_handler(uint8_t rhport) { | ||||
|   // RxFIFO non-empty interrupt handling. | ||||
|   if (int_status & GINTSTS_RXFLVL) { | ||||
|     // RXFLVL bit is read-only | ||||
|  | ||||
|     // Mask out RXFLVL while reading data from FIFO | ||||
|     dwc2->gintmsk &= ~GINTMSK_RXFLVLM; | ||||
|     dwc2->gintmsk &= ~GINTMSK_RXFLVLM; // disable RXFLVL interrupt while reading | ||||
|  | ||||
|     do { | ||||
|       // Loop until all available packets were handled | ||||
|       handle_rxflvl_irq(rhport); | ||||
|       handle_rxflvl_irq(rhport); // read all packets | ||||
|     } while(dwc2->gintsts & GINTSTS_RXFLVL); | ||||
|  | ||||
|     dwc2->gintmsk |= GINTMSK_RXFLVLM; | ||||
|   | ||||
| @@ -1954,9 +1954,9 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo   ) == 0x1000, "incorrect size"); | ||||
| #define DOEPINT_NYET_Msk                 (0x1UL << DOEPINT_NYET_Pos)              // 0x00004000 | ||||
| #define DOEPINT_NYET                     DOEPINT_NYET_Msk                         // NYET interrupt | ||||
|  | ||||
| #define DOEPINT_DMA_STPKTRX_Pos          (15U) | ||||
| #define DOEPINT_DMA_STPKTRX_Msk          (0x1UL << DOEPINT_DMA_STPKTRX_Pos)       // 0x00008000 | ||||
| #define DOEPINT_DMA_STPKTRX              DOEPINT_DMA_STPKTRX_Msk                  // Setup Packet Received in Buffer DMA Mode | ||||
| #define DOEPINT_STPKTRX_Pos              (15U) | ||||
| #define DOEPINT_STPKTRX_Msk              (0x1UL << DOEPINT_STPKTRX_Pos)           // 0x00008000 | ||||
| #define DOEPINT_STPKTRX                  DOEPINT_STPKTRX_Msk                      // Setup Packet Received | ||||
|  | ||||
| /********************  Bit definition for DOEPTSIZ register  ********************/ | ||||
| #define DOEPTSIZ_XFRSIZ_Pos              (0U) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 hathach
					hathach