USB_VCP performance

The official pyboard running MicroPython.
This is the reference design and main target board for MicroPython.
You can buy one at the store.
Target audience: Users with a pyboard.
Post Reply
manitou
Posts: 73
Joined: Wed Feb 25, 2015 12:15 am

USB_VCP performance

Post by manitou » Wed May 20, 2015 6:48 pm

I have measured USB performance (latency, read rate) on various MCU's (teensy, DUE, maple, UNO) using the framework described at
http://www.pjrc.com/teensy/benchmark_us ... ceive.html

Using the same host harness (on Ubuntu laptop), I used the following pyboard program to measure latency

Code: Select all

#  from teensy latency_test /dev/ttyACM0
import pyb
usb_vcp = pyb.USB_VCP()
pyb.LED(1).on()
pyb.delay(5000)
# wait for host to connect to ACM0
while not usb_vcp.isconnected():
	pass
pyb.LED(1).off()

while True:
	if usb_vcp.any() :
		x = usb_vcp.read(1)
		if x == b'x' :
			usb_vcp.write('0')
			usb_vcp.write('1')
			usb_vcp.write('2')
			usb_vcp.write('x')

The results for the pyboard were a bit slow compared to teensy 3.1 and even UNO, and the test failed if the host tried sending more than 500 bytes. The 10ms delay is probably dictated by timer3 USBD_CDC_POLLING_INTERVAL

Code: Select all

	                 teensy 3.1             UNO             pyboard
       latency @ 1 bytes: 0.10 ms 	     4.09 ms 	     10.00 ms 
       latency @ 2 bytes: 0.10 ms 	     4.09 ms 	     10.00 ms 
       latency @ 12 bytes: 0.10 ms	     4.09 ms 	     10.00 ms 
       latency @ 30 bytes: 0.14 ms 	     4.09 ms 	     10.00 ms 
       latency @ 62 bytes: 0.19 ms	     8.19 ms 	     10.00 ms 
       latency @ 71 bytes: 0.21 ms	     8.19 ms 	     10.00 ms 
       latency @ 128 bytes: 0.26 ms	     12.28 ms 	     10.00 ms 
       latency @ 500 bytes: 0.64 ms	     45.05 ms 	     20.00 ms 
       latency @ 1000 bytes: 1.07 ms	     86.01 ms 		?
       latency @ 2000 bytes: 2.03 ms	     172.04 ms 		?
       latency @ 4000 bytes: 3.88 ms	     344.07 ms 		?
       latency @ 8000 bytes: 7.45 ms	     684.04 ms 		?

The readbytes test did NOT really work on the pyboard. the host sends 30000 bytes for a total of 1 million bytes. In fact, the host seems to send at its maximum rate as there appears to be no feedback (flow control) from the pyboard USB. With no "recv" in the pyboard program, the host side is happy to send away! Here is the little pyboard receiver

Code: Select all

#  from teensy latency_test /dev/ttyACM0    TODO ??
# recv is blocking, read is not
import pyb
usb_vcp = pyb.USB_VCP()
pyb.LED(1).on()
pyb.delay(5000)
# wait for host to connect to ACM0
while not usb_vcp.isconnected():
	pass
pyb.LED(1).off()

while True:
		x = usb_vcp.recv(500)

As usual, I could have messed up the Python (not my "native" language), but if not, I'm surprised that the pyboard USB_VCP is not doing some sort of USB flow control??

readbytes on teensy 3.1 averages 1,150,244 bytes/second, on UNO average is 11,761 bytes/sec.

EDIT: if I change the host send size from 30000 to 512, then the pyboard does do some recv's -- though not 1 million bytes worth.
Last edited by manitou on Tue May 26, 2015 7:56 pm, edited 1 time in total.

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: USB_VCP performance

Post by dhylands » Wed May 20, 2015 11:28 pm

Interesting. I'll have to dig into the USB stuff.

I've just been writing some code to do file transfers from the host to the pyboard and I wound up using 512 byte transfers with an explicit ack having to be sent back to the host to send the next 512 bytes.

manitou
Posts: 73
Joined: Wed Feb 25, 2015 12:15 am

Re: USB_VCP performance

Post by manitou » Thu May 21, 2015 12:54 am

well, i've made some progress sending in 512 byte chunks from the host and using the following program to recv, I am receiving 1 million bytes +

Code: Select all

#  from teensy receive_test /dev/ttyACM0   
# recv is blocking (timeout 5000ms), read is not
import pyb

msg = 'nothing'
sw = pyb.Switch()
sw.callback(lambda:uart.write(msg))
uart = pyb.UART(1, 9600)
uart.write('starting  ')
buff = bytearray(500)
bytes =0

usb_vcp = pyb.USB_VCP()
pyb.LED(1).on()
pyb.delay(5000)
# wait for host to connect to ACM0
while not usb_vcp.isconnected():
	pass
pyb.LED(1).off()


while True:
#		uart.write('recv {} \r\n'.format(bytes))
		n = usb_vcp.recv(buff)
		if n != 0 :
			bytes += n
			msg = 'bytes {} \r\n'.format(bytes)

the host send rate using 512-byte chunks is 512,043 bytes/second.

I still think the USB_VCP should be doing some sort of USB flow control ...

Post Reply