AT90USB162 Endpoint Interrupts funktionieren nicht

#6875767
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.
#6875801
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.
#6876598
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.
#6876677
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()
#6876704
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.
#6876850
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.
#6876854
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.
Moderator Persönliche Seite #6876882
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.
#6876919
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.
Moderator Persönliche Seite #6876923
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.
#6876938
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.
#6876943
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.
Angehängte Dateien:
#6876999
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.
Moderator Persönliche Seite #6877042
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.
Moderator Persönliche Seite #6877157
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.
Angehängte Dateien:
#6877353
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) ?
#6877727
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.
Angehängte Dateien:
#6877736
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)
#6877743
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.
#6877770
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.
Angehängte Dateien:
Moderator Persönliche Seite #6877785
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/
#6877816
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.
#6877826
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.
#6877982
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.
#6879072
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.
Gast #6879090
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?
#6879100
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 ?
Moderator Persönliche Seite #6879102
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.
#6879113
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.
#6879126
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 ?
Gast #6879128
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!
#6879135
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.
Gast #6879139
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.
Moderator Persönliche Seite #6879144
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.)
Moderator Persönliche Seite #6879146
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.
Gast #6879151
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.
Moderator Persönliche Seite #6879159
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.
#6879166
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.
#6879170
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)
Moderator Persönliche Seite #6879173
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.
#6879176
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.
Moderator Persönliche Seite #6879181
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.
Moderator Persönliche Seite #6879185
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.
#6879223
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.
Angehängte Dateien:
#6879410
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. :-)
#6879694
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 ?
Angehängte Dateien:
#6879729
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.
#6879737
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.
#6879752
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
#6879758
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.
#6879804
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
#6879827
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 ?
Moderator Persönliche Seite #6879840
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.
#6879852
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).
Angehängte Dateien:
Moderator Persönliche Seite #6879878
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.
#6879911
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.
Moderator Persönliche Seite #6880145
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.
#6880175
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.
Moderator Persönliche Seite #6880200
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.
Moderator Persönliche Seite #6880204
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>
Moderator Persönliche Seite #6880394
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.
Angehängte Dateien:
#6880419
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.
#6880948
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
#6880967
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.
Moderator Persönliche Seite #6882332
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*.
#6882381
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.
Moderator Persönliche Seite #6882428
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
Moderator Persönliche Seite #6882439
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.)
Moderator Persönliche Seite #6882473
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).
#6882539
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
....
Moderator Persönliche Seite #6882706
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
Angehängte Dateien:
Moderator Persönliche Seite #6882933
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
#6883171
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.
Moderator Persönliche Seite #6883218
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. 
;-)
#6883349
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 ?
Moderator Persönliche Seite #6883450
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.
#6889160
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 ?
Moderator Persönliche Seite #6889178
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.
#6889236
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" ...
#6889541
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).
Moderator Persönliche Seite #6889690
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.
#6890295
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.
Moderator Persönliche Seite #6890431
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.
#6892338
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.
Moderator Persönliche Seite #6892435
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.
Angehängte Dateien:
#6892479
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.
#6895599
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.
Angehängte Dateien:
#6895604
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.
Moderator Persönliche Seite #6895686
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.
#6895875
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).
Moderator Persönliche Seite #6895943
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.
#6896679
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.
Angehängte Dateien:
#6899967
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 
?
#6900449
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.
#6900477
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)
#6900499
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.
#6900513
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.
#6900682
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.
Moderator Persönliche Seite #6900944
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
Moderator Persönliche Seite #6900994
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.
Moderator Persönliche Seite #6901201
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.
Moderator Persönliche Seite #6901205
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren