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

cdc device: claim endpoint before checking fifo availability

- add pre-check to reduce mutex lock in usbd_edpt_claim
hathach 5 лет назад
Родитель
Сommit
23e6ee2ea2
2 измененных файлов с 22 добавлено и 6 удалено
  1. 18 5
      src/class/cdc/cdc_device.c
  2. 4 1
      src/device/usbd.c

+ 18 - 5
src/class/cdc/cdc_device.c

@@ -75,14 +75,27 @@ CFG_TUSB_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC];
 
 static void _prep_out_transaction (cdcd_interface_t* p_cdc)
 {
+  uint8_t const rhport = TUD_OPT_RHPORT;
+  uint16_t available = tu_fifo_remaining(&p_cdc->rx_ff);
+
   // Prepare for incoming data but only allow what we can store in the ring buffer.
-  uint16_t const available = tu_fifo_remaining(&p_cdc->rx_ff);
-  TU_VERIFY( available >= sizeof(p_cdc->epout_buf), );
+  // TODO Actually we can still carry out the transfer, keeping count of received bytes
+  // and slowly move it to the FIFO when read().
+  // This pre-check reduces endpoint claiming
+  TU_VERIFY(available >= sizeof(p_cdc->epout_buf), );
+
+  // claim endpoint
+  TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_out), );
 
-  // claim endpoint and submit transfer
-  if ( usbd_edpt_claim(TUD_OPT_RHPORT, p_cdc->ep_out) )
+  // fifo can be changed before endpoint is claimed
+  available = tu_fifo_remaining(&p_cdc->rx_ff);
+
+  if ( available >= sizeof(p_cdc->epout_buf) )  {
+    usbd_edpt_xfer(rhport, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf));
+  }else
   {
-    usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf));
+    // Release endpoint since we don't make any transfer
+    usbd_edpt_release(rhport, p_cdc->ep_out);
   }
 }
 

+ 4 - 1
src/device/usbd.c

@@ -1100,11 +1100,14 @@ bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr)
   uint8_t const dir   = tu_edpt_dir(ep_addr);
 
 #if CFG_TUSB_OS != OPT_OS_NONE
+  // pre-check to help reducing mutex lock
+  TU_VERIFY((_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0));
+
   osal_mutex_lock(_usbd_mutex, OSAL_TIMEOUT_WAIT_FOREVER);
 #endif
 
   // can only claim the endpoint if it is not busy and not claimed yet.
-  bool ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0);
+  bool const ret = (_usbd_dev.ep_status[epnum][dir].busy == 0) && (_usbd_dev.ep_status[epnum][dir].claimed == 0);
   if (ret)
   {
     _usbd_dev.ep_status[epnum][dir].claimed = 1;