LUFA CLASS_CDC Example - USB Data Transmission Speeds (128A1U Xplained Pro)

Go To Last Post
15 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey everyone,

 

I've been working on a project involving the CDC Virtual Serial driver from the LUFA library. I'm using it to send a 49,150 byte block of data to the PC (Device_CDC_SendData() function), With this method, I'm currently measuring a max data transmission rate (XMEGA A1U XPRO --> PC) of ~0.2MBytes/sec, which is far below the theoretical maximum for USB 2.0 Full Speed (1.5Mbytes/sec) that I would like to reach. 

 

Here is the part of my code (XMEGA A1U) dealing with the Tx/Rx functions:

 

int main (void){

    ptr = START_PTR; //ptr is a 32-bit pointer that helps access data in external SRAM

    SetupHardware();	//Set up USB hardware

	/* Create a regular character stream for the interface so that it can be used with the stdio.h functions */
	CDC_Device_CreateStream(&VirtualSerial_CDC_Interface, &USBSerialStream);

	GlobalInterruptEnable();

	for (;;)
	{
		CDC_Device_SendData(&VirtualSerial_CDC_Interface, START_PTR, END_PTR-START_PTR); //Sending a buffer of data bounded by hex addresses START_PTR and END_PTR

		/* Below lines are mandatory, aren't they?*/
		CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
		USB_USBTask();
	}
}
	

Transmission speed is measured using a host (PC) program. The program calculates transmission rate by dividing the # of received bytes by the time taken to receive it.

 

Is there a way (or more than one way :D) to speed up the Transmission Rate to something closer to the theoretical max. speed of USB 2.0 (1.5MBytes/sec)?

Which of these is likely to be the culprit?

  1. My implementation of the Tx/Rx (code below)
  2. Inefficiencies in the host's data-receiving code (not attached here) written to measure the transmission speed
  3. Something else?

 

Thanks for your time!

 

-by98

Last Edited: Tue. Jun 6, 2017 - 05:50 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I don't know.  For starters I don't think you can get more that around 1 megabyte per second under ideal conditions.  That's all I've ever got in testing.  For one thing, there is a fair amount of overhead in the USB protocol.

 

I just ran a throughput test with USB CDC ACM and I measured a little less than 1 megabyte per second.  It surprised me that it was that fast. 

 

I use my own code in the Xmega.  I'm receiving it on the PC with hyperterminal which captures it to a text file.  I'm sending 1023 bytes per write.  As soon as it is sent, I send it again. 

Last Edited: Wed. Jun 7, 2017 - 07:29 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've been trying to use the in-built Device_CDC_SendData() function, which allows me to send multiple-byte buffers together. Using this, I've been repeatedly sending the same 49088-byte block, so I guess that's similar to your code.

 

1Mbyte/second would be great for my purposes! Would you be able to attach your code/project? I'd be very interested in trying to figure out how to speed up my current transmission speed :)

 

Thanks,

- by98

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My code is C++.  If you use C, that could be a bit of a problem.  Maybe I could come up with something you could use.

 

I don't know LUFA, and I don't understand a 49088 block.  The maximum you can send in one write operation is 1023 bytes.  I suppose the LUFA driver splits that up.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Steve,

 

Yep, it does get split up into smaller pieces by the LUFA driver (based on the specified max payload size, I think).

 

- by98

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do we know where the bottleneck lies?  It seems to me it could be the PC program or it could be the AVR.

 

I think the next step is to figure out which it is. 

 

I could give you a program to put on the AVR that would send data as fast as it could. 

 

The other way is for you to use another program on the PC.   I use Hyperterm for this purpose.  If you aren't familiar with it, it could take some time to figure out what to click to set it up.  I could give some advice.

 

If you are running XP, you have it, but I suppose you aren't running XP.  So here it is.

 

 

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the .zip, I've opened and set it up somewhat. How have you been using HyperTerminal (I noticed it has text capture functionality)? 

"I could give you a program to put on the AVR that would send data as fast as it could. "

It would be awesome if you could send a copy of your program. It would make it easier to replicate your setup (PC and AVR sides of things) and isolate the problem.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I do use the text capture to measure throughput.  After it's running, I start the capture and then stop it after 10 seconds (or whatever) to give me a rough idea of the speed.  I'm getting around 9.5 megabytes in ten seconds.  Hyperterm says "text" capture but it seems to get the same byte count if I send all ascii or send garbage.

 

I'll send all 'A' characters unless you want something different.  I'll have it send whenever it's running unless you want to use a push button etc. to control it.

 

I'll send a hex file which I think will run on your chip even though I built it for 128a4u.  I just loaded it on a 256a3bu and it ran okay.

 

I will remove a lot of stuff from the build that you won't be using.  I could blink an LED if you have one and I know what pin it's on.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here is a hex file that should send continuously.

 

In this version you have to hit a key in hyperterm to start it.  Hitting a key again will stop it, etc..  I had thought it would start sending automatically, but apparently my startup code finishes before the USB connection is made.

 

This could be inconvenient if you are using a different program on the PC.  It should be easy to have it start sending automatically.  I'll just have the startup code delay until the USB is operational.

 

 

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Steve,

 

Thanks for the file! I'm trying to load it onto the board but doesn't seem to work. After loading the code, there's a message saying something down the lines of "USB Device has malfunctioned".

 

I used the Tools-->Device Programming-->Memories option to load the HEX file into the Flash section of the chip (is that the right way to do it?). Online searches tell me this is the right way to load code.

 

Maybe it didn't work because the file was meant for the 128a4u? Maybe I can adapt your A4U C++ code to C code (for my A1U)? Let me know what you think.

 

-by98

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't know what to think.  I use bootloaders but I don't know if that makes a difference.  I'll see about making a project I can send to you.  Do use AS 6.2 or AS 7?

 

Have you tried using Hyperterm on the PC connected to your AVR running your AVR software, or would that be difficult to do?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So every time you reset or cycle power on the AVR you get the USB device has malfunctioned?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I use the 32kHz RC oscillator and DFLL to set the 48MHz frequency.  It is more than accurate enough for my PCs.  Maybe your PC is very picky.  If you use a crystal, that could be it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Steve,

 

  • I'm using AS7
  • Yes, the device malfunctions every time the AVR power cycles/resets
  • The "32MHz DFLL to 48MHz" definitely works, because that's what LUFA Example does

 

What do you suggest we do?

 

- by98

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I made a hex file with all endpoint register structs on 16 byte boundaries.   Something is different with your chip, and I think it's worth a try. 

 

I made it for your a1u chip but I don't think that matters.  The builds for a1u work fine on my a4u chips.  Of course this build with the 16 byte boundaries wouldn't run, but the regular 8 byte boundary builds work on my chips.

 

 

Attachment(s):