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

Merge pull request #506 from duempel/cdc_without_dtr

CDC without DTR being set
Ha Thach 5 лет назад
Родитель
Сommit
2bfcd446a5

+ 2 - 0
examples/device/cdc_dual_ports/src/main.c

@@ -83,6 +83,8 @@ static void cdc_task(void)
 
   for (itf = 0; itf < CFG_TUD_CDC; itf++)
   {
+    // connected() check for DTR bit
+    // Most but not all terminal client set this when making connection
     if ( tud_cdc_n_connected(itf) )
     {
       if ( tud_cdc_n_available(itf) )

+ 6 - 2
examples/device/cdc_msc/src/main.c

@@ -105,7 +105,9 @@ void tud_resume_cb(void)
 //--------------------------------------------------------------------+
 void cdc_task(void)
 {
-  if ( tud_cdc_connected() )
+  // connected() check for DTR bit
+  // Most but not all terminal client set this when making connection
+  // if ( tud_cdc_connected() )
   {
     // connected and there are data available
     if ( tud_cdc_available() )
@@ -131,12 +133,14 @@ void cdc_task(void)
 void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
 {
   (void) itf;
+  (void) rts;
 
   // connected
-  if ( dtr && rts )
+  if ( dtr )
   {
     // print initial message when connected
     tud_cdc_write_str("\r\nTinyUSB CDC MSC device example\r\n");
+    tud_cdc_write_flush();
   }
 }
 

+ 7 - 3
examples/device/cdc_msc_freertos/src/main.c

@@ -168,9 +168,11 @@ void cdc_task(void* params)
   // RTOS forever loop
   while ( 1 )
   {
-    if ( tud_cdc_connected() )
+    // connected() check for DTR bit
+    // Most but not all terminal client set this when making connection
+    // if ( tud_cdc_connected() )
     {
-      // connected and there are data available
+      // There are data available
       if ( tud_cdc_available() )
       {
         uint8_t buf[64];
@@ -198,12 +200,14 @@ void cdc_task(void* params)
 void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
 {
   (void) itf;
+  (void) rts;
 
   // connected
-  if ( dtr && rts )
+  if ( dtr )
   {
     // print initial message when connected
     tud_cdc_write_str("\r\nTinyUSB CDC MSC device with FreeRTOS example\r\n");
+    tud_cdc_write_flush();
   }
 }
 

+ 23 - 6
src/class/cdc/cdc_device.c

@@ -178,6 +178,9 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf)
 {
   cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
 
+  // Skip if usb is not ready yet
+  TU_VERIFY( tud_ready(), 0 );
+
   // No data to send
   if ( !tu_fifo_count(&p_cdc->tx_ff) ) return 0;
 
@@ -189,7 +192,7 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf)
   // Pull data from FIFO
   uint16_t const count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf));
 
-  if ( count && tud_cdc_n_connected(itf) )
+  if ( count )
   {
     TU_ASSERT( usbd_edpt_xfer(rhport, p_cdc->ep_in, p_cdc->epin_buf, count), 0 );
     return count;
@@ -207,6 +210,10 @@ uint32_t tud_cdc_n_write_available (uint8_t itf)
   return tu_fifo_remaining(&_cdcd_itf[itf].tx_ff);
 }
 
+bool tud_cdc_n_write_clear (uint8_t itf)
+{
+  return tu_fifo_clear(&_cdcd_itf[itf].tx_ff);
+}
 
 //--------------------------------------------------------------------+
 // USBD Driver API
@@ -227,9 +234,13 @@ void cdcd_init(void)
     p_cdc->line_coding.parity    = 0;
     p_cdc->line_coding.data_bits = 8;
 
-    // config fifo
+    // Config RX fifo
     tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, TU_ARRAY_SIZE(p_cdc->rx_ff_buf), 1, false);
-    tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, false);
+
+    // Config TX fifo as overwritable at initialization and will be changed to non-overwritable
+    // if terminal supports DTR bit. Without DTR we do not know if data is actually polled by terminal.
+    // In this way, the most current data is prioritized.
+    tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, true);
 
 #if CFG_FIFO_MUTEX
     tu_fifo_config_mutex(&p_cdc->rx_ff, osal_mutex_create(&p_cdc->rx_ff_mutex));
@@ -244,9 +255,12 @@ void cdcd_reset(uint8_t rhport)
 
   for(uint8_t i=0; i<CFG_TUD_CDC; i++)
   {
-    tu_memclr(&_cdcd_itf[i], ITF_MEM_RESET_SIZE);
-    tu_fifo_clear(&_cdcd_itf[i].rx_ff);
-    tu_fifo_clear(&_cdcd_itf[i].tx_ff);
+    cdcd_interface_t* p_cdc = &_cdcd_itf[i];
+
+    tu_memclr(p_cdc, ITF_MEM_RESET_SIZE);
+    tu_fifo_clear(&p_cdc->rx_ff);
+    tu_fifo_clear(&p_cdc->tx_ff);
+    tu_fifo_set_overwritable(&p_cdc->tx_ff, true);
   }
 }
 
