Forum: Mikrocontroller und Digitale Elektronik AT90USB162 Endpoint Interrupts funktionieren nicht


von Marvin K. (m_marvin)


Lesenswert?

Hallo, ich bin neu hier im Forum, und habe mich angemeldet weil ich das 
erste mal ein Problem mit meinem Microcontroller habe, das ich selbst 
durch mehrwöchiges suchen nach Infos nicht lösen konnte:

Ich habe mir ein par AT90USB162 gekauft, um ein par Projekte mit USB 
Schnittstelle umzusetzen, ich habe mir das Datenblatt durchgelesen, das 
erste Programm geschrieben und hochgeladen, nach dem es ein par Fehler 
gab hab ich ein par Beispiele im Internet gesucht und die Fehler auch 
beheben können.

Allerdings gibt es einen Fehler, den ich einfach nicht behoben bekomme:
Die Endpoint Interrupts (USB_COM_vect) werden einfach nicht aufgerufen.

Mein AT90USB wird von Windows als USB Gerät erkannt, die generellen USB 
Interrupts werden korrekt aufgerufen und der USB Controller + Endpunkte 
konfiguriert, aber nach einigen Sekunden sagt Windows, das der AT90 
nicht auf die Anforderung einer Gerätebeschreibung reagiert hat (SETUP 
Packet ist wurde nicht beantwortet).

Ich habe auf alle erdenklichen arten und weisen versucht das RXSTPI Bit 
abzufragen, Ergebnis: es wird nie gesetzt, und auch sonst werden keine 
USB_COM_vext Interrupts ausgelöst, mit dem Oszilloskop hab ich aber 
prüfen können, das (zumindest vom Computer/Host aus) Daten an den uC 
gesendet werden.

Ich habe ein kurzes Programm geschrieben was zumindest die 
Endpunktkonfiguration und die beiden Interrupt Vektoren implementiert, 
eventuell kann mir einer weiterhelfen:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
#define LED_1 PD4
5
#define LED_2 PD5
6
7
ISR(USB_COM_vect, ISR_BLOCK)
8
{
9
  uint8_t epint = UEINTX;
10
  UEINTX = 0;
11
  if (epint & (1 << RXSTPI))
12
  {
13
    PORTD |= (1 << LED_2);
14
  }
15
}
16
17
ISR(USB_GEN_vect, ISR_BLOCK)
18
{
19
  uint8_t uint = UDINT;
20
  UDINT = 0;
21
  if (uint & (1 << EORSTI))
22
  {
23
    
24
    UENUM = 0;
25
    UECONX |= (1 << EPEN);
26
    UECFG0X = 0;
27
    UECFG1X = 16;
28
    UECFG1X |= (1 << ALLOC);
29
    while (UESTA0X & (1 << CFGOK) == 0);
30
    
31
    PORTD |= (1 << LED_1);
32
    
33
  }
34
}
35
36
int main(void)
37
{
38
  
39
  DDRD |= (1 << LED_1) | (1 << LED_2);
40
  
41
  PLLCSR |= (1 << PLLE);
42
  PLLCSR &= ~(1 << PLLP2);
43
  PLLCSR &= ~(1 << PLLP1);
44
  PLLCSR &= ~(1 << PLLP0);
45
  while ((PLLCSR & (1 << PLOCK)) == 0);
46
  USBCON |= (1 << USBE);
47
  USBCON &= ~(1 << FRZCLK);
48
  UDCON &= ~(1 << DETACH);
49
  
50
  sei();
51
  UDIEN |= (1 << EORSTE);
52
  UEIENX |= (1 << RXSTPE);
53
  
54
  while (1)
55
  {
56
    if (UEINT & (1 << RXSTPI)) PORTD |= (1 << LED_2);
57
  }
58
  
59
}

Verhalten: LED 1 leuchtet auf sobald der das Gerät eingesteckt wurde, 
und der Endpunkt konfiguriert wurde, LED 2 sollte aufleuchten sobald das 
erste SETUP-Paket eingetroffen ist, tut sie aber nicht (für Testzwecke 
hab ich 2 verschiedene Abfragen eingebaut, in der main loop und im 
Interrupt).

Fehler von der Elektrischen Seite hab ich schon ausgeschlossen, alles 
mehrfach mit Oszilloskop und Multimeter durchgemessen, Daten kommen an 
und Leitungen sind korrekt angeschlossen, nach USB Norm und AT90USB 
Datenblatt.

Ich hoffe hier kann mir jemand helfen.

von Jim M. (turboj)


Lesenswert?

Marvin K. schrieb:
> Mein AT90USB wird von Windows als USB Gerät erkannt, die generellen USB
> Interrupts werden korrekt aufgerufen und der USB Controller + Endpunkte
> konfiguriert, aber nach einigen Sekunden sagt Windows, das der AT90
> nicht auf die Anforderung einer Gerätebeschreibung reagiert hat (SETUP
> Packet ist wurde nicht beantwortet).

Ich sehen in dem Code oben keine korrekte Implementation des 
nicht-trivialen EP0, über den alle Desktriptoren abgerufen werden.

Ein Code 43 ist dann die normale Reaktion von Windows.

von Thomas Z. (usbman)


Lesenswert?

Die PLL Initialisierung ist auch irgendwie komisch. Welchen Quarz bzw 
Clock benutzt du?

: Bearbeitet durch User
von Marvin K. (m_marvin)


Lesenswert?

Beitrag "Re: AT90USB162 Endpoint Interrupts funktionieren nicht"

(Ich weis nicht ob ich das mit dem Verweisen auf einen Beitrag richtig 
gemacht hab)

Ich nutze einen 8MHz Quartz, laut dem Datenblatt des uCs müsste ich die 
PLLP0-PLLP2 Bits des PLL Registers dann auf 000 setzen, ich habe das im 
Beispiel in 3 einzelnen Zeilen gemacht, da ich die beiden verschiedenen 
Einstellungen getestet hab, man könnte es aber auch in eine Zeile 
schreiben oder weg lassen (000 ist Standart soweit ich weis).

Beitrag "Re: AT90USB162 Endpoint Interrupts funktionieren nicht"

Ich konfiguriere EP0 doch im USB_GEN_vect Interrupt, oder hab ich da was 
falsch verstanden?
1
UENUM = 0;              // EP0 Anwählen
2
UECONX |= (1 << EPEN);        // EP0 Aktivieren
3
UECFG0X = 0;            // Controll-EP
4
UECFG1X = 16;            // 16 Byte, one Bank
5
UECFG1X |= (1 << ALLOC);      // Allocate memory
6
while (UESTA0X & (1 << CFGOK) == 0);// Warten auf "CFGOK"

Ich habe hier die Fehlererkennung wenn das setzen des ALLOC Bits 
fehlschlägt weggelassen, damit der Code übersichtlich bleibt, und die 
aktuelle Konfiguration scheint ja auch zu Funktionieren (CFGOK wird 
gesetzt).
Und ich hab auch schon verschiedene Konfigurationen für UECFG1X 
ausprobiert, diese hier hab ich aus einem Beispiel-Code von GitHub.

Wenn ich hier was falsch habe, wäre das schonmal ein großer Vorschritt, 
ich finde nämlich kaum Infos zum konfigurieren der Endpunkte, das ist 
das einzige was ich finden konnte.

von Thomas Z. (usbman)


Lesenswert?

Marvin K. schrieb:
> Ich konfiguriere EP0 doch im USB_GEN_vect Interrupt, oder hab ich da was
> falsch verstanden?

ja und die LED1 geht ja auch an wie du selbst schreibst. Es gibt aber 
keinerlei Code für die Chapter9 Requests.
Du must mindestens GetDescriptor(Device und Config), SetAddress() und 
SetConfig implementieren, zusätzlich ist es hilfreich den USB Reset 
auszuwerten und dort alle wichtigen Variablen zurücksetzen.
Solange das nicht implementiert ist enumeriert nichts. Wo sind den deine 
Deskriptoren?

Der Ablauf unter Win ist etwa folgender
- UsbReset
- GetDescriptor(Device)
- UsbReset
- SetAddr()
- GetDescriptor(Device)
- GetDescriptor(Configuration)
- SetConfig()

von Marvin K. (m_marvin)


Lesenswert?

Ich weis, das hab ich aber in diesem Beispiel weg gelassen, wie ich oben 
schon geschrieben habe, das Problem ist das die USB_COM_vect Interrupts 
nicht funktionieren, ich kann diese Requests ja nicht einfach wahllos 
senden, sondern muss auf das SETUP des Hosts warten, ich empfange aber 
keins -> LED 2 leuchtet nicht.

: Bearbeitet durch User
von Marvin K. (m_marvin)


Lesenswert?

Zusammengefasst bin ich an dem Punkt wo ich auf das erste SETUP Request 
des Hosts warte, aber irgendwie keins bekomme.

von Thomas Z. (usbman)


Lesenswert?

nun das Datenblatt sagt
CONTROL endpoints should not be managed by interrupts, but only by 
polling the status bits

Das hast du wohl auch probiert aber die EP Nummer nicht auf 0 gestellt.

von Marvin K. (m_marvin)


Lesenswert?

Oh, das habe ich in dem Beispielcode tatsächlich vergessen, aber ich hab 
es gerade ergänzt, und wie in den Vorherigen versuchen auch, keine 
änderung:
1
while (1)
2
{
3
  UENUM = 0;
4
  if (UEINT & (1 << RXSTPI)) PORTD |= (1 << LED_2);
5
}
Das entsprechende Bit wird einfach nie gesetzt.

von Thomas Z. (usbman)


Lesenswert?

Ich muss ehrlicher weise zugeben dass ich kein ATMega Profi bin. Der 
Initialisierungsteil sieht aber für mich ok aus, auch wenn die magic 
numbers nicht so mein Ding sind.

Dann bleibt natürlich noch D+ und D- vertauscht als Fehler Quelle oder 
eine fUSB != 48Mhz. Wobei ich sagen würde die PLL passt für 8 MHz und 
ext. Quarz

Edit: Muss da nicht irgendwo der Usb Speicherblock eingestellt werden. 
So kenne ich das jedenfalls von anderen Chips.

: Bearbeitet durch User
von Marvin K. (m_marvin)


Lesenswert?

Also, egal was ich bisher gemacht habe, ich habe noch keinen einzigen 
Endpoint Interrupt zum auslösen gebracht (sowohl USB_COM_vect, als auch 
die Bits im Register).

Und was meinst du mit Speicherblock ?
Ich kenne nur die Einstellung ob es eine "one Bank" oder eine "double 
Bank" ist, da ich bisher nicht wirklich rausfinden konnte, was damit 
überhaupt gemeint ist, hab ich es wie in allen Beispielen die ich bisher 
gefunden hab auch, bei "one Bank" belassen.

: Bearbeitet durch User
von Thomas Z. (usbman)


Lesenswert?

nochwas 16 Byte EP0  Fifo ist nicht so üblich ich mach immer 8 Bytes.
Es fehlt m.M. noch ein EpFifo Reset
UERST= 1; EP0 Fifo
UERST= 0;

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Thomas Z. schrieb:
> nochwas 16 Byte EP0  Fifo ist nicht so üblich ich mach immer 8 Bytes.

Sicher?

Ich habe hier nur Code für die größeren USB-AVRs, aber da habe ich 16 
Byte für den Interrupt-EP (der bei CDC zwingend vorhanden sein muss, 
auch wenn er nichts macht) und 64 Byte für alle anderen EPs.

Auf Anhieb sehe ich jetzt auch nichts. Ich gehe mal davon aus, dass die 
PLL einrastet, weil ansonsten auch die erste LED wohl nicht angehen 
sollte.

von Thomas Z. (usbman)


Lesenswert?

Jörg W. schrieb:
> Sicher?

ja ganz sicher BULK EPs sind immer 64Byte das ist sogar in der Spec für 
fullspeed vorgeschrieben. Control mach ich immer 8 Bytes, den unnützen 
Interrupt EP bei CDC auch. Das vor allem weil bei den meisten Chips nur 
begrenzt Fifo Ram vorhanden ist.

Das macht zwar den GetDescriptor Request etwas langsamer weil ev. 
mehrere DataStages notwendig sind aber damit kann ich leben. Oft werden 
64Bytes für den Control Ep nur dehalb verwendet, weil die FW nicht mit 
mehren DataStages korrekt umgehen kann.

@Marvin
OneBank / TwoBank heist bei anderen Chips double buffer.
Zum Speicher siehe 19.6 Memory management.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Thomas Z. schrieb:
> Oft werden 64Bytes für den Control Ep nur dehalb verwendet, weil die FW
> nicht mit mehren DataStages korrekt umgehen kann.

Nö, das funktioniert bei mir schon, irgendeine der SETUP-Geschichten 
passt auch in 64 Byte nicht mehr direkt rein.

Andererseits haben die großen USB-AVRs deutlich mehr FIFO. Die kleinen 
haben nur 176 Bytes, wenn man 2 x 64 für die Daten-Endpunkte abzieht, 
bleiben nur noch 48 für den Rest. 8 verplempert man für den 
Interrupt-EP, damit kann der Control-EP aber trotzdem noch 16 oder 32 
Byte groß sein.

Double buffering fällt bei dem bissel FIFO sowieso aus.

von Marvin K. (m_marvin)


Lesenswert?

Also, mein Code sieht jetzt so aus:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
5
#define LED_1 PD4
6
#define LED_2 PD5
7
8
ISR(USB_GEN_vect, ISR_BLOCK)
9
{
10
  uint8_t uint = UDINT;
11
  UDINT = 0;
12
  if (uint & (1 << EORSTI))
13
  {
14
    
15
    UERST = 31;              // Reset FIFO
16
    UERST = 0;
17
    
18
    UENUM = 0;              // EP0 Anwählen
19
    UECONX |= (1 << EPEN);        // EP0 Aktivieren
20
    UECFG0X = 0;            // Controll-EP
21
    UECFG1X = 0;            // 8 Byte, one Bank
22
    UECFG1X |= (1 << ALLOC);      // Allocate memory
23
    while (UESTA0X & (1 << CFGOK) == 0);// Warten auf "CFGOK"
24
    
25
    PORTD |= (1 << LED_1);
26
    
27
  }
28
}
29
30
int main(void)
31
{
32
  
33
  DDRD |= (1 << LED_1) | (1 << LED_2);
34
  
35
  PLLCSR = 
36
  PLLCSR |= (1 << PLLE);
37
  while ((PLLCSR & (1 << PLOCK)) == 0);
38
  USBCON |= (1 << USBE);
39
  USBCON &= ~(1 << FRZCLK);
40
  UDCON &= ~(1 << DETACH);
41
  
42
  sei();
43
  UDIEN |= (1 << EORSTE);
44
  UEIENX |= (1 << RXSTPE);
45
  
46
  while (1)
47
  {
48
    UENUM = 0;
49
    if (UEINT & (1 << RXSTPI)) PORTD |= (1 << LED_2);
50
  }
51
  
52
}
Aber es hat sich nichts geändert, ich hab auch schon alle möglichen EP0 
FIFO Größen ausprobiert, und auch schon diverse andere Einstellungen 
variiert, es bleibt dabei das weder ein Interrupt noch das RXSTPI Bit 
gesetzt wird, ich auch schon D+/D- getauscht um diesen Fehler 
auszuschließen.

: Bearbeitet durch User
von Marvin K. (m_marvin)


Angehängte Dateien:

Lesenswert?

Ich habe übrigens auch mit dem Windows Tool USBView mal versucht ein par 
Infos zu erhalten, es sagt allerdings nur FailedEnumeration und ERROR No 
open Pipses, kann das mit dem Endpunkt zusammenhängen, oder liegt das 
nur an dem Fehlenden SETUP Package ?

USBView Ausgabe als Bild im Angang.
Die Ausgabe ist immer identisch, egal ob ich die Requests implementiere 
oder nicht, oder welchen Code ich verwende.

: Bearbeitet durch User
von Thomas Z. (usbman)


Lesenswert?

solange bist du noch lange nicht. USB View kann erst funktionieren wenn 
dein Device zumindest halbwegs durch die EMUM kommt.

von Marvin K. (m_marvin)


Lesenswert?

Hat eventuell jemand einen Beispielcode für den AT90USB162 der 
Funktioniert?

von Thomas Z. (usbman)


Lesenswert?


von Marvin K. (m_marvin)


Angehängte Dateien:

Lesenswert?

Nicht wirklich, ich kann kein Chinesisch (Übersetzen geht nicht, das 
sind offenbar Bilder), und die anderen Links führen alle zu "404 Seite 
nicht gefunden" ...

von Thomas Z. (usbman)


Lesenswert?


von Marvin K. (m_marvin)


Lesenswert?

