فهرست منبع

basically finish code for control transfer & test code

hathach 13 سال پیش
والد
کامیت
7557a807a9
2فایلهای تغییر یافته به همراه78 افزوده شده و 38 حذف شده
  1. 48 21
      tests/test/host/ehci/test_ehci_pipe_xfer.c
  2. 30 17
      tinyusb/host/ehci/ehci.c

+ 48 - 21
tests/test/host/ehci/test_ehci_pipe_xfer.c

@@ -121,10 +121,31 @@ tusb_std_request_t request_get_dev_desc =
     .wLength  = 18
 };
 
+void verify_qtd(ehci_qtd_t *p_qtd, uint8_t p_data[], uint16_t length)
+{
+  TEST_ASSERT_TRUE(p_qtd->alternate.terminate); // not used, always invalid
+
+  TEST_ASSERT_FALSE(p_qtd->pingstate_err);
+  TEST_ASSERT_FALSE(p_qtd->non_hs_split_state);
+  TEST_ASSERT_FALSE(p_qtd->non_hs_period_missed_uframe);
+  TEST_ASSERT_FALSE(p_qtd->xact_err);
+  TEST_ASSERT_FALSE(p_qtd->babble_err);
+  TEST_ASSERT_FALSE(p_qtd->buffer_err);
+  TEST_ASSERT_FALSE(p_qtd->halted);
+  TEST_ASSERT_TRUE(p_qtd->active);
+
+  TEST_ASSERT_EQUAL(3, p_qtd->cerr);
+  TEST_ASSERT_EQUAL(0, p_qtd->current_page);
+  TEST_ASSERT_EQUAL(length, p_qtd->total_bytes);
+
+  TEST_ASSERT_EQUAL_HEX(p_data, p_qtd->buffer[0]);
+}
+
 void test_control_addr0_xfer_get_check_qhd_qtd_mapping(void)
 {
   dev_addr = 0;
   ehci_qhd_t * const p_qhd = async_head;
+
   hcd_pipe_control_open(dev_addr, control_max_packet_size);
 
   //------------- Code Under TEST -------------//
@@ -135,13 +156,15 @@ void test_control_addr0_xfer_get_check_qhd_qtd_mapping(void)
   p_status = &ehci_data.addr0.qtd[2];
 
   TEST_ASSERT_EQUAL_HEX( p_setup, p_qhd->qtd_overlay.next.address );
-
   TEST_ASSERT_EQUAL_HEX( p_setup  , p_qhd->p_qtd_list);
   TEST_ASSERT_EQUAL_HEX( p_data   , p_setup->next.address);
   TEST_ASSERT_EQUAL_HEX( p_status , p_data->next.address );
   TEST_ASSERT_TRUE( p_status->next.terminate );
+
+  verify_qtd(p_setup, &ehci_data.addr0.request, 8);
 }
 
