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

nrf52 cdc example work on nrf52840pdk

- add tud_cdc_flush(), auto flush with sof is enabled by default.
-
hathach 8 лет назад
Родитель
Сommit
2f0fcf80e0

+ 43 - 13
hw/mcu/nordic/nrf52/tusb_port/dcd_nrf52.c

@@ -134,12 +134,10 @@ static void power_usb_event_handler(nrf_drv_power_usb_evt_t event)
 
       nrf_usbd_isosplit_set(NRF_USBD_ISOSPLIT_Half);
 
-      // Enable interrupt
+      // Enable interrupt. SOF is used as CDC auto flush
       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
+                           USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPIN0_Msk |  USBD_INTEN_ENDEPOUT0_Msk |
+                           USBD_INTEN_EPDATA_Msk   | USBD_INTEN_SOF_Msk;
 
       //  if (enable_sof || nrf_drv_usbd_errata_104())
       //  {
@@ -200,7 +198,7 @@ bool tusb_dcd_init (uint8_t port)
   {
       .handler = power_usb_event_handler
   };
-  VERIFY( NRF_SUCCESS == nrf_drv_power_usbevt_init(&config) );
+  return ( NRF_SUCCESS == nrf_drv_power_usbevt_init(&config) );
 }
 
 void tusb_dcd_connect (uint8_t port)
@@ -215,7 +213,6 @@ void tusb_dcd_disconnect (uint8_t port)
 void tusb_dcd_set_address (uint8_t port, uint8_t dev_addr)
 {
   (void) port;
-
   // Set Address is automatically update by hw controller
 }
 
@@ -223,7 +220,6 @@ void tusb_dcd_set_config (uint8_t port, uint8_t config_num)
 {
   (void) port;
   (void) config_num;
-
   // Nothing to do
 }
 
@@ -330,16 +326,24 @@ void tusb_dcd_control_stall (uint8_t port)
  *------------------------------------------------------------------*/
 static void normal_xact_start(uint8_t epnum, uint8_t dir)
 {
-  // Each transaction is up to Max Packet Size
   nom_xfer_t* xfer = &_dcd.xfer[dir][epnum-1];
 
+  // Each transaction is up to Max Packet Size
   uint8_t const xact_len = min16_of(xfer->total_len - xfer->actual_len, xfer->mps);
 
   if ( dir == TUSB_DIR_OUT )
   {
+    // HW issue on nrf5284 sample, SIZE.EPOUT won't trigger ACK as spec
+    // use the back door interface as sdk for walk around
+    #if 0
     // Overwrite size will allow hw to accept data
     NRF_USBD->SIZE.EPOUT[epnum] = 0;
     __ISB(); __DSB();
+    #else
+    *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7C5 + 2*epnum;
+    *((volatile uint32_t *)(NRF_USBD_BASE + 0x804)) = 0;
+    (void) (((volatile uint32_t *)(NRF_USBD_BASE + 0x804)));
+    #endif
   }else
   {
     NRF_USBD->EPIN[epnum].PTR    = (uint32_t) xfer->buffer;
@@ -413,10 +417,19 @@ void tusb_dcd_edpt_clear_stall (uint8_t port, uint8_t ep_addr)
 
 }
 
-// TODO may remove
 bool tusb_dcd_edpt_busy (uint8_t port, uint8_t ep_addr)
 {
-  return true;
+  (void) port;
+
+  // USBD shouldn't check control endpoint state
+  if ( 0 == ep_addr ) return false;
+
+  uint8_t const epnum = edpt_number(ep_addr);
+  uint8_t const dir   = edpt_dir(ep_addr);
+
+  nom_xfer_t* xfer = &_dcd.xfer[dir][epnum-1];
+
+  return xfer->actual_len < xfer->total_len;
 }
 
 /*------------------------------------------------------------------*/
@@ -443,7 +456,6 @@ void USBD_IRQHandler(void)
   }
 
   /*------------- Interrupt Processing -------------*/
-
   if ( int_status & USBD_INTEN_USBRESET_Msk )
   {
     bus_reset();
@@ -451,6 +463,11 @@ void USBD_IRQHandler(void)
     tusb_dcd_bus_event(0, USBD_BUS_EVENT_RESET);
   }
 
+  if ( int_status & USBD_INTEN_SOF_Msk )
+  {
+    tusb_dcd_bus_event(0, USBD_BUS_EVENT_SOF);
+  }
+
   if ( int_status & EDPT_END_ALL_MASK )
   {
     // DMA complete move data from SRAM -> Endpoint
@@ -524,7 +541,7 @@ void USBD_IRQHandler(void)
           normal_xact_start(epnum, TUSB_DIR_IN);
         } else
         {
-          // xfer complete
+          // BULK/INT IN complete
           tusb_dcd_xfer_complete(0, epnum | TUSB_DIR_IN_MASK, xfer->actual_len, true);
         }
       }
