CDCACM serial at 480 Mbits

Status
Not open for further replies.

hoho

Well-known member
I'll start a separate dedicated thread as I seem to have the problem narrowed down (that's the initial thread: https://forum.pjrc.com/threads/56595-USB-Host-Force-Detection).

I try to connect a CDCACM serial device to Teensy's 3.6 USB host at 480 Mbits speed and it seems to lack the proper software support. If Teensy is forced to 12 Mbits (by uncommenting «//USBHS_PORTSC1 |= USBHS_PORTSC_PFSC; // force 12 Mbit/sec» line in ehci.cpp), the serial gets connected and working fine.

At 480 Mbits spead the serial is not detected. However if I make this change (basically, commenting out all the checks), it seems to work (I didn't do extreme testing so far, just a few semi-manual tests of bidirectional data transmission over the connected serial):

Code:
diff --git a/USBHost_t36.h b/USBHost_t36.h
index efb78ca..3645899 100644
--- a/USBHost_t36.h
+++ b/USBHost_t36.h
@@ -1384,7 +1384,7 @@ class USBSerial: public USBDriver, public Stream {
 
 
 	// FIXME: need different USBSerial, with bigger buffers for 480 Mbit & faster speed
-	enum { BUFFER_SIZE = 648 }; // must hold at least 6 max size packets, plus 2 extra bytes
+	enum { BUFFER_SIZE = 6000 }; // must hold at least 6 max size packets, plus 2 extra bytes
 	enum { DEFAULT_WRITE_TIMEOUT = 3500};
 	USBSerial(USBHost &host) : txtimer(this) { init(); }
 	void begin(uint32_t baud, uint32_t format=USBHOST_SERIAL_8N1);
diff --git a/serial.cpp b/serial.cpp
index d6bb58c..4230265 100644
--- a/serial.cpp
+++ b/serial.cpp
@@ -29,6 +29,8 @@
 #define print   USBHost::print_
 #define println USBHost::println_
 
+#define PACKET_SIZE 512
+
 //#define ENABLE_DEBUG_PINS
 
 #ifdef ENABLE_DEBUG_PINS
@@ -189,7 +191,7 @@ bool USBSerial::claim(Device_t *dev, int type, const uint8_t *descriptors, uint3
 			}
 			sertype = CDCACM;
 			rxpipe->callback_function = rx_callback;
-			queue_Data_Transfer(rxpipe, rx1, (rx_size < 64)? rx_size : 64, this);
+			queue_Data_Transfer(rxpipe, rx1, (rx_size < PACKET_SIZE)? rx_size : PACKET_SIZE, this);
 			rxstate = 1;
 			if (rx_size > 128) {
 				queue_Data_Transfer(rxpipe, rx2, rx_size, this);
@@ -239,8 +241,8 @@ bool USBSerial::claim(Device_t *dev, int type, const uint8_t *descriptors, uint3
 		while (count_end_points-- && ((rxep == 0) || txep == 0)) {
 			if (descriptors[descriptor_index] != 7) return false; // length 7
 			if (descriptors[descriptor_index+1] != 5) return false; // ep desc
-			if ((descriptors[descriptor_index+3] == 2) 
-				&& (descriptors[descriptor_index+4] <= 64)
+			if ((descriptors[descriptor_index+3] == 2)
+				&& (descriptors[descriptor_index+4] <= PACKET_SIZE)
 				&& (descriptors[descriptor_index+5] == 0)) {
 				// have a bulk EP size 
 				if (descriptors[descriptor_index+2] & 0x80 ) {
@@ -353,21 +355,21 @@ bool USBSerial::claim(Device_t *dev, int type, const uint8_t *descriptors, uint3
 	if (descriptors[6] != 0) return false; // bInterfaceSubClass
 	if (descriptors[7] != 0) return false; // bInterfaceProtocol
 
-	if (descriptors[9] != 7) return false; // length 7
-	if (descriptors[10] != 5) return false; // ep desc
+	// if (descriptors[9] != 7) return false; // length 7
+	// if (descriptors[10] != 5) return false; // ep desc
 	uint32_t txep = descriptors[11];
-	uint32_t txsize = descriptors[13];
-	if (descriptors[12] != 2) return false; // bulk type
-	if (descriptors[13] > 64) return false; // size 64 Max
-	if (descriptors[14] != 0) return false;
+	uint32_t txsize = PACKET_SIZE; //descriptors[13];
+	// if (descriptors[12] != 2) return false; // bulk type
+	// if (descriptors[13] > 64) return false; // size 64 Max
+	// if (descriptors[14] != 0) return false;
 
-	if (descriptors[16] != 7) return false; // length 7
-	if (descriptors[17] != 5) return false; // ep desc
+	// if (descriptors[16] != 7) return false; // length 7
+	// if (descriptors[17] != 5) return false; // ep desc
 	uint32_t rxep = descriptors[18];
-	uint32_t rxsize = descriptors[20];
-	if (descriptors[19] != 2) return false; // bulk type
-	if (descriptors[20] > 64) return false; // size 64 Max
-	if (descriptors[21] != 0) return false;
+	uint32_t rxsize = PACKET_SIZE; //descriptors[20];
+	// if (descriptors[19] != 2) return false; // bulk type
+	// if (descriptors[20] > 64) return false; // size 64 Max
+	// if (descriptors[21] != 0) return false;
 	if (!check_rxtx_ep(rxep, txep)) return false;
 	interface = descriptors[2];
 
@@ -383,10 +385,10 @@ bool USBSerial::claim(Device_t *dev, int type, const uint8_t *descriptors, uint3
 	}
 	sertype = CDCACM;
 	rxpipe->callback_function = rx_callback;
-	queue_Data_Transfer(rxpipe, rx1, 64, this);
+	queue_Data_Transfer(rxpipe, rx1, PACKET_SIZE, this);
 	rxstate = 1;
 	if (rxsize > 128) {
-		queue_Data_Transfer(rxpipe, rx2, 64, this);
+		queue_Data_Transfer(rxpipe, rx2, PACKET_SIZE, this);
 		rxstate = 3;
 	}
 	txstate = 0;

Which is of course a hack.
I have also noticed this line in the code: «// FIXME: need different USBSerial, with bigger buffers for 480 Mbit & faster speed». So, I suppose the one who has written it (I suppose Paul Stoffregen) has a proper fix in mind already. Paul, I'm wondering if you can share your thoughts, plans and suggestions.

Here is the debug info of how my device's connection log looks like (without the changes above):

Code:
new_Device: 480 Mbit/sec
new_Pipe
enumeration:
enumeration:
enumeration:
Device Descriptor:
  12 01 00 02 02 00 00 40 25 05 A7 A4 04 04 01 02 00 01 
    VendorID = 0525, ProductID = A4A7, Version = 0404
    Class/Subclass/Protocol = 2 / 0 / 0
    Number of Configurations = 1
enumeration:
enumeration:
Manufacturer: Linux 4.4.49-s5p4418 with c0040000.dwc2otg
enumeration:
Product: Gadget Serial v2.4
enumeration:
Config data length = 75
enumeration:
Configuration Descriptor:
  09 02 4B 00 02 02 04 C0 01 
    NumInterfaces = 2
    ConfigurationValue = 2
  08 0B 00 02 02 02 01 07 
    Interface Association = 0 through 1
    Class / Subclass / Protocol = 2 / 2 / 7
  09 04 00 00 01 02 02 01 05 
    Interface = 0
    Number of endpoints = 1
    Class/Subclass/Protocol = 2 / 2 / 1
  05 24 00 10 01 
  05 24 01 00 01 
  04 24 02 02 
  05 24 06 00 01 
  07 05 82 03 0A 00 09 
    Endpoint = 2 IN
    Type = Interrupt
    Max Size = 10
    Polling Interval = 9
  09 04 01 00 02 0A 00 00 06 
    Interface = 1
    Number of endpoints = 2
    Class/Subclass/Protocol = 10 / 0 / 0
  07 05 81 02 00 02 00 
    Endpoint = 1 IN
    Type = Bulk
    Max Size = 512
    Polling Interval = 0
  07 05 01 02 00 02 00 
    Endpoint = 1 OUT
    Type = Bulk
    Max Size = 512
    Polling Interval = 0
enumeration:
USBHub memory usage = 960
USBHub claim_device this=1FFF32C0
USBHub memory usage = 960
USBHub claim_device this=1FFF3720
HIDParser claim this=1FFF2680
HIDParser claim this=1FFF2CA0
HIDParser claim this=1FFF3AE0
USBSerial claim this=1FFF2020
vid=525, pid=A4A7, bDeviceClass = 2, bDeviceSubClass = 0, bDeviceProtocol = 0
08 0B 00 02 02 02 01 07 09 04 00 00 01 02 02 01 05 05 24 00 10 01 05 24 01 00 01 04 24 02 02 05 24 06 00 01 07 05 82 03 0A 00 09 09 04 01 00 02 0A 00 00 06 07 05 81 02 00 02 00 07 05 01 02 00 02 00 
Descriptor 11 = IAD
Descriptor 4 = INTERFACE
HIDParser claim this=1FFF2680
HIDParser claim this=1FFF2CA0
HIDParser claim this=1FFF3AE0
USBSerial claim this=1FFF2020
vid=525, pid=A4A7, bDeviceClass = 2, bDeviceSubClass = 0, bDeviceProtocol = 0
09 04 00 00 01 02 02 01 05 05 24 00 10 01 05 24 01 00 01 04 24 02 02 05 24 06 00 01 07 05 82 03 0A 00 09 09 04 01 00 02 0A 00 00 06 07 05 81 02 00 02 00 07 05 01 02 00 02 00 
Descriptor 36 =  ???
Descriptor 36 =  ???
Descriptor 36 =  ???
Descriptor 36 =  ???
Descriptor 5 = ENDPOINT
Descriptor 4 = INTERFACE
HIDParser claim this=1FFF2680
HIDParser claim this=1FFF2CA0
HIDParser claim this=1FFF3AE0
USBSerial claim this=1FFF2020
vid=525, pid=A4A7, bDeviceClass = 2, bDeviceSubClass = 0, bDeviceProtocol = 0
09 04 01 00 02 0A 00 00 06 07 05 81 02 00 02 00 07 05 01 02 00 02 00 
Descriptor 5 = ENDPOINT
Descriptor 5 = ENDPOINT

Also having a read() function which returns a single character feels to be rather insufficient at these speeds. But I suppose I am confident enough to try to implement a bulk read function on my own (which is totally not the case for tweaking the USB negotiation part).

Thanks!
 
Status
Not open for further replies.
Back
Top