+
 void test_control_xfer_get(void)
 {
   ehci_qhd_t * const p_qhd = &ehci_data.device[dev_addr].control.qhd;
@@ -151,35 +174,32 @@ void test_control_xfer_get(void)
   hcd_pipe_control_xfer(dev_addr, &request_get_dev_desc, xfer_data);
 
   TEST_ASSERT_EQUAL_HEX( p_setup, p_qhd->qtd_overlay.next.address );
-
   TEST_ASSERT_EQUAL_HEX( p_setup  , p_qhd->p_qtd_list);
   TEST_ASSERT_EQUAL_HEX( p_data   , p_setup->next.address);
   TEST_ASSERT_EQUAL_HEX( p_status , p_data->next.address );
   TEST_ASSERT_TRUE( p_status->next.terminate );
 
-  ehci_qtd_t *p_qtd = p_setup;
-  TEST_ASSERT_TRUE(p_qtd->alternate.terminate); // not used, always invalid
+  //------------- SETUP -------------//
+  uint8_t* p_request = (uint8_t *) &ehci_data.device[dev_addr].control.request;
+  verify_qtd(p_setup, p_request, 8);
 
-  TEST_ASSERT_FALSE(p_qtd->pingstate_err);
-  TEST_ASSERT_FALSE(p_qtd->non_hs_split_state);
-  TEST_ASSERT_FALSE(p_qtd->non_hs_period_missed_uframe);
-  TEST_ASSERT_FALSE(p_qtd->xact_err);
-  TEST_ASSERT_FALSE(p_qtd->babble_err);
-  TEST_ASSERT_FALSE(p_qtd->buffer_err);
-  TEST_ASSERT_FALSE(p_qtd->halted);
-  TEST_ASSERT_TRUE(p_qtd->active);
+  TEST_ASSERT_EQUAL_MEMORY(&request_get_dev_desc, p_request, sizeof(tusb_std_request_t));
 
-  TEST_ASSERT_EQUAL(3, p_qtd->cerr);
-  TEST_ASSERT_EQUAL(0, p_qtd->current_page);
-  TEST_ASSERT_FALSE(p_qtd->int_on_complete);
-  TEST_ASSERT_EQUAL(8, p_qtd->total_bytes);
-  TEST_ASSERT_FALSE(p_qtd->data_toggle);
+  TEST_ASSERT_FALSE(p_setup->int_on_complete);
+  TEST_ASSERT_FALSE(p_setup->data_toggle);
+  TEST_ASSERT_EQUAL(EHCI_PID_SETUP, p_setup->pid);
 
-  uint8_t *p_data = (uint8_t *) &ehci_data.device[dev_addr].control.request;
-  TEST_ASSERT_EQUAL_HEX(p_data, p_qtd->buffer[0]);
-  TEST_ASSERT_EQUAL_MEMORY(&request_get_dev_desc, p_data, sizeof(tusb_std_request_t));
+  //------------- DATA -------------//
+  verify_qtd(p_data, xfer_data, request_get_dev_desc.wLength);
+  TEST_ASSERT_FALSE(p_data->int_on_complete);
+  TEST_ASSERT_TRUE(p_data->data_toggle);
+  TEST_ASSERT_EQUAL(EHCI_PID_IN, p_data->pid);
 
-  TEST_ASSERT_EQUAL(EHCI_PID_SETUP, p_qtd->pid);
+  //------------- STATUS -------------//
+  verify_qtd(p_status, NULL, 0);
+  TEST_ASSERT_TRUE(p_status->int_on_complete);
+  TEST_ASSERT_TRUE(p_status->data_toggle);
+  TEST_ASSERT_EQUAL(EHCI_PID_OUT, p_status->pid);
 }
 
 void test_control_xfer_set(void)
@@ -197,9 +217,16 @@ void test_control_xfer_set(void)
   //------------- Code Under TEST -------------//
   hcd_pipe_control_xfer(dev_addr, &request_set_dev_addr, xfer_data);
 
+  TEST_ASSERT_EQUAL_HEX( p_setup, p_qhd->qtd_overlay.next.address );
   TEST_ASSERT_EQUAL_HEX( p_setup  , p_qhd->p_qtd_list);
   TEST_ASSERT_EQUAL_HEX( p_status , p_setup->next.address );
   TEST_ASSERT_TRUE( p_status->next.terminate );
+
+  //------------- STATUS -------------//
+  verify_qtd(p_status, NULL, 0);
+  TEST_ASSERT_TRUE(p_status->int_on_complete);
+  TEST_ASSERT_TRUE(p_status->data_toggle);
+  TEST_ASSERT_EQUAL(EHCI_PID_IN, p_status->pid);
 }
 
 

+ 30 - 17
tinyusb/host/ehci/ehci.c

@@ -246,6 +246,7 @@ tusb_error_t hcd_controller_reset(uint8_t hostid)
 // PIPE API
 //--------------------------------------------------------------------+
 static void queue_head_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, uint16_t max_packet_size, uint8_t endpoint_addr, uint8_t xfer_type);
