EmbDev.net

Forum: ARM programming with GCC/GNU tools USB Bulk-Tranfer: Datarate very low (Sam7SE)


von Christian W. (bluejac)


Rate this post
useful
not useful
Hi,
just posted this also at the at91.com forum but hopefully anybody can
help me here
I set up a little USB Bulk-Transfer program to have a simple connection
to my PC. On the PC-side I use libUSB for sending and receiving data. I
uses the Thesycon application to check up the correct
installation/enumaration of the usb-connection, too.

I want to have a datarate about 6-12 MBit/sec but get 0,18 MBit/sec
(180kBit/sec). The Sam7SE(512) is capable theoretically to support 12
MBit/s and I don't know why the rate is so slow.

The code for the same with using the usb.h from Atmel:
1
int main()
2
{
3
  unsigned char tmp[] =
4
"123456789012345678901234567890123456789012345678901234567890123";
5
    unsigned char bStatus;
6
7
    // Initialize the serial driver
8
    BULK_Init(&sBulk, &sUsb);
9
10
    // Wait for the device to be powered before connecting it
11
    while (!ISSET(USB_GetState(&sUsb), USB_STATE_POWERED));
12
13
    USB_Connect(&sUsb);
14
15
  while (1)
16
  {
17
18
    // Send data to USB host
19
    do {
20
      bStatus = USB_Write(
21
            sBulk.pUsb, //Pointer to a S_usb instance
22
            0x01,  //Number of the endpoint through which to send the
23
data
24
            tmp, //databuffer to send
25
            sizeof(tmp),     //Size of the databuffer
26
            0,   //Callback function to invoke
27
                       //when the transfer finishes
28
            0);  //Optional parameter to pass to
29
                       //the callback function
30
31
    } while (bStatus != USB_STATUS_SUCCESS);
32
    }
33
}

My discriptor-settings:
1
const S_usb_device_descriptor sDevice = {
2
3
    sizeof(S_usb_device_descriptor),
4
    USB_DEVICE_DESCRIPTOR,           // DEVICE Descriptor Type
5
    USB2_00,                         // USB 2.0 specification
6
    USB_CLASS_DEVICE,              // USB Communication class code
7
USB_CLASS_DEVICE = 0x00
8
    0x00,                            // No device subclass code
9
    0x00,                            // No device protocol code
10
    USB_ENDPOINT0_MAXPACKETSIZE,     // Maximum packet size for endpoint
11
zero
12
    USB_VENDOR,                      // Vendor ID
13
    PRODUCT_ID,                      // Product ID
14
    0x0001,                          // Device release number 0.01
15
    0x01,                            // Index of manufacturer
16
description
17
    0x02,                            // Index of product description
18
    0x03,                            // Index of serial number
19
description
20
    0x01                             // One possible configuration
21
};
22
23
//! \brief  Device configuration descriptor
24
//! \see    S_bulk_configuration_descriptor
25
const S_bulk_configuration_descriptor sConfiguration = {
26
27
    // Standard configuration descriptor
28
    {
29
        sizeof(S_usb_configuration_descriptor),
30
        USB_CONFIGURATION_DESCRIPTOR,        // CONFIGURATION descriptor
31
type
32
        sizeof(S_bulk_configuration_descriptor),
33
        0x01,    // 1 interfaces is used by this configuration
34
        0x01,    // 0x01 is used to select this configuration
35
        0x00,    // No string to describe this configuration
36
        USB_CONFIG_SELF_WAKEUP,  // Device is self-powered and
37
                      // does not support remote wakeup
38
        USB_POWER_MA(100)  // Maximum power consumption of the
39
                      // device is 100mA
40
    },
41
    // Data class interface descriptor
42
    {
43
        sizeof(S_usb_interface_descriptor),
44
        USB_INTERFACE_DESCRIPTOR,        //  = 0x04
45
        0x00,        // Interface
46
        0x00,        // No alternate settings
47
        0x02,        // Two endpoints used
48
        0xFF,        // Data class code
49
        0x00,        // No subclass code
50
        0x00,        // No protocol code
51
        0x00         // No description string
52
    },
53
    // Bulk-OUT endpoint descriptor
54
    {
55
        sizeof(S_usb_endpoint_descriptor),
56
        USB_ENDPOINT_DESCRIPTOR,      // ENDPOINT descriptor type
57
        0x01,       // OUT endpoint, address 1
58
        0x05,       // Bulk endpoint
59
        64,         // Endpoint size is 64 bytes
60
        0x00        // Must be 0x00 for full-speed bulk endpoints
61
    },
62
    // Bulk-IN endpoint descriptor
63
    {
64
        sizeof(S_usb_endpoint_descriptor),
65
        USB_ENDPOINT_DESCRIPTOR,      // ENDPOINT descriptor type
66
        0x82,               // IN endpoint, address 2
67
        ENDPOINT_TYPE_BULK, // Bulk endpoint
68
        64,                 // Endpoint size is 64 bytes
69
        0x00                // Must be 0x00 for full-speed bulk
70
endpoints
71
    },

I hope anybody have the solution for my problem.

Thanks and regards,
Christian

von Michael W. (mictronics)


Rate this post
useful
not useful
I discovered the same problem when I implemented USB MSD on
AT91SAM7S128.

I found at least two reason which slow down USB.

1.
The 64Byte Endpoint size is a problem if you want to tranfer large data
blocks, ie. 512Byte sectors of SD card. You can only transfer 64Byte
blocks, ever block needs protocol handshake between host and device, and
this creates a lot of overhead on the transfer - slowing down the
connection.

2.
My UDP driver in AT91 works with interrupts, but the MSD and Bulk
handler uses polling.
I discovered that any disturbance of the UDP code flow will slow down
transfer speed as well.
ie. A hardware timer with interrupt, setup to provide a system tick will
badly influence the transfer speed.

In an MP3 player project where my USB MSD is running, and when USB is
active, then I disable all things which might disturb the USB handler.

But even then I get no more then 2.1MBits/s when I use the USB MSD
class.

/Michael

von Christian W. (bluejac)


Rate this post
useful
not useful
Thank you for the answer.

I cannot imagine that the SAM7 provide this bad USB-connectivity. Such a
often used microcontroller...

Today I realised that my program only to the  correct work in case
adding the code-line

"TRACE_INIT();"

after the variable initialization. I don't understand what this function
do and why this is necessary. Maybee this is the reason for my bad
connection. Anybody who knows more?

Christian

von Michael W. (mictronics)


Rate this post
useful
not useful
TRACE_INIT() is a macro in file ..\core\trace.h

If you use tracing then the debug unit will be initialized by this
macro.

#if !defined(NOTRACES)
    #define TRACE_INIT()    AT91F_DBGU_Init(AT91C_MASTER_CLOCK,
DBGU_BAUDRATE)
#else
    #define TRACE_INIT(...)