@@ -372,6 +386,9 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
         bool const rts = tu_bit_test(request->wValue, 1);
 
         p_cdc->line_state = (uint8_t) request->wValue;
+        
+        // Disable fifo overwriting if DTR bit is set
+        tu_fifo_set_overwritable(&p_cdc->tx_ff, !dtr);
 
         TU_LOG2("  Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts);
 

+ 9 - 0
src/class/cdc/cdc_device.h

@@ -102,6 +102,9 @@ uint32_t tud_cdc_n_write_flush     (uint8_t itf);
 // Return the number of bytes (characters) available for writing to TX FIFO buffer in a single n_write operation.
 uint32_t tud_cdc_n_write_available (uint8_t itf);
 
+// Clear the transmit FIFO
+bool tud_cdc_n_write_clear (uint8_t itf);
+
 //--------------------------------------------------------------------+
 // Application API (Single Port)
 //--------------------------------------------------------------------+
@@ -121,6 +124,7 @@ static inline uint32_t tud_cdc_write           (void const* buffer, uint32_t buf
 static inline uint32_t tud_cdc_write_str       (char const* str);
 static inline uint32_t tud_cdc_write_flush     (void);
 static inline uint32_t tud_cdc_write_available (void);
+static inline bool     tud_cdc_write_clear     (void);
 
 //--------------------------------------------------------------------+
 // Application Callback API (weak is optional)
@@ -230,6 +234,11 @@ static inline uint32_t tud_cdc_write_available(void)
   return tud_cdc_n_write_available(0);
 }
 
+static inline bool tud_cdc_write_clear(void)
+{
+  return tud_cdc_n_write_clear(0);
+}
+
 /** @} */
 /** @} */
 

+ 21 - 0
src/common/tusb_fifo.c

@@ -597,6 +597,27 @@ bool tu_fifo_clear(tu_fifo_t *f)
   return true;
 }
 
+/******************************************************************************/
+/*!
+    @brief Change the fifo mode to overwritable or not overwritable
+
+    @param[in]  f
+                Pointer to the FIFO buffer to manipulate
+    @param[in]  overwritable
+                Overwritable mode the fifo is set to
+*/
+/******************************************************************************/
+bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable)
+{
+  tu_fifo_lock(f);
+
+  f->overwritable = overwritable;
+
+  tu_fifo_unlock(f);
+
+  return true;
+}
+
 /******************************************************************************/
 /*!
     @brief Advance write pointer - intended to be used in combination with DMA.

+ 1 - 0
src/common/tusb_fifo.h

@@ -89,6 +89,7 @@ typedef struct
         .non_used_index_space   = 0xFFFF - 2*_depth-1,                  \
     }
 
+bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable);
 bool tu_fifo_clear(tu_fifo_t *f);
 bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable);