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

improve nrf52 dcd, add fix for hw ACK issue with bulk

hathach 8 лет назад
Родитель
Сommit
2b85a8fd46
2 измененных файлов с 80 добавлено и 41 удалено
  1. 0 6
      tinyusb/class/cdc/cdc_device.c
  2. 80 35
      tinyusb/portable/nordic/nrf5x/dcd_nrf5x.c

+ 0 - 6
tinyusb/class/cdc/cdc_device.c

@@ -66,13 +66,7 @@ typedef struct {
 }cdcd_interface_t;
 }cdcd_interface_t;
 
 
 // TODO multiple rhport
 // TODO multiple rhport
-#if CFG_TUSB_MCU == OPT_MCU_NRF5X
-// FIXME nrf52 OUT bug ( Controller ACK data even we didn't prepare transfer )
-CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _tmp_rx_buf[600];
-#else
 CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _tmp_rx_buf[64];
 CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _tmp_rx_buf[64];
-#endif
-
 CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _tmp_tx_buf[64];
 CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _tmp_tx_buf[64];
 
 
 FIFO_DEF(_rx_ff, CFG_TUD_CDC_BUFSIZE, uint8_t, true);
 FIFO_DEF(_rx_ff, CFG_TUD_CDC_BUFSIZE, uint8_t, true);

+ 80 - 35
tinyusb/portable/nordic/nrf5x/dcd_nrf5x.c

@@ -70,6 +70,9 @@ typedef struct
   uint16_t actual_len;
   uint16_t actual_len;
   uint8_t  mps; // max packet size
   uint8_t  mps; // max packet size
 
 
+  // FIXME nrf52840 does not NAK OUT packet properly
+  bool     data_received;
+
 } nom_xfer_t;
 } nom_xfer_t;
 
 
 /*static*/ struct
 /*static*/ struct
@@ -163,7 +166,7 @@ static void edpt_dma_end(void)
   _dcd.dma_running = false;
   _dcd.dma_running = false;
 }
 }
 
 
-static void control_xact_start(void)
+static void xact_control_start(void)
 {
 {
   // Each transaction is up to 64 bytes
   // Each transaction is up to 64 bytes
   uint8_t const xact_len = min16_of(_dcd.control.total_len-_dcd.control.actual_len, MAX_PACKET_SIZE);
   uint8_t const xact_len = min16_of(_dcd.control.total_len-_dcd.control.actual_len, MAX_PACKET_SIZE);
@@ -200,7 +203,7 @@ bool dcd_control_xfer (uint8_t rhport, tusb_dir_t dir, uint8_t * buffer, uint16_
     _dcd.control.buffer     = buffer;
     _dcd.control.buffer     = buffer;
     _dcd.control.dir        = (uint8_t) dir;
     _dcd.control.dir        = (uint8_t) dir;
 
 
-    control_xact_start();
+    xact_control_start();
   }else
   }else
   {
   {
     // Status Phase
     // Status Phase
@@ -220,27 +223,55 @@ static inline nom_xfer_t* get_td(uint8_t epnum, uint8_t dir)
   return &_dcd.xfer[epnum-1][dir];
   return &_dcd.xfer[epnum-1][dir];
 }
 }
 
 
-static void normal_xact_start(uint8_t epnum, uint8_t dir)
+/*------------- Bulk/Int OUT transfer -------------*/
+
+/**
+ * Prepare Bulk/Int out transaction, Endpoint start to accept/ACK Data
+ * @param epnum
+ */
+static void xact_out_prepare(uint8_t epnum)
 {
 {
-  if ( dir == TUSB_DIR_OUT )
-  {
-    // Overwrite size will allow hw to accept data
-    NRF_USBD->SIZE.EPOUT[epnum] = 0;
-    __ISB(); __DSB();
-  }else
-  {
-    nom_xfer_t* xfer = get_td(epnum, dir);
+  // Write any value to size will allow hw to ACK (accept data)
+  NRF_USBD->SIZE.EPOUT[epnum] = 0;
+  __ISB(); __DSB();
+}
 
 
-    // Each transaction is up to Max Packet Size
-    uint8_t const xact_len = min16_of(xfer->total_len - xfer->actual_len, xfer->mps);
+static void xact_out_dma(uint8_t epnum)
+{
+  nom_xfer_t* xfer = get_td(epnum, TUSB_DIR_OUT);
 
 
-    NRF_USBD->EPIN[epnum].PTR    = (uint32_t) xfer->buffer;
-    NRF_USBD->EPIN[epnum].MAXCNT = xact_len;
+  uint8_t const xact_len = NRF_USBD->SIZE.EPOUT[epnum];
 
 
-    xfer->buffer += xact_len;
+  // Trigger DMA move data from Endpoint -> SRAM
+  NRF_USBD->EPOUT[epnum].PTR    = (uint32_t) xfer->buffer;
+  NRF_USBD->EPOUT[epnum].MAXCNT = xact_len;
 
 
-    edpt_dma_start(epnum, TUSB_DIR_IN);
-  }
+  edpt_dma_start(epnum, TUSB_DIR_OUT);
+
+  xfer->buffer     += xact_len;
+  xfer->actual_len += xact_len;
+}
+
+
+/*------------- Bulk/Int IN transfer -------------*/
+
+/**
+ * Prepare Bulk/Int in transaction, transfer data from Memory -> Endpoint
+ * @param epnum
+ */
+static void xact_in_prepare(uint8_t epnum)
+{
+  nom_xfer_t* xfer = get_td(epnum, TUSB_DIR_IN);
+
+  // Each transaction is up to Max Packet Size
+  uint8_t const xact_len = min16_of(xfer->total_len - xfer->actual_len, xfer->mps);
+
+  NRF_USBD->EPIN[epnum].PTR    = (uint32_t) xfer->buffer;
+  NRF_USBD->EPIN[epnum].MAXCNT = xact_len;
+
+  xfer->buffer += xact_len;
+
+  edpt_dma_start(epnum, TUSB_DIR_IN);
 }
 }
 
 
 bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
 bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
@@ -279,7 +310,23 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
   xfer->total_len  = total_bytes;
   xfer->total_len  = total_bytes;
   xfer->actual_len = 0;
   xfer->actual_len = 0;
 
 
-  normal_xact_start(epnum, dir);
+  if ( dir == TUSB_DIR_OUT )
+  {
+    if ( xfer->data_received )
+    {
+      xfer->data_received = false;
+
+      // FIXME nrf52840 does not NAK OUT packet properly
+      // Data already received preivously
+      xact_out_dma(epnum);
+    }else
+    {
+      xact_out_prepare(epnum);
+    }
+  }else
+  {
+    xact_in_prepare(epnum);
+  }
 
 
   return true;
   return true;
 }
 }
