Browse Source

enhance cdc device API

hathach 8 years ago
parent
commit
4ddac8bc88

+ 11 - 56
examples/device/device_virtual_com/src/cdc_device_app.c

@@ -42,40 +42,20 @@
 //--------------------------------------------------------------------+
 // INCLUDE
 //--------------------------------------------------------------------+
-enum { SERIAL_BUFFER_SIZE = 64 };
 
 //--------------------------------------------------------------------+
 // MACRO CONSTANT TYPEDEF
 //--------------------------------------------------------------------+
-static osal_semaphore_t sem_hdl;
 
 //--------------------------------------------------------------------+
 // INTERNAL OBJECT & FUNCTION DECLARATION
 //--------------------------------------------------------------------+
-TUSB_CFG_ATTR_USBRAM static uint8_t serial_rx_buffer[SERIAL_BUFFER_SIZE];
-TUSB_CFG_ATTR_USBRAM static uint8_t serial_tx_buffer[SERIAL_BUFFER_SIZE];
-
-FIFO_DEF(fifo_serial, SERIAL_BUFFER_SIZE, uint8_t, true);
 
 //--------------------------------------------------------------------+
 // tinyusb callbacks
 //--------------------------------------------------------------------+
-void cdc_serial_app_mount(uint8_t coreid)
-{
-  osal_semaphore_reset(sem_hdl);
-
-  tud_cdc_receive(coreid, serial_rx_buffer, SERIAL_BUFFER_SIZE, true);
-}
-
-void cdc_serial_app_umount(uint8_t coreid)
+void tud_cdc_rx_cb(uint8_t coreid)
 {
-
-}
-
-void tud_cdc_rx_cb(uint8_t coreid, uint32_t xferred_bytes)
-{
-  fifo_write_n(&fifo_serial, serial_rx_buffer, xferred_bytes);
-  osal_semaphore_post(sem_hdl);  // notify main task
 }
 
 //--------------------------------------------------------------------+
@@ -83,50 +63,25 @@ void tud_cdc_rx_cb(uint8_t coreid, uint32_t xferred_bytes)
 //--------------------------------------------------------------------+
 void cdc_serial_app_init(void)
 {
-  sem_hdl = osal_semaphore_create(1, 0);
-  VERIFY(sem_hdl, );
 }
 
-tusb_error_t cdc_serial_subtask(void);
+void cdc_serial_app_mount(uint8_t coreid)
+{
+}
 
-void cdc_serial_app_task(void* param)
+void cdc_serial_app_umount(uint8_t coreid)
 {
-  (void) param;
 
-  OSAL_TASK_BEGIN
-  cdc_serial_subtask();
-  OSAL_TASK_END
 }
 
-tusb_error_t cdc_serial_subtask(void)
+void cdc_serial_app_task(void)
 {
-  OSAL_SUBTASK_BEGIN
-
-  tusb_error_t error;
-  (void) error; // suppress compiler's warnings
+  if ( tud_mounted(0) && tud_cdc_available(0) )
+  {
+    uint8_t buf[64];
 
-  osal_semaphore_wait(sem_hdl, OSAL_TIMEOUT_WAIT_FOREVER, &error);
+    uint32_t count = tud_cdc_read(0, buf, sizeof(buf));
 
-  if ( tud_mounted(0) )
-  {
-    // echo back data in the fifo
-    if ( !tud_cdc_busy(0, CDC_PIPE_DATA_IN) )
-    {
-      uint16_t count=0;
-      while( fifo_read(&fifo_serial, &serial_tx_buffer[count]) )
-      {
-        count++;
-      }
-
-      if (count)
-      {
-        tud_cdc_send(0, serial_tx_buffer, count, false);
-      }
-    }
-
-    // getting more data from host
-    tud_cdc_receive(0, serial_rx_buffer, SERIAL_BUFFER_SIZE, true);
+    tud_cdc_write(0, buf, count);
   }
-
-  OSAL_SUBTASK_END
 }

+ 1 - 1
examples/device/device_virtual_com/src/cdc_device_app.h

@@ -54,7 +54,7 @@
 #endif
 
 void cdc_serial_app_init(void);
-void cdc_serial_app_task(void* param);
+void cdc_serial_app_task(void);
 
 void cdc_serial_app_mount(uint8_t coreid);
 void cdc_serial_app_umount(uint8_t coreid);

+ 1 - 1
examples/device/device_virtual_com/src/main.c

@@ -74,7 +74,7 @@ int main(void)
     tusb_task();
 
     led_blinking_task();
-    cdc_serial_app_task(NULL);
+    cdc_serial_app_task();
   }
 
   return 0;