Ich wollte mich eigentlich nicht mit LUFA beschäftigen, ich habe es mal 
ausprobiert, und ca 500 Fehlermeldungen über nicht vorhandene 
Definitionen und Fehlende Dateien bekommen (hab eines der Beispiel 
Projekte geöffnet).

Generell war mein Ziel eigentlich mir selber eine minimalistische 
Bibliothek für diverse USB Projekte erstellen wollte.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Marvin K. schrieb:
> Generell war mein Ziel eigentlich mir selber eine minimalistische
> Bibliothek für diverse USB Projekte erstellen wollte.

Das ist an sich auch kein schlechter Ansatz. Habe ich damals in μracoli 
auch gemacht, nachdem ich mir andere Beispiele angesehen habe und als zu 
komplex fand.

Muss heute Abend mal schauen, ob ich für die kleinen AVRs noch was 
finde.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

Schau mal, das hier habe ich noch gefunden. Das stammt von

https://www.circuitben.com/node/4

(Das entsprechende Interface hatte ich mir damals für meinen Tek492 
gebaut.)

Die Funktionen read_reg() und write_reg() gehen auf den 
Mikrocontroller-Bus des Tek492, den man auf diese Weise über USB (über 
ein vendor class device) zugreifen kann.

Das alles sollte doch klein und fein genug sein, als Basis für 
Experimente zu dienen, denke ich mal. Ich habe auch noch ein kleines 
Devboard mit einem AT90USB162 da liegen. Falls du nicht weiter kommst, 
kann ich damit auch ein wenig spielen.

von Marvin K. (m_marvin)


Lesenswert?

Ich werde das morgen mal Ausprobieren.

Ich hätte da noch ne kure Frage, die nur indirekt mit dem Problem zu tun 
hat, ich wollte gerade mal einen Schaltplan in KiCad erstellen von dem 
aktuellen Aufbau mit dem AT90USB, allerdings hab ich eine verbuggte 
globale Bibliothek die das Importieren meiner ganzen Bauteile (Darunter 
der AT90) verhindert, weis einer wie man Bibliotheken in KiCad löscht 
(finde dazu nichts im Internet) ?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Erstens kannst du sie natürlich über Preferences -> Manage Symbol 
Libraries warten. Zweitens kannst du auch ganz brutal mit dem File 
Manager die entsprechende Datei aus dem Weg räumen. Das gibt dann 'ne 
Warnung, aber danach geht es weiter.

von Marvin K. (m_marvin)


Angehängte Dateien:

Lesenswert?

Danke, ich hab es dauernd über diesen Bibliothekseditor versucht, aber 
der dient wohl nur zum Anzeigen der Bibliotheken, und die Datei löschen 
geht nicht, da ich keine Datei habe, das ist das Problem mit der 
Bibliothek, die lag auf einer Festplatte die nicht mehr Existiert.
Ich konnte sie aber über die Einstellungen löschen.

Ich habe eben mal den Code (usb_429) auf den AT90 geladen, hat ohne 
Probleme geklappt. Ich hab es einfach mal am PC eingesteckt, es wurde 
wieder nicht erkannt, mir ist schon klar das ich wahrscheinlich ein par 
Anpassungen vornehmen muss, ich wollte nur mal testen ob was passiert. 
Und eine Sache hat sich verändert, ich weis aber nicht ob das was zu 
bedeuten hat:

USBView zeigt jetzt etwas mehr Infos an, es sagt jetzt
"Companion Port Number: 10"
und
"Companion Hub Symbolic Link Name: USB#ROOT_HUB..."

Bei meinen vorherigen Versuchen waren diese Felder immer 0 oder gar 
nicht Vorhanden.

: Bearbeitet durch User
von Thomas Z. (usbman)


Lesenswert?

Marvin K. schrieb:
> USBView zeigt jetzt etwas mehr Infos an, es sagt jetzt
> "Companion Port Number: 10"
> und
> "Companion Hub Symbolic Link Name: USB#ROOT_HUB..."

das ist weil u nun einen anderen Port benutzt und hat nichts zu sagen.
Ich gehe dvon aus das der Code von Jörg auch ohne Änderungen läuft.

Du hast ein HW Problem (kaputtes Kabel, falsche Verbindung, D+, D- 
vertauscht)

von Marvin K. (m_marvin)


Lesenswert?

Ich glaube auch das es irgend was mit der Hardware zu tun hat, da ich 
noch weiter AT90USB habe, werde ich später mal einen anderen testen, ich 
bezweifle nämlich das einer der Der Wiederstände oder Kondensatoren 
einen Fehler hat (habe ja mit dem Multimeter mal alle Spannungen und mit 
dem Oszilloskop D+ und D- gemessen).

Ansonsten zeigt der Code auch nach dem ich alle Vendor Requests und I/O 
Pins deaktiviert habe (so das nur noch der SETUP und Request Teil 
läuft), exakt das selbe verhalten, bis zum USB_GEN_vect EORSTI läuft 
alles, aber das RXTSPI Bit wird nicht gesetzt.

Mir ist auch aufgefallen das der Setup Teil hier über das USB_COM_vect 
Interrupt gehandelt wird, ich dachte das sollte sp nicht sein.

Ich zeichne jetzt wo ich meine KiCad Bibliothek laden konnte mal kurz 
einen Schaltplan von meinem Aufbau, eventuell liegt da ja ein Fehler den 
ich nicht finde.

von Marvin K. (m_marvin)


Angehängte Dateien:

Lesenswert?

Ich hab meinen Versuchsaufbau mal als Schaltplan gezeichnet, alles ist 
auf einem Steckbrett aufgebaut, und mit Jumper-Kabeln verbunden.
Ich konnte durch Messungen bisher keine Elektrischen Fehler feststellen, 
aber
2 Besonderheiten sind zu beachten:

1. Ich hatte keinen 22 Ohm Wiederstand für die D+/D- Leitungen, und habe 
daher 2 11 Ohm Wiederständer genommen, sollte aber eingendlich kein 
Problem sein, oder ?
Beide Leitungen haben jetzt einen Wiederstand von 20 Ohm (Habe durch 
Messungen mit einem Multimeter versucht, zumindest gleiche Werte durch 
Variieren der Wiederstände zu bekommen, auf 22 Ohm hab ich es nicht 
bekommen).

2. Der AT90USB162 ist nicht in einem DIL/DIP Gehäuse erhältlich, ich 
habe eine Adapterplatte gefräst und ihn aufgelötet.
Ich habe alles durchgemessen und die Kontakte sind soweit ich das sagen 
kann alle in Ordnung, nur ein I/O Pin hatte ein Problem (Beschädigte 
Lötstelle), aber den benutze ich in der Schaltung nicht.

Ein Annotationsfehler hat die Wiederstandswerte überschrieben, ich 
musste den Schaltplan neu hochladen, allerdings hab ich nicht 
rausgefunden wie ich den Fehlerhaften lösche.

: Bearbeitet durch User
von Thomas Z. (usbman)


Lesenswert?

Die Widerstände sind nicht besonders kritisch. Kritischer würde ich 
sehen dass nicht alle Gnds und Vcc angeschlossen sind. Aber das müssen 
Leute kommentieren die sich besser mit AVR auskennen.

von Stephan (Gast)


Lesenswert?

UGND ist sicher nur im Schaltplan nicht angeschlossen?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Thomas Z. schrieb:
> Kritischer würde ich sehen dass nicht alle Gnds und Vcc angeschlossen
> sind.

Sie müssen alle angeschlossen und alle abgeblockt sein – am besten 
gleich auf der Adapterplatine. Kleine SMD-Cs lassen sich direkt zwischen 
die Pins löten.

Mir ist auch gerade nicht klar, ob das nun "bus-powered" oder 
"self-powered" sein soll. Die entsprechenden grundsätzlichen 
Applikationsschaltungen finden sich im Datenblatt, mit Varianten für 
unterschiedliche Versorgungsspannungen.

Leider gibt's für das "Minimus AVR USB"-Board, welches ich habe, keine 
Schaltpläne und auch nur noch eine historische Version der Webseite:

https://web.archive.org/web/20140105020019/http://www.minimususb.com/

von Marvin K. (m_marvin)


Lesenswert?

Ich ich habe alle VCC und GND abgesehen von den für die Analog Sachen 
angeschlossen, ich habe gerade bemerkt das da noch ein Fehler im 
Schaltplan ist (UGND nicht angeschlossen).

Ich habe gerade mal die Adapterplatte mit dem AT90USB vom Steckbrett 
entfernt, und alle Löstellen neu angelötet, ich habe vorher und nachher 
die Wiederstände gemessen, und keine wirkliche Änderung festgestellt.
Alle bei ~0 Ohm (ein Standard Multimeter ist halt auch nicht so genau, 
denke ich mal)

Ich habe den Chip wieder eingebaut, und nochmal mit dem PC verbunden, 
dieses mal wurde er erkannt, beide LEDs leuchten und USBView zeigt die 
Descriptoren an.

Ich weis nicht was das Problem war und was es behoben hat, aber ich 
vermute mal ein Wackelkontakt bei einem der Pins, der durch die 
Messspitze des Multimeters immer zusammengedrückt wurde, und daher bei 
der Messung immer als OK durch ging.

Ich werde jetzt nochmal meinen original Code drauf spielen, mit eigenen 
Descriptoren und Requesthandler.

: Bearbeitet durch User
von Marvin K. (m_marvin)


Lesenswert?

Interesant, laut USBView hängt mein Code nach dem ersten Descriptor.
Es wartet auf den nächsten und zeigt "Enumerating" an, ich hätte nicht 
gedacht das Windows so eine Geduld hat und jetzt bestimmt schon 20 
Sekunden wartet, bis es einen Fehler anzeigt.

Auf jeden fall funktioniert jetzt die Hardware, ich werde mich dann mal 
weiter mit dem Code beschäftigen, und diesen Fehler beheben.

Mein Code läuft jetzt übrigens wie auch das Beispiel "usb_429" (ich weis 
leider nicht den richtigen Name des Projektes) komplett über Interrupts, 
also auch die Setup Requests, auch wenn es laut USB Spezifikation nicht 
gewollt ist, scheint es problemlos zu funktionieren.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Marvin K. schrieb:
> Ich ich habe alle VCC und GND abgesehen von den für die Analog Sachen

Auch AVcc muss angeschlossen sein. Dient bei diesem AVR insbesondere 
auch der Spannungsversorgung der PLL.

von Marvin K. (m_marvin)


Lesenswert?

Also, die Hardware funktioniert jetzt, aber beider Software macht jetzt 
nichts sinn.
Der Beispielcode funktioniert, aber selbst wenn ich nur ein par 
konstanten verschiebe, nicht ändere nur z.B. ganz oben im Code sammle, 
funktioniert es nicht mehr (es kompiliert und lässt sich aufspielen, 
aber der AT90 wird dann nicht mehr erkannt).
Es wäre mir neu das das ändern der reinfolge der Konstanten eine 
änderung ihres wertes zur folge hat (ich rede von einfach Konstanten wie
1
#define INTF_SIZE 9
).

Ich werde morgen nochmal von Grund auf neu anfangen, und versuchen zu 
verstehen was da vor sich geht.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Nur mal so: Compiler-Optimierung hast du eingeschaltet, ja?

von Marvin K. (m_marvin)


Lesenswert?

Diese Einstellung kenne ich nicht, wo finde ich das den, und was bewirkt 
es ?

Ich hab den Code jetzt so weit, das ich die Requests empfange und 
auslesen kann (auch schon getestet, Daten werden richtig übertragen, ich 
empfange einen GET_DESCRIPTOR request).

Aber wenn ich dann antworte, und den DeviceDescriptor übergebe, bekommt 
ich nur immer wieder einen USB Reset vom host, das widerholt sich ca 4-5 
mal, dann bricht er ab und es kommt wieder "USB Gerät nicht erkannt".

USBView zeigt wieder überall 0 an, wobei ich nicht weis ob es überhaupt 
was anderes anzeigen würde bevor nicht ALLES korrekt übertragen wurde.

Was kann da die Ursache sein ?
Die Daten werden vom AT90 aus korrekt gesendet, ich hab es schon 
getestet, hier ist mein Code der das senden der Descriptoren übernimmt:
1
void writeUSB(const void* buffer, uint16_t length, uint8_t epsize)
2
{
3
  uint8_t sentBytes = 0;
4
  while (length--)
5
  {
6
7
    UEDATX = pgm_read_byte(buffer++);
8
    sentBytes++;
9
    
10
    if (sentBytes == epsize || length == 0)
11
    {
12
      sentBytes = 0;
13
      clr(UEINTX, TXINI);                
14
      while (!(UEINTX & ((1 << TXINI) | (1 << RXOUTI))));  
15
      if (UEINTX & RXOUTI) return;
16
    }
17
  }
18
  
19
  wfb(UEINTX, RXOUTI);
20
  clr(UEINTX, RXOUTI);
21
}

set und clr setzen bzw. löschen nur Bits in Registern.
wfb ist lediglich eine Funktion die so lange eine schleife ausführt, bis 
ein Bit gesetzt wurde.

von Marvin K. (m_marvin)


Lesenswert?

Die Abfolge ist:

USB Reset
- Get Descriptor (Device)
USB Reset
- Get Descriptor (Device)
USB Reset
- Get Descriptor (Device)
USB Reset
- Get Descriptor (Device)
Abbruch -> Gerät nicht erkannt

Immer 4 mal (gerade durch einen Zähler ca. 10 mal geprüft)

von c-hater (Gast)


Lesenswert?

Marvin K. schrieb:
> Die Abfolge ist:
>
> USB Reset
> - Get Descriptor (Device)
> USB Reset
> - Get Descriptor (Device)
> USB Reset
> - Get Descriptor (Device)
> USB Reset
> - Get Descriptor (Device)
> Abbruch -> Gerät nicht erkannt
>
> Immer 4 mal (gerade durch einen Zähler ca. 10 mal geprüft)

D.h. einfach: Das Device ist nicht in der Lage, seinen Discriptor 
verständlich rauszuballern. Windows versucht das vier mal, dann gibt es 
auf, weil nur Bullshit (oder garnix) als Ergebnis des Requests kam.

Mit Linux als Host würde das Spiel genau so laufen, bloß die Zahl der 
Wiederholungen wäre möglicherweise anders.

Was soll ein OS auch anderes tun, wenn das Device so blöd ist, dass es 
nicht mal die grundlegendsten Requests korrekt beantworten kann?

von Marvin K. (m_marvin)


Lesenswert?

Ja, ich weis wie das OS da reagiert, meine Frage ist ja ob jemand 
erkennt warum das so ist, ich hab den Code ja eingefügt.
Ich habe zum Test mal Stadt in den UEDATX in PORTD geschrieben, und ein 
delay eingefügt, und mir 8 LEDs angeschaut die an PORTD hängen.
Sie stimmten überein mit dem Descriptor den ich geschrieben hab, und der 
wiederum stimmt mit den USB Normen überein, also, wo ist hier das 
Problem ?

Hab ich vergessen wärend des Sendens irgend ein Bit zu setzen oder so ?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Marvin K. schrieb:
> Diese Einstellung kenne ich nicht, wo finde ich das den, und was bewirkt
> es ?

Dass der Code in vernünftiger Geschwindigkeit abgearbeitet wird und 
nicht in Zeitlupe.

> Was kann da die Ursache sein ?

Eben beispielsweise Timing-Probleme.

> Die Daten werden vom AT90 aus korrekt gesendet, ich hab es schon
> getestet

Womit hast du das denn getestet?

Wenn du mir einen compilierbaren Code gibst (also nicht nur Schnipsel), 
kann ich das hier auf meinem Demoboard mal nachvollziehen.

von Marvin K. (m_marvin)


Lesenswert?

Ich hab den Fehler gerade gefunden, er war sowas von dämlich -.-
Ich hab im "typedef struct" Bereich vom Descriptor an einer stelle stadt 
uint16_t uint8_t genutzt, weshalb der Descriptor 1 Byte zu kurz war, und 
abgelehnt wurde, ich hab es korrigiert jezt wurde er erkannt und wird in 
USB View angezeigt.

von Marvin K. (m_marvin)


Lesenswert?

Ich hab mich wahrscheinlich vertippt als ich den Aufbau aus der USB 
Spezifikation abgetippt hab und so ein Fehler fällt halt kaum auf 
zwischen den ganzen uint8_t und uint16_t ...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Na, das ist doch mal was.

Den Knopf für die Compileroptimierung solltest du trotzdem noch finden. 
Auf der Kommandozeile wäre das die Option -O1 oder -Os, aber vermutlich 
wirst du wohl irgendeine IDE benutzen, die den Compiler für dich 
aufruft.

von Marvin K. (m_marvin)


Lesenswert?

Ich nutze Atmel Studio 7 bzw. Microchop Studio 7

von Marvin K. (m_marvin)


Lesenswert?