+
 static inline ehci_qhd_t* const get_control_qhd(uint8_t dev_addr) ATTR_ALWAYS_INLINE ATTR_PURE ATTR_WARN_UNUSED_RESULT;
 static inline ehci_qtd_t* get_control_qtds(uint8_t dev_addr) ATTR_ALWAYS_INLINE ATTR_PURE ATTR_WARN_UNUSED_RESULT;
 static inline tusb_std_request_t* const get_control_request_ptr(uint8_t dev_addr) ATTR_ALWAYS_INLINE ATTR_PURE ATTR_WARN_UNUSED_RESULT;
@@ -301,6 +302,20 @@ pipe_handle_t hcd_pipe_open(uint8_t dev_addr, tusb_descriptor_endpoint_t const *
   return null_handle;
 }
 
+static void queue_td_init(ehci_qtd_t* p_qtd, uint32_t data_ptr, uint16_t total_bytes)
+{
+  memclr_(p_qtd, sizeof(ehci_qtd_t));
+
+  p_qtd->alternate.terminate = 1; // not used, always set to terminated
+  p_qtd->active = 1;
+  p_qtd->cerr = 3; // TODO 3 consecutive errors tolerance
+  p_qtd->data_toggle = 0;
+  p_qtd->total_bytes = total_bytes;
+
+  p_qtd->buffer[0] = data_ptr;
+
+}
+
 tusb_error_t  hcd_pipe_control_xfer(uint8_t dev_addr, tusb_std_request_t const * p_request, uint8_t data[])
 {
   ehci_qhd_t * const p_qhd = get_control_qhd(dev_addr);
@@ -309,21 +324,19 @@ tusb_error_t  hcd_pipe_control_xfer(uint8_t dev_addr, tusb_std_request_t const *
   ehci_qtd_t *p_data   = p_setup + 1;
   ehci_qtd_t *p_status = p_setup + 2;
 
-  memclr_(p_setup, sizeof(ehci_qtd_t));
-  p_setup->next.address = (uint32_t) p_data;
-  p_setup->active = 1;
-  p_setup->cerr = 3; // TODO 3 consecutive errors tolerance
-  p_setup->data_toggle = 0;
-  p_setup->total_bytes = 8; // sizeof (tusb_std_request_t)
-
-  p_setup->buffer[0] = (uint32_t) get_control_request_ptr(dev_addr);
-  *(get_control_request_ptr(dev_addr)) = *p_request;
+  //------------- SETUP Phase -------------//
+  *(get_control_request_ptr(dev_addr)) = *p_request; // copy request
 
+  queue_td_init(p_setup, (uint32_t) get_control_request_ptr(dev_addr), 8);
   p_setup->pid = EHCI_PID_SETUP;
+  p_setup->next.address = (uint32_t) p_data;
 
+  //------------- DATA Phase -------------//
   if (p_request->wLength > 0)
   {
-
+    queue_td_init(p_data, (uint32_t) data, p_request->wLength);
+    p_data->data_toggle = 1;
+    p_data->pid         = p_request->bmRequestType.direction ? EHCI_PID_IN : EHCI_PID_OUT;
   }else
   {
     p_data = p_setup;
@@ -331,15 +344,15 @@ tusb_error_t  hcd_pipe_control_xfer(uint8_t dev_addr, tusb_std_request_t const *
 
   p_data->next.address = (uint32_t) p_status;
 
-  p_status->next.terminate = 1;
-
-  //------------- alternate link is not used -------------//
-  p_data->alternate.terminate = 1;
-  p_setup->alternate.terminate = 1;
-  p_data->alternate.terminate = 1;
+  //------------- STATUS Phase -------------//
+  queue_td_init(p_status, 0, 0); // zero-length data
+  p_status->int_on_complete = 1;
+  p_status->data_toggle     = 1;
+  p_status->pid             = p_request->bmRequestType.direction ? EHCI_PID_OUT : EHCI_PID_IN; // reverse direction of data phase
+  p_status->next.terminate  = 1;
 
   //------------- hook TD List to Queue Head -------------//
-  p_qhd->p_qtd_list = p_setup;
+  p_qhd->p_qtd_list               = p_setup;
   p_qhd->qtd_overlay.next.address = (uint32_t) p_setup;
 
   return TUSB_ERROR_NONE;