+ 1 - 1
hw/bsp/board.c

@@ -37,7 +37,7 @@
 /**************************************************************************/
 
 #include "board.h"
-#include "app_os_prio.h"
+//#include "app_os_prio.h"
 
 #if TUSB_CFG_OS == TUSB_OS_NONE
 

+ 6 - 2
hw/mcu/nxp/lpc43xx/hal/dcd_lpc43xx.c

@@ -252,7 +252,7 @@ bool hal_dcd_init(uint8_t coreid)
 
   lpc_usb->ENDPOINTLISTADDR = (uint32_t) p_dcd->qhd; // Endpoint List Address has to be 2K alignment
   lpc_usb->USBSTS_D  = lpc_usb->USBSTS_D;
-  lpc_usb->USBINTR_D = INT_MASK_USB | INT_MASK_ERROR | INT_MASK_PORT_CHANGE | INT_MASK_RESET | INT_MASK_SUSPEND; // | INT_MASK_SOF;
+  lpc_usb->USBINTR_D = INT_MASK_USB | INT_MASK_ERROR | INT_MASK_PORT_CHANGE | INT_MASK_RESET | INT_MASK_SUSPEND /*| INT_MASK_SOF */;
 
   lpc_usb->USBCMD_D &= ~0x00FF0000; // Interrupt Threshold Interval = 0
   lpc_usb->USBCMD_D |= BIT_(0); // connect
@@ -593,7 +593,11 @@ void hal_dcd_isr(uint8_t coreid)
     }
   }
 
-  if (int_status & INT_MASK_SOF) {}
+  if (int_status & INT_MASK_SOF)
+  {
+//    hal_dcd_bus_event(coreid, USBD_BUS_EVENT_SOF);
+  }
+
   if (int_status & INT_MASK_NAK) {}
   if (int_status & INT_MASK_ERROR) ASSERT(false, VOID_RETURN);
 }

+ 78 - 14
tinyusb/class/cdc/cdc_device.c

@@ -56,9 +56,20 @@ typedef struct {
   uint8_t interface_number;
   cdc_acm_capability_t acm_capability;
 
+  bool connected;
+
   endpoint_handle_t edpt_hdl[3]; // notification, data in, data out
 }cdcd_data_t;
 
+// TODO multiple port
+TUSB_CFG_ATTR_USBRAM uint8_t _tmp_rx_buf[64];
+TUSB_CFG_ATTR_USBRAM uint8_t _tmp_tx_buf[64];
+
+#define CFG_TUD_CDC_BUFSIZE   128
+
+FIFO_DEF(_rx_ff, CFG_TUD_CDC_BUFSIZE, uint8_t, true);
+FIFO_DEF(_tx_ff, CFG_TUD_CDC_BUFSIZE, uint8_t, true);
+
 //--------------------------------------------------------------------+
 // INTERNAL OBJECT & FUNCTION DECLARATION
 //--------------------------------------------------------------------+
