Forum: Mikrocontroller und Digitale Elektronik USB-Interrupt synchronisieren


von Reinhard (gotbread)


Angehängte Dateien:

Lesenswert?

Hallo :)

Ich bin seit einiger Zeit am bau eines Gamecube-zu-USB-converters. Das 
Projekt ist auch fast fertig, einziges Problem ist im Augenblick, dass 
der USB-Interrupt und das Abfragen des Gamecontrollers zeitlich 
kollidieren.

Im Normalfall gewinnt USB, da Interrupt, und ich bekomme fehlerhafte 
Daten.
Ausschalten kann ich die Interrupts während abfragen auch nicht, da mein 
Gerät sonst nicht mehr erkannt wird.

Das Abfragen dauert um die 400µS und der USB-Interrupt kommt jede 
Millisekunde. An sich kein Problem, nur wie synchronisier ich das?

Ein anderer ( 
http://www.raphnet.net/electronique/gc_n64_usb/index_en.php ) hat 
anscheinend schon so ein Gerät gebaut und weißt auf die Problematik hin, 
er legt sich einfach schalfen und wenn er nach dem Interrupt aufwacht, 
fragt er das Gerät ab.

Das selbe hab ich auch schon probiert, nur scheint der Interrupt nicht 
auszulösen (INT0 hängt auch an D+). Ich habe testweise mal eine LED vor 
dem schalfen eingeschaltet und nach dem aufwachen ausgeschaltet (grüne 
Linie, gelbe ist D-). Die regelmäßigen Abfragen wecken den AVR jedoch 
nicht auf.

Ich habe auch schon versucht, durch zählen der Interrupts festzustellen 
wann meine Daten ungültig geworden sind, jedoch hat dies ebenfalls nicht 
funktioniert.

Controller ist ein AtTiny45, welcher an 3.3V läuft. Die Firmware nutzt 
V-USB, auf Hostseite libusb-win (funktioniert prima).

Im Anhang einmal der ganze Projektordner sowie das Oszi-bild (sry für 
die Größe, wenn ich es skaliere, erkennt man die peaks nicht mehr).

Schonmal vielen Dank für eure Hilfe und ein schönes Wochenende :)

von Lehrmann M. (ubimbo)


Lesenswert?

Reinhard Seibt schrieb:
> Ausschalten kann ich die Interrupts während abfragen auch nicht, da mein
> Gerät sonst nicht mehr erkannt wird.

Dann stimmt irgendwas mit deinem Program nicht und das ganze läuft Amok. 
Selbstverstänndlich kann man die Interrupts am Mikrocontroller disabeln. 
Das hat rein garnichts mit der Funktion des USB-Controllers zu tun. Die 
Interrupts die aufkommen sind ja nur Notifys des USB-Controllers an den 
Mikrocontroller, dass sich der USB Aufmerksamkeit wünscht.

von Reinhard (gotbread)


Lesenswert?

Lehrmann Michael schrieb:
> Die
> Interrupts die aufkommen sind ja nur Notifys des USB-Controllers an den
> Mikrocontroller, dass sich der USB Aufmerksamkeit wünscht.

Richtig, aber sobald ich diese Notifiys durch ausgeschaltete Interrupts 
verpasse, meldet mir der PC "Gerät nicht erkannt". Das Spielchen geht 
die ganze Zeit, er erkennt es, (vermutlich die ersten 3 Impulse), dann 
wieder nicht, und so weiter.

Darf ich USB-Interrupts verpassen? (denke mal nicht)

von Thomas (Gast)


Lesenswert?

Hallo,

Reinhard Seibt schrieb:
> Darf ich USB-Interrupts verpassen? (denke mal nicht)

Bei V-USB ist das so eine Sache, V steht für "virtuell" und das Ganze 
ist per Software gelöst und synchronisiert mit Hilfe genau ausgezählter 
Assembler-Befehle.

Bei USB sollen/müssen auch die schon genannten
"Notifys des USB-Controllers"
beantwortet werden auch wenn der Slave "nicht bereit" ist, dann halt mit 
NACK. Hardware-Units machen das von selbst aber hier gehts halt nur via 
interrupt und deshalb darf der USB-interrupt nicht disabled werden ohne 
dass der PC meckert!

Ich hab zwei Vorschläge für Dich:
1) - Du definierst dir eine globale Variable die du am Ende der 
USB-Interruptroutine (in V-USB suchen) auf 1 setzt.
In deinem Programm pollst du diese Variable und wenn sie auf 1 steht 
machst du deine Abfrage und setzt sie am Ende wieder auf 0. Dann wieder 
pollen ob sie 1 ist usw. ...

2) damit das Ganze etwas entspannter abläuft setzt du die Zeit der
"Notifys des USB-Controllers" auf 2 Millisekunden, das reicht auch.
In V-USB gibt es dafür ein define für "USB_CFG_INTR_POLL_INTERVAL"(in 
V-USB suchen) das jetzt auf 1 steht und das du auf 2 setzt.

Gruss Thomas

von Thomas (Gast)


Lesenswert?

Hab noch vergessen zu sagen dass in einem Programm mit V-USB auch andere
ISR-Routinen nichts zu suchen haben, da sie die Interrupt-Reaktionszeit 
für USB undefinierbar machen und eine Synchronisation auf das USB Signal 
stören bzw. verhindern. Man hat nur Ärger.
Der ganze Rest muss im Polling-Verfahren gelöst werden.

Gruss Thomas

von Thomas (Gast)


Lesenswert?

Ich hab jetzt mal selbst gesucht nach

> "USB_CFG_INTR_POLL_INTERVAL"

und das gilt nur für "interrupt" endpoints

Such nach "...POLL_INTERVAL" in deinem config-File und gib dort die zeit 
in Millisekunden an.

Gruss Thomas

von Reinhard (gotbread)


Lesenswert?

Danke soweit schon mal für die interessanten Antworten :)

In dem Programm nutze ich keine eigenen ISRs, also sollte V-USB 
eigentlich nichts im weg stehen. Die Möglichkeit das Poll-Intervall zu 
verändern kannte ich bisher nicht, aber das löst das Problem ja nicht 
grundsätzlich.

Was mir aufgefallen ist, die kurzen Abfragen befinden sich nur auf der 
D- Leitung, D+ scheint davon nichts mitzubekommen und deswegen auch 
nicht aufzuwachen. Ich probiere mal Einen entsprechenden Interrupt zu 
verwenden (er macht nichts, nur um wach zu werden).

MfG gotbread

von Reinhard (gotbread)


Lesenswert?

Es scheint tatsächlich zu funktionieren, ich habe einfach nur eine leere 
ISR PCINT0, welche dev avr aufweckt. Nach einem vorgeschlagenen delay 
von 100µS frage ich den Controller ab, und siehe da, das Ergebnis ist 
richtig :)

Wahrscheinlich hat sich das Problem damit erledigt, also nochmals Danke 
für die Tipps

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.