#endif

von Christian W. (bluejac)


Rate this post
useful
not useful
Thanks, but why doesn't start my USB connection without this macro?

With the macro USB connection starts but is very slow.

von Michael W. (mictronics)


Rate this post
useful
not useful
Christian W. wrote:
> Thanks, but why doesn't start my USB connection without this macro?
>
> With the macro USB connection starts but is very slow.

The reason for slowing down the connection is simple:
With TRACE_INIT you create a lot of debugging output on the DBGU, since
it's a serial connection things will be slowed down.

But I can't tell why it doesn't start without.

When you compile the code without TRACE_INIT, are there warnings created
by the compiler?

von Christian W. (bluejac)


Rate this post
useful
not useful
I guess something like that.

No, I get no warning and no error. I notice the wrong functionality by
connecting the microcontroller to the PC. Vendor ID and Product ID are
not recognized from the USB host. Once again, here the main code I
programmed. If I comment the line marked with "<--" (line 3), the
program won't start correctly.

------------------------------------------------------------
int main()
{
  // sendbuffer, size 64 Byte
  unsigned char tmp[] =
"123456789012345678901234567890123456789012345678901234567890123";

    unsigned char bStatus;

    TRACE_INIT(); // <--

    // Initialize the serial driver
    BULK_Init(&sBulk, &sUsb);

    // Wait for the device to be powered before connecting it
    while (!ISSET(USB_GetState(&sUsb), USB_STATE_POWERED));

    USB_Connect(&sUsb);

    // LEDs init
    //configure_leds();

  while (1)
  {
    // Send data to USB host
    do {
      bStatus = USB_Write(
      sBulk.pUsb, //Pointer to a S_usb instance
      BULK_EPT_DATA_IN,  //Number of the endpoint through which to send
the data
      tmp, //Pointer to a buffer containing the data to send
      sizeof(tmp), //Size of the data buffer
      0, //Callback function to invoke when the transfer finishes
      0); //Optional parameter to pass to the callback function
    } while (bStatus != USB_STATUS_SUCCESS);



    }
}

von Michael W. (mictronics)


Rate this post
useful
not useful
Go to the ../core/ folder of your framework code, there you can find the
file trace.h

Inside you find the function:

extern inline void AT91F_DBGU_Init(unsigned int dMCK,
unsigned int dBaudrate)
{
    // Clock DBGU and configure its pins
    AT91F_DBGU_CfgPMC();
    AT91F_DBGU_CfgPIO();

    AT91F_US_Configure((AT91PS_USART) AT91C_BASE_DBGU,
                       dMCK,
                       AT91C_US_ASYNC_MODE,
                       dBaudrate,
                       0);

    // Enable Transmitter & Receiver
    AT91F_US_EnableTx((AT91PS_USART) AT91C_BASE_DBGU);
    AT91F_US_EnableRx((AT91PS_USART) AT91C_BASE_DBGU);
}