@@ -158,13 +169,13 @@ tusb_error_t cdcd_open(uint8_t coreid, tusb_descriptor_interface_t const * p_int
     for(uint32_t i=0; i<2; i++)
     {
       tusb_descriptor_endpoint_t const *p_endpoint = (tusb_descriptor_endpoint_t const *) p_desc;
-      ASSERT_INT(TUSB_DESC_TYPE_ENDPOINT, p_endpoint->bDescriptorType, TUSB_ERROR_DESCRIPTOR_CORRUPTED);
-      ASSERT_INT(TUSB_XFER_BULK, p_endpoint->bmAttributes.xfer, TUSB_ERROR_DESCRIPTOR_CORRUPTED);
+      ASSERT_(TUSB_DESC_TYPE_ENDPOINT == p_endpoint->bDescriptorType, TUSB_ERROR_DESCRIPTOR_CORRUPTED);
+      ASSERT_(TUSB_XFER_BULK == p_endpoint->bmAttributes.xfer, TUSB_ERROR_DESCRIPTOR_CORRUPTED);
 
       endpoint_handle_t * p_edpt_hdl =  ( p_endpoint->bEndpointAddress &  TUSB_DIR_DEV_TO_HOST_MASK ) ?
           &p_cdc->edpt_hdl[CDC_PIPE_DATA_IN] : &p_cdc->edpt_hdl[CDC_PIPE_DATA_OUT] ;
 
-      VERIFY( hal_dcd_pipe_open(coreid, p_endpoint, p_edpt_hdl), TUSB_ERROR_DCD_OPEN_PIPE_FAILED);
+      ASSERT_( hal_dcd_pipe_open(coreid, p_endpoint, p_edpt_hdl), TUSB_ERROR_DCD_OPEN_PIPE_FAILED);
 
       (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH];
       p_desc = descriptor_next( p_desc );
@@ -173,6 +184,10 @@ tusb_error_t cdcd_open(uint8_t coreid, tusb_descriptor_interface_t const * p_int
 
   p_cdc->interface_number   = p_interface_desc->bInterfaceNumber;
 
+  // Prepare for incoming data
+  hal_dcd_pipe_xfer(p_cdc->edpt_hdl[CDC_PIPE_DATA_OUT], _tmp_rx_buf, sizeof(_tmp_rx_buf), true);
+
+
   return TUSB_ERROR_NONE;
 }
 
@@ -180,6 +195,9 @@ void cdcd_close(uint8_t coreid)
 {
   // no need to close opened pipe, dcd bus reset will put controller's endpoints to default state
   memclr_(&cdcd_data[coreid], sizeof(cdcd_data_t));
+
+  fifo_clear(&_rx_ff);
+  fifo_clear(&_tx_ff);
 }
 
 tusb_error_t cdcd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * p_request)
@@ -207,16 +225,21 @@ tusb_error_t cdcd_control_request_subtask(uint8_t coreid, tusb_control_request_t
         ACTIVE_DTE_NOT_PRESENT = 0x0002
       };
 
+      cdcd_data_t * p_cdc = &cdcd_data[coreid];
+
       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;
@@ -231,21 +254,62 @@ tusb_error_t cdcd_xfer_cb(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32
 {
   cdcd_data_t const * p_cdc = &cdcd_data[edpt_hdl.coreid];
 
-  if ( endpointhandle_is_equal(edpt_hdl, p_cdc->edpt_hdl[CDC_PIPE_DATA_OUT]) )
+  if ( edpt_equal(edpt_hdl, p_cdc->edpt_hdl[CDC_PIPE_DATA_OUT]) )
   {
-    tud_cdc_rx_cb(edpt_hdl.coreid, xferred_bytes);
-  }
+    fifo_write_n(&_rx_ff, _tmp_rx_buf, xferred_bytes);
 
-//  for(cdc_pipeid_t pipeid=CDC_PIPE_NOTIFICATION; pipeid < CDC_PIPE_ERROR; pipeid++ )
-//  {
-//    if ( endpointhandle_is_equal(edpt_hdl, p_cdc->edpt_hdl[pipeid]) )
-//    {
-//      tud_cdc_xfer_cb(edpt_hdl.coreid, event, pipeid, xferred_bytes);
-//      break;
-//    }
-//  }
+    // preparing for next
+    hal_dcd_pipe_xfer(p_cdc->edpt_hdl[CDC_PIPE_DATA_OUT], _tmp_rx_buf, sizeof(_tmp_rx_buf), true);
+
+    // fire callback
+    tud_cdc_rx_cb(edpt_hdl.coreid);
+  }
 
   return TUSB_ERROR_NONE;
 }
 
+void cdcd_sof(uint8_t coreid)
+{
+  endpoint_handle_t ep = cdcd_data[coreid].edpt_hdl[CDC_PIPE_DATA_IN];
+
+  if ( !dcd_pipe_is_busy( ep ) )
+  {
+    uint16_t count = fifo_read_n(&_tx_ff, _tmp_tx_buf, sizeof(_tmp_tx_buf));
+
+    hal_dcd_pipe_xfer(ep, _tmp_tx_buf, count, false);
+  }
+}
+
+uint32_t tud_cdc_available(uint8_t coreid)
+{
+  return fifo_count(&_rx_ff);
+}
+
+bool tud_cdc_connected(uint8_t coreid)
+{
+  return cdcd_data[coreid].connected;
+}
+
+int tud_cdc_read_char(uint8_t coreid)
+{
+  uint8_t ch;
+  return fifo_read(&_rx_ff, &ch) ? ch : (-1);
+}
+
+uint32_t tud_cdc_read(uint8_t coreid, void* buffer, uint32_t bufsize)
+{
+  return fifo_read_n(&_rx_ff, buffer, bufsize);
+}
+
+uint32_t tud_cdc_write_char(uint8_t coreid, char ch)
+{
+  return fifo_write(&_tx_ff, &ch);
+}
+
+uint32_t tud_cdc_write(uint8_t coreid, void const* buffer, uint32_t bufsize)
+{
+  return fifo_write_n(&_tx_ff, buffer, bufsize);
+}
+
+
 #endif

+ 13 - 1
tinyusb/class/cdc/cdc_device.h

@@ -95,6 +95,16 @@ tusb_error_t tud_cdc_send(uint8_t coreid, void * p_data, uint32_t length, bool i
  */
 tusb_error_t tud_cdc_receive(uint8_t coreid, void * p_buffer, uint32_t length, bool is_notify);
 
+bool     tud_cdc_connected(uint8_t coreid);
+uint32_t tud_cdc_available(uint8_t coreid);
+
+int      tud_cdc_read_char(uint8_t coreid);
+uint32_t tud_cdc_read(uint8_t coreid, void* buffer, uint32_t bufsize);
+
+uint32_t tud_cdc_write_char(uint8_t coreid, char ch);
+uint32_t tud_cdc_write(uint8_t coreid, void const* buffer, uint32_t bufsize);
+
+
 //--------------------------------------------------------------------+
 // APPLICATION CALLBACK API
 //--------------------------------------------------------------------+
@@ -109,7 +119,7 @@ tusb_error_t tud_cdc_receive(uint8_t coreid, void * p_buffer, uint32_t length, b
 void tud_cdc_xfer_cb(uint8_t coreid, tusb_event_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes);
 //void tud_cdc_line_coding_changed_cb(uint8_t coreid, cdc_line_coding_t* p_line_coding);
 
-void tud_cdc_rx_cb(uint8_t coreid, uint32_t xferred_bytes);
+void tud_cdc_rx_cb(uint8_t coreid);
 
 //--------------------------------------------------------------------+
 // USBD-CLASS DRIVER API
@@ -122,6 +132,8 @@ tusb_error_t cdcd_control_request_subtask(uint8_t coreid, tusb_control_request_t
 tusb_error_t cdcd_xfer_cb(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32_t xferred_bytes);
 void cdcd_close(uint8_t coreid);
 
+void cdcd_sof(uint8_t coreid);
+
 #endif
 
 #ifdef __cplusplus

+ 1 - 0
tinyusb/device/dcd.h

@@ -53,6 +53,7 @@ typedef enum
 {
   USBD_BUS_EVENT_RESET = 1,
   USBD_BUS_EVENT_UNPLUGGED,
+  USBD_BUS_EVENT_SOF,
   USBD_BUS_EVENT_SUSPENDED,
   USBD_BUS_EVENT_RESUME
 }usbd_bus_event_type_t;

+ 50 - 3
tinyusb/device/usbd.c

@@ -63,6 +63,8 @@ static usbd_class_driver_t const usbd_class_drivers[] =
         .open                    = hidd_open,
         .control_request_subtask = hidd_control_request_subtask,
         .xfer_cb                 = hidd_xfer_cb,
+//        .routine                 = NULL,
+        .sof                     = NULL,
         .close                   = hidd_close
     },
   #endif
@@ -74,6 +76,8 @@ static usbd_class_driver_t const usbd_class_drivers[] =
         .open                    = mscd_open,
         .control_request_subtask = mscd_control_request_subtask,
         .xfer_cb                 = mscd_xfer_cb,
+//        .routine                 = NULL,
+        .sof                     = NULL,
         .close                   = mscd_close
     },
   #endif
@@ -85,6 +89,8 @@ static usbd_class_driver_t const usbd_class_drivers[] =
         .open                    = cdcd_open,
         .control_request_subtask = cdcd_control_request_subtask,
         .xfer_cb                 = cdcd_xfer_cb,
+//        .routine                 = NULL,
+        .sof                     = cdcd_sof,
         .close                   = cdcd_close
     },
   #endif
@@ -117,7 +123,8 @@ enum { USBD_TASK_QUEUE_DEPTH = 16 };
 typedef enum
 {
   USBD_EVENTID_SETUP_RECEIVED = 1,
-  USBD_EVENTID_XFER_DONE
+  USBD_EVENTID_XFER_DONE,
+  USBD_EVENTID_SOF
 }usbd_eventid_t;
 
 typedef struct ATTR_ALIGNED(4)
@@ -128,7 +135,7 @@ typedef struct ATTR_ALIGNED(4)
   uint8_t reserved;
 
   union {
-    tusb_control_request_t setup_received; // USBD_EVENTID_SETUP_RECEIVED
+    tusb_control_request_t setup_received;
 
     struct { // USBD_EVENTID_XFER_DONE
       endpoint_handle_t edpt_hdl;
@@ -213,8 +220,27 @@ static tusb_error_t usbd_body_subtask(void)
   error = TUSB_ERROR_NONE;
 
   memclr_(&event, sizeof(usbd_task_event_t));
+
+#if 1
   osal_queue_receive(usbd_queue_hdl, &event, OSAL_TIMEOUT_WAIT_FOREVER, &error);
   SUBTASK_ASSERT_STATUS(error);
+#else
+  enum { ROUTINE_INTERVAL_MS = 10 };
+  osal_queue_receive(usbd_queue_hdl, &event, ROUTINE_INTERVAL_MS, &error);
+  if ( error != TUSB_ERROR_NONE )
+  {
+    // time out, run class routine then
+    if ( error == TUSB_ERROR_OSAL_TIMEOUT)
+    {
+      for (uint8_t class_code = TUSB_CLASS_AUDIO; class_code < USBD_CLASS_DRIVER_COUNT; class_code++)
+      {
+        if ( usbd_class_drivers[class_code].routine ) usbd_class_drivers[class_code].routine();
+      }
+    }
+
+    SUBTASK_RETURN(error);
+  }
+#endif
 
   if ( USBD_EVENTID_SETUP_RECEIVED == event.event_id )
   {
@@ -229,7 +255,17 @@ static tusb_error_t usbd_body_subtask(void)
         usbd_class_drivers[class_code].xfer_cb( event.xfer_done.edpt_hdl, (tusb_event_t) event.sub_event_id, event.xfer_done.xferred_byte);
       }
     }
-  }else
+  }else if (USBD_EVENTID_SOF == event.event_id)
+  {
+    for (uint8_t class_code = TUSB_CLASS_AUDIO; class_code < USBD_CLASS_DRIVER_COUNT; class_code++)
+    {
+      if ( usbd_class_drivers[class_code].sof )
+      {
+        usbd_class_drivers[class_code].sof( event.coreid );
+      }
+    }
+  }
+  else
   {
     SUBTASK_ASSERT(false);
   }