Endlich, es kommt keine "USB Gerät nicht erkannt Meldung", das ist das 
erste mal das einer meiner Codes funktioniert. xD
Jetzt muss ich nur noch die ganzen Descriptoren und Requests 
implementieren die noch Fehlen, vieles in USB View ist deshalb noch mit 
"ERROR" markiert.

von Marvin K. (m_marvin)


Lesenswert?

Ich werde gleich noch nach dieser Compiler Option suchen, ich denke mein 
Problem mit den Interrupts und dem AT90 ist jetzt gelöst.

Aber weis eigentlich jemand was es mit dieser vendorId auf sich hat?
Ich habe gelesen das die von USB Org vergeben wird, was sollte man den 
da nehmen wenn man kein "offizieller Hersteller" ist ?

von c-hater (Gast)


Lesenswert?

Marvin K. schrieb:
> Ich nutze Atmel Studio 7 bzw. Microchop Studio 7

Da stellt man das in den Projektoptionen unter dem Unterpunkt Toolchain 
ein. Vorsicht: es gibt zwei Stellen für Optimierungsoptionen, Compiler 
und Linker. Im konkreten Fall dürften allerdings nur die 
Compilereinstellungen relevant sein. Wenn überhaupt...

Denn: auf die Interrupt-Performance hat das eher wenig Einfluß. Die ist 
ohne Optimierung ganz grausam und mit -02 immer noch sehr armselig.

Asm rules!

von Marvin K. (m_marvin)


Lesenswert?

Hm, wenn ich das einschalte (option -O2) wird mein AT90 nicht mehr 
erkannt und es kommt wieder nur schrott an (Device Descriptor wird 
abgelehnt).

Betrifft diese Option in irgend einer Form daten die im Programmspeicher 
abgelegt sind ?
Ich habe den Descriptor  mit __attribute__((packed)) im PROGMEM 
abgelegt.

von c-hater (Gast)


Lesenswert?

Marvin K. schrieb:

> Aber weis eigentlich jemand was es mit dieser vendorId auf sich hat?
> Ich habe gelesen das die von USB Org vergeben wird, was sollte man den
> da nehmen wenn man kein "offizieller Hersteller" ist ?

Solange du das Ergebnis nur für dich selber benutzt, spielt das keine 
Geige.

Wenn du es aber in irgendeiner Form anderen zugänglich machen willst, 
musst du in den sauren Apfel beissen und die Kohle an die Wegelagerer 
abdrücken. Da führt praktisch kein Weg dran vorbei.

Für die rein private Nutzung kann man "abandoned" VendorIDs verwenden. 
Da ist man ziemlich sicher, dass einem irgendein Treiber eines "legalen" 
Gerätes irgendwann unerwartet dazwischen pfuscht.

von Marvin K. (m_marvin)


Lesenswert?

Interesant, mit "optimize most (-O3)" geht es wieder.
Was sollte ich den nehmen?
Ich meine, bisher hat es auch mit der Standartoption "Optimize debugging 
experience (-Og)" funktioniert.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Marvin K. schrieb:
> Aber weis eigentlich jemand was es mit dieser vendorId auf sich hat?
> Ich habe gelesen das die von USB Org vergeben wird, was sollte man den
> da nehmen wenn man kein "offizieller Hersteller" ist ?

Da musst du dir was aus den Fingern saugen. Vielleicht einen Hersteller 
wählen, der inzwischen zurückgezogen hat.

Für die Vendor ID lediglich 16 Bits vorzusehen, ist eins der größten 
Gurken, die sich USB geleistet hat – zumal zu der Zeit, als sie das 
verbrochen haben, das Problem zur Neige gehender IPv4-Adressen schon 
längst auf dem Tisch lag. Es hätten wohl drei Finger genügt um 
abzuzählen, dass 65000 Hersteller weltweit ganz schnell erreicht sein 
werden.

Anfangs konnte man eine Vendor-ID noch für ein überschaubares Sümmchen 
"Verwaltungsgebühr" einkaufen, sollen am Anfang wohl USD 500 gewesen 
sein, lange Zeit waren es USD 1000. Wurde dann immer teurer.

Um das Übel für Kleinanwender/-hersteller (die im USB-IF halt keine 
Fürsprecher groß haben) noch zu verschlimmern: zu Zeiten, da der Preis 
noch moderat war, gab es ein paar Leutchen, die sich eine Vendor-ID 
erkauft haben und dann ein Mini-Geschäft damit aufgebaut haben, von 
dieser Vendor-ID Product-ID-Bereiche für kleines Geld weiter zu 
verkaufen. Denen hat das USB-IF unter Androhung juristischer 
Konsequenzen ihr Tun untersagt. (Ob sie diese Konsequenzen bspw. in 
Europa juristisch überhaupt hätten durch bekommen, angesichts dessen, 
dass sie ja die ID offiziell nicht verkaufen sondern "nur" eine 
"Verwaltungsgebühr" erheben, ist fraglich. Aber eine derart kleine Firma 
lässt es da halt nicht drauf ankommen.)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Marvin K. schrieb:
> Interesant, mit "optimize most (-O3)" geht es wieder.

Muss eigentlich mit jeglicher Optimierung zum Laufen zu bekommen sein, 
nur -O0 (Optimierung ausgeschaltet) ist fragwürdig.

Ich denke, du hast da noch irgendeine andere Sache drin.

Marvin K. schrieb:
> Ich habe den Descriptor  mit attribute((packed)) im PROGMEM abgelegt.

Das Attribut kannst du dir bei einem AVR klemmen. Das ist ein 
8-Bit-Prozessor, der hat keine Anforderungen an das Alignment, sodass 
alle structs immer "packed" sind.

von c-hater (Gast)


Lesenswert?

Marvin K. schrieb:

> Hm, wenn ich das einschalte (option -O2) wird mein AT90 nicht mehr
> erkannt und es kommt wieder nur schrott an (Device Descriptor wird
> abgelehnt).

Dann hast du einen "Bug" im Code. Irgendwelchen Kram, der nach der 
Reinen Lehre verzichtbar ist und deswegen rausoptimiert wird.

Typisch wären irgendwelche handgestrickten Warteschleifen oder etwas in 
der Art. Aber auch UB sorgt immer mal wieder für nette Überraschungen.

Auch wieder: Asm rules. Damit kann man bessere Performance erzielen und 
muss sich nicht mit mehr oder weniger überraschenden 
Optimierungsergebnissen eines abgehobenen Compilers rumschlagen. Wenn da 
was optimiert wird, dann macht man das selber. An den Stellen, wo 
tatsächlich optimiert werden muss und nur dort.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

c-hater schrieb:
> Auch wieder: Asm rules.

Ja klar.

Dann wäre er allerdings wahrscheinlich jetzt noch bei der Vorrede statt 
schon irgendwas zu haben, was am USB mitredet. ;-)

> Irgendwelchen Kram, der nach der Reinen Lehre verzichtbar ist und
> deswegen rausoptimiert wird.

Sowas simples wie ein vergessenes "volatile" wird es nicht sein. Er 
hatte ja zuvor -Og, nicht -O0.

Mutmaßen kann man viel. Wenn ich compilierbaren Code bekomme, schau ich 
mir das mal an (wenn's sein muss, finde ich auch einen Zugang zu einem 
USB-Analyzer). Atmel-Studio-Dateien brauch' ich nicht, benutze ich 
sowieso nicht. Ein Makefile wäre schön, wenngleich das vom Studio 
generierte erfahrungsgemäß grauenvoll ist.

von Marvin K. (m_marvin)


Lesenswert?

Ich mache den Code erstmal soweit fertig das meine ganzen USB Sachen 
funktionieren, mit -Og funktioniert es ja, wenn das klapt, lade ich den 
Code mal hoch, es kann gut sein das gerade noch unnötiger Kram drin ist, 
weil ich an diversen Stellen Debug-Warteschleifen oder ähnliches drin 
hab.

z.B. wenn die Adresse gesetzt wurde, zeigt es das mit einer LED an und 
wartet eine halbe Sekunde.

Solche Sachen entferne ich jetzt halt nach und nach wenn ich weis das 
alles funktioniert.

von Marvin K. (m_marvin)


Lesenswert?

Hä, ich habe gerade mal alle Descriptornafragen abgefangen die nicht 
behandelt wurden, weil kein entsprechender Descriptor implementiert ist, 
Windows fragt nach dem Descriptor mit der ID 0x06, es gibt aber keinen 
Descriptor mit 0x06 als ID oder ?

Ich hab jetzt
DEVICE 0x01
CONFIG 0x02
STRING 0x03
INTERFACE 0x04
ENDPOINT 0x05
(Hab die Zahlen gerade aus dem Gedächtnis aufgeschrieben, kann sein das 
was vertauscht ist)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Marvin K. schrieb:
> z.B. wenn die Adresse gesetzt wurde, zeigt es das mit einer LED an und
> wartet eine halbe Sekunde.

Wenn du in der Zeit wirklich wartest, kann das für USB schnell tödlich 
sein.

Der Host bekommt ganz schnell mal "kalte Füße", wenn da am anderen Ende 
keiner mehr reagiert. Zwar deckt der USB-Makro im Controller schon 
manches der zeitkritischen Dinge ab (indem er bspw. ein NAK sendet, wenn 
er noch keine neuen Infos von der Software hat), aber ganz allgemein 
gilt, dass man bei einer USB-Firmware "zeitnah" reagieren können sollte.

Aus dem Grunde ist es auch unpraktikabel, bei so einer Firmware groß mit 
dem Debugger ranzugehen: sowie du einen Breakpoint erreicht hast, 
schreibt der USB-Host das Device dann ab, weil es nicht mehr reagiert.

von Marvin K. (m_marvin)


Lesenswert?

Wie eben gesagt: Ich entferne die sachen jetzt nach und nach wenn ich 
weis das alles funktioniert.
Das mit dem warten wenn die Adresse gesetzt wurde, war ja z.B. nur weil 
ich bisher nichts weiter implementiert hatte, jetzt wo ich weitere 
Sachen danach einbaue, kommt das natürlich weg.

Was ich aber festgestellt hab, was mich sehr verwundert hat:
Als ich eine Warte zeit beim senden der Daten hatte, um sie mir am PORTD 
ausgeben zu lassen, hat es Windows nicht gestört als ich zwischen den 
Bytes teilweise bis zu 500ms Wartezeit hatte, ich hätte da mit einem 
Abbruch gerechnet.
Scheinbar verkraftet Windows so große Wartezeiten manchmal sogar.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite



Lesenswert?

Marvin K. schrieb:
> Hä, ich habe gerade mal alle Descriptornafragen abgefangen die nicht
> behandelt wurden, weil kein entsprechender Descriptor implementiert ist,
> Windows fragt nach dem Descriptor mit der ID 0x06, es gibt aber keinen
> Descriptor mit 0x06 als ID oder ?

Auszug aus dem USB-2.0-Standard.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Wichtig ist, wenn du Dinge nicht implementierst (wie diesen device 
qualifier), dass du sie dann sauber ablehnst. Einfach nur "nichts tun" 
ist tödlich.

Passage aus meinem µracoli-Code dafür:
1
            if (!process_setup_message())
2
            {
3
                /*
4
                 * SETUP request not understood: STALL the current
5
                 * setup message, either during the data or status
6
                 * phase.  Automatically gets cleared when receiving
7
                 * the next SETUP packet.
8
                 */
9
                UECONX |= _BV(STALLRQ);
10
                UEINTX &= ~_BV(RXSTPI);
11
            }

process_setup_message() gibt false zurück, wenn sie keine Idee hatte, 
was die SETUP-Nachricht denn wollte. Eine Anfrage nach dem device 
qualifier descriptor würde bspw. dahin führen.

: Bearbeitet durch Moderator
von Marvin K. (m_marvin)


Angehängte Dateien:

Lesenswert?

Das hab ich eingebaut, wenn ein Request nicht zugeordnet werden konnte, 
wird ein STALL zurückgegeben.

Ich habe alle Infos zu Descriptoren von einer anderen Webseite, wo es 
nur etwas vereinfachter erklärt wird, ich denke die haben das da einfach 
weggelassen, weil man es nicht unbedingt braucht.

Mein Code funktioniert jetzt zumindest soweit das ich alle wichtigen 
Deskriptoren übertragen kann, morgen mache ich noch die 
Endpunk-Deskriptoren und generell nicht-controll Endpunkte für 
spezifische Funktionen.

: Bearbeitet durch User
von Thomas Z. (usbman)


Lesenswert?

Da fehlt noch das Handling für SetConfiguration bzw GetConfiguration. 
USBView zeigt als ConfigValue 0 obwohl im Descriptor 1 steht. Ansonsten 
passt das, da du ja noch keine Pipes hast. Das Device kann dann halt nur 
auf Control Requests reagieren.
Wegen der IDs würde ich mir keinen Kopf machen. Falls das ein CDC wird, 
spielen die sowieso keine wesentliche Rolle. Ich nehme da immer 0xDEAD 
0xBEEF. :-)

von Thomas Z. (usbman)


Lesenswert?

Jörg W. schrieb:
> sollen am Anfang wohl USD 500 gewesen sein
200 USD Gebühr um etwa 1998. Danach zuerst 600 USD und eine ganze Zeit 
1000 USD.

von Marvin K. (m_marvin)


Angehängte Dateien:

Lesenswert?

Ich habe jetzt den ganzen Code in eine eigene .cpp datei verschoben, 
eine Include Datei erstellt und alles aufgeräumt, soweit funktioniert 
jetzt auch alles, nur 2 Probleme sind eben noch aufgetreten, die mir 
beide nicht viel sagen:

Das erste kommt nur sehr selten vor, wenn ich das Gerät z.B. 50 mal 
einstecke und wieder raus ziehe aus dem USB Anschluss de PCs, kommt in 
ca 1 der 50 Fälle wieder "Gerät nicht erkannt".
Ich habe wieder ein par Debug-LEDs eingebaut, und es scheint in einem 
von 50 Fällen nach dem senden des Device Deskriptors keine Antwort mehr 
zu bekommen, es hängt in der Warteschleife für das RXOUTI Bit nach dem 
senden fest, und bekommt keine Antwort vom Host.
Ich habe ein Timeout eingebaut, das es nur ca 2 Sekunden wartet, und 
wenn dann nichts kommt es den Vorgang abbricht, aber das ist denke ich 
nur eine vorübergehende Lösung.
Ich habe jetzt auch Compiler Optimierung an, nachdem ich alle Debug 
Sachen von vorher entfernt hab läuft das einwandfrei.
Kann es sein das das wirklich am host liegt, oder ist es warscheinlicher 
das in meinem Code ein Fehler vorliegt?
Ich mein, in ~ 90% der fälle funktioniert es ja, ich kann mir irgendwie 
nicht vorstellen das da ein "Fehler mit Zufallschance" drin ist.

Das 2. Problem tritt immer auf, USBView zeigt nämlich meine String 
Deskriptoren nicht am, es sagt immer "String Descriptor for index 1 not 
available while device is in low power state.".
Was genau bedeutet das?
Ich habe rausgefunden das das kommt wenn das Gerät länger nicht aktiv 
war, und daher in den Suppend-Mode gegangen ist, aber wärend der 
Konfiguration und Enumeration ist doch eigentlich dauerhaft Aktivität 
auf dem Bus oder ?

: Bearbeitet durch User
von Marvin K. (m_marvin)


Lesenswert?

Ich sollte noch dazu sagen, jetzt wo das Timeout in der Warteschleife 
ist, wird es immer erkannt, aber es dauert halt in einem von 50 Fällen 
ungefähr 4 Sekunden bis es erkannt wurde, weil halt ein 2. versuch vom 
Host gestartet wird.

von Thomas Z. (usbman)


Lesenswert?

Set bez GetConfiguration nicht oder nicht richtig implementiert wie 
schon geschrieben.

UsbSpec: ein nicht configuriertes Gerät geht in den Powerdown mode.

von Marvin K. (m_marvin)


Lesenswert?

Ich habe Set und Get Configuration eigentlich implementiert, ich hab 
garnicht bemerkt das da immer noch 0 steht, ich habe es eben mal wieder 
abgefangen und es wird gar kein SET_CONFIGURATION Request gesendet.

Ich empfange:
- USB Reset
- SET ADRESS
- GET DESCRIPTOR (mehrfach, für Device und Configuration denke ich mal)

Und dann nichts mehr
USB View zeigt was in dem Screenshot zu sehen ist.

von Thomas Z. (usbman)


Lesenswert?

Marvin K. schrieb:
> Ich empfange:
> - USB Reset
> - SET ADRESS
> - GET DESCRIPTOR (mehrfach, für Device und Configuration denke ich mal)

