Forum: Mikrocontroller und Digitale Elektronik VUSB Long Transfers Test


von R. B. (dxx255)


Lesenswert?

Hallo,
Ich habe versucht, Datenübertragungen von 1024 Bytes mittels VUSB 
zwischen einem Ubuntu-PC und einem ATMEGA328p zu realisieren. Nur aus 
irgendeinem mir nicht ersichtlichen Grund funktioniert dieses einfache 
Bsp nicht.
Könnte mir jemand sagen wo mein Fehler liegt?
Danke im Voraus
Folgender Code(µC):
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <avr/wdt.h>
4
#include <stdlib.h>
5
#include "usbdrv.h"
6
#define F_CPU 16000000L
7
#include <util/delay.h>
8
#define USB_PC_IN 0
9
#define USB_PC_OUT 1
10
static uchar buf[1024];
11
static unsigned int dataReceived = 0, dataLength = 0;
12
unsigned int i=0;
13
USB_PUBLIC uchar usbFunctionWrite(uchar *data, uchar len) {
14
                    
15
    for(i = 0; dataReceived < dataLength && i < len; i++, dataReceived++)
16
        buf[dataReceived] = data[i];
17
    return (dataReceived == dataLength); // 1 if we received it all, 0 if not
18
}
19
USB_PUBLIC usbMsgLen_t usbFunctionSetup(uchar data[8]) {
20
    usbRequest_t *rq = (void *)data; // cast data to correct type
21
        
22
    switch(rq->bRequest) { // custom command is in the bRequest field
23
    case USB_PC_IN: // send data to PC
24
  { 
25
       usbMsgLen_t len = sizeof(buf);             // we return up to 1024 bytes
26
        if(len > rq->wLength.word)          // if the host requests less than we have
27
            len = rq->wLength.word;         // return only the amount requested
28
        usbMsgPtr = buf;                 // tell driver where the buffer starts
29
        return len;
30
  }
31
    case USB_PC_OUT: // receive data from PC
32
        dataLength = (uchar)rq->wLength.word;
33
        dataReceived = 0;
34
        if(dataLength > sizeof(buf)) // limit to buffer size
35
            dataLength = sizeof(buf);
36
                        
37
        return USB_NO_MSG; // usbFunctionWrite will be called now
38
    }
39
40
    return 0; // should not get here
41
42
}
43
44
int main() {
45
       wdt_enable(WDTO_1S); // enable 1s watchdog timer
46
      usbInit();
47
      usbDeviceDisconnect(); // enforce re-enumeration
48
      for(i = 0; i<250; i++) { // wait 500 ms
49
          wdt_reset(); // keep the watchdog happy
50
          _delay_ms(2);
51
      }
52
      usbDeviceConnect();
53
        
54
      sei(); // Enable interrupts after re-enumeration
55
        
56
      while(1) {
57
          wdt_reset(); // keep the watchdog happy
58
          usbPoll();
59
      }
60
        
61
      return 0;
62
}
Code PC-Seite:
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <string.h>
4
#include <usb.h>
5
#define USB_PC_IN 0
6
#define USB_PC_OUT 1
7
#include "usb_help.c"
8
int main(int argc, char **argv) {
9
      usb_dev_handle *handle = NULL;
10
    
11
      int i = 0;
12
      char buffer[1024];
13
  char retBuf[1024];
14
  for(i;i<1024;i++){
15
    buffer[i]=(char)i%128;
16
  }
17
      handle = usbOpenDevice(0x16C0, "vendor", 0x05DC, "product");
18
      if(handle == NULL) {
19
          fprintf(stderr, "Could not find USB device!\n");
20
          exit(1);
21
      }
22
  i = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, USB_PC_OUT, 0, 0, (char *)buffer, 1024, 5000);
23
  i = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, USB_PC_IN, 0, 0, (char *)retBuf, 1024, 5000);
24
    if(i < 0)
25
        fprintf(stderr, "USB error: %s\n", usb_strerror());
26
  for(i=0;i<1024;i++){
27
    if(buffer[i]!=retBuf[i]){
28
      printf("Error: Unvollständige Übertragung!i:%d\n",i);break;
29
    }
30
  }
31
  
32
    usb_close(handle);
33
    return 0;
34
}

P.S.: Der PC gibt "Error: Unvollständige Übertragung!i:1" aus

von R. B. (dxx255)


Lesenswert?

Es muss aber ein Softwarefehler sein, da die Hardware mit anderen 
Programmen funktioniert

von Easylife (Gast)


Lesenswert?

Die Größe von Endpoint 0 ist limitiert auf 64 Bytes.
D.h. 1024 bytes werden in 16 "short-packets" übertragen.

Gut möglich, dass deine Funktionen hardwareseitig oder host-seitig die 
short packets nicht automatisch handeln, und du dich selbst drum kümmern 
musst.
Da 1024/64 genau 16 sind, muss als 17. packet ein packet mit 0 byte 
größe übertragen werden.

Hast du einen USB Analyzer mit dem du dir angucken kannst, was auf dem 
Bus tatsächlich übertragen wird?

