Pārlūkot izejas kodu

nrf52 control transfer work reliably

hathach 8 gadi atpakaļ
vecāks
revīzija
b0ec6124e0

+ 53 - 9
hw/mcu/nordic/nrf52/tusb_port/dcd_nrf52.c

@@ -61,6 +61,8 @@ static struct
     uint16_t xfer_len;
     uint8_t  dir;
   }control;
+
+  bool dma_running;
 }_dcd_data;
 
 /*------------------------------------------------------------------*/
@@ -138,9 +140,10 @@ static void power_usb_event_handler(nrf_drv_power_usb_evt_t event)
       nrf_usbd_isosplit_set(NRF_USBD_ISOSPLIT_Half);
 
       // Enable interrupt
-      NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | /*USBD_INTEN_STARTED_Msk |*/
-          /*USBD_INTEN_ENDEPIN0_Msk |*/ USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPOUT0_Msk | USBD_INTEN_EP0SETUP_Msk |
-          USBD_INTEN_USBEVENT_Msk | USBD_INTEN_EPDATA_Msk | USBD_INTEN_ACCESSFAULT_Msk;
+      NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_USBEVENT_Msk | USBD_INTEN_ACCESSFAULT_Msk |
+          USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk |
+          /*USBD_INTEN_ENDEPIN0_Msk |*/  USBD_INTEN_ENDEPOUT0_Msk |
+          /*USBD_INTEN_STARTED_Msk |*/  USBD_INTEN_EPDATA_Msk ;
       //USBD_INTEN_SOF_Msk
 
       //  if (enable_sof || nrf_drv_usbd_errata_104())