@@ -382,7 +429,7 @@ void USBD_IRQHandler(void)
       // IN: data transferred from Endpoint -> Host
       // IN: data transferred from Endpoint -> Host
       if ( _dcd.control.actual_len < _dcd.control.total_len )
       if ( _dcd.control.actual_len < _dcd.control.total_len )
       {
       {
-        control_xact_start();
+        xact_control_start();
       }else
       }else
       {
       {
         // Control IN complete
         // Control IN complete
@@ -396,7 +443,7 @@ void USBD_IRQHandler(void)
   {
   {
     if ( _dcd.control.actual_len < _dcd.control.total_len )
     if ( _dcd.control.actual_len < _dcd.control.total_len )
     {
     {
-      control_xact_start();
+      xact_control_start();
     }else
     }else
     {
     {
       // Control OUT complete
       // Control OUT complete
@@ -423,7 +470,7 @@ void USBD_IRQHandler(void)
         if ( xfer->actual_len < xfer->total_len )
         if ( xfer->actual_len < xfer->total_len )
         {
         {
           // more to xfer
           // more to xfer
-          normal_xact_start(epnum, TUSB_DIR_IN);
+          xact_in_prepare(epnum);
         } else
         } else
         {
         {
           // BULK/INT IN complete
           // BULK/INT IN complete
@@ -439,19 +486,17 @@ void USBD_IRQHandler(void)
       {
       {
         nom_xfer_t* xfer = get_td(epnum, TUSB_DIR_OUT);
         nom_xfer_t* xfer = get_td(epnum, TUSB_DIR_OUT);
 
 
-        uint8_t const xact_len = NRF_USBD->SIZE.EPOUT[epnum];
-
-        // FIXME nrf52840 rev A does not NAK OUT packet properly
-        TU_ASSERT(xfer->actual_len < xfer->total_len, );
-
-        // Trigger DMA move data from Endpoint -> SRAM
-        NRF_USBD->EPOUT[epnum].PTR    = (uint32_t) xfer->buffer;
-        NRF_USBD->EPOUT[epnum].MAXCNT = xact_len;
-
-        edpt_dma_start(epnum, TUSB_DIR_OUT);
+        if (xfer->actual_len < xfer->total_len)
+        {
+          xact_out_dma(epnum);
+        }else
+        {
+          // FIXME nrf52840 does not NAK OUT packet properly
+          // It will always ACK next package although we haven't write to SIZE yet
 
 
-        xfer->buffer     += xact_len;
-        xfer->actual_len += xact_len;
+          // Mark this endpoint with data received
+          xfer->data_received = true;
+        }
       }
       }
     }
     }
   }
   }
@@ -469,7 +514,7 @@ void USBD_IRQHandler(void)
       if ( (xact_len == xfer->mps) && (xfer->actual_len < xfer->total_len) )
       if ( (xact_len == xfer->mps) && (xfer->actual_len < xfer->total_len) )
       {
       {
         // Prepare for more data from Host -> Endpoint
         // Prepare for more data from Host -> Endpoint
-        normal_xact_start(epnum, TUSB_DIR_OUT);
+        xact_out_prepare(epnum);
       }else
       }else
       {
       {
         xfer->total_len = xfer->actual_len;
         xfer->total_len = xfer->actual_len;