@@ -562,10 +579,23 @@ void USBD_IRQHandler(void)
       if ( (NRF_USBD->EPOUT[epnum].AMOUNT == xfer->mps) && (xfer->actual_len < xfer->total_len) )
       {
         // Allow Host -> Endpoint
+
+        // HW issue on nrf5284 sample, SIZE.EPOUT won't trigger ACK as spec
+        // use the back door interface as sdk for walk around
+        #if 0
+        // Overwrite size will allow hw to accept data
         NRF_USBD->SIZE.EPOUT[epnum] = 0;
         __ISB(); __DSB();
+        #else
+        *((volatile uint32_t *)(NRF_USBD_BASE + 0x800)) = 0x7C5 + 2*epnum;
+        *((volatile uint32_t *)(NRF_USBD_BASE + 0x804)) = 0;
+        (void) (((volatile uint32_t *)(NRF_USBD_BASE + 0x804)));
+        #endif
       }else
       {
+        xfer->total_len = xfer->actual_len;
+
+        // BULK/INT OUT complete
         tusb_dcd_xfer_complete(0, epnum, xfer->actual_len, true);
       }
     }

+ 13 - 7
tinyusb/class/cdc/cdc_device.c

@@ -280,18 +280,24 @@ tusb_error_t cdcd_xfer_cb(uint8_t port, uint8_t ep_addr, tusb_event_t event, uin
   return TUSB_ERROR_NONE;
 }
 
-void cdcd_sof(uint8_t port)
+bool tud_n_cdc_flush (uint8_t port)
 {
-  if ( !tud_n_cdc_connected(port) ) return;
+  VERIFY( tud_n_cdc_connected(port) );
 
   uint8_t edpt = cdcd_data[port].ep_addr[CDC_PIPE_DATA_IN];
 
-  if ( !tusb_dcd_edpt_busy(port, edpt) )
-  {
-    uint16_t count = fifo_read_n(&_tx_ff, _tmp_tx_buf, sizeof(_tmp_tx_buf));
+  VERIFY( !tusb_dcd_edpt_busy(port, edpt) );
 
-    TU_ASSERT( tusb_dcd_edpt_xfer(port, edpt, _tmp_tx_buf, count, false), TUSB_ERROR_DCD_EDPT_XFER);
-  }
+
+  uint16_t count = fifo_read_n(&_tx_ff, _tmp_tx_buf, sizeof(_tmp_tx_buf));
+  TU_ASSERT( tusb_dcd_edpt_xfer(port, edpt, _tmp_tx_buf, count, false) );
+
+  return true;
+}
+
+void cdcd_sof(uint8_t port)
+{
+  tud_n_cdc_flush(port);
 }
 
 #endif

+ 7 - 5
tinyusb/class/cdc/cdc_device.h

@@ -63,18 +63,20 @@ uint32_t tud_n_cdc_read       (uint8_t port, void* buffer, uint32_t bufsize);
 
 uint32_t tud_n_cdc_write_char (uint8_t port, char ch);
 uint32_t tud_n_cdc_write      (uint8_t port, void const* buffer, uint32_t bufsize);
+bool     tud_n_cdc_flush      (uint8_t port);
 
 //--------------------------------------------------------------------+
 // APPLICATION API (Single Port)
 //--------------------------------------------------------------------+
-static inline bool     tud_cdc_connected  (void)                                 { return tud_n_cdc_connected(0); }
-static inline uint32_t tud_cdc_available  (void)                                 { return tud_n_cdc_available(0); }
+static inline bool     tud_cdc_connected  (void)                                 { return tud_n_cdc_connected(0);              }
+static inline uint32_t tud_cdc_available  (void)                                 { return tud_n_cdc_available(0);              }
 
-static inline int      tud_cdc_read_char  (void)                                 { return tud_n_cdc_read_char(0); }
-static inline uint32_t tud_cdc_read       (void* buffer, uint32_t bufsize)       { return tud_n_cdc_read(0, buffer, bufsize); }
+static inline int      tud_cdc_read_char  (void)                                 { return tud_n_cdc_read_char(0);              }
+static inline uint32_t tud_cdc_read       (void* buffer, uint32_t bufsize)       { return tud_n_cdc_read(0, buffer, bufsize);  }
 
-static inline uint32_t tud_cdc_write_char (char ch)                              { return tud_n_cdc_write_char(0, ch); }
+static inline uint32_t tud_cdc_write_char (char ch)                              { return tud_n_cdc_write_char(0, ch);         }
 static inline uint32_t tud_cdc_write      (void const* buffer, uint32_t bufsize) { return tud_n_cdc_write(0, buffer, bufsize); }
+static inline bool     tud_cdc_flush      (void)                                 { return tud_n_cdc_flush(0);                  }
 
 //--------------------------------------------------------------------+
 // APPLICATION CALLBACK API

+ 1 - 3
tinyusb/tusb_dcd.h

@@ -87,13 +87,11 @@ void tusb_dcd_control_stall    (uint8_t port);
 bool tusb_dcd_edpt_open        (uint8_t port, tusb_descriptor_endpoint_t const * p_endpoint_desc);
 bool tusb_dcd_edpt_xfer        (uint8_t port, uint8_t edpt_addr, uint8_t * buffer, uint16_t total_bytes, bool int_on_complete);
 bool tusb_dcd_edpt_queue_xfer  (uint8_t port, uint8_t edpt_addr, uint8_t * buffer, uint16_t total_bytes); // only queue, not transferring yet
+bool tusb_dcd_edpt_busy        (uint8_t port, uint8_t edpt_addr);
 
 void tusb_dcd_edpt_stall       (uint8_t port, uint8_t edpt_addr);
 void tusb_dcd_edpt_clear_stall (uint8_t port, uint8_t edpt_addr);
 
-// TODO may remove
-bool tusb_dcd_edpt_busy        (uint8_t port, uint8_t edpt_addr);
-
 #ifdef __cplusplus
  }
 #endif