Wenn du größere Datenmengen schnell übertragen willst, benötigst du für 
jede Richtung einen extra Endpoint (bulk oder isochronous). Die können 
mehr als 64 bytes in einem Paket.

von R. B. (dxx255)


Lesenswert?

Nein ich habe leider keinen solchen Analyzer. Wie definiere ich einen 
extra Endpoint? Und welche Art wäre besser? Ist das mit VUSB überhaupt 
möglich?

von Detlef K. (adenin)


Angehängte Dateien:

Lesenswert?

Mit Wireshake hat man auch unter Linux einen guten USB-Analyser.
Wen noch nicht geladen, dann vorher das Modul usbmon laden.
1
sudo modprobe usbmon

http://wiki.wireshark.org/CaptureSetup/USB#Linux

von Easylife (Gast)


Lesenswert?

Roman B. schrieb:
> Nein ich habe leider keinen solchen Analyzer. Wie definiere ich einen
> extra Endpoint?

Dazu muss der Devicedescriptor des Gerätes entsprechend erweitert 
werden.

> Und welche Art wäre besser?

Isochronous nimmt man z.B. für Streaming (z.B. Audio), für das auf dem 
Bus eine feste Bandbreite reserviert wird. Es gibt aber kein 
Error-Handling. Kaputte Pakete werden verworfen.

Bulk für alles andere (Mass Storage etc.).

Ist das mit VUSB überhaupt
> möglich?

Weiss ich nicht.

Mal anders herum gefragt:
Welche Datenmenge willst du denn pro Sekunde übertragen.
Evtl. reicht Endpoint 0 mit short packets ja auch aus.

von R. B. (dxx255)


Lesenswert?

Ich will nur 1024 Bytes hin und wieder zurück schicken.

von holger (Gast)


Lesenswert?

>Ich will nur 1024 Bytes hin und wieder zurück schicken.

Dann wirst du das wohl in mehreren kleineren Häppchen tun müssen.

von easylife (Gast)


Lesenswert?

Roman B. schrieb:
> Ich will nur 1024 Bytes hin und wieder zurück schicken.

das geht, eben in 64 byte happen. und davon gehen max. 1000 stueck pro 
sek.
wenn das reicht, machs ueber ep0.

du musst rausfinden, ob deine funktionen ein grosses paket automatisch 
zerlegen/zusammensetzen. ansonsten musst du das von hand prigrammieren.

von Frank K. (fchk)


Lesenswert?

VUSB ist ja grundsätzlich Low Speed. Und für Low Speed Devices gilt, 
dass Datenpakete maximal 8 Bytes groß sein dürfen. Bei Full Speed sind 
64 Byte Pakete erlaubt. Siehe USB 2.0 Standard, Kapitel 8, Abschnitt 
8.4.4 "Data Packets".

Außerdem kannst Du nur Control und Interrupt Transfers zu einem Low 
Speed Device durchführen, Bulk Transfers erlaubt der USB 2.0 Standard 
nicht. Siehe USB 2.0 Standard, Kapitel 5, Abschnitt 5.8.3 "Bulk Transfer 
Packet Size Constraints": "A low-speed device must not have bulk 
endpoints."

Also bleibe bei Control Transfers, spalte Dein Kilobyte in 8-Byte 
Päckchen und verschicke die.

Wenn Du mit dieser Lösung unzufrieden bist, dann musst Du halt einen 
richtigen USB-Controller verwenden, der Full-Speed USB in Hardware 
macht. Das ist dann auch wirklich USB 2.0 Standard-konform.

fchk

von R. B. (dxx255)


Lesenswert?

Funktioniert doch nicht:(
Ich werde es einfach mittels mehrerer control-Übertragungen realisieren.

Danke trotzdem:)

von easylife (Gast)


Lesenswert?

vusb=low speed?! das ist ja wirklich mist. 8 bytes ist ja nichts. hast 
du keine moeglichkeit wenigstens full-speed zu nutzen?

von R. B. (dxx255)


Lesenswert?

Nein, hab leider keinen Hardware-USB-Controller:( Macht aber nix - hab 
zwei Funktionen geschrieben die den Datentransfer in 128 Byte Blöcken 
übernehmen! Das klappt einwandfrei:) Nur mehr als 254 Byte kann ich 
nicht auf einmal transferieren (auch mit USB_CFG_LONG_TRANSFERS=1 
nicht)- daher die 128 Byte Blöcke.

Ich persönlich finde VUSB echt gut weil man mithilfe von 5 
"Standard-Bauteilen" (3 Widerstände, 2 Zener-Dioden) einen AVR über USB 
kommunizieren lassen kann. Man muss sich halt manchmal softwaretechnisch 
etwas behelfen aber sonst klappt´s (bei mir zumindest) einwandfrei 
(obwohl ich mich mit USB nicht besonders gut auskenne - mehr als 
control-transfers bring ich nicht zustande).

Danke für die Hilfe - Problem gelöst

P.S.: Danke für den Tipp mit Wireshark als USB Analyzer

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.