From 92e17d3bdf2371031967f949659edb91b72fb63f Mon Sep 17 00:00:00 2001
From: NIIBE Yutaka <gniibe@fsij.org>
Date: Thu, 7 Apr 2016 14:44:58 +0900
Subject: USB stack for STM32F103 improvement

---
 example-cdc/sample.c        | 20 ++++++++--
 example-cdc/sample.ld       |  8 ++--
 example-cdc/usb-cdc.c       | 96 +++++++++++++++++++++++++++------------------
 example-cdc/usb_lld.h       |  2 +
 example-cdc/usb_stm32f103.c | 43 +-------------------
 5 files changed, 82 insertions(+), 87 deletions(-)

(limited to 'example-cdc')

diff --git a/example-cdc/sample.c b/example-cdc/sample.c
index 4e61980..7a6b99f 100644
--- a/example-cdc/sample.c
+++ b/example-cdc/sample.c
@@ -129,6 +129,7 @@ main (int argc, const char *argv[])
 {
   struct stream *st;
   uint8_t count;
+  extern uint32_t bDeviceState;
 
   (void)argc;
   (void)argv;
@@ -153,11 +154,14 @@ main (int argc, const char *argv[])
   chopstx_cond_signal (&cnd1);
   chopstx_mutex_unlock (&mtx);
 
-  count= 0;
+  u = 1;
+  while (bDeviceState != CONFIGURED)
+    chopstx_usec_wait (500*1000);
+
+  count = 0;
   while (1)
     {
       uint8_t s[64];
-      u = 1;
 
       if (stream_wait_connection (st) < 0)
 	{
@@ -165,6 +169,11 @@ main (int argc, const char *argv[])
 	  continue;
 	}
 
+      chopstx_usec_wait (500*1000);
+
+      /* Send ZLP at the beginning.  */
+      stream_send (st, s, 0);
+
       memcpy (s, "xx: Hello, World with Chopstx!\r\n\000", 32);
       s[0] = hexchar (count >> 4);
       s[1] = hexchar (count & 0x0f);
@@ -180,8 +189,11 @@ main (int argc, const char *argv[])
 	  if (size < 0)
 	    break;
 
-	  if (stream_send (st, s, size) < 0)
-	    break;
+	  if (size >= 0)
+	    {
+	      if (stream_send (st, s, size) < 0)
+		break;
+	    }
 
 	  u ^= 1;
 	}
diff --git a/example-cdc/sample.ld b/example-cdc/sample.ld
index 322165b..dd53a0e 100644
--- a/example-cdc/sample.ld
+++ b/example-cdc/sample.ld
@@ -2,10 +2,10 @@
  * ST32F103 memory setup.
  */
 __main_stack_size__     = 0x0100;  /* Exception handlers     */
-__process0_stack_size__  = 0x0100;  /* Main program           */
-__process1_stack_size__  = 0x0100; /* first thread program */
-__process2_stack_size__  = 0x0100; /* second thread program */
-__process3_stack_size__  = 0x0100; /* third thread program */
+__process0_stack_size__  = 0x0200;  /* Main program           */
+__process1_stack_size__  = 0x0200; /* first thread program */
+__process2_stack_size__  = 0x0200; /* second thread program */
+__process3_stack_size__  = 0x0200; /* third thread program */
 
 MEMORY
 {
diff --git a/example-cdc/usb-cdc.c b/example-cdc/usb-cdc.c
index 5b569b4..d2c4961 100644
--- a/example-cdc/usb-cdc.c
+++ b/example-cdc/usb-cdc.c
@@ -157,7 +157,7 @@ static const uint8_t vcom_string3[28] = {
 
 #define NUM_INTERFACES 2
 
-static uint32_t bDeviceState = UNCONNECTED; /* USB device status */
+uint32_t bDeviceState = UNCONNECTED; /* USB device status */
 
 
 void
@@ -400,35 +400,38 @@ usb_cb_interface (uint8_t cmd, struct req_args *arg)
 
 
 void
-EP1_IN_Callback (void)
+usb_cb_tx_done (uint8_t ep_num)
 {
-  chopstx_mutex_lock (&stream.mtx);
-  if ((stream.flags & FLAG_SEND_AVAIL))
+  if (ep_num == ENDP1)
+    {
+      chopstx_mutex_lock (&stream.mtx);
+      if ((stream.flags & FLAG_SEND_AVAIL))
+	{
+	  stream.flags &= ~FLAG_SEND_AVAIL;
+	  chopstx_cond_signal (&stream.cnd);
+	}
+      chopstx_mutex_unlock (&stream.mtx);
+    }
+  else if (ep_num == ENDP2)
     {
-      stream.flags &= ~FLAG_SEND_AVAIL;
-      chopstx_cond_signal (&stream.cnd);
     }
-  chopstx_mutex_unlock (&stream.mtx);
-}
-
-void
-EP2_IN_Callback (void)
-{
 }
 
 void
-EP3_OUT_Callback (void)
+usb_cb_rx_ready (uint8_t ep_num)
 {
-  chopstx_mutex_lock (&stream.mtx);
-  if ((stream.flags & FLAG_RECV_AVAIL) == 0)
+  if (ep_num == ENDP3)
     {
-      stream.flags |= FLAG_RECV_AVAIL;
-      chopstx_cond_signal (&stream.cnd);
+      chopstx_mutex_lock (&stream.mtx);
+      if ((stream.flags & FLAG_RECV_AVAIL) == 0)
+	{
+	  stream.flags |= FLAG_RECV_AVAIL;
+	  chopstx_cond_signal (&stream.cnd);
+	}
+      chopstx_mutex_unlock (&stream.mtx);
     }
-  chopstx_mutex_unlock (&stream.mtx);
 }
 
-
 struct stream *
 stream_open (void)
 {
@@ -441,7 +444,7 @@ int
 stream_wait_connection (struct stream *st)
 {
   chopstx_mutex_lock (&st->mtx);
-  if ((stream.flags & FLAG_CONNECTED) == 0)
+  while ((stream.flags & FLAG_CONNECTED) == 0)
     chopstx_cond_wait (&st->cnd, &st->mtx);
   chopstx_mutex_unlock (&st->mtx);
   stream.flags &= ~FLAG_SEND_AVAIL;
@@ -452,46 +455,63 @@ stream_wait_connection (struct stream *st)
 int
 stream_send (struct stream *st, uint8_t *buf, uint8_t count)
 {
+  int r = 0;
+
   chopstx_mutex_lock (&st->mtx);
   if ((stream.flags & FLAG_CONNECTED) == 0)
-    {
-      chopstx_mutex_unlock (&st->mtx);
-      return -1;
-    }
+    r = -1;
   else
     {
       usb_lld_write (ENDP1, buf, count);
       stream.flags |= FLAG_SEND_AVAIL;
-      while ((stream.flags & FLAG_SEND_AVAIL))
-	chopstx_cond_wait (&st->cnd, &st->mtx);
+      do
+	{
+	  chopstx_cond_wait (&st->cnd, &st->mtx);
+	  if ((stream.flags & FLAG_SEND_AVAIL) == 0)
+	    break;
+	  else if ((stream.flags & FLAG_CONNECTED) == 0)
+	    {
+	      r = -1;
+	      break;
+	    }
+	}
+      while (1);
     }
   chopstx_mutex_unlock (&st->mtx);
-  return 0;
+  return r;
 }
 
 
 int
 stream_recv (struct stream *st, uint8_t *buf)
 {
-  int recv_size;
+  int r;
 
   chopstx_mutex_lock (&st->mtx);
   if ((stream.flags & FLAG_CONNECTED) == 0)
-    {
-      chopstx_mutex_unlock (&st->mtx);
-      return -1;
-    }
+    r = -1;
   else
     {
       usb_lld_rx_enable (ENDP3);
       stream.flags &= ~FLAG_RECV_AVAIL;
-      while ((stream.flags & FLAG_RECV_AVAIL) == 0)
-	chopstx_cond_wait (&st->cnd, &st->mtx);
-
-      recv_size = usb_lld_rx_data_len (ENDP3);
-      usb_lld_rxcpy (buf, ENDP3, 0, recv_size);
+      do
+	{
+	  chopstx_cond_wait (&st->cnd, &st->mtx);
+	  if ((stream.flags & FLAG_RECV_AVAIL))
+	    {
+	      r = usb_lld_rx_data_len (ENDP3);
+	      usb_lld_rxcpy (buf, ENDP3, 0, r);
+	      break;
+	    }
+	  else if ((stream.flags & FLAG_CONNECTED) == 0)
+	    {
+	      r = -1;
+	      break;
+	    }
+	}
+      while (1);
     }
   chopstx_mutex_unlock (&st->mtx);
 
-  return recv_size;
+  return r;
 }
diff --git a/example-cdc/usb_lld.h b/example-cdc/usb_lld.h
index 34a1068..86de9bc 100644
--- a/example-cdc/usb_lld.h
+++ b/example-cdc/usb_lld.h
@@ -63,6 +63,8 @@ int usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
 int usb_cb_handle_event (uint8_t event_type, uint16_t value);
 void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no,
 			       struct req_args *arg);
+void usb_cb_tx_done (uint8_t ep_num);
+void usb_cb_rx_ready (uint8_t ep_num);
 
 enum {
   USB_EVENT_ADDRESS,
diff --git a/example-cdc/usb_stm32f103.c b/example-cdc/usb_stm32f103.c
index cf494e9..2dac791 100644
--- a/example-cdc/usb_stm32f103.c
+++ b/example-cdc/usb_stm32f103.c
@@ -843,27 +843,6 @@ static void handle_out0 (void)
     dev_p->state = STALLED;
 }
 
-static void nop_proc (void)
-{
-}
-
-#define WEAK __attribute__ ((weak, alias ("nop_proc")))
-void WEAK EP1_IN_Callback (void);
-void WEAK EP2_IN_Callback (void);
-void WEAK EP3_IN_Callback (void);
-void WEAK EP4_IN_Callback (void);
-void WEAK EP5_IN_Callback (void);
-void WEAK EP6_IN_Callback (void);
-void WEAK EP7_IN_Callback (void);
-
-void WEAK EP1_OUT_Callback (void);
-void WEAK EP2_OUT_Callback (void);
-void WEAK EP3_OUT_Callback (void);
-void WEAK EP4_OUT_Callback (void);
-void WEAK EP5_OUT_Callback (void);
-void WEAK EP6_OUT_Callback (void);
-void WEAK EP7_OUT_Callback (void);
-
 static void
 usb_handle_transfer (uint16_t istr_value)
 {
@@ -901,31 +880,13 @@ usb_handle_transfer (uint16_t istr_value)
       if ((ep_value & EP_CTR_RX))
 	{
 	  st103_ep_clear_ctr_rx (ep_index);
-	  switch ((ep_index - 1))
-	    {
-	    case 0: EP1_OUT_Callback ();  break;
-	    case 1: EP2_OUT_Callback ();  break;
-	    case 2: EP3_OUT_Callback ();  break;
-	    case 3: EP4_OUT_Callback ();  break;
-	    case 4: EP5_OUT_Callback ();  break;
-	    case 5: EP6_OUT_Callback ();  break;
-	    case 6: EP7_OUT_Callback ();  break;
-	    }
+	  usb_cb_rx_ready (ep_index);
 	}
 
       if ((ep_value & EP_CTR_TX))
 	{
 	  st103_ep_clear_ctr_tx (ep_index);
-	  switch ((ep_index - 1))
-	    {
-	    case 0: EP1_IN_Callback ();  break;
-	    case 1: EP2_IN_Callback ();  break;
-	    case 2: EP3_IN_Callback ();  break;
-	    case 3: EP4_IN_Callback ();  break;
-	    case 4: EP5_IN_Callback ();  break;
-	    case 5: EP6_IN_Callback ();  break;
-	    case 6: EP7_IN_Callback ();  break;
-	    }
+	  usb_cb_tx_done (ep_index);
 	}
     }
 }
-- 
cgit v1.2.3