für Win ist das so nicht richtig, der Reset kommt mehrfach. Wenn du 
keinen SetConfiguration bekommst ist die Enum nicht abgeschlossen. 
Windows schickt dein device in den Suspend weil es nicht mit deinen 
Antworten zufrieden ist.

Wirf die Delays raus und merke dir den usbstatus in einer Variable.
So etwa StatePowered, StateReset,StateAddressed, StateConfigured, 
StateSuspended, (0..4)
Dann kannst du in deiner Mainschleife die LEDs über den usbstatus 
anzeigen.

von Marvin K. (m_marvin)


Lesenswert?

Ich habe keine delays, und ich empfange mehrere Resets, ich habe nur den 
letzten hingeschrieben, da der erste ja ebenfalls nur ein GET_DESCRIPTOR 
ausführt.
Ich habe zuerst eine Abfrage an den Begin jedes Requests gemacht.
1
if (request.bRequest == xy) PORTD = 0xFF;
Wodurch ich verifizieren konnte das ich folgende Requests erhalte:
- GET_DESCRIPTOR
- SET_ADDRESS
Bei allen anderen blieben die LEDs Dunkel
Dann hab ich jedem Request nacheinander eine LED zugewiesen, und die LED 
gesetzt wenn ein solcher Request empfangen wurde, daher weis ich die 
Reihenfolge NACH DEM LETZTEN USB Reset:
- GET_DESCRIPTOR
- SET_ADDRESS
Aber wieder, kein SET_CONFIGURATION

von Marvin K. (m_marvin)


Lesenswert?

Da alle Descriptoren ankommen und korrekt in USBView angezeigt werden, 
und auch die Adresse korrekt gesetzt wurde, kann es ja schonmal nicht an 
den von mir gesendeten Daten liegen (die sind ja angekommen).
Und andere Requests empfange ich nicht, aber irgendwo muss ja ein Fehler 
sein.

von Thomas Z. (usbman)


Lesenswert?

Setzt du beim UsbReset deine Device Addresse auf 0 zurück?

von Marvin K. (m_marvin)


Lesenswert?

Oh, das mache ich tatsächlich nicht, hab ich vergessen, aber wie können 
dann alle Anderen Roquesits korrekt funktionieren, und dieser eine nicht 
?

von Marvin K. (m_marvin)


Lesenswert?

Hab es eingefügt, aber es bleibt immer noch bei den beiden Requests, der 
SET_CONFIG Request steht weiter aus ...

von Thomas Z. (usbman)


Lesenswert?

nun dann kommt nur GetDescriptor(config) in Frage. Dir ist klar dass der 
bei dir 2 mal kommen muss?
1. Mit wLength = 0x0009
2. Mit wLength = 0x0012

Im ersten Fall darfst du nur die ersten 9 Bytes senden.

Anders gesagt:
Du darfst niemals mehr als wLength Bytes zurück geben aber weniger falls 
ein Descriptor kürzer ist

: Bearbeitet durch User
von Marvin K. (m_marvin)


Lesenswert?

Das hab ich schon bedacht, ich prüfe es nochmal, aber eigentlich sende 
ich nur soviel wie gefordert.

von Marvin K. (m_marvin)


Lesenswert?

Ich Empfange einmal ein GET_DESCRIPTOR mit einer wLength von 64 und 
einmal mit einer wLength von 18.
Das mit der 64 kommt daher das ich einen EPSIZE von 64 hab oder ?
Sollte ich das eventuell ändern ?

von Thomas Z. (usbman)


Lesenswert?

Der erste GetDescriptor(Device) kommt immer mit wLength = 0x0040. Das 
ist eine Eigenheit von Windows. Unter Linux und MacOs wäre das 0x0008.
Strings werden übrigens immer mit 0x0100 abgefragt.

Es könnte noch sein das deine Status Stage nicht ok ist.

von Marvin K. (m_marvin)


Lesenswert?

Das müsste dann ja aber die nach dem letzten GET_DESCRIPTOR sein, das 
macht ja aber kein sinn, da die vorherigen auch alle akzeptiert werden, 
und auch korrekt in USBView angezeigt werden.
Alle GET_DESCRIPTOR anfragen nutzen den selben Code.
Gibt es eventuell ein Tool mit dem man noch mehr Infos als mit USB View 
bekommt ?
Beispielsweise weshalb die Verbindung unterbrochen wurde ?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Marvin K. schrieb:
> Gibt es eventuell ein Tool mit dem man noch mehr Infos als mit USB View
> bekommt ?

Erstens kannst du natürlich ein anderes OS nehmen und schauen, was die 
machen. Eventuell auch eins, bei dem man USB-Debugging einschalten kann 
… Ansonsten gibt's (teure) Hardware-USB-Analyzer. Dem Nutzernamen nach 
:) würde ich vermuten, dass Thomas sowas hat, ich könnte auch einen 
Zugang dazu auftreiben, denke ich. Wie schon mal beschrieben, brauche 
ich dann aber einen compilierbaren Sourcecode. Diese Geräte liefern 
ziemlich detaillierte Berichte, an welchen Stellen das Gerät sich nicht 
korrekt verhält.

von Marvin K. (m_marvin)


Lesenswert?

Ok, also aktuell habe ich keinen PC zur Verfügung um sowas zu testen 
aber ich hatte schon länger mal vor eine VM für sowas einzurichten.

Ich lade den Code gleich mal hoch.

von Marvin K. (m_marvin)


Angehängte Dateien:

Lesenswert?

Hier ist der Sourcecode und der Makefile, ich weis nicht genau ob noch 
mehr Dateien von Atmel Studio 7 benötigt werden, aber genaugenommen 
würde ja sogar der Code alleine reichen, außer der Compiler Optimierung 
hab ich nichts verändert.

Ich sollte noch dazu sagen, das ich relativ neu in C++ bin, bisher hab 
ich hauptsächlich mit Java und Visual Basic programmiert, aber da Java 
und C sich relativ ähnlich sind, konnte ich recht schnell größere 
Programme schreiben (nicht nur für AVR).

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Marvin K. schrieb:
> ich hatte schon länger mal vor eine VM für sowas einzurichten.

Wird in dieem Falle vermutlich nicht so viel helfen, denn der Host muss 
ja das USB-Gerät erstmal erkennen, bevor er in der Lage ist, es an den 
Gast weiter zu reichen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Marvin K. schrieb:
> Hier ist der Sourcecode und der Makefile

(rant)
Oh ja, ich liebe diese Studio-generierten Makefiles. Mit ihren "Device 
packs" jetzt werden die immer schlimmer, da sie nun auch noch die 
-B-Option des Compilers verbiegen müssen. Außerdem überall die Programme 
mit vollständigem Pfad und .exe am Ende, damit es auch garantiert 
unportabel wird … Außerdem ist "all" nicht das erste Target, sodass ein 
simples "make" halt dann nicht alles baut wie sonst üblich.
(end-of-rant)

Ich bekomme folgende Warnungen und Fehler, wenn ich das compiliere:
1
avr-g++ -funsigned-char -funsigned-bitfields -DDEBUG  -Og -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -g2 -Wall -mmcu=at90usb162 -c -MD -MP -MF "usbl.d" -MT"usbl.d" -MT"usbl.o"   -o "usbl.o" ".././usbl.cpp" 
2
In file included from .././usbl.cpp:13:
3
/usr/local/avr/include/util/delay.h:92:3: warning: #warning "F_CPU not defined for <util/delay.h>" [-Wcpp]
4
   92 | # warning "F_CPU not defined for <util/delay.h>"
5
      |   ^~~~~~~
6
.././usbl.cpp: In function ‘void readUSB(void*, uint16_t)’:
7
.././usbl.cpp:123:14: warning: ISO C++ forbids incrementing a pointer of type ‘void*’ [-Wpointer-arith]
8
  123 |   *(uint8_t*)buffer++ = UEDATX; // Read data in buffer
9
      |              ^~~~~~
10
In file included from .././config.h:12,
11
                 from .././usbl.cpp:12:
12
.././usbl.cpp: In function ‘void writeUSB(const void*, uint16_t, uint8_t, bool)’:
13
.././usbl.cpp:151:27: warning: ISO C++ forbids incrementing a pointer of type ‘const void*’ [-Wpointer-arith]
14
  151 |    UEDATX = pgm_read_byte(buffer++);
15
      |                           ^~~~~~
16
.././usbl.cpp:155:24: warning: ISO C++ forbids incrementing a pointer of type ‘const void*’ [-Wpointer-arith]
17
  155 |    UEDATX = *(uint8_t*)buffer++;
18
      |                        ^~~~~~
19
In file included from .././usbl.cpp:12:
20
.././config.h: In function ‘void __static_initialization_and_destruction_0(int, int)’:
21
.././config.h:64:29: error: variable ‘manufacturerString’ with dynamic initialization put into program memory area
22
   64 | const USB_String_Descriptor manufacturerString PROGMEM =
23
      |                             ^~~~~~~~~~~~~~~~~~
24
gmake: *** [Makefile:89: usbl.o] Error 1

Kann ich hier natürlich reparieren, aber ich frage mich, warum 
insbesondere letzterer Fehler bei dir nicht auftaucht. Du versuchst, in 
der Initialisierung ein strdup() einzubauen. Das geht so nicht. Das muss 
man als separaten String anlegen, auf den verwiesen wird. Denk auch 
dran, dass USB-Strings alle UTF-16 sein müssen.

Ich habe das jetzt erstmal so zusammen gehackt:
1
char manu[] = "T\0E\0S\0T\0";
2
const USB_String_Descriptor manufacturerString PROGMEM =
3
{
4
        .bLength = 2 + 4,
5
        .bDescriptorType = DESCRIPTOR_TYPE_STRING,
6
        .bString = manu,
7
};

Ultimativ wirst du die Strings aus den Descriptoren natürlich auch im 
PROGMEM haben wollen. Mir ist sowieso nicht klar, warum dein .bString 
nicht bereits const char * ist, aber das allein würde ja auch noch 
nicht helfen; die Routine, die den Descriptor liest, muss ja dann auch 
aus dem Flash lesen statt aus dem RAM.

(OK, wenn man den Descriptor dynamisch zur Laufzeit zusammen bauen 
können will, dann geht es mit const natürlich nicht.)

Außerdem erinnere ich mich, dass man noch einen String descriptor für 
die language #0 braucht, in dem dann drin steht, welche Sprachen alle 
unterstützt werden.

Auch das mit dem fehlenden F_CPU hätte dich stutzig machen sollen: du 
hast in main.cpp (aber nur dort) ein F_CPU definiert, allerdings auf 1 
MHz – fährst du die CPU denn mit 1 MHz? Fürs USB brauchst du ja einen 
8-MHz-Takt.

Warum dein buffer-Zeiger nicht gleich einer auf uint8_t ist, ist mir 
auch nicht klar.

von Marvin K. (m_marvin)


Lesenswert?

Ach, das hab ich vergessen zu entfernen, bei den String-Descriptoren hab 
ich nur rumprobiert, ich Wuste ich hab was vergessen, bevor ich es 
hochlade -.-
Ich hatte die komplet entfernt als ich die Tests gemacht hab, aber am 
ende wieder eingefügt, als ich das Projekt geschlossen hab (um halt den 
Forschritt nicht zu verlieren).
Vergiss die einfach und lösch sie raus.
Den F_CPU hatte ich für die aller ersten Tests am Anfang mal gesetzt, um 
wenigstens irgend ein Delay zu haben (hab den Code aus der main eines 
anderen Projektes kopiert), hab auch das vergessen zu löschen.

Sowas passiert halt leider wenn man alles mögliche versucht um einen 
Fehler zu finden, und dann nicht alles rauslöscht ...

Also ja: die CPU läuft mit 8 MHz.

Und der Grund weshalb die String-Sachen so schlimm sind ist, das ich 
absolut keinen Plan hatte wie die funktionieren, das war das erste mal 
das ich einen String in C gebraucht hab, und in jeder anderen 
Programmiersprache hat man ja diverse Typen wie String oder 
StringBuilder, aber in C auf einem AVR hab ich sowas noch nie benutzt.

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Naja, wie geschrieben, bei USB kommt noch dazu, dass du 16-Bit-Strings 
brauchst. Die normalen C-Strings sind halt erstmal 8 Bit pro Zeichen.

von Marvin K. (m_marvin)


Lesenswert?

Ach, das wird einer der Gründe sein warum ich so viele Probleme damit 
hatte.
Hab ich wohl vergessen, aber wie gesagt, die String Descriptoren sind 
mir erstmal egal, ich will das die Konfiguration funktioniert.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Bei mir geht im Moment leider noch gar nichts, aber auch mit der anderen 
("known good") Firmware. Scheint irgendwie an FLIP zu liegen hier, muss 
ich später mal analysieren.

von Thomas Z. (usbman)


Lesenswert?

@Marvin

Zum AVR Code kann ich wenig beitragen. Das ist nicht meine Welt.

Aber:
Beim case stringdesc fehlt das Error flag und ein break.

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

OK. Der Punkt war, dass auf meinem Demoboard ein 16-MHz-Quarz verbaut 
ist, sodass ich die PLL anpassen musste.

Was mir übrigens nicht ganz klar ist, warum du sowas schreibst:
1
  set(PLLCSR, PLLP0);
2
  clr(PLLCSR, PLLP1);
3
  clr(PLLCSR, PLLP2);
4
  set(PLLCSR, PLLE);

statt einfach das Register in einem Rutsch zu schreiben:
1
        PLLCSR = _BV(PLLP0) /* | _BV(PLLP1) | _BV(PLLP2) */ | _BV(PLLE);

(_BV macht weiter nichts als die Bitmaske zu einer Bitnummer zu 
ermitteln. Der Name ist eher historisch, war in der avr-libc halt schon 
immer so.)

Manchmal hat es sicher Sinn sicherzustellen, dass eine bestimmte 
Reihenfolge bei den Bits gewährleistet ist, aber gerade hier sieht das 
m.E. in einer Zeile übersichtlicher aus. Die auskommentierten Bits 
sollen zeigen, dass genau diese Bits halt 0 bleiben.

Nun, an meinem FreeBSD benimmt sich das Teil jetzt völlig normal. Die 
Folge der Requests ist:
1
SETUP   0       1,894
2
  00 05 03 00 00 00 00 00
3
4
IN      0       1,894
5
  
6
7
SETUP   0       1,908
8
  80 06 00 01 00 00 08 00
9
10
IN      0       2,159
11
  12 01 00 02 FF 00 00 40
12
13
OUT     0       2,159
14
  
15
16
SETUP   0       2,162
17
  80 06 00 01 00 00 12 00
18
19
IN      0       2,413
20
  12 01 00 02 FF 00 00 40 FF 00 FF 00 00 01 00 00 00 01
21
22
OUT     0       2,413
23
  
24
25
SETUP   0       2,413
26
  80 06 00 02 00 00 09 00
27
28
IN      0       2,413
29
  09 02 12 00 01 01 00 C0 32
30
31
OUT     0       2,413
32
  
33
34
SETUP   0       2,413
35
  80 06 00 02 00 00 12 00
36
37
IN      0       2,414
38
  09 02 12 00 01 01 00 C0 32 09 04 00 00 00 FF 00 00 00
39
40
OUT     0       2,414
41
  
42
43
SETUP   0       2,414
44
  80 00 00 00 00 00 02 00
45
46
IN      0       2,414
47
  01 00
48
49
OUT     0       2,414
50
  
51
52
SETUP   0       2,415
53
  00 09 01 00 00 00 00 00
54
55
IN      0       2,415

An einem Windows sieht das nicht so grundlegend anders aus, außer dass 
halt zwei Windows-spezifische Anfragen jeweils mit einem STALL 
beantwortet werden. Den einen bezeichnet mein Analyzer als "String 
Microsoft OS", das andere ist dieser device qualifier.
1
SETUP   0       0,293
2
  80 06 00 01 00 00 40 00
3
4
IN      0       0,544
5
  12 01 00 02 FF 00 00 40 FF 00 FF 00 00 01 00 00 00 01
6
7
OUT     0       0,544
8
  
9
10
SETUP   0       0,635
11
  00 05 05 00 00 00 00 00
12
13
IN      0       0,635
14
  
15
16
SETUP   0       0,647
17
  80 06 00 01 00 00 12 00
18
19
IN      0       0,897
20
  12 01 00 02 FF 00 00 40 FF 00 FF 00 00 01 00 00 00 01
21
22
OUT     0       0,898
23
  
24
25
SETUP   0       0,905
26
  80 06 00 02 00 00 FF 00
27
28
IN      0       0,905
29
  09 02 12 00 01 01 00 C0 32 09 04 00 00 00 FF 00 00 00
30
31
OUT     0       0,905
32
  
33
34
SETUP   0       0,906
35
  80 06 EE 03 00 00 12 00
36
37
IN      0       0,906
38
  
39
40
SETUP   0       0,907
41
  80 06 00 06 00 00 0A 00