@@ -212,28 +215,41 @@ void tusb_dcd_set_config (uint8_t port, uint8_t config_num)
 
 static void control_xact_start(void)
 {
+  // Each transaction is up to 64 bytes
   uint8_t xact_len = min16_of(_dcd_data.control.xfer_len, MAX_PACKET_SIZE);
 
   if ( _dcd_data.control.dir == TUSB_DIR_OUT )
   {
+    // TODO control out
+    NRF_USBD->EPOUT[0].PTR    = (uint32_t) _dcd_data.control.buffer;
+    NRF_USBD->EPOUT[0].MAXCNT = xact_len;
 
+    NRF_USBD->TASKS_EP0RCVOUT = 1;
   }else
   {
-    // Each transaction is up to 64 bytes
     NRF_USBD->EPIN[0].PTR        = (uint32_t) _dcd_data.control.buffer;
     NRF_USBD->EPIN[0].MAXCNT     = xact_len;
-    NRF_USBD->TASKS_STARTEPIN[0] = 1;
 
-    _dcd_data.control.buffer   += xact_len;
-    _dcd_data.control.xfer_len -= xact_len;
+    NRF_USBD->TASKS_STARTEPIN[0] = 1;
   }
+
+  _dcd_data.control.buffer   += xact_len;
+  _dcd_data.control.xfer_len -= xact_len;
+
 }
 
 static void control_xact_done(void)
 {
   if ( _dcd_data.control.xfer_len > 0 )
   {
-    control_xact_start();
+    if ( _dcd_data.control.dir == TUSB_DIR_OUT )
+    {
+      // out control need to wait for END EPOUT event before updating Pointer
+      NRF_USBD->TASKS_STARTEPOUT[0] = 1;
+    }else
+    {
+      control_xact_start();
+    }
   }else
   {
     tusb_dcd_xfer_complete(0, 0, 0, true);
@@ -272,6 +288,8 @@ void tusb_dcd_control_stall (uint8_t port)
  *------------------------------------------------------------------*/
 bool tusb_dcd_edpt_open (uint8_t port, tusb_descriptor_endpoint_t const * p_endpoint_desc)
 {
+  (void) port;
+
   return true;
 }
 
@@ -450,6 +468,32 @@ void USBD_IRQHandler(void)
 
   if ( int_status & USBD_INTEN_EP0DATADONE_Msk )
   {
-    control_xact_done();
+    if ( _dcd_data.control.dir == TUSB_DIR_OUT )
+    {
+      // out control need to wait for END EPOUT (DMA complete) event
+      NRF_USBD->TASKS_STARTEPOUT[0] = 1;
+    }else
+    {
+      if ( _dcd_data.control.xfer_len > 0 )
+      {
+        control_xact_start();
+      }else
+      {
+        // Data IN xfer complete
+        tusb_dcd_xfer_complete(0, 0, 0, true);
+      }
+    }
+  }
+
+  if ( int_status & USBD_INTEN_ENDEPOUT0_Msk)
+  {
+    if ( _dcd_data.control.xfer_len > 0 )
+    {
+      control_xact_start();
+    }else
+    {
+      // Data OUT xfer complete
+      tusb_dcd_xfer_complete(0, 0, 0, true);
+    }
   }
 }

+ 39 - 37
tinyusb/class/cdc/cdc_device.c

@@ -212,52 +212,54 @@ void cdcd_close(uint8_t port)
 
 tusb_error_t cdcd_control_request_subtask(uint8_t port, tusb_control_request_t const * p_request)
 {
+  OSAL_SUBTASK_BEGIN
+
+  tusb_error_t err;
+
   //------------- Class Specific Request -------------//
   if (p_request->bmRequestType_bit.type != TUSB_REQ_TYPE_CLASS) return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT;
 
-  switch(p_request->bRequest)
+  if (CDC_REQUEST_GET_LINE_CODING == p_request->bRequest)
   {
-    case CDC_REQUEST_GET_LINE_CODING:
-      tusb_dcd_control_xfer(port, (tusb_dir_t) p_request->bmRequestType_bit.direction,
-                            (uint8_t*) &cdcd_line_coding[port], min16_of(sizeof(cdc_line_coding_t), p_request->wLength), false );
-    break;
-
-    case CDC_REQUEST_SET_LINE_CODING:
-      tusb_dcd_control_xfer(port, (tusb_dir_t) p_request->bmRequestType_bit.direction,
-                            (uint8_t*) &cdcd_line_coding[port], min16_of(sizeof(cdc_line_coding_t), p_request->wLength), false );
-      // TODO notify application on xfer completea
-    break;
-
-    case CDC_REQUEST_SET_CONTROL_LINE_STATE: // TODO extract DTE present
-    {
-      enum {
-        ACTIVE_DTE_PRESENT     = 0x0003,
-        ACTIVE_DTE_NOT_PRESENT = 0x0002
-      };
+    OSAL_SUBTASK_INVOKED( usbd_control_xfer_substak(port, (tusb_dir_t) p_request->bmRequestType_bit.direction,
+                                                    (uint8_t*) &cdcd_line_coding[port], min16_of(sizeof(cdc_line_coding_t), p_request->wLength)), err );
+  }
+  else if (CDC_REQUEST_SET_LINE_CODING == p_request->bRequest)
+  {
+    OSAL_SUBTASK_INVOKED( usbd_control_xfer_substak(port, (tusb_dir_t) p_request->bmRequestType_bit.direction,
+                                                    (uint8_t*) &cdcd_line_coding[port], min16_of(sizeof(cdc_line_coding_t), p_request->wLength)), err );
+    // TODO notify application on xfer completea
+  }
+  else if (CDC_REQUEST_SET_CONTROL_LINE_STATE == p_request->bRequest )
+  {
+    enum {
+      ACTIVE_DTE_PRESENT     = 0x0003,
+      ACTIVE_DTE_NOT_PRESENT = 0x0002
+    };
 
-      cdcd_data_t * p_cdc = &cdcd_data[port];
+    cdcd_data_t * p_cdc = &cdcd_data[port];
 
-      if (p_request->wValue == ACTIVE_DTE_PRESENT)
-      {
-        // terminal connected
-        p_cdc->connected = true;
-      }
-      else if (p_request->wValue == ACTIVE_DTE_NOT_PRESENT)
-      {
-        // terminal disconnected
-        p_cdc->connected = false;
-      }else
-      {
-        // De-active --> disconnected
-        p_cdc->connected = false;
-      }
+    if (p_request->wValue == ACTIVE_DTE_PRESENT)
+    {
+      // terminal connected
+      p_cdc->connected = true;
+    }
+    else if (p_request->wValue == ACTIVE_DTE_NOT_PRESENT)
+    {
+      // terminal disconnected
+      p_cdc->connected = false;
+    }else
+    {
+      // De-active --> disconnected
+      p_cdc->connected = false;
     }
-    break;
-
-    default: return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT;
+  }
+  else
+  {
+    SUBTASK_RETURN(TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT);
   }
 
-  return TUSB_ERROR_NONE;
+  OSAL_SUBTASK_END
 }
 
 tusb_error_t cdcd_xfer_cb(uint8_t port, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes)

+ 4 - 5
tinyusb/device/usbd.c

@@ -302,7 +302,7 @@ tusb_error_t usbd_control_xfer_substak(uint8_t port, tusb_dir_t dir, uint8_t * b
   }
 
   // Status opposite direction with Zero Length
-  tusb_dcd_control_xfer(port, (tusb_dir_t) (1-dir), NULL, 0, true);
+  usbd_control_status(port, 1-dir);
 
   // no need to blocking wait for status to complete
 
@@ -329,7 +329,6 @@ tusb_error_t usbd_control_request_subtask(uint8_t port, tusb_control_request_t c
 
       if ( TUSB_ERROR_NONE == error )
       {
-//        tusb_dcd_control_xfer(port, (tusb_dir_t) p_request->bmRequestType_bit.direction, (uint8_t*) p_buffer, length, false);
         OSAL_SUBTASK_INVOKED ( usbd_control_xfer_substak(port, (tusb_dir_t) p_request->bmRequestType_bit.direction, (uint8_t*) p_buffer, length ), error );;
       }
     }
@@ -379,12 +378,12 @@ tusb_error_t usbd_control_request_subtask(uint8_t port, tusb_control_request_t c
   }
 
   if(TUSB_ERROR_NONE != error)
-  { // Response with Protocol Stall if request is not supported
+  {
+    // Response with Protocol Stall if request is not supported
     tusb_dcd_control_stall(port);
   }else if (p_request->wLength == 0)
   {
-    // zero length for non-data
-    tusb_dcd_control_xfer(port, (tusb_dir_t) p_request->bmRequestType_bit.direction, NULL, 0, false);
+    usbd_control_status(port, (tusb_dir_t) p_request->bmRequestType_bit.direction);
   }
 
   OSAL_SUBTASK_END

+ 7 - 0
tinyusb/device/usbd.h

@@ -130,6 +130,13 @@ void tud_umount_cb(uint8_t port);
 
 extern osal_semaphore_t usbd_control_xfer_sem_hdl;
 
+tusb_error_t usbd_control_xfer_substak(uint8_t port, tusb_dir_t dir, uint8_t * buffer, uint16_t length);
+
+static inline bool usbd_control_status(uint8_t port, tusb_dir_t dir)
+{
+  tusb_dcd_control_xfer(port , dir, NULL, 0, false);
+}
+
 tusb_error_t usbd_init(void);
 void usbd_task( void* param);