enhance dwc2
This commit is contained in:
		| @@ -1,6 +1,7 @@ | |||||||
| set(MCU_VARIANT XMC4500) | set(MCU_VARIANT XMC4500) | ||||||
|  |  | ||||||
| set(JLINK_DEVICE XMC4500-1024) | 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) | set(LD_FILE_GNU ${SDK_DIR}/CMSIS/Infineon/COMPONENT_${MCU_VARIANT}/Source/TOOLCHAIN_GCC_ARM/XMC4500x1024.ld) | ||||||
|  |  | ||||||
| function(update_board TARGET) | function(update_board TARGET) | ||||||
|   | |||||||
| @@ -398,12 +398,8 @@ static void bus_reset(uint8_t rhport) { | |||||||
|   tu_memclr(xfer_status, sizeof(xfer_status)); |   tu_memclr(xfer_status, sizeof(xfer_status)); | ||||||
|  |  | ||||||
|   _sof_en = false; |   _sof_en = false; | ||||||
|  |  | ||||||
|   _allocated_ep_in_count = 1; |   _allocated_ep_in_count = 1; | ||||||
|  |  | ||||||
|   // clear device address |  | ||||||
|   dwc2->dcfg &= ~DCFG_DAD_Msk; |  | ||||||
|  |  | ||||||
|   // 1. NAK for all OUT endpoints |   // 1. NAK for all OUT endpoints | ||||||
|   for (uint8_t n = 0; n < ep_count; n++) { |   for (uint8_t n = 0; n < ep_count; n++) { | ||||||
|     dwc2->epout[n].doepctl |= DOEPCTL_SNAK; |     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_tx(dwc2, 0x10); // all tx fifo | ||||||
|   dfifo_flush_rx(dwc2); |   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->daintmsk = TU_BIT(DAINTMSK_OEPM_Pos) | TU_BIT(DAINTMSK_IEPM_Pos); | ||||||
|   dwc2->doepmsk = DOEPMSK_STUPM | DOEPMSK_XFRCM; |   dwc2->doepmsk = DOEPMSK_STUPM | DOEPMSK_XFRCM; | ||||||
|   dwc2->diepmsk = DIEPMSK_TOM | DIEPMSK_XFRCM; |   dwc2->diepmsk = DIEPMSK_TOM | DIEPMSK_XFRCM; | ||||||
|  |  | ||||||
|  |   // 4. Set up DFIFO | ||||||
|   dfifo_init(rhport); |   dfifo_init(rhport); | ||||||
|  |  | ||||||
|  |   // 5. Reset device address | ||||||
|  |   dwc2->dcfg &= ~DCFG_DAD_Msk; | ||||||
|  |  | ||||||
|   // Fixed both control EP0 size to 64 bytes |   // Fixed both control EP0 size to 64 bytes | ||||||
|   dwc2->epin[0].diepctl &= ~(0x03 << DIEPCTL_MPSIZ_Pos); |   dwc2->epin[0].diepctl &= ~(0x03 << DIEPCTL_MPSIZ_Pos); | ||||||
|   dwc2->epout[0].doepctl &= ~(0x03 << DOEPCTL_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; |   uint16_t const short_packet_size = total_bytes % xfer->max_size; | ||||||
|  |  | ||||||
|   // Zero-size packet is special case. |   // 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 |   // Schedule packets to be sent within interrupt | ||||||
|   edpt_schedule_packets(rhport, epnum, dir, num_packets, total_bytes); |   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 | // Interrupt Handler | ||||||
| //-------------------------------------------------------------------- | //-------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | // Process shared receive FIFO, this interrupt is only used in Slave mode | ||||||
| static void handle_rxflvl_irq(uint8_t rhport) { | static void handle_rxflvl_irq(uint8_t rhport) { | ||||||
|   dwc2_regs_t* dwc2 = DWC2_REG(rhport); |   dwc2_regs_t* dwc2 = DWC2_REG(rhport); | ||||||
|   volatile uint32_t const* rx_fifo = dwc2->fifo[0]; |   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 pktsts = (grxstsp & GRXSTSP_PKTSTS_Msk) >> GRXSTSP_PKTSTS_Pos; | ||||||
|   uint8_t const epnum = (grxstsp & GRXSTSP_EPNUM_Msk) >> GRXSTSP_EPNUM_Pos; |   uint8_t const epnum = (grxstsp & GRXSTSP_EPNUM_Msk) >> GRXSTSP_EPNUM_Pos; | ||||||
|   uint16_t const bcnt = (grxstsp & GRXSTSP_BCNT_Msk) >> GRXSTSP_BCNT_Pos; |   uint16_t const bcnt = (grxstsp & GRXSTSP_BCNT_Msk) >> GRXSTSP_BCNT_Pos; | ||||||
|  |  | ||||||
|   dwc2_epout_t* epout = &dwc2->epout[epnum]; |   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) { |   switch (pktsts) { | ||||||
|     // Global OUT NAK: do nothing |     // Global OUT NAK: do nothing | ||||||
|     case GRXSTS_PKTSTS_GLOBALOUTNAK: |     case GRXSTS_PKTSTS_GLOBALOUTNAK: | ||||||
| @@ -971,15 +962,14 @@ static void handle_rxflvl_irq(uint8_t rhport) { | |||||||
|  |  | ||||||
|     case GRXSTS_PKTSTS_SETUPRX: |     case GRXSTS_PKTSTS_SETUPRX: | ||||||
|       // Setup packet received |       // 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[0] = (*rx_fifo); | ||||||
|       _setup_packet[1] = (*rx_fifo); |       _setup_packet[1] = (*rx_fifo); | ||||||
|       break; |       break; | ||||||
|  |  | ||||||
|     case GRXSTS_PKTSTS_SETUPDONE: |     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); |       epout->doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); | ||||||
|       break; |       break; | ||||||
|  |  | ||||||
| @@ -1011,8 +1001,8 @@ static void handle_rxflvl_irq(uint8_t rhport) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     case GRXSTS_PKTSTS_OUTDONE: |     case GRXSTS_PKTSTS_OUTDONE: | ||||||
|       /* Out packet done (Interrupt) |       /* Out packet done | ||||||
|          After this entry is popped from the receive FIFO, the controller asserts a Transfer Completed interrupt on |          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() */ |          the specified OUT endpoint which will be handled by handle_epout_irq() */ | ||||||
|       break; |       break; | ||||||
|  |  | ||||||
| @@ -1034,51 +1024,56 @@ static void handle_epout_irq(uint8_t rhport) { | |||||||
|       const uint32_t doepint = epout->doepint; |       const uint32_t doepint = epout->doepint; | ||||||
|       TU_ASSERT((epout->doepint & DOEPINT_AHBERR) == 0, ); |       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 |       // OUT XFER complete | ||||||
|       if (doepint & DOEPINT_XFRC) { |       if (doepint & DOEPINT_XFRC) { | ||||||
|         epout->doepint = DOEPINT_XFRC; |         epout->doepint = DOEPINT_XFRC; | ||||||
|  |  | ||||||
|         xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); |         // 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(dma_enabled(dwc2)) { | ||||||
|           if (doepint & DOEPINT_SETUP) { |             if ((epnum == 0) && ep0_pending[TUSB_DIR_OUT]) { | ||||||
|             // STPKTRX is only available for version from 3_00a |               // EP0 can only handle one packet Schedule another packet to be received. | ||||||
|             if ((doepint & DOEPINT_DMA_STPKTRX) && (dwc2->gsnpsid > DWC2_CORE_REV_3_00a)) { |               edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT, 1, ep0_pending[TUSB_DIR_OUT]); | ||||||
|               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 { |             } else { | ||||||
|               // EP0 can only handle one packet |               // Fix packet length | ||||||
|               if ((epnum == 0) && ep0_pending[TUSB_DIR_OUT]) { |               uint16_t remain = (epout->doeptsiz & DOEPTSIZ_XFRSIZ_Msk) >> DOEPTSIZ_XFRSIZ_Pos; | ||||||
|                 // Schedule another packet to be received. |               xfer->total_len -= remain; | ||||||
|                 edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT, 1, ep0_pending[TUSB_DIR_OUT]); |               // this is ZLP, so prepare EP0 for next setup | ||||||
|               } else { |               if(epnum == 0 && xfer->total_len == 0) { | ||||||
|                 // Fix packet length |                 dma_setup_prepare(rhport); | ||||||
|                 uint16_t remain = (epout->doeptsiz & DOEPTSIZ_XFRSIZ_Msk) >> DOEPTSIZ_XFRSIZ_Pos; |  | ||||||
|                 xfer->total_len -= remain; |  | ||||||
|                 // this is ZLP, so prepare EP0 for next setup |  | ||||||
|                 if(epnum == 0 && xfer->total_len == 0) { |  | ||||||
|                   dma_setup_prepare(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; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|  |               dcd_event_xfer_complete(rhport, epnum, xfer->total_len, XFER_RESULT_SUCCESS, true); | ||||||
|  |             } | ||||||
|  |           } else { | ||||||
|             // EP0 can only handle one packet |             // EP0 can only handle one packet | ||||||
|             if ((epnum == 0) && ep0_pending[TUSB_DIR_OUT]) { |             if ((epnum == 0) && ep0_pending[TUSB_DIR_OUT]) { | ||||||
|               // Schedule another packet to be received. |               // 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. |   // RxFIFO non-empty interrupt handling. | ||||||
|   if (int_status & GINTSTS_RXFLVL) { |   if (int_status & GINTSTS_RXFLVL) { | ||||||
|     // RXFLVL bit is read-only |     // RXFLVL bit is read-only | ||||||
|  |     dwc2->gintmsk &= ~GINTMSK_RXFLVLM; // disable RXFLVL interrupt while reading | ||||||
|     // Mask out RXFLVL while reading data from FIFO |  | ||||||
|     dwc2->gintmsk &= ~GINTMSK_RXFLVLM; |  | ||||||
|  |  | ||||||
|     do { |     do { | ||||||
|       // Loop until all available packets were handled |       handle_rxflvl_irq(rhport); // read all packets | ||||||
|       handle_rxflvl_irq(rhport); |  | ||||||
|     } while(dwc2->gintsts & GINTSTS_RXFLVL); |     } while(dwc2->gintsts & GINTSTS_RXFLVL); | ||||||
|  |  | ||||||
|     dwc2->gintmsk |= GINTMSK_RXFLVLM; |     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_Msk                 (0x1UL << DOEPINT_NYET_Pos)              // 0x00004000 | ||||||
| #define DOEPINT_NYET                     DOEPINT_NYET_Msk                         // NYET interrupt | #define DOEPINT_NYET                     DOEPINT_NYET_Msk                         // NYET interrupt | ||||||
|  |  | ||||||
| #define DOEPINT_DMA_STPKTRX_Pos          (15U) | #define DOEPINT_STPKTRX_Pos              (15U) | ||||||
| #define DOEPINT_DMA_STPKTRX_Msk          (0x1UL << DOEPINT_DMA_STPKTRX_Pos)       // 0x00008000 | #define DOEPINT_STPKTRX_Msk              (0x1UL << DOEPINT_STPKTRX_Pos)           // 0x00008000 | ||||||
| #define DOEPINT_DMA_STPKTRX              DOEPINT_DMA_STPKTRX_Msk                  // Setup Packet Received in Buffer DMA Mode | #define DOEPINT_STPKTRX                  DOEPINT_STPKTRX_Msk                      // Setup Packet Received | ||||||
|  |  | ||||||
| /********************  Bit definition for DOEPTSIZ register  ********************/ | /********************  Bit definition for DOEPTSIZ register  ********************/ | ||||||
| #define DOEPTSIZ_XFRSIZ_Pos              (0U) | #define DOEPTSIZ_XFRSIZ_Pos              (0U) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 hathach
					hathach