42
43
IN      0       0,907
44
  
45
46
SETUP   0       1,133
47
  80 06 00 01 00 00 12 00
48
49
IN      0       1,383
50
  12 01 00 02 FF 00 00 40 FF 00 FF 00 00 01 00 00 00 01
51
52
OUT     0       1,383
53
  
54
55
SETUP   0       1,384
56
  80 06 00 02 00 00 09 00
57
58
IN      0       1,384
59
  09 02 12 00 01 01 00 C0 32
60
61
OUT     0       1,384
62
  
63
64
SETUP   0       1,385
65
  80 06 00 02 00 00 12 00
66
67
IN      0       1,385
68
  09 02 12 00 01 01 00 C0 32 09 04 00 00 00 FF 00 00 00
69
70
OUT     0       1,385
71
[pre]
72
73
Zu guter Letzt noch Linux. Das fragt auch nach dem device qualifier, gleich dreimal :), bevor es dann doch ohne einen solchen weiter macht.
74
75
[pre]
76
SETUP   0       0,380
77
  80 06 00 01 00 00 40 00
78
79
IN      0       0,631
80
  12 01 00 02 FF 00 00 40 FF 00 FF 00 00 01 00 00 00 01
81
82
OUT     0       0,633
83
  
84
85
SETUP   0       0,744
86
  00 05 01 00 00 00 00 00
87
88
IN      0       0,745
89
  
90
91
SETUP   0       0,760
92
  80 06 00 01 00 00 12 00
93
94
IN      0       1,011
95
  12 01 00 02 FF 00 00 40 FF 00 FF 00 00 01 00 00 00 01
96
97
OUT     0       1,013
98
  
99
100
SETUP   0       1,014
101
  80 06 00 06 00 00 0A 00
102
103
IN      0       1,015
104
  
105
106
SETUP   0       1,016
107
  80 06 00 06 00 00 0A 00
108
109
IN      0       1,017
110
  
111
112
SETUP   0       1,018
113
  80 06 00 06 00 00 0A 00
114
115
IN      0       1,019
116
  
117
118
SETUP   0       1,020
119
  80 06 00 02 00 00 09 00
120
121
IN      0       1,021
122
  09 02 12 00 01 01 00 C0 32
123
124
OUT     0       1,023
125
  
126
127
SETUP   0       1,024
128
  80 06 00 02 00 00 12 00
129
130
IN      0       1,025
131
  09 02 12 00 01 01 00 C0 32 09 04 00 00 00 FF 00 00 00
132
133
OUT     0       1,027
134
  
135
136
SETUP   0       1,028
137
  00 09 01 00 00 00 00 00
138
139
IN      0       1,029

Summa summarum würde ich mal sagen, dass bis hier alles im grünen 
Bereich ist.

von Marvin K. (m_marvin)


Lesenswert?

Das erklärt dann leider weder dieses Problem das ich durch einen Timeout 
lösen musste, noch dass ich keine String Descriptoren nutzen kann (oder 
anders gesagt, das die Konfiguration nicht gesetzt wird).

Wird sie denn bei deinen Tests korrekt gesetzt ?
Bei mir steht da halt 0x00 und das Gerät geht in diesen Susppend/Power 
Down mode.

Und zu diesen umständlichen Konfigurationen, ich weis das das 
umständlich ist, macht es aber einfacher mal kurz was zu ändern (einfach 
set durch clr z.B. ersetzen).
Wenn ich weis das alles Funktioniert wollte ich noch sowas wie btm (kurz 
für "bit mask") machen, wo ich dann z.B: schreiben kann
1
btm(PLLCSR, PLL0, 0, 1, 0);
Also quasi erst der Register, dann das Erste Bit und dann die Bits die 
von da aus gesetzt werden sollen.
Oder irgend was in der Art, das ist nur eine vorübergehende Lösung damit 
ich schnell Sachen ändern kann, wie gesagt in C besonders in AVR hab ich 
noch nicht so viel gemacht, meist nur Simple Sachen mit I/O Ports, und 
wenig mit größerer Register manipulation.

von Thomas Z. (usbman)


Lesenswert?

Der DeviceQualifier sollte verschwinden sobald usbBCD auf 0x0110 
gestellt wird.

Der 0xEE String ist unter Windows Teil der WinUSB Erkennung. MS stellt 
damit fest ob WinUSB als Treiber benutzt werden soll.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Marvin K. schrieb:
> Das erklärt dann leider weder dieses Problem das ich durch einen Timeout
> lösen musste, noch dass ich keine String Descriptoren nutzen kann (oder
> anders gesagt, das die Konfiguration nicht gesetzt wird).

Die String indices stehen derzeit ja alle auf 0, insofern werden keine 
string descriptors abgefragt.

Dass du für selbige noch bissel was tun musst, hatten wir ja schon 
diskutiert. Du brauchst einen String descriptor mit Index 0, bei mir 
sieht der so aus:
1
static struct string_descriptor_langs const PROGMEM string_descriptor_langs =
2
{
3
    .bLength = sizeof(struct string_descriptor_langs),
4
    .bDescriptorType = STRING_DESC,
5
    .wLANGID =
6
    {
7
        [0] = 0x0409            /* US English */
8
    }
9
};

und du musst die anderen ordentlich UTF-16 codieren.
1
{
2
    .bLength = sizeof(struct string_descriptor) +
3
        sizeof(USB_VENDOR_NAME) - sizeof(wchar_t),
4
    .bDescriptorType = STRING_DESC,
5
    .bString = USB_VENDOR_NAME
6
};

mit USB_VENDOR_NAME
1
#define URACOLI_USB_VENDOR_NAME  L"URACOLI"

Beim AVR-GCC sind wide strings standardmäßig 16 bit breit, daher geht 
das hier so.

> Bei mir steht da halt 0x00 und das Gerät geht in diesen Susppend/Power
> Down mode.

Power down erfolgt hier nicht, und die Konfiguration sah unter allen 
drei Ziel-Betriebssystemen erstmal soweit erfolgreich aus.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Thomas Z. schrieb:
> Der DeviceQualifier sollte verschwinden sobald usbBCD auf 0x0110
> gestellt wird.

Was ohnehin zweckmäßig ist, denn mehr als Fullspeed machen diese 
Controller eh nicht. Da muss man dann die USB-Version auch nicht auf 2.0 
festlegen wollen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Hier noch die Ausgaben unter FreeBSD:
1
# usbconfig -d 5.3 dump_device_desc
2
ugen5.3: <vendor 0x00ff product 0x00ff> at usbus5, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (100mA)
3
4
  bLength = 0x0012
5
  bDescriptorType = 0x0001
6
  bcdUSB = 0x0200
7
  bDeviceClass = 0x00ff  <Vendor specific>
8
  bDeviceSubClass = 0x0000
9
  bDeviceProtocol = 0x0000
10
  bMaxPacketSize0 = 0x0040
11
  idVendor = 0x00ff
12
  idProduct = 0x00ff
13
  bcdDevice = 0x0100
14
  iManufacturer = 0x0000  <no string>
15
  iProduct = 0x0000  <no string>
16
  iSerialNumber = 0x0000  <no string>
17
  bNumConfigurations = 0x0001
18
19
# usbconfig -d 5.3 dump_curr_config_desc
20
ugen5.3: <vendor 0x00ff product 0x00ff> at usbus5, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (100mA)
21
22
23
 Configuration index 0
24
25
    bLength = 0x0009
26
    bDescriptorType = 0x0002
27
    wTotalLength = 0x0012
28
    bNumInterfaces = 0x0001
29
    bConfigurationValue = 0x0001
30
    iConfiguration = 0x0000  <no string>
31
    bmAttributes = 0x00c0
32
    bMaxPower = 0x0032
33
34
    Interface 0
35
      bLength = 0x0009
36
      bDescriptorType = 0x0004
37
      bInterfaceNumber = 0x0000
38
      bAlternateSetting = 0x0000
39
      bNumEndpoints = 0x0000
40
      bInterfaceClass = 0x00ff  <Vendor specific>
41
      bInterfaceSubClass = 0x0000
42
      bInterfaceProtocol = 0x0000
43
      iInterface = 0x0000  <no string>

: Bearbeitet durch Moderator
von Thomas Z. (usbman)


Lesenswert?

Jörg W. schrieb:
> SETUP   0       1,028
>   00 09 01 00 00 00 00 00
> IN      0       1,029

Dieser Request fehlt in der Windows Variante (SetConfiguration) weshalb 
das Ding unter Win nicht enumeriert.
Ich würde deshalb testweise einfach mal einen Bulk EP hinzufügen bei den 
Descriptoren hinzufügen. Nur um sicherzugehen dass Win da nichts falsch 
versteht.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Thomas Z. schrieb:
> Dieser Request fehlt in der Windows Variante (SetConfiguration)

Stimmt.

Du meinst, sie schicken das nicht los, weil es keine Endpoints gibt 
außer dem control endpoint?

von Thomas Z. (usbman)


Lesenswert?

Jörg W. schrieb:
> Du meinst, sie schicken das nicht los, weil es keine Endpoints gibt
> außer dem control endpoint?

wäre eine Möglichkeit. Ich bin mir nicht sicher ob ich sowas schon mal 
gemacht habe. Bei Windows weis mans nie. Manchmal sind die bei MS total 
pingelig manchmal lassen Sie auch grobe Fehler durchgehen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

Zumindest behauptet Windows, das Teil sei konfiguriert. Hat natürlich 
keinen Treiber installiert – an der Stelle ist Windows anders als alle 
anderen OSe. Die haben nämlich immer einen low-level driver, über den 
man (bspw. per libusb) grundsätzlich erst einmal auf das Gerät zugreifen 
kann.

Könnte natürlich sein, dass Windows keine Konfiguration auswählen will, 
solange kein Treiber da ist. Das Einfachste wäre es vermutlich, du 
würdest erstmal ein HID bauen. Das ist relativ simpel, und es hat selbst 
in Windows immer einen Treiber.

von Thomas Z. (usbman)


Lesenswert?

Ich bin mir nicht zu 100% sicher wer im Treiberstack das SetConfigure() 
macht.
Ich teste gerne und oft mit dem Thesicon USBIO Demo Treiber(*), dort 
macht SetConfigure() die DemoApp. Es ist also möglich dass das gar nicht 
mehr zum Enum Code gehört.
Vielleicht hat Win auch einfach ein Problem wenn es keine Pipe gibt. Was 
ich aber sicher sagen kann ist dass ein SetConigure() auch kommt wenn 
kein Treiber zugeordnet ist.

(*)
Da es das USBIO demo für W10 nicht mehr frei zum runterladen gibt mache 
diese Tests in einer VM mit Win XP.

von Marvin K. (m_marvin)


Lesenswert?

Ich habe jetzt mal die String Descriptoren korrekt implementiert, und 
zum Test einen Language und einen Manufacturer Descriptor erstellt, ich 
erhalte aber weiterhin diese Meldung.
1
iManufacturer:                     0x01
2
String Descriptor for index 1 not available while device is in low power state.

von Marvin K. (m_marvin)


Lesenswert?

Ich habe jetzt auch mal einen weiteren Endpoint implementiert, dennoch 
sagt USBView "No open pipes":
1
[Port4] 
2
3
4
Is Port User Connectable:         yes
5
Is Port Debug Capable:            no
6
Companion Port Number:            10
7
Companion Hub Symbolic Link Name: USB#ROOT_HUB30#7&124f193f&0&0#{f18a0e88-c30c-11d0-8815-00a0c906bed8}
8
Protocols Supported:
9
 USB 1.1:                         yes
10
 USB 2.0:                         yes
11
 USB 3.0:                         no
12
13
       ---===>Device Information<===---
14
String Descriptor for index 2 not available while device is in low power state.
15
16
ConnectionStatus:                  
17
Current Config Value:              0x00  -> Device Bus Speed: Full (is not SuperSpeed or higher capable)
18
Device Address:                    0x05
19
Open Pipes:                           0
20
*!*ERROR:  No open pipes!
21
22
          ===>Device Descriptor<===
23
bLength:                           0x12
24
bDescriptorType:                   0x01
25
bcdUSB:                          0x0110
26
bDeviceClass:                      0xFF  -> This is a Vendor Specific Device
27
bDeviceSubClass:                   0x00
28
bDeviceProtocol:                   0x00
29
bMaxPacketSize0:                   0x40 = (64) Bytes
30
idVendor:                        0x00FF = Vendor ID not listed with USB.org
31
idProduct:                       0x00FF
32
bcdDevice:                       0x0100
33
iManufacturer:                     0x01
34
String Descriptor for index 1 not available while device is in low power state.
35
iProduct:                          0x02
36
String Descriptor for index 2 not available while device is in low power state.
37
iSerialNumber:                     0x03
38
String Descriptor for index 3 not available while device is in low power state.
39
bNumConfigurations:                0x01
40
41
       ---===>Full Configuration Descriptor<===---
42
43
          ===>Configuration Descriptor<===
44
bLength:                           0x09
45
bDescriptorType:                   0x02
46
wTotalLength:                    0x0019  -> Validated
47
bNumInterfaces:                    0x01
48
bConfigurationValue:               0x01
49
iConfiguration:                    0x00
50
bmAttributes:                      0xC0  -> Self Powered
51
MaxPower:                          0x32 = 100 mA
52
53
          ===>Interface Descriptor<===
54
bLength:                           0x09
55
bDescriptorType:                   0x04
56
bInterfaceNumber:                  0x00
57
bAlternateSetting:                 0x00
58
bNumEndpoints:                     0x01
59
bInterfaceClass:                   0xFF  -> Interface Class Unknown to USBView
60
bInterfaceSubClass:                0x00
61
bInterfaceProtocol:                0x00
62
iInterface:                        0x00
63
64
          ===>Endpoint Descriptor<===
65
bLength:                           0x07
66
bDescriptorType:                   0x05
67
bEndpointAddress:                  0x81  -> Direction: IN - EndpointID: 1
68
bmAttributes:                      0x02  -> Bulk Transfer Type
69
wMaxPacketSize:                  0x0010 = 0x10 bytes
70
bInterval:                         0x80

von Thomas Z. (usbman)


Lesenswert?

1. bulk mit <> 64 bytes ist nicht erlaubt!
2. bInterval bei bulk ist nicht definiert

von Marvin K. (m_marvin)


Lesenswert?

1. Ich hab doch 16 Bytes, nicht 64. Und ich hab es eben auch nochmal auf 
8 reduziert, bewirkt auch keine Änderung.
2. Ach stimmt, vergessen, hab es entfernt (auch keine Änderung).

von Thomas Z. (usbman)


Lesenswert?

Marvin K. schrieb:
> 1. Ich hab doch 16 Bytes, nicht 64. Und ich hab es eben auch
> nochmal auf
> 8 reduziert, bewirkt auch keine Änderung.
> 2. Ach stimmt, vergessen, hab es entfernt (auch keine Änderung).

die spec sagt ganz klar bulk EPs müssen 64 Bytes haben.
Also entweder stellst du auf Interrupt um un dann kann bInterval ein 
Wert zugewiesen werden. oder du machst bulk mit 64 bytes und bInterval 
auf 0.

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Schieb' doch nochmal den Sourcecode rüber.

von Thomas Z. (usbman)


Lesenswert?

hast du denn mal den Treiberdialog gesehen? Falls ja deinstalliere mal 
im Gerätemanager (ausgeblendete Geräte sichtbar), und mit Haken Treiber 
entfernen.

von Marvin K. (m_marvin)


Angehängte Dateien:

Lesenswert?

Hier ist mein aktuelle vollständiger Sourcecode.
Wie beschrieben funktioniert er soweit einwandfrei, nur dass ich keine 
String Deskriptoren nutzen kann, und USBView immer sagt, das Gerät sei 
im "low power Modus", und ich auch keinen SET_CONFIGURATION Deskriptor 
empfange.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Schau ich heute Abend mal rein (und schicke es durch den Analyzer).

: Bearbeitet durch Moderator
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Nur nebenbei: die Unsitte, einen void* als Byte-Zeiger zu benutzen, hast 
du noch nicht abgestellt:
1
avr-g++ -funsigned-char -funsigned-bitfields -DDEBUG  -Og -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -g2 -Wall -mmcu=at90usb162 -c -MD -MP -MF "usbl.d" -MT"usbl.d" -MT"usbl.o"   -o "usbl.o" ".././usbl.cpp" 
2
.././usbl.cpp: In function ‘void readUSB(void*, uint16_t)’:
3
.././usbl.cpp:128:14: warning: ISO C++ forbids incrementing a pointer of type ‘void*’ [-Wpointer-arith]
4
  128 |   *(uint8_t*)buffer++ = UEDATX; // Read data in buffer
5
      |              ^~~~~~