In this function comment one line after another and check which line
cause your code to fail.

Seems you forgot something to configure or setup the right way, and this
function does it for you. So without, your code fails.

von Christian W. (bluejac)


Rate this post
useful
not useful
Ok, done.

Setting the last line in comment is the only action I could do. I looked
for the code related to "AT91F_US_EnableTx((AT91PS_USART)
AT91C_BASE_DBGU);" and found this in my lib_AT91SAM7SE512.h file:

__inline void AT91F_US_EnableTx (
  AT91PS_USART pUSART)     // \arg pointer to a USART controller
{
    //* Enable  transmitter
    pUSART->US_CR = AT91C_US_TXEN;
}

AT91C_US_TXEN is defined to enable the DBGU transmitter in the related
SAM7-File. In my case "AT91SAM7SE512.h":

#define AT91C_US_TXEN         ((unsigned int) 0x1 <<  6) // (DBGU)
Transmitter Enable

But I have no idea why thr transmitter has to be enabled for a
functioning USB connection. I don't use this port in any way...

Anybody else has an idea?

Regards, Christian

von Christian W. (bluejac)


Rate this post
useful
not useful
Ok, found the reason, why I can't connect via USB with my
Microcontroller without TRACE_INIT(). In the usb.h and udp.c are
trace-functions added by ATMEL and when I try to send information via
DGBU-Port without any UART-Clock the programm pauses at this point.
I didn't see this because I haven't a Debug-Modus. My PC crashes by
starting the Debug-Mode :-(

After removing the trace-functions I get 4,1 MBit/s with my
Bulk-Settings. It is not bad, but shouldn't be the speed up to 8-10
MBit/s?

von Mrmz M. (mrmz)


Rate this post
useful
not useful
Hi everyone,

Christian W. wrote:

> After removing the trace-functions I get 4,1 MBit/s with my
> Bulk-Settings. It is not bad, but shouldn't be the speed up to 8-10
> MBit/s?
i am interested where have you got source code for your msd from?is is
Amtel's?
with what code you commmunicate with SDcard? I'm using Michael Wolf's
programme from http://www.mictronics.de/?page=arm_examples,i turned off
all the TRACE's (using macros) by i got transfer rate about
60kbytes/s(when i copy to my sd).
Christian i wonder if you could give me your programme so i could see
what are the diffrances?

i'm using at91sam7x i visited few sites and i collected some info,
if you want to make your msd work faster you must:
- use dma(to spi)
- use dualbank for endpoints
- use multi sector read command for sd card
i consider using bigger endpoints but i read that for msd
fullspeed(12MB/s)endpoint can not be bigger than 64

von Thibaut V. (aethaniel)


Rate this post
useful
not useful
Christian W. wrote:
> Ok, found the reason, why I can't connect via USB with my
> Microcontroller without TRACE_INIT(). In the usb.h and udp.c are
> trace-functions added by ATMEL and when I try to send information via
> DGBU-Port without any UART-Clock the programm pauses at this point.
> I didn't see this because I haven't a Debug-Modus. My PC crashes by
> starting the Debug-Mode :-(
>
> After removing the trace-functions I get 4,1 MBit/s with my
> Bulk-Settings. It is not bad, but shouldn't be the speed up to 8-10
> MBit/s?

Hi,

I'm very surprised by the 4.1 Mbit/s data rate!

I'm currently developing a USB MSD Key based on SAM7SE and got 600
kbit/s using standard Atmel software package 1.4 and RAM buffer, no NAND
flash nor SD card.

If you could explain how you obtain that data rates, i would be glad!!!
:-D

Futhermore, I obtained the same results using Segger embOS and emUSB
stack but using NAND flash.

Regards

von Thibaut V. (aethaniel)


Rate this post
useful
not useful
Hi,

I have to apologize, I was wrong on my datarates :

It isn't 600kbits/s but 600KBYTES/s, so I'm no more surprised :-p

I'm currently trying to improve that rates to reach 800KB/s but I'm not
sure to be able to obtain that.....

See you

von shivakumara d. (Company: eagle photonics) (shivakumara)


Rate this post
useful
not useful
hi friends i am shiva its my project im planning to use AT91SAM7s64 arm 
controller so i want know about data transfer rate B/W usb and pc and up 
to  wat size of buffer i can use to get maximum speed by using bulk 
transfer... please give me if u have any program i can use to achieve 
maximum speed please help me friends

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.