Browse Source

Merge pull request #1434 from Skyler84/rp2040-hcd-bulk

Rp2040 hcd bulk
Ha Thach 3 years ago
parent
commit
9e9f331503
2 changed files with 40 additions and 18 deletions
  1. 14 0
      src/common/tusb_types.h
  2. 26 18
      src/portable/raspberrypi/rp2040/hcd_rp2040.c

+ 14 - 0
src/common/tusb_types.h

@@ -513,6 +513,20 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_edpt_packet_size(tusb_desc_endpo
   return tu_le16toh(desc_ep->wMaxPacketSize) & TU_GENMASK(10, 0);
   return tu_le16toh(desc_ep->wMaxPacketSize) & TU_GENMASK(10, 0);
 }
 }
 
 
+#if CFG_TUSB_DEBUG
+TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_dir_str(tusb_dir_t dir)
+{
+  static const char *str[] = {"out", "in"};
+  return str[dir];
+}
+
+TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_type_str(tusb_xfer_type_t t)
+{
+  static const char *str[] = {"control", "isochronous", "bulk", "interrupt"};
+  return str[t];
+}
+#endif
+
 //--------------------------------------------------------------------+
 //--------------------------------------------------------------------+
 // Descriptor helper
 // Descriptor helper
 //--------------------------------------------------------------------+
 //--------------------------------------------------------------------+

+ 26 - 18
src/portable/raspberrypi/rp2040/hcd_rp2040.c

@@ -138,20 +138,25 @@ static void __tusb_irq_path_func(hw_handle_buff_status)(void)
         _handle_buff_status_bit(bit, ep);
         _handle_buff_status_bit(bit, ep);
     }
     }
 
 
-    // Check interrupt endpoints
+    // Check "interrupt" (asynchronous) endpoints for both IN and OUT
     for (uint i = 1; i <= USB_HOST_INTERRUPT_ENDPOINTS && remaining_buffers; i++)
     for (uint i = 1; i <= USB_HOST_INTERRUPT_ENDPOINTS && remaining_buffers; i++)
     {
     {
-        // EPX is bit 0
-        // IEP1 is bit 2
-        // IEP2 is bit 4
-        // IEP3 is bit 6
+        // EPX is bit 0 & 1
+        // IEP1 IN  is bit 2
+        // IEP1 OUT is bit 3
+        // IEP2 IN  is bit 4
+        // IEP2 OUT is bit 5
+        // IEP3 IN  is bit 6
+        // IEP3 OUT is bit 7
         // etc
         // etc
-        bit = 1 << (i*2);
-
-        if (remaining_buffers & bit)
+        for(uint j = 0; j < 2; j++)
         {
         {
-            remaining_buffers &= ~bit;
-            _handle_buff_status_bit(bit, &ep_pool[i]);
+            bit = 1 << (i*2+j);
+            if (remaining_buffers & bit)
+            {
+                remaining_buffers &= ~bit;
+                _handle_buff_status_bit(bit, &ep_pool[i]);
+            }
         }
         }
     }
     }
 
 
@@ -273,10 +278,12 @@ static struct hw_endpoint *_hw_endpoint_allocate(uint8_t transfer_type)
 {
 {
     struct hw_endpoint *ep = NULL;
     struct hw_endpoint *ep = NULL;
 
 
-    if (transfer_type == TUSB_XFER_INTERRUPT)
+    if (transfer_type != TUSB_XFER_CONTROL)
     {
     {
+        // Note: even though datasheet name these "Interrupt" endpoints. These are actually
+        // "Asynchronous" endpoints and can be used for other type such as: Bulk  (ISO need confirmation)
         ep = _next_free_interrupt_ep();
         ep = _next_free_interrupt_ep();
-        pico_info("Allocate interrupt ep %d\n", ep->interrupt_num);
+        pico_info("Allocate %s ep %d\n", tu_edpt_type_str(transfer_type), ep->interrupt_num);
         assert(ep);
         assert(ep);
         ep->buffer_control = &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num].ctrl;
         ep->buffer_control = &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num].ctrl;
         ep->endpoint_control = &usbh_dpram->int_ep_ctrl[ep->interrupt_num].ctrl;
         ep->endpoint_control = &usbh_dpram->int_ep_ctrl[ep->interrupt_num].ctrl;
@@ -337,13 +344,13 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t
     pico_trace("endpoint control (0x%p) <- 0x%x\n", ep->endpoint_control, ep_reg);
     pico_trace("endpoint control (0x%p) <- 0x%x\n", ep->endpoint_control, ep_reg);
     ep->configured = true;
     ep->configured = true;
 
 
-    if (bmInterval)
+    if (ep != &epx)
     {
     {
-        // This is an interrupt endpoint
-        // so need to set up interrupt endpoint address control register with:
-        // device address
-        // endpoint number / direction
-        // preamble
+        // Endpoint has its own addr_endp and interrupt bits to be setup!
+        // This is an interrupt/async endpoint. so need to set up ADDR_ENDP register with:
+        // - device address
+        // - endpoint number / direction
+        // - preamble
         uint32_t reg = (uint32_t) (dev_addr | (num << USB_ADDR_ENDP1_ENDPOINT_LSB));
         uint32_t reg = (uint32_t) (dev_addr | (num << USB_ADDR_ENDP1_ENDPOINT_LSB));
 
 
         if (dir == TUSB_DIR_OUT)
         if (dir == TUSB_DIR_OUT)
@@ -523,6 +530,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
 
 
     // Get appropriate ep. Either EPX or interrupt endpoint
     // Get appropriate ep. Either EPX or interrupt endpoint
     struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr);
     struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr);
+
     TU_ASSERT(ep);
     TU_ASSERT(ep);
 
 
     // EP should be inactive
     // EP should be inactive