6
In file included from .././config.h:12,
7
                 from .././usbl.cpp:12:
8
.././usbl.cpp: In function ‘void writeUSB(const void*, uint16_t, uint8_t, bool)’:
9
.././usbl.cpp:156:27: warning: ISO C++ forbids incrementing a pointer of type ‘const void*’ [-Wpointer-arith]
10
  156 |    UEDATX = pgm_read_byte(buffer++);
11
      |                           ^~~~~~
12
.././usbl.cpp:160:24: warning: ISO C++ forbids incrementing a pointer of type ‘const void*’ [-Wpointer-arith]
13
  160 |    UEDATX = *(uint8_t*)buffer++;
14
      |                        ^~~~~~

Und nein, dier Herum-Casterei auf einen uint8_t*, der danach 
dereferenziert wird, hat da keinen Sinn.  buffer selbst gehört als 
uint8_t* deklariert statt als void*.

: Bearbeitet durch Moderator
von Marvin K. (m_marvin)


Lesenswert?

Ich hab es mit uint_8t* versucht, aber Atmel Studio wollte es dann nie 
kompilieren, es ist dann immer zu irgend einer zufälligen Zeile 
gesprungen und hat sowas gesagt wie "first use of xy" dabei war an 
dieser stelle alles in Ordnung ...
Manchmal springt es dann auch einfach zu einer leeren Zeile und sagt das 
da irgend ein Fehler ist.
Ich hab keine Ahnung woran das liegt, eventuell muss ich den Code mal 
mit einer anderen IDE öffnen, ich glaub das liegt an Atmel Studio.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hier der Patch, wie das (halbwegs) korrekt ist. Sind immer noch 
typecasts drin, irgendwie muss man halt einen "Zeiger auf irgendwas" in 
einen "Zeiger auf Byte" umwandeln, aber jetzt wird zumindest nicht mehr 
versucht, einen void-Zeiger zu inkrementieren.

: Bearbeitet durch Moderator
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Naja, die String-Descriptoren geben nur mittelmäßigen Blödsinn von sich, 
angefangen bei dem für die language ID.
1
SETUP   0       2,412
2
  80 06 00 03 00 00 02 00
3
4
IN      0       2,412
5
  91 83
6
7
OUT     0       2,412
8
  
9
10
SETUP   0       2,412
11
  80 06 00 03 00 00 04 00
12
13
IN      0       2,412
14
  91 83 80 83
15
16
OUT     0       2,412
17
  
18
19
SETUP   0       2,412
20
  80 06 03 03 80 83 02 00
21
22
IN      0       2,413
23
  18 03
24
25
OUT     0       2,413
26
  
27
28
SETUP   0       2,413
29
  80 06 03 03 80 83 18 00
30
31
IN      0       2,413
32
  18 03 20 01 22 03 36 01 0C 03 56 01 12 01 10 01 FF 00 00 40 FF 00 FF 00
33
34
OUT     0       2,413
35
  
36
37
SETUP   0       2,413
38
  80 06 01 03 80 83 02 00
39
40
IN      0       2,414
41
  0C 03
42
43
OUT     0       2,414
44
  
45
46
SETUP   0       2,414
47
  80 06 01 03 80 83 0C 00
48
49
IN      0       2,414
50
  0C 03 56 01 12 01 10 01 FF 00 00 40
51
52
OUT     0       2,414
53
  
54
55
SETUP   0       2,415
56
  80 06 02 03 80 83 02 00
57
58
IN      0       2,415
59
  22 03
60
61
OUT     0       2,415
62
  
63
64
SETUP   0       2,415
65
  80 06 02 03 80 83 22 00
66
67
IN      0       2,416
68
  22 03 36 01 0C 03 56 01 12 01 10 01 FF 00 00 40 FF 00 FF 00 00 01 01 02 03 01 00 11 24 1F BE CF EF D2
69
70
OUT     0       2,416
71
  
72
73
SETUP   0       2,416
74
  80 06 00 02 00 00 09 00
75
76
IN      0       2,416
77
  09 02 19 00 01 01 00 C0 32
78
79
OUT     0       2,416
80
  
81
82
SETUP   0       2,416
83
  80 06 00 02 00 00 19 00
84
85
IN      0       2,417
86
  09 02 19 00 01 01 00 C0 32 09 04 00 00 01 FF 00 00 00 07 05 81 02 40 00 00
87
88
OUT     0       2,417

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Das
1
typedef struct  
2
{
3
  uint8_t      bLength;      // Byte count of this descriptor
4
  uint8_t      bDescriptorType;  // Type of the Descriptor
5
  const wchar_t*  wString;      // List of chars representing the string
6
} __attribute__((packed)) USB_String_Descriptor;

funktioniert natürlich so nicht. Der ganze Descriptor wird ja dann 
linear "abgearbeitet". Damit gibst du (korrekt) bLength aus, dann 
(korrekt) bDescriptorType, danach gibst du den Zeiger auf wString aus, 
hernach nur noch Unfug.

Wenn du das so schön hintereinander weg schreiben willst, musst du den 
Platz für das Array mit den strings im Descriptor selbst allozieren, 
statt da nur einen Pointer hinzulegen.

(Deine Makro-Wurschtelei macht es nicht gerade einfacher, durch den Code 
durchzusteigen.)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Hab gerade versucht, das dadurch zu lösen, dass man das Array in die 
struct selbst mit aufnimmt. Aber hier stolpert man drüber, dass diese 
Initializer in C++ wohl eher neu sind (in C gibt es sie seit C99).

Während ein Clang ein
1
struct foo {
2
      wchar_t foo[42];
3
} foobar = { .foo = L"FOOBAR" };

problemlos frisst, erbricht sich der GCC daran und meckert was über "C99 
designator ‘foo’ outside aggregate initializer".

Entweder compilierst du den ganzen USB-Kram als C statt C++, oder du 
baust die Teile auf C++ um (statische Objekte mit Konstruktor).

von Thomas Z. (usbman)


Lesenswert?

ich halte sowas ja immer noch für am übersichtlichten auch wenn man 
abzählen muss.
1
const uint8_t blablub[16] PROGMEM =
2
{
3
   sizeof(blablub), 0x03,
4
   'b',0x00,
5
   'l',0x00,
6
   'a',0x00,
7
   'b',0x00,
8
   'l',0x00,
9
   'u',0x00,
10
   'b',0x00
11
};
12
13
....
14
  case DESCRIPTOR_TYPE_STRING:
15
       switch(descriptorIndex) 
16
       {
17
          ....
18
          case 1: //str id 1
19
               descriptorPointer = &blablub;
20
               descriptorSize    = *blablub[0]; 
21
               break; 
22
          ....   
23
       }
24
....

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Thomas Z. schrieb:
> descriptorSize    = *blablub[0];

Geht bei AVR und Progmem nicht.

Aber ja, vom Prinzip schon.

Was auch alles andere als nett ist ist, dass in config.h Funktionen 
definiert sind. Sowas gehört in eine .c / .cpp Datei.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ohne C99-Syntax bekommt man die Initialisierung inline hin, funktioniert 
aber trotzdem noch nicht. Schau ich mir später an.

von Thomas Z. (usbman)


Lesenswert?

Jörg W. schrieb:
> Thomas Z. schrieb:
>> descriptorSize    = *blablub[0];
>
> Geht bei AVR und Progmem nicht.
Ok, da kenn ich mich zu wenig aus ... man kann nicht aus dem ProgMem 
derefernzieren?

dann ev descriptorSize = sizeof(blablub);
Nachteil: im Header muss das dann korrekt deklariert werden wenn es sich 
nicht im usb.c File befindet.

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

Thomas Z. schrieb:

> Ok, da kenn ich mich zu wenig aus ... man kann nicht aus dem ProgMem
> derefernzieren?

Ja, zumindest nicht "klassisch". Mit Johanns Erweiterung __flash geht es 
korrekt, aber die gibt es nur im C-Modus, nicht bei C++, weil sich C++ 
irgendwie gegen neue type qualifier wehrt.

@Marvin: dein hin- und her Gehüpfe zwischen constants.h und config.h ist 
lästig. Der language ID descriptor (der ja auch nur ein string 
descriptor ist) steht in der einen Datei, die anderen string 
descriptoren in der anderen. Dadurch ist dir halt auch entgangen, dass 
du bei dem mit der language ID das PROGMEM vergessen hattest, sodass er 
im RAM abgelegt worden ist, während die Auslesefunktion ihn natürlich 
aus dem Flash lesen will.

Mit dem aktuellen Diff kommen die string descriptors korrekt raus:
1
# usbconfig ugen5.3 dump_curr_config_desc -d 5.3 dump_device_desc
2
ugen5.3: <TEST AT90USB162 Test> at usbus5, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (100mA)
3
4
5
 Configuration index 0
6
7
    bLength = 0x0009 
8
    bDescriptorType = 0x0002 
9
    wTotalLength = 0x0019 
10
    bNumInterfaces = 0x0001 
11
    bConfigurationValue = 0x0001 
12
    iConfiguration = 0x0000  <no string>
13
    bmAttributes = 0x00c0 
14
    bMaxPower = 0x0032 
15
16
    Interface 0
17
      bLength = 0x0009 
18
      bDescriptorType = 0x0004 
19
      bInterfaceNumber = 0x0000 
20
      bAlternateSetting = 0x0000 
21
      bNumEndpoints = 0x0001 
22
      bInterfaceClass = 0x00ff  <Vendor specific>
23
      bInterfaceSubClass = 0x0000 
24
      bInterfaceProtocol = 0x0000 
25
      iInterface = 0x0000  <no string>
26
27
     Endpoint 0
28
        bLength = 0x0007 
29
        bDescriptorType = 0x0005 
30
        bEndpointAddress = 0x0081  <IN>
31
        bmAttributes = 0x0002  <BULK>
32
        wMaxPacketSize = 0x0040 
33
        bInterval = 0x0000 
34
        bRefresh = 0x0000 
35
        bSynchAddress = 0x0000 
36
37
38
39
ugen5.3: <TEST AT90USB162 Test> at usbus5, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (100mA)
40
41
  bLength = 0x0012 
42
  bDescriptorType = 0x0001 
43
  bcdUSB = 0x0110 
44
  bDeviceClass = 0x00ff  <Vendor specific>
45
  bDeviceSubClass = 0x0000 
46
  bDeviceProtocol = 0x0000 
47
  bMaxPacketSize0 = 0x0040 
48
  idVendor = 0x00ff 
49
  idProduct = 0x00ff 
50
  bcdDevice = 0x0100 
51
  iManufacturer = 0x0001  <TEST>
52
  iProduct = 0x0002  <AT90USB162 Test>
53
  iSerialNumber = 0x0003  <IDSJAKFHFS>
54
  bNumConfigurations = 0x0001

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Warum Windows immer noch kein set configuration macht, da habe ich aber 
keine Idee.

von Thomas Z. (usbman)


Lesenswert?

Jörg W. schrieb:
> Warum Windows immer noch kein set configuration macht, da habe ich aber
> keine Idee.

Wie gesagt das ist vermutlich schon Teil des Treibers, denn es ja für 
das Teil ja (noch) nicht gibt.
@marvin vieleicht probierst du mal für diese Firmware via zadig einen 
LibUsb Treiber zuzuweisen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Habe das hier mal probiert, und in der Tat, danach ist auch Windows 
gewillt, ein set configuration abzusetzen.
1
SETUP   0       2,358
2
  80 06 00 01 00 00 40 00
3
4
IN      0       2,358
5
  12 01 10 01 FF 00 00 40 FF 00 FF 00 00 01 01 02 03 01
6
7
OUT     0       2,358
8
  
9
10
SETUP   0       2,446
11
  00 05 39 00 00 00 00 00
12
13
IN      0       2,446
14
  
15
16
SETUP   0       2,457
17
  80 06 00 01 00 00 12 00
18
19
IN      0       2,457
20
  12 01 10 01 FF 00 00 40 FF 00 FF 00 00 01 01 02 03 01
21
22
OUT     0       2,457
23
  
24
25
SETUP   0       2,463
26
  80 06 00 02 00 00 FF 00
27
28
IN      0       2,464
29
  09 02 19 00 01 01 00 C0 32 09 04 00 00 01 FF 00 00 00 07 05 81 02 40 00 00
30
31
OUT     0       2,464
32
  
33
34
SETUP   0       2,464
35
  80 06 03 03 09 04 FF 00
36
37
IN      0       2,465
38
  16 03 49 00 44 00 53 00 4A 00 41 00 4B 00 46 00 48 00 46 00 53 00
39
40
OUT     0       2,465
41
  
42
43
SETUP   0       2,465
44
  80 06 00 03 00 00 FF 00
45
46
IN      0       2,465
47
  04 03 09 04
48
49
OUT     0       2,465
50
  
51
52
SETUP   0       2,465
53
  80 06 02 03 09 04 FF 00
54
55
IN      0       2,466
56
  20 03 41 00 54 00 39 00 30 00 55 00 53 00 42 00 31 00 36 00 32 00 20 00 54 00 65 00 73 00 74 00
57
58
OUT     0       2,466
59
  
60
61
SETUP   0       2,679
62
  80 06 00 01 00 00 12 00
63
64
IN      0       2,680
65
  12 01 10 01 FF 00 00 40 FF 00 FF 00 00 01 01 02 03 01
66
67
OUT     0       2,680
68
  
69
70
SETUP   0       2,680
71
  80 06 00 02 00 00 09 00
72
73
IN      0       2,680
74
  09 02 19 00 01 01 00 C0 32
75
76
OUT     0       2,680
77
  
78
79
SETUP   0       2,680
80
  80 06 00 02 00 00 19 00
81
82
IN      0       2,681
83
  09 02 19 00 01 01 00 C0 32 09 04 00 00 01 FF 00 00 00 07 05 81 02 40 00 00
84
85
OUT     0       2,681
86
  
87
88
SETUP   0       2,688
89
  80 06 00 01 00 00 12 00
90
91
IN      0       2,688
92
  12 01 10 01 FF 00 00 40 FF 00 FF 00 00 01 01 02 03 01
93
94
OUT     0       2,688
95
  
96
97
SETUP   0       2,688
98
  80 06 00 02 00 00 09 00
99
100
IN      0       2,689
101
  09 02 19 00 01 01 00 C0 32
102
103
OUT     0       2,689
104
  
105
106
SETUP   0       2,689
107
  80 06 00 02 00 00 19 00
108
109
IN      0       2,689
110
  09 02 19 00 01 01 00 C0 32 09 04 00 00 01 FF 00 00 00 07 05 81 02 40 00 00
111
112
OUT     0       2,690
113
  
114
115
SETUP   0       2,690
116
  80 06 00 01 00 00 12 00
117
118
IN      0       2,690
119
  12 01 10 01 FF 00 00 40 FF 00 FF 00 00 01 01 02 03 01
120
121
OUT     0       2,690
122
  
123
124
SETUP   0       2,690
125
  80 06 00 02 00 00 09 00
126
127
IN      0       2,691
128
  09 02 19 00 01 01 00 C0 32
129
130
OUT     0       2,691
131
  
132
133
SETUP   0       2,691
134
  80 06 00 02 00 00 19 00
135
136
IN      0       2,691
137
  09 02 19 00 01 01 00 C0 32 09 04 00 00 01 FF 00 00 00 07 05 81 02 40 00 00
138
139
OUT     0       2,691
140
  
141
142
SETUP   0       2,691
143
  00 09 01 00 00 00 00 00
144
145
IN      0       2,692
146
  
147
148
SETUP   0       2,695
149
  80 06 00 03 00 00 FF 00
150
151
IN      0       2,695
152
  04 03 09 04
153
154
OUT     0       2,695
155
  
156
157
SETUP   0       2,696
158
  80 06 01 03 09 04 FF 00
159
160
IN      0       2,696
161
  0A 03 54 00 45 00 53 00 54 00
162
163
OUT     0       2,696
164
  
165
166
SETUP   0       2,696
167
  80 06 02 03 09 04 FF 00
168
169
IN      0       2,697
170
  20 03 41 00 54 00 39 00 30 00 55 00 53 00 42 00 31 00 36 00 32 00 20 00 54 00 65 00 73 00 74 00
171
172
OUT     0       2,697

von Marvin K. (m_marvin)


Lesenswert?

Danke, ich probiere das mal aus (alles was bisher so vorgeschlagen 
wurde) und schaue ob es dann auch bei mir mal klappen will.

Zu den ganzen "Designfehlern" im C Code, wie dass Funktionen in der .h 
stehen:
Ich weis, das das aktuell etwas Chaotisch ist, ich musste halt andauernd 
was ändern, weil irgend was nicht Funktioniert hat, ich werde das wenn 
es denn mal funktioniert ordentlich sortieren.
Dazu kommt halt das ich in C relativ neu bin, gerade die ganzen Pointer 
Sachen musste ich mir erstmal anschauen.