@@ -429,6 +465,17 @@ void hal_dcd_bus_event(uint8_t coreid, usbd_bus_event_type_t bus_event)
       tud_umount_cb(coreid);
     break;
 
+    case USBD_BUS_EVENT_SOF:
+    {
+      usbd_task_event_t task_event =
+      {
+          .coreid          = coreid,
+          .event_id        = USBD_EVENTID_SOF,
+      };
+      osal_queue_send(usbd_queue_hdl, &task_event);
+    }
+    break;
+
     case USBD_BUS_EVENT_UNPLUGGED : break;
 
     case USBD_BUS_EVENT_SUSPENDED:

+ 7 - 5
tinyusb/device/usbd.h

@@ -77,11 +77,13 @@ typedef struct {
 extern tusbd_descriptor_pointer_t tusbd_descriptor_pointers;
 
 typedef struct {
-  void (* const init) (void);
-  tusb_error_t (* const open)(uint8_t, tusb_descriptor_interface_t const *, uint16_t*);
-  tusb_error_t (* const control_request_subtask) (uint8_t, tusb_control_request_t const *);
-  tusb_error_t (* const xfer_cb) (endpoint_handle_t, tusb_event_t, uint32_t);
-  void (* const close) (uint8_t);
+  void (* init) (void);
+  tusb_error_t (* open)(uint8_t, tusb_descriptor_interface_t const *, uint16_t*);
+  tusb_error_t (* control_request_subtask) (uint8_t coreid, tusb_control_request_t const *);
+  tusb_error_t (* xfer_cb) (endpoint_handle_t, tusb_event_t, uint32_t);
+//  void (* routine)(void);
+  void (* sof)(uint8_t coreid);
+  void (* close) (uint8_t);
 } usbd_class_driver_t;
 
 //--------------------------------------------------------------------+