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.