Aber zu dem Problem mit dem Zeiger im struct, das seltsame ist dass ich 
diesen Teil aus einem Beispiel von GitHub habe, und da hat es 
funktioniert (habe es durch ausgeben der Werte per LEDs getestet).
Allerdings habe ich den Auslesecode nicht übernommen, ich schätze da war 
irgend eine Regelung eingebaut, das wenn er an diesen Punkt kommt, er 
automatisch das Array des Zeigers lädt, anstatt den Zeiger selbst.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Marvin K. schrieb:
> Danke, ich probiere das mal aus (alles was bisher so vorgeschlagen
> wurde) und schaue ob es dann auch bei mir mal klappen will.

Ich habe das hier jetzt sowieso in ein Git-Repo lokal reingeschmissen. 
Wenn du willst, kann ich das auch auf Github hochladen.

> Aber zu dem Problem mit dem Zeiger im struct, das seltsame ist dass ich
> diesen Teil aus einem Beispiel von GitHub habe, und da hat es
> funktioniert (habe es durch ausgeben der Werte per LEDs getestet).
> Allerdings habe ich den Auslesecode nicht übernommen, ich schätze da war
> irgend eine Regelung eingebaut, das wenn er an diesen Punkt kommt, er
> automatisch das Array des Zeigers lädt, anstatt den Zeiger selbst.

Wahrscheinlich.

Aber ultimativ willst du diese vendor & product strings sowieso im Flash 
haben. Flash-Strings als Zeiger weiterreichen benötigt (zumindest ohne 
__flash Schlüsselwort) separat angelegte String-Objekte. Wenn du den 
String hingegen gleich im Descriptor-Objekt ablegst, steht er "von sich 
aus" im Flash, das ist das, was ich da jetzt gemacht habe.

Außerdem hast du da gleich noch ein Beispiel, wie man einen Makro über 
mehrere Zeilen aufsplitten kann, damit er etwas übersichtlicher wird. 
;-)

von Marvin K. (m_marvin)


Lesenswert?

Ich habe jetzt mal alle Änderungen übernommen, jetzt wird mir auch 
langsam klar wie das mit den Strings und Arrays funktioniert, ist schon 
ziemlich verwirrend wenn man das das erste mal auf einem AVR macht.

Die Strings funktionieren jetzt, ich hab die Deskriptoren mit einem 
einfachen uint8_t Array realisiert, das eine fixe Größe hat und im 
Progmem liegt.

Nur der Language Deskriptor hat ein par seltsame Probleme, erst habe ich 
es hier mit versucht:
1
typedef struct
2
{
3
  uint8_t      bLength;      // Byte count of this descriptor
4
  uint8_t      bDescriptorType;  // Type of the Descriptor
5
  uint16_t    wLANGID[1];      // Language ID as word
6
} __attribute__((packed)) USB_Lang_Descriptor;
7
const USB_Lang_Descriptor languageDescriptor PROGMEM =
8
{
9
  .bLength = 4,
10
  .bDescriptorType = DESCRIPTOR_TYPE_STRING,
11
  .wLANGID = {
12
    [0] = LANG_ID_ENGLISH
13
  }
14
};
Es hat soweit geklappt das manchmal alle Deskriptoren manchmal aber auch 
nur 1 oder 2 angezeigt wurde, bei den anderen stand dann wieder das das 
Gerät im low power mode sei.
Interesanterweise, hat es sich jedes mal geändert, wenn ich in USBView 
"Refresh" gemacht hab, nach jeder Aktuallisierung wurden andere Strings 
angezeigt, mal 1 und 3 mal nur 1 mal 2 und 3 etc.

Dann habe ich es das auch durch ein Array ersetzt, was mir sinnvoller 
erschien, da die Strings auch in Arrays stehen:
1
const uint8_t languageDescriptor[4] PROGMEM =
2
{
3
  sizeof(languageDescriptor), DESCRIPTOR_TYPE_STRING,
4
  (uint8_t) (LANG_ID_ENGLISH >> 8), (uint8_t) (LANG_ID_ENGLISH & 0xFF)
5
};

Hier zeigt er nun das an:
1
iManufacturer:                     0x01
2
*!*WARNING:  1 is an invalid Language ID
3
ABC!!!!"
4
iProduct:                          0x02
5
String Descriptor for index 2 not available while device is in low power state.
6
iSerialNumber:                     0x03
7
*!*WARNING:  3 is an invalid Language ID
8
ABC!!!!"
Der erste und der 3. Deskriptor wird angezeigt, der 2. nicht, und bei 
denen die angezeigt werden steht "xy is an invalid Language ID".
Was hat das zu bedeuten, ich habe die Werte doch gleich belassen, kann 
mir einer sagen warum was anderes (offenbar falsches) beim host an 
kommt, wenn ich die Werte in einem Array, anstatt in einem struct 
speichere ?

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Naja, alles Probleme, die ich dir schon gelöst hatte.

Ich habe dir auch vorgemacht, wie man die string descriptors so einbaut, 
dass sie eine flexible Länge haben.

Habe das einfach mal auf Github hochgeladen:

https://github.com/dl8dtl/USB162

Mach damit, was du möchtest. ;-) Kannst auch gern Schreibzugriff da 
drauf bekommen, wenn du weitere kleine Schritte veröffentlichen willst. 
Solche "bare metal" Codes sind oft dann doch Mangelware.

Ich habe auch einige Erfahrungen im SCSI-Bereich, das kann man gut 
gebrauchen, wenn es um USB Mass Storage geht. Das Protokoll dafür ist 
ein (abgespecktes) SCSI.

: Bearbeitet durch Moderator
von Marvin K. (m_marvin)


Lesenswert?

Ich habe dein Beispiel getestet, es kompiliert bei mir aber nicht.
1
#define WCHAR_TO_STRING_DESCRIPTOR(wchar) { \
2
  sizeof(USB_String_Descriptor) + sizeof(wchar) - 2, \
3
  DESCRIPTOR_TYPE_STRING, \
4
  wchar \
5
}
Es sagt immer
1
statement-expressions are not allowed outside functions or nor template-argument lists
und markiert die stelle
1
sizeof(wchar)
Wenn ich diese stelle durch einen Fixen Wert wie z.B. 4 ersetzt, 
funktioniert es, warum darf ich an dieser stelle kein sizeof() nutzen, 
bzw. warum funktioniert es dann bei dir ?
Hat das was mit meinem Compiler zu tun ?

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Marvin K. schrieb:
> Hat das was mit meinem Compiler zu tun ?

Kann natürlich sein. So ganz ist mir nicht klar, was er damit sagt, aber 
im C++-Standard kenne ich mich zugegebenermaßen nur wenig aus. sizeof() 
ist eigentlich ein Operator (auch wenn es wie eine Funktion aussieht).

Eventuell mal die Einstellung für die Version des C++-Standards suchen 
und was anderes auswählen?

Bei mir werkelt ein GCC 10.x, weiß nicht, welche Version der als default 
für den C++-Standard benutzt. Habe mal die Version auf C++17 (+ GNU 
Erweiterungen) gesetzt, damit compiliert es hier. Habe die 
Aktualisierung im Makefile auf Github hochgeladen.

von Marvin K. (m_marvin)


Lesenswert?

Egal was ich mache, er weigert sich das sizeof(wchar) zu kompilieren.
Ich glaube Atmel Studio ignoriert auch alle meine Einstellungen.
Wenn ich mit -std=c++11 verwende (z.B.) sagt es bei einigen codestellen 
dennoch das ich erste c++11 aktivieren wohl, obwohl ich das ja schon 
hab.
Und wenn ich es direkt im Makefile ändere überschreibt es das einfach 
wieder sobald ich speichern drücke.

Gibt es eventuell noch eine andere Funktion zum ermitteln der länge 
eines arrays?
Ich habe es schon mit diversen Pointer-Tricks versucht, die ich im 
Internet gefunden habe, aber bei allen sagt Atmel immer "unqualified id 
before xy" ...

von Thomas Z. (usbman)


Lesenswert?

Ich würde dem Parameter wchar im Makro mal einen anderen Namen geben und 
dann noch mal testen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Marvin K. schrieb:
> Und wenn ich es direkt im Makefile ändere überschreibt es das einfach
> wieder sobald ich speichern drücke.

Kannst du dem denn nicht irgendwo sagen, dass du dein eigenes Makefile 
nimmst und es die Finger davon lassen soll?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Thomas Z. schrieb:
> Ich würde dem Parameter wchar im Makro mal einen anderen Namen geben und
> dann noch mal testen.

Wobei reserviert nur 'wchar_t' ist, nicht 'wchar'.

Außerdem compiliert der Salat bei mir ja problemlos.

von Marvin K. (m_marvin)


Lesenswert?

Jörg W. schrieb:
> Kannst du dem denn nicht irgendwo sagen, dass du dein eigenes Makefile
> nimmst und es die Finger davon lassen soll?

Ich hab bisher keine solche Option finden können, ich hab bestimt 
mehrere Stunden in Menüs rumgeklickt, und alle möglichen (für mich) 
nutzlosen Optionen gefunden, aber nichts was einen "Custom-Makefile" 
oder eine andere Lösung hervorgebracht hat ...

Und wie gesagt, wenn ich sage er soll eine andere Compilerversion nutzen 
(diese Einstellung hab ich gefunden) ignoriert er das (im makefile steht 
immer noch das gleiche).

Muss ich eventuell den Toolchain updaten oder sowas?
Ich hab bisher nur "normale" AVRs Programmiert (Ohne spezielle 
Schnittstellen)
Aber kann es sein das ich für den AT90USB ein Update brauche?
Aktuell hab ich den avr8-gnu-toolchain 5.4.0, hab aber bei einer kurzen 
Google Suche auch nichts neueres gefunden (zumindest für Windows).

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Marvin K. schrieb:
> Aber kann es sein das ich für den AT90USB ein Update brauche?

Für den selbst nicht.

Aber halt möglicherweise für meinen Konstrukt, im Makro via sizeof() 
gleich die Länge des Strings zu ermitteln.

> Aktuell hab ich den avr8-gnu-toolchain 5.4.0

Das sagt alles und nichts, weil das rein Atmel/Microchips Nummerierung 
ist. Welche Versionen von Compiler und Binutils sich dahinter verbergen, 
kann man dem nicht entnehmen.

von Marvin K. (m_marvin)


Lesenswert?

Ich weis nicht warum, aber auf ein mal kompiliert es.
Ich habe eigentlich nur den Language Descriptor wieder zu einem Array 
gemacht, der hatte damit aber eigentlich Garnichts zu tun, er hatte sein 
eigenes struct.

Auf jeden fall kann ich es jetzt kompilieren und an den PC anschließen, 
aber es sagt weiterhin "String descriptor xy not aviable, device in low 
power state".

Ich werde morgen mal einen Treiber dafür schreiben (nur damit es 
konfiguriert wird) und schauen ob es sich dann eventuell ändert, 
ansonsten funktioniert alles ja schon länger bis auf die besagten 
Strings.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Marvin K. schrieb:
> Ich werde morgen mal einen Treiber dafür schreiben (nur damit es
> konfiguriert wird)

Brauchst du keinen schreiben. Zadig wurde schon genannt, damit kannst du 
einfach einen libusb-Treiber drauf konfigurieren lassen.

> und schauen ob es sich dann eventuell ändert,
> ansonsten funktioniert alles ja schon länger bis auf die besagten
> Strings.

Die sollten aber schon funktionieren.

Meiner Erinnerung nach kann man mittlerweile auch unter Windows mit 
irgendeinem Plugin oder Treiber USB-Tracing via Wireshark machen. 
Vielleicht bringt dich das ja weiter?

Etwas seltsam ist es schon, denn hier hat das an mehreren 
Betriebssystemen problemlos inklusive der Stringdeskriptoren 
funktioniert.

von Marvin K. (m_marvin)


Lesenswert?

