Просмотр исходного кода

make dwc2 stm32 rhport support dynamic

hathach 3 лет назад
Родитель
Сommit
31134f41a1

+ 44 - 36
src/portable/synopsys/dwc2/dcd_dwc2.c

@@ -50,12 +50,14 @@
   #error "Unsupported MCUs"
 #endif
 
+// Note _dwc2_controller[] must be defined by port header
+
 //--------------------------------------------------------------------+
 // MACRO TYPEDEF CONSTANT ENUM
 //--------------------------------------------------------------------+
 
 // DWC2 registers
-#define DWC2_REG(_port)       ((dwc2_regs_t*) DWC2_REG_BASE)
+#define DWC2_REG(_port)       ((dwc2_regs_t*) _dwc2_controller[_port].reg_base)
 
 // Debug level for DWC2
 #define DWC2_DEBUG    2
@@ -72,7 +74,6 @@
 #define dcache_clean_invalidate(_addr, _size)
 #endif
 
-
 static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[2];
 
 typedef struct {
@@ -97,34 +98,32 @@ static bool     _out_ep_closed;                   // Flag to check if RX FIFO si
 static bool _sof_en;
 
 // Calculate the RX FIFO size according to recommendations from reference manual
-static inline uint16_t calc_rx_ff_size(uint16_t ep_size)
+static inline uint16_t calc_grxfsiz(uint16_t max_ep_size, uint8_t ep_count)
 {
-  return 15 + 2*(ep_size/4) + 2*DWC2_EP_MAX;
+  return 15 + 2*(max_ep_size/4) + 2*ep_count;
 }
 
 static void update_grxfsiz(uint8_t rhport)
 {
-  (void) rhport;
-
-  dwc2_regs_t * dwc2 = DWC2_REG(rhport);
+  dwc2_regs_t * dwc2     = DWC2_REG(rhport);
+  uint8_t const ep_count = _dwc2_controller[rhport].ep_count;
 
   // Determine largest EP size for RX FIFO
   uint16_t max_epsize = 0;
-  for (uint8_t epnum = 0; epnum < DWC2_EP_MAX; epnum++)
+  for (uint8_t epnum = 0; epnum < ep_count; epnum++)
   {
     max_epsize = tu_max16(max_epsize, xfer_status[epnum][TUSB_DIR_OUT].max_size);
   }
 
   // Update size of RX FIFO
-  dwc2->grxfsiz = calc_rx_ff_size(max_epsize);
+  dwc2->grxfsiz = calc_grxfsiz(max_epsize, ep_count);
 }
 
-// Setup the control endpoint 0.
+// Start of Bus Reset
 static void bus_reset(uint8_t rhport)
 {
-  (void) rhport;
-
-  dwc2_regs_t * dwc2 = DWC2_REG(rhport);
+  dwc2_regs_t * dwc2     = DWC2_REG(rhport);
+  uint8_t const ep_count = _dwc2_controller[rhport].ep_count;
 
   tu_memclr(xfer_status, sizeof(xfer_status));
   _out_ep_closed = false;
@@ -135,7 +134,7 @@ static void bus_reset(uint8_t rhport)
   dwc2->dcfg &= ~DCFG_DAD_Msk;
 
   // 1. NAK for all OUT endpoints
-  for ( uint8_t n = 0; n < DWC2_EP_MAX; n++ )
+  for ( uint8_t n = 0; n < ep_count; n++ )
   {
     dwc2->epout[n].doepctl |= DOEPCTL_SNAK;
   }
@@ -185,22 +184,24 @@ static void bus_reset(uint8_t rhport)
   //   - 2 for each used OUT endpoint
   //
   //   Therefore GRXFSIZ = 13 + 1 + 1 + 2 x (Largest-EPsize/4) + 2 x EPOUTnum
-  //   - FullSpeed (64 Bytes ): GRXFSIZ = 15 + 2 x  16 + 2 x DWC2_EP_MAX = 47  + 2 x DWC2_EP_MAX
-  //   - Highspeed (512 bytes): GRXFSIZ = 15 + 2 x 128 + 2 x DWC2_EP_MAX = 271 + 2 x DWC2_EP_MAX
+  //   - FullSpeed (64 Bytes ): GRXFSIZ = 15 + 2 x  16 + 2 x ep_count = 47  + 2 x ep_count
+  //   - Highspeed (512 bytes): GRXFSIZ = 15 + 2 x 128 + 2 x ep_count = 271 + 2 x ep_count
   //
   //   NOTE: Largest-EPsize & EPOUTnum is actual used endpoints in configuration. Since DCD has no knowledge
-  //   of the overall picture yet. We will use the worst scenario: largest possible + DWC2_EP_MAX
+  //   of the overall picture yet. We will use the worst scenario: largest possible + ep_count
   //
   //   For Isochronous, largest EP size can be 1023/1024 for FS/HS respectively. In addition if multiple ISO
   //   are enabled at least "2 x (Largest-EPsize/4) + 1" are recommended.  Maybe provide a macro for application to
   //   overwrite this.
 
-  dwc2->grxfsiz = calc_rx_ff_size(TUD_OPT_HIGH_SPEED ? 512 : 64);
+  // EP0 out max is 64
+  dwc2->grxfsiz = calc_grxfsiz(64, ep_count);
 
+  // Setup the control endpoint 0
   _allocated_fifo_words_tx = 16;
 
   // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word )
-  dwc2->dieptxf0 = (16 << DIEPTXF0_TX0FD_Pos) | (DWC2_EP_FIFO_SIZE/4 - _allocated_fifo_words_tx);
+  dwc2->dieptxf0 = (16 << DIEPTXF0_TX0FD_Pos) | (_dwc2_controller[rhport].ep_fifo_size/4 - _allocated_fifo_words_tx);
 
   // Fixed control EP0 size to 64 bytes
   dwc2->epin[0].diepctl &= ~(0x03 << DIEPCTL_MPSIZ_Pos);
@@ -363,7 +364,11 @@ static void reset_core(dwc2_regs_t * dwc2)
 static bool phy_hs_supported(dwc2_regs_t * dwc2)
 {
   // note: esp32 incorrect report its hs_phy_type as utmi
+#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
+  return false;
+#else
   return TUD_OPT_HIGH_SPEED && dwc2->ghwcfg2_bm.hs_phy_type != HS_PHY_TYPE_NONE;
+#endif
 }
 
 static void phy_fs_init(dwc2_regs_t * dwc2)
@@ -620,12 +625,13 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
 {
   (void) rhport;
 
-  dwc2_regs_t * dwc2 = DWC2_REG(rhport);
+  dwc2_regs_t * dwc2     = DWC2_REG(rhport);
+  uint8_t const ep_count = _dwc2_controller[rhport].ep_count;
 
   uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress);
   uint8_t const dir   = tu_edpt_dir(desc_edpt->bEndpointAddress);
 
-  TU_ASSERT(epnum < DWC2_EP_MAX);
+  TU_ASSERT(epnum < ep_count);
 
   xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir);
   xfer->max_size = tu_edpt_packet_size(desc_edpt);
@@ -636,12 +642,12 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
   if(dir == TUSB_DIR_OUT)
   {
     // Calculate required size of RX FIFO
-    uint16_t const sz = calc_rx_ff_size(4*fifo_size);
+    uint16_t const sz = calc_grxfsiz(4*fifo_size, ep_count);
 
     // If size_rx needs to be extended check if possible and if so enlarge it
     if (dwc2->grxfsiz < sz)
     {
-      TU_ASSERT(sz + _allocated_fifo_words_tx <= DWC2_EP_FIFO_SIZE/4);
+      TU_ASSERT(sz + _allocated_fifo_words_tx <= _dwc2_controller[rhport].ep_fifo_size/4);
 
       // Enlarge RX FIFO
       dwc2->grxfsiz = sz;
@@ -678,15 +684,15 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
     // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n".
 
     // Check if free space is available
-    TU_ASSERT(_allocated_fifo_words_tx + fifo_size + dwc2->grxfsiz <= DWC2_EP_FIFO_SIZE/4);
+    TU_ASSERT(_allocated_fifo_words_tx + fifo_size + dwc2->grxfsiz <= _dwc2_controller[rhport].ep_fifo_size/4);
 
     _allocated_fifo_words_tx += fifo_size;
 
-    TU_LOG(DWC2_DEBUG, "    Allocated %u bytes at offset %u", fifo_size*4, DWC2_EP_FIFO_SIZE-_allocated_fifo_words_tx*4);
+    TU_LOG(DWC2_DEBUG, "    Allocated %u bytes at offset %lu", fifo_size*4, _dwc2_controller[rhport].ep_fifo_size-_allocated_fifo_words_tx*4);
 
     // DIEPTXF starts at FIFO #1.
     // Both TXFD and TXSA are in unit of 32-bit words.
-    dwc2->dieptxf[epnum - 1] = (fifo_size << DIEPTXF_INEPTXFD_Pos) | (DWC2_EP_FIFO_SIZE/4 - _allocated_fifo_words_tx);
+    dwc2->dieptxf[epnum - 1] = (fifo_size << DIEPTXF_INEPTXFD_Pos) | (_dwc2_controller[rhport].ep_fifo_size/4 - _allocated_fifo_words_tx);
 
     dwc2->epin[epnum].diepctl |= (1 << DIEPCTL_USBAEP_Pos) |
                                  (epnum << DIEPCTL_TXFNUM_Pos) |
@@ -703,14 +709,13 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
 // Close all non-control endpoints, cancel all pending transfers if any.
 void dcd_edpt_close_all (uint8_t rhport)
 {
-  (void) rhport;
-
-  dwc2_regs_t * dwc2 = DWC2_REG(rhport);
+  dwc2_regs_t * dwc2     = DWC2_REG(rhport);
+  uint8_t const ep_count = _dwc2_controller[rhport].ep_count;
 
   // Disable non-control interrupt
   dwc2->daintmsk = (1 << DAINTMSK_OEPM_Pos) | (1 << DAINTMSK_IEPM_Pos);
 
-  for(uint8_t n = 1; n < DWC2_EP_MAX; n++)
+  for(uint8_t n = 1; n < ep_count; n++)
   {
     // disable OUT endpoint
     dwc2->epout[n].doepctl = 0;
@@ -871,8 +876,9 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr)
   {
     uint16_t const fifo_size = (dwc2->dieptxf[epnum - 1] & DIEPTXF_INEPTXFD_Msk) >> DIEPTXF_INEPTXFD_Pos;
     uint16_t const fifo_start = (dwc2->dieptxf[epnum - 1] & DIEPTXF_INEPTXSA_Msk) >> DIEPTXF_INEPTXSA_Pos;
+
     // For now only the last opened endpoint can be closed without fuss.
-    TU_ASSERT(fifo_start == DWC2_EP_FIFO_SIZE/4 - _allocated_fifo_words_tx,);
+    TU_ASSERT(fifo_start == _dwc2_controller[rhport].ep_fifo_size/4 - _allocated_fifo_words_tx,);
     _allocated_fifo_words_tx -= fifo_size;
   }
   else
@@ -1075,11 +1081,12 @@ static void handle_rxflvl_irq(uint8_t rhport)
 
 static void handle_epout_irq (uint8_t rhport)
 {
-  dwc2_regs_t *dwc2 = DWC2_REG(rhport);
+  dwc2_regs_t * dwc2     = DWC2_REG(rhport);
+  uint8_t const ep_count = _dwc2_controller[rhport].ep_count;
 
   // DAINT for a given EP clears when DOEPINTx is cleared.
   // OEPINT will be cleared when DAINT's out bits are cleared.
-  for ( uint8_t n = 0; n < DWC2_EP_MAX; n++ )
+  for ( uint8_t n = 0; n < ep_count; n++ )
   {
     if ( dwc2->daint & TU_BIT(DAINT_OEPINT_Pos + n) )
     {
@@ -1126,12 +1133,13 @@ static void handle_epout_irq (uint8_t rhport)
 
 static void handle_epin_irq (uint8_t rhport)
 {
-  dwc2_regs_t *dwc2 = DWC2_REG(rhport);
-  dwc2_epin_t* epin = dwc2->epin;
+  dwc2_regs_t * dwc2     = DWC2_REG(rhport);
+  uint8_t const ep_count = _dwc2_controller[rhport].ep_count;
+  dwc2_epin_t* epin      = dwc2->epin;
 
   // DAINT for a given EP clears when DIEPINTx is cleared.
   // IEPINT will be cleared when DAINT's out bits are cleared.
-  for ( uint8_t n = 0; n < DWC2_EP_MAX; n++ )
+  for ( uint8_t n = 0; n < ep_count; n++ )
   {
     if ( dwc2->daint & TU_BIT(DAINT_IEPINT_Pos + n) )
     {

+ 40 - 21
src/portable/synopsys/dwc2/dwc2_stm32.h

@@ -56,12 +56,9 @@
   #define EP_FIFO_SIZE_FS 4096
   #define EP_MAX_HS       9
   #define EP_FIFO_SIZE_HS 4096
-  #if (! defined USB2_OTG_FS)
-    // H7 with only 1 USB port: H72x / H73x / H7Ax / H7Bx
-    // USB_OTG_FS_PERIPH_BASE and OTG_FS_IRQn not defined
-    #define USB_OTG_FS_PERIPH_BASE  USB1_OTG_HS_PERIPH_BASE
-    #define OTG_FS_IRQn             OTG_HS_IRQn
-  #endif
+
+  // NOTE: H7 with only 1 USB port: H72x / H73x / H7Ax / H7Bx
+  // USB_OTG_FS_PERIPH_BASE and OTG_FS_IRQn not defined
 
 #elif CFG_TUSB_MCU == OPT_MCU_STM32F7
   #include "stm32f7xx.h"
@@ -79,35 +76,57 @@
   #error "Unsupported MCUs"
 #endif
 
-// On STM32 we associate Port0 to OTG_FS, and Port1 to OTG_HS
-#if TUD_OPT_RHPORT == 0
-  #define DWC2_REG_BASE       USB_OTG_FS_PERIPH_BASE
-  #define DWC2_EP_MAX         EP_MAX_FS
-  #define DWC2_EP_FIFO_SIZE   EP_FIFO_SIZE_FS
-  #define RHPORT_IRQn         OTG_FS_IRQn
-
+// OTG HS always has higher number of endpoints than FS
+#ifdef EP_MAX_HS
+  #define DWC2_EP_MAX   EP_MAX_HS
 #else
-  #define DWC2_REG_BASE       USB_OTG_HS_PERIPH_BASE
-  #define DWC2_EP_MAX         EP_MAX_HS
-  #define DWC2_EP_FIFO_SIZE   EP_FIFO_SIZE_HS
-  #define RHPORT_IRQn         OTG_HS_IRQn
+  #define DWC2_EP_MAX   EP_MAX_FS
+#endif
 
+// On STM32 we associate Port0 to OTG_FS, and Port1 to OTG_HS
+//#if TUD_OPT_RHPORT == 0
+//  #define DWC2_REG_BASE       USB_OTG_FS_PERIPH_BASE
+//  #define DWC2_EP_MAX         EP_MAX_FS
+//  #define DWC2_EP_FIFO_SIZE   EP_FIFO_SIZE_FS
+//  #define RHPORT_IRQn         OTG_FS_IRQn
+//
+//#else
+//  #define DWC2_REG_BASE       USB_OTG_HS_PERIPH_BASE
+//  #define DWC2_EP_MAX         EP_MAX_HS
+//  #define DWC2_EP_FIFO_SIZE   EP_FIFO_SIZE_HS
+//  #define RHPORT_IRQn         OTG_HS_IRQn
+//
+//#endif
+
+// On STM32 for consistency we associate
+// - Port0 to OTG_FS, and Port1 to OTG_HS
+static const dwc2_controller_t _dwc2_controller[] =
+{
+#ifdef USB_OTG_FS_PERIPH_BASE
+  { .reg_base = USB_OTG_FS_PERIPH_BASE, .irqnum = OTG_FS_IRQn, .ep_count = EP_MAX_FS, .ep_fifo_size = EP_FIFO_SIZE_FS},
+#endif
+
+#ifdef USB_OTG_HS_PERIPH_BASE
+  { .reg_base = USB_OTG_HS_PERIPH_BASE, .irqnum = OTG_HS_IRQn, .ep_count = EP_MAX_HS, .ep_fifo_size = EP_FIFO_SIZE_HS},
 #endif
+};
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
 
 extern uint32_t SystemCoreClock;
 
 TU_ATTR_ALWAYS_INLINE
 static inline void dwc2_dcd_int_enable(uint8_t rhport)
 {
-  (void) rhport;
-  NVIC_EnableIRQ(RHPORT_IRQn);
+  NVIC_EnableIRQ(_dwc2_controller[rhport].irqnum);
 }
 
 TU_ATTR_ALWAYS_INLINE
 static inline void dwc2_dcd_int_disable (uint8_t rhport)
 {
-  (void) rhport;
-  NVIC_DisableIRQ(RHPORT_IRQn);
+  NVIC_DisableIRQ(_dwc2_controller[rhport].irqnum);
 }
 
 TU_ATTR_ALWAYS_INLINE

+ 13 - 4
src/portable/synopsys/dwc2/dwc2_type.h

@@ -19,6 +19,19 @@
 
 #include "stdint.h"
 
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// Controller
+typedef struct
+{
+  uint32_t reg_base;
+  uint32_t irqnum;
+  uint8_t  ep_count;
+  uint32_t ep_fifo_size;
+}dwc2_controller_t;
+
 /* DWC OTG HW Release versions */
 #define DWC2_CORE_REV_2_71a   0x4f54271a
 #define DWC2_CORE_REV_2_72a   0x4f54272a
@@ -40,10 +53,6 @@
 #define DWC2_FS_IOT_ID        0x55310000
 #define DWC2_HS_IOT_ID        0x55320000
 
-#ifdef __cplusplus
- extern "C" {
-#endif
-
 #if 0
 // HS PHY
 typedef struct