Forum: Mikrocontroller und Digitale Elektronik ATmega32u4 Bulk Read Handling


von Chris W. (spaft)


Lesenswert?

Hallo Zusammen,

aktuell arbeite ich an einem kleinen Projekt, bei dem ich einen 
ATmega32u4 per USB mit einem herkömmlichen PC kommunizieren lassen 
möchte. Soweit läuft alles ganz gut, der ATmega32u4 kann ich am PC als 
Bulk Vendor Device anmelden, Treiber wird geladen und die grundsätzliche 
Kommunikation steht.

Der ATmega32u4 besitzt neben dem Control-Endpunkt vier weitere 
Endpunkte: Interrupt IN/Out und Bulk IN/OUT. Über die 
Interrupt-Endpunkte klappt Lesen und Schreiben wunderbar und fehlerlos. 
Gerade beim Lesen, wird der ATmega32u4 durchgehend vom Host gepollt, ob 
Daten zum lesen bereit liegen. Dies muss nicht immer der Fall sein.

Nachfolgend Ablauf auf dem PC zum pollen von Daten:
1
// Ablauf in einem separaten Thread
2
3
char* ReadBuffer = (char*)malloc(255 * sizeof(char));
4
5
  while(1)
6
  {
7
    ///////////
8
    // Write //
9
    ///////////
10
    
11
    // Aus Übersichtsgründen weggelassen
12
    
13
    //////////
14
    // Read //
15
    //////////
16
    int BytesRead = 0;
17
    bool SuccessfulRead = ReadDataBulk(ReadBuffer, 255, &BytesRead);
18
19
    if(!SuccessfulRead)
20
    {
21
      // Something went wrong
22
      break;
23
    }
24
25
    if(BytesRead > 0)
26
    {
27
      for(int i=0;i<BytesRead;i++)
28
      {
29
        printf("%c", ReadBuffer[i]);
30
      }
31
      printf("\n");
32
    }
33
34
    Sleep(1);
35
  }



Die Behandlung des IN-Request auf dem ATmega32u4 sieht wie folgt aus:
1
uint8_t  bufferTX[64];
2
uint8_t  bufferTXRead;
3
uint8_t  bufferTXWrite;
4
5
...
6
7
void usbEndpointINHandler(void)
8
{
9
  if((UEINTX & (1 << NAKINI)) == (1 << NAKINI))    // IN Request from the host has been received
10
  {
11
    UEINTX &= ~(1 << NAKINI);            // Clear the interrupt flag
12
    if((UEINTX & (1 << TXINI)) == (1 << TXINI))    // Check if bank free
13
    {
14
      UEINTX &= ~(1 << TXINI);          // Occupy the bank
15
      while(bufferTXRead!=bufferTXWrite)
16
      {
17
        UEDATX = bufferTX[bufferTXRead++];    // Write data to FIFO
18
        if(bufferTXRead==64)
19
        {
20
          bufferTXRead = 0;
21
        }
22
      }
23
      UEINTX &= ~(1 << FIFOCON);          // Send the data
24
    }
25
  }
26
}

Für den Fall, dass ich vom PC aus über den Bulk-Endpunkt polle, tritt 
das Problem auf, dass der PC in der Funktion "ReadDataBulk" hängen 
bleibt und diese nicht mehr verlässt. Daduch hängt der Thread und keine 
weitere Kommunikation ist mehr möglich.
Und zwar bin ich der Meinung, dass der Fehler in der Behandlung eines 
Bulk IN-Requests liegt.

Laut der folgenden Quelle 
http://www.beyondlogic.org/usbnutshell/usb4.shtml#Bulk, muss für den 
Fall das es keine Daten zum Senden gibt, ein NAK-Handshake gesendet 
werden. Die Überprüfung, ob ich Daten zum Senden vorliegen habe ist sehr 
einfach, nur mein Problem ist:
Wie kann ich ein NAK senden, wenn keine Daten vorliegen??

Dazu die Fragen:
1) Wie kann ich dem USB-Controller im ATmega32u4 sagen, dass er ein NAK 
senden soll?
2) Macht der USB-Controller dieses vllt. automatisch, wenn keine Daten 
in den FIFO geschrieben wurden und trotzdem Daten gesendet werden 
sollen?
3) Ist meine Vermutung überhaupt richtig, dass es an einem fehlenden NAK 
liegen kann.

Soweit von meiner Seite aus. Ich bedanke mich im Vorfeld für Lösungen 
und konstruktive Anregungen. :)

Beste Grüße und einen schönen Sonntag.

von Jim M. (turboj)


Lesenswert?

Du scheinst einen Fehler in ReadDataBulk zu haben. Diese Funktion ist 
uns unbekannt, kannst Du die auch mal hier posten?

NAK denden die meisten USB Implementationen automagisch, wenn keine 
Daten im USB Endpoint Buffer drin sind (-> Handbuch).

Dein Code scheint ohne Daten einfach Zero Packets zu senden. Eventuell 
kommt ReadDataBulk damit nicht klar, ich würde dort einen 
Programmierfehler vermuten.

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.