Ich hab nochmal die Änderungen von @Jörg W. geladen 
(https://github.com/dl8dtl/USB162) und auf den AT90 gespielt, es verhält 
sich exakt wie meins.
Die String-Deskriptoren werden nicht angezeigt (low power mode) und es 
braucht ewig um von Windows erkannt zu werden, nach dem einstecken 
dauert es bestimmt 10 Sekunden bis das "Ding-Ding" kommt, wenn man ein 
Gerät einsteckt. Manchmal kommt auch nach ca. 20 Sekunden einfach "Gerät 
nicht erkannt".

Als ich es aber damals getestet hab, als ich noch gar keine String 
Descriptoren implementiert hatte, hat es einwandfrei funktioniert.
Es scheint als gäbe es wieder irgend ein Hardwareproblem, was auch 
erklären würde, weshalb mein Code bei anderen funktioniert.

Was könnte eine so extreme Verlangsamung des Verbindungsaufbaus 
verursachen?
Manchmal ist es so extrem das ich wenn ich das Gerät in USBView 
anklicke, das Fenster als "Reagiert nicht" markiert wird, und ich ca. 20 
Sekunden warten muss bis die Daten angezeigt werden.

Ich hab nichts an der Hardware verändert, und das es jetzt bei jedem 
Code ist den ich teste, muss es irgend was Projekt-unabhängiges sein, 
die Daten kommen ja durch (bis auf die Strings), und die Datenleitungen 
hab ich jetzt mehrfach geprüft, nachdem ich sie neu angelötet hab haben 
sie definitiv kontakt.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

Marvin K. schrieb:
> Was könnte eine so extreme Verlangsamung des Verbindungsaufbaus
> verursachen?

Naja, der USB-Pfad in der Hardware selbst. Andererseits ist das ja 
gerade mal Fullspeed USB, also 12 Mbit/s. Das ist jetzt keine 
Raketenwissenschaft.

Für alle Fälle hier mal ELF- und Hex-Datei aus meinem Compilat, damit du 
ausschließen kannst, ob es irgendwie am Compilieren liegt bei dir.

von Thomas Z. (usbman)


Lesenswert?

Marvin K. schrieb:
> Was könnte eine so extreme Verlangsamung des Verbindungsaufbaus
> verursachen?

Ich glaube ja dass du einen Fehler suchst wo gar keiner ist. Das 
DingDong was du bekommst ist die Meldung dass Win aufgegeben hat.
Ich glaube auch nicht dass fehlerhafte String Descriptoren die Ursache 
sind. Das kannst du aber der leicht testen indem du die String IDs im 
Devicedescriptor auf 0 setzt. Dann kommen keine String Requests mehr.

Du solltest im Device Manager mal aufräumen. Win bzw PNP hat oftmals ein 
Problem wenn ein fehlerhaftes Device angeschlossen wird. Durch das 
Aufräumen erzwingst du neu den Treiber Dialog.

Das Verhalten passt dazu dass kein Treiber geladen wird. Dann muss das 
Device deaktiviert werden, die Spec fordert dass inaktive Devices in den 
Powerdown geschickt werden. Das ist genau das was usbd mit deinem Device 
macht.

Du könntest auch mal bei geöffnetem Device Manager einfach dein Device 
anstecken und schauen was da unter USB passiert.

: Bearbeitet durch User
von Marvin K. (m_marvin)


Angehängte Dateien:

Lesenswert?

Das DingDong kommt auch wenn ein Gerät erkannt wurde, das hat nichts 
damit zu tun das ein Fehler aufgetreten ist.
Wenn ich eine Tastatur oder einen USB Stick einstecke kommt es auch, und 
zwar ca. 3 Sekunden nach dem einstecken.

Ich stelle gerade aber fest, das jedes Gerät so eine extreme Verzögerung 
beim einstecken hat, das ist aber nicht normal, ich hab seit dem ich mit 
dem AT90 rumprobiere, nichts mehr eingesteckt, aus er einem USB Stick 
der bekannt war, sehr langsam zu sein (ka warum).

Also verglichen mit der langsamen Reaktionszeit der anderen Geräte die 
ich einstecke, verhält sich mein AT90 also sogar ganz normal.
Noch verwirrender ist, das ich nochmal meinem Code draufgeladen habe, 
jetzt verbindet es ich innerhalb von ca. 1 Sekunde, wärend andere Geräte 
weiterhin sehr langsam sind.
Es scheint als ob es an meinem PC liegt und nicht am Gerät, ich habe 
gerade keinen 2. PC zur Verfügung, um es dort zu testen, aber es scheint 
als ob sich mein Gerät normal verbindet, und das Problem mit der langen 
Wartezeit vom PC kommt.

Eines ändert sich aber nie:
1
String Descriptor for index 2 not available while device is in low power state.
erscheint zufällig bei mindestens einem der 3 Stringdescriptoren.

Ich habe mal die .elf Datei auf den AT90 geladen, sie funktioniert, er 
wird erkannt und die Stringdescriptoren werden geladen, weshalb das 
Gerät jetzt auch ein Namen hat.

Ich hab meinen Code mal angehängt, eventuell hab ich ja doch noch irgend 
einen Fehler, die elf bzw. hex ist auch dabei, vielleicht kann ja 
nochmal jemand der die mittel hat den Verlauf analysieren und mir sagen 
warum die Strings nur manchmal ankommen, wie gesagt, einige werden immer 
mal wieder angezeigt.
Da die elf von Jörg W. funktioniert, muss der Fehler ja am Compiler oder 
dem Code liegen (bis auf das mit der großen Verzögerung, das ändert sich 
auch mit der elf nicht und ist bei jedem Gerät, offenbar zufällig, 
scheint mein PC zu sein).

Jörg W. schrieb:
> Für alle Fälle hier mal ELF- und Hex-Datei aus meinem Compilat, damit du
> ausschließen kannst, ob es irgendwie am Compilieren liegt bei dir.

Eventuell könntest du mir nochmal den Code senden den du da kompiliert 
hast, dann mache ich das auch und schaue ob meine elf ein anderes 
verhalten hervorbringt.

: Bearbeitet durch User
von Marvin K. (m_marvin)


Lesenswert?

Ach, ich hab in dem Code den ich hochgeladen hab der einfach heit halber 
nur 1 String Descriptor aktiviert, aber man kann sie einfach alle 
aktivieren, dann sollte es das Verhalten zeigen das ich habe (das immer 
mal wieder einer ankommt).

In diesem Zustand sagt es bei diesem einen dauerhaft das er nicht 
ankommt.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Marvin K. schrieb:
> Eventuell könntest du mir nochmal den Code senden den du da kompiliert
> hast

Kannst du direkt aus dem Github-Repo nehmen. Wenn du es schaffst, auf 
der Kommandozeile den $PATH zu setzen und ein "make" aufzurufen, kannst 
du auch das mitgelieferte Makefile benutzen.

Ansonsten kannst du natürlich dein Kompilat (ELF-File) nochmal hier 
abladen, welches dein Compiler aus dem gleichen Code produziert hat, 
dann könnte man das vergleichen.

von Marvin K. (m_marvin)


Lesenswert?

Ich hab den Code mit meinem Makefile (Atmel Studio 7) kompilliert und 
auf den AT90 geladen, er verhält sich nicht so wie er soll, er verbindet 
sich nur in 50% der Fälle, in den anderen sagt Windows "Gerät nicht 
erkannt".

Die ELF hab ich angehängt, ich musste im Code aber eine Stelle ändern 
damit es zu kompilieren ging:
1
typedef struct  
2
{
3
  uint8_t      bLength;      // Byte count of this descriptor
4
  uint8_t      bDescriptorType;  // Type of the Descriptor
5
  const wchar_t wString[];      // List of chars representing the string
6
} __attribute__((packed)) USB_String_Descriptor;
wurde zu
1
typedef struct  
2
{
3
  uint8_t      bLength;      // Byte count of this descriptor
4
  uint8_t      bDescriptorType;  // Type of the Descriptor
5
  const wchar_t wString[42];      // List of chars representing the string
6
} __attribute__((packed)) USB_String_Descriptor;

Ich musste das Array mit einer Größte initialisieren, ansonsten hat es 
immer mit 0 initialisiert und der Compiler gab beim setzen des Wertes 
aus das das Array mit einer Größe von 0 zu klein für den String xy sei.
Hat das eventuell was zu bedeuten ?
Ich hab es in meinem Code direkt mit einem bestimten Wert initialisiert.
Eine maximallänge für die Strings ist ja nicht schlimm, und es wird ja 
sowieso nur der Teil des Arrays ausgelesen den ich angebe (im Feld 
bLength).

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Marvin K. schrieb:
> Ich hab den Code mit meinem Makefile (Atmel Studio 7) kompilliert und
> auf den AT90 geladen, er verhält sich nicht so wie er soll, er verbindet
> sich nur in 50% der Fälle, in den anderen sagt Windows "Gerät nicht
> erkannt".

Das ist natürlich Mist. Computer sollten deterministisch arbeiten.

> Die ELF hab ich angehängt, ich musste im Code aber eine Stelle ändern
> damit es zu kompilieren ging:

Naja, flexible array members sind nie in den C++-Standard eingeflossen. 
Das C++-Konsortium wünscht offenbar nicht so viele "C-ismen" in seiner 
Sprache für Dinge, die man in C++ anders lösen könnte. Geht bestimmt 
irgendwo über Templates oder sowas, bin grad zu faul mir das anzutun.

Offenbar akzeptiert meine AVR-GCC-Version das auch im C++-Modus, deine 
nicht.

Ist natürlich die Frage, ob du überhaupt C++ brauchst – eigentlich 
benutzt du ja kein einziges C++-Feature, wenn ich das richtig sehe.

ELF-File sehe ich mir mal an.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jörg W. schrieb:
> ELF-File sehe ich mir mal an.

Öhm, hätte ich, aber da war kein Anhang …

von Marvin K. (m_marvin)


Angehängte Dateien:

Lesenswert?

Oh, ich hab wohl die Datei versehentlich gelöscht bevor ich sie 
hochgeladen hab, hier ist sie.

von Marvin K. (m_marvin)


Angehängte Dateien:

Lesenswert?

Nur nochmal eine kurze Zusammenfassung, wie die Lage aktuell ist, da es 
gerade meiner Meinung nach etwas chaotisch wurde, mit den verschiedenen 
Versionen des Codes:

- Code von Jörg als von ihm kompilierte ELF -> Arbeitet einwandfrei
- Code von Jörg als von mir kompilierte ELF -> Funktioniert nur 
manchmal, keine Strings
- Mein original Code -> Funktioniert immer, aber keine Strings, bzw nur 
manchmal 1-2 von 3
- Code den jemand mir vor längerem gesendet hat (weis leider nicht mehr 
wer), der ursprünglich einwandfrei funktioniert hat, und nach dem ich 
mich gerichtet hab -> Funktioniert immer, aber eben falls keine Strings 
mehr.

Hochgeladen hab ich meinen Originalcode und die ELF die ich mit Jörgs 
Code kompiliert habe.

: Bearbeitet durch User
von Marvin K. (m_marvin)


Lesenswert?

Ich habe durch langes rumprobieren jetzt noch rausgefunden, das meinem 
Code zwar anfragen zu String Deskriptoren gesendet werden, allerdings 
immer nur für den Language Deskriptor.
Welchen Grund könnte es den geben, das Windows nur den Language 
Deskriptor abfragt, und die anderen erst gar nicht versucht zu bekommen 
?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Hmm, wollte dein ELF-File gerade hier probieren - aber das geht 
natürlich nicht, denn mein Devboard benutzt einen 16-MHz-Quarz.

Wenn du willst, kannst du es mir nochmal mit den PLL-Einstellungen für 
16 MHz hochladen, dann teste ich das hier (inklusive USB-Analyzer).

von Thomas Z. (usbman)


Lesenswert?

Marvin K. schrieb:
> Welchen Grund könnte es den geben, das Windows nur den Language
> Deskriptor abfragt, und die anderen erst gar nicht versucht zu bekommen
> ?

Vielleicht weil da kein korrekter Descriptor zurück kommt?
Schau dir die Requests mal mit Usblyzer an.

: Bearbeitet durch User
von Marvin K. (m_marvin)


Lesenswert?

Also ich hab mir mal die Testversion von USBlyzer installiert, und 
irgendwie funktioniert es nicht, sobald ich versuche den AT90 
Aufzuzeichnen, wird er nicht mehr erkannt ("Fehler beim anfordern einer 
Gerätebeschreibung").
Stoppe ich die Aufzeichnung, funktioniert es wieder.
Zeichne ich den ganzen HUB auf, funktioniert es auch, allerdings scheint 
die Aufzeichnung dann keine Daten zu den angeschlossenen Geräten sondern 
wirklich nur zum HUB zu enthalten.

von Marvin K. (m_marvin)


Lesenswert?

Gibt es irgend was was ich in USBlyzer einstellen muss, bevor ich die 
Setup Requests aufzeichnen kann, ohne das es zu einem "Fehler beim 
Anfordern einer Gerätebeschreibung" kommt ?

von Marvin K. (m_marvin)


Angehängte Dateien:

Lesenswert?

Hier sind die Infos die ich bekomme wenn ich den AT90 aufzeichne (und 
somit einen "Fehler beim Anfordern einer Gerätebeschreibung" 
verursache).

Ich verstehe nicht ganz was "Set Power" ist, es ist rot markiert.

von Marvin K. (m_marvin)


Lesenswert?

Ich habe mir noch ein anderen USB Analyzer runtergeladen, dieser 
wiederum Zeigt den AT90 erst gar nicht als Gerät an, alle anderen Geräte 
allerdings schon.

Aber warum sagen Die Programme alle das mein Gerät nicht existiert / 
erzeugen Fehler beim Aufzeichnen, während  USBView und der Gerätemanager 
es anzeigen ? (Bis auf den Treiber und die Strings)

von Thomas Z. (usbman)


Lesenswert?

nun alle diese USB Analyzer setzen ein Gerät vorraus was durch die Enum 
kommt.
Solange das nicht passiert ist sind die nicht so hilfreich.

Es gibt bei usb.org noch ein Tool was dir vielleicht halfen kann USB2CV.
Das schaltet den kompletten Hostcontroller in den Debug mode. Das 
funktioniert recht brauchbar am Laptop (mit Touchpad). Damit lassen sich 
alle Chapter9 requests einzeln oder zusammen auf Compilance prüfen.

Achtung:
Es ist zwingend notwendig dass Maus und Tastatur nicht über den Host 
angesprochen werden der in den Debug mode geschaltet wird. Das ist bei 
einem Laptop üblicherweise gegeben.
Auf einem PC sollte das DUT an einem getrennten Host hängen (Steckkarte) 
weil sonst der PC nicht mehr bedienbar ist.

https://www.usb.org/document-library/usb20cv-x64-bit

Setpower ist ein HubRequest der betrifft dich nur indirekt.

: Bearbeitet durch User
von Marvin K. (m_marvin)


Lesenswert?

Aber mein Gerät kommt doch durch die Enumaration, zumindest bin ich 
davon ausgegangen das die Meldung "Gerät wurde Erfolgreich eingerichtet" 
und die Tatsache das alle Descriptoren (bis auf die Strings) in USB View 
korrekt angezeigt werden dies bedeutet, oder hab ich da was falsch 
verstanden ?

Ich habe eben auch mal alle Descriptoren von einer simplen 
USB-Festplatte übernommen, und es auf den AT90 Geladen, im Gerätemanager 
wird er als "USB-Massenspeicher" mit allen Daten des Original Gerätes 
angezeigt, im Prinzip eine 1 zu 1 Kopie, mit einem unterschied:
Da steht das das Gerät nicht gestartet werden konnte, kein Grund, nur 
das es nicht geklappt hat.
Und das Ausrufezeichen das anzeigt das kein Treiber installiert ist ist 
zu sehen.

Ich lade mir das Tool mal runter und probiere es damit aus.

: Bearbeitet durch User
von Marvin K. (m_marvin)


Angehängte Dateien:

Lesenswert?

Ich hab USB2CV mal installiert, und sowohl auf meinem Laptop als auf 
meinem PC kommt diese Fehlermeldung.

von Thomas Z. (usbman)


Lesenswert?

Hast du keine usb2 Buchsen mehr? Es gibt auch noch usb3CV, damit habe 
ich keine näheren Erfahrungen.

von Thomas Z. (usbman)


Lesenswert?

Noch eine Idee. Du schreibst immer von UsbView, das ist ziemlich alt 
soweit ich mich erinnere. Versuch mal UsbTreeView.

von Marvin K. (m_marvin)


Lesenswert?

Also, der AT90 kann ja gar kein USB3 und da ich an meinem PC 2 
verschiedene Buchsen habe (Blaue und Schwartze) und in der Beschreibung 
stand das die Blauen USB 3 Buchsen sind, bin ich davon ausgegangen das 
die schwarzen Buchsen weiterhin USB 2 sind.
Mein PC hat an sich laut USBlyzer 5 USB Hostcontroller.
3 Davon sind in Benutzung für die ganzen USB Ports am PC, ich denke mal 
das sind dann wohl alles USB 3 Controller die auch USB 2 Ports haben 
oder die Farben der Anschlüsse am Gehäuse, stimmen nicht überein mit dem 
was in der Anleitung steht.

Und USBView hab ich aus diversen Anleitungen und Dokumentationen zum 
AT90.
Ich lade mit mal UsbTreeView und dieses USB3CV runter.

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

So, ich habe mal dein ELF-File so gepatcht, dass PLLP0 in PLLCSR setzt, 
damit es auf meinem 16-MHz-Devboard läuft.

Deine string descriptor haben einfach eine viel zu große Längenangabe, 
und dieweil dahinter dann Nullbytes übertragen werden, wird das vom OS 
als ungültiger String angesehen.

Deine Variante:
1
SETUP   0       10.270
2
  80 06 02 03 09 04 FF 00
3
4
IN      0       10.271
5
  74 03 41 00 54 00 39 00 30 00 55 00 53 00 42 00 31 00 36 00 32 00 20 00 54 00 65 00 73 00 74 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Mein Binary, aus dem gleichen Sourcecode erzeugt:
1
SETUP   0       0.409
2
  80 06 02 03 09 04 FF 00
3
4
IN      0       0.410
5
  20 03 41 00 54 00 39 00 30 00 55 00 53 00 42 00 31 00 36 00 32 00 20 00 54 00 65 00 73 00 74 00

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Du siehst hier auch die 10 Sekunden Verzögerung, das scheint 
Windows-spezifisch zu sein: wenn der Kram nicht gleich funktioniert, 
wartet es 10 Sekunden und probiert's nochmal. Dann erst kommt auch der 
"Dödel". Bei meinem ELF-File kommt der "Dödel" sofort beim Reinstecken.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Jörg W. schrieb:
> Deine string descriptor haben einfach eine viel zu große Längenangabe

Ist auch völlig logisch. Diese Berechnung:
1
#define WCHAR_TO_STRING_DESCRIPTOR(wchar) { \
2
    sizeof(USB_String_Descriptor) + sizeof(wchar) - 2, \
3
      DESCRIPTOR_TYPE_STRING, \
4
      wchar \
5
}

setzt ja voraus, dass sizeof(USB_String_Descriptor) eben nicht bereits 
den tatsächlichen Platz für den String enthält, sondern nur den Teil vor 
dem eigentlichen String.

Die ganze sizeof-Rechnung kann man sich natürlich auch sparen und da 
gleich eine 2 einsetzen. Da von dieser wieder eine 2 am Ende subtrahiert 
wird (wegen des abschließenden \0 ist sizeof(wchar) länger), bleibt 
davon einfach nichts mehr übrig.

Ich habe den entsprechenden Code ohne flexible array member in mein 
Git-Repo geschoben.

von Marvin K. (m_marvin)


Lesenswert?

Hm, ich dachte sizeof ermittelt nur die Länge von dem Pointer des Array, 
ich probiere es später mal.

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Marvin K. schrieb:
> ich dachte sizeof ermittelt nur die Länge von dem Pointer des Array

Das wäre beim AVR gleich 2 – aber hier gibt's keinen Pointer, denn das 
Array ist ja Bestandteil der Struktur. Ist auch sinnvoll, denn so kann 
man das alles hintereinander aus dem Speicher "herunterrattern". 
Natürlich sind die flexible array members von C99 noch sinnvoller *), 
denn man muss nur den Platz belegen, der wirklich gebraucht wird. Musst 
du das C++-Kommittee fragen, warum sie das dort nicht haben wollten.

*) Ein Array unbestimmter Länge am Ende einer struct, wobei die 
tatsächliche Länge durch die Initialisierung dann ermittelt wird. 
Außerhalb von structs gibt es das ohnehin schon, denn das
1
char foo[] = "Hello, world!";

war schon immer möglich, und es ist auch etwas komplett anderes als
1
const char *foo = "Hello world!";

Letzteres legt nämlich ein anonymes Array an und hinterlegt in foo nur 
den Zeiger.

: Bearbeitet durch Moderator
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Übrigens waren mir damals bei meinen ersten Gehversuchen mit den 
USB-AVRs zwei Dinge wirklich hilfreich:

* eine UART am USB-AVR, mit der man sich Debugausgaben mitmeißeln konnte
* aktiviertes USB-Debugging auf einem FreeBSD-Host (allerdings einem 
"Bastelrechner", der sonst keinen USB-Traffic hatte), denn damit konnte 
man beispielsweise all das, was ich dir jetzt hier vom USB-Analyzer 
gezeigt habe, auch bei fehlgeschlagener Einbindung ins System anhand der 
Debug-Daten nachvollziehen

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.