Hallo Liebe µC Gemeinde, ich war mir eigentlich sicher diesen Thread schon vor 20min geschrieben zu haben aber offensichtlich habe ich ihn garnicht abgeschickt. Egal, falls ich das doch getan haben sollte tut mir das leid. Zum Thema: Ich arbeite mich gerade in die USB Geschichte ein und will dazu USB Controller auf dem LPC1837 Controller von NXP (32Bit) ansteuern. Dieser treibt mich allerdings in den Wahnsinn. Im Datenblatt steht geschrieben, das ich einen Speicher in Form eines Arrays anlegen soll, der die sogenannten EndPointQueueHeads enthält. Somit ist dieser eine Liste von EndPointQueueHeads, im Datenblatt bezeichnet als EndPointQueueList. Für diese Liste gibt es einen Register, in dem ich die Adresse dieser Liste ablegen soll. Das dumme daran: Dieser Register ist von LPC_OPEN definiert als int Zahl. Dazu kommt, das die untersten 10Bits von diesem Register reserviert sind. WIe soll ich bitte auf einem 32Bit System eine Adresse übergeben wenn, die unteren 10bit garnicht gelesen werden? Wenn ich diesen Register nun beschreiben will mit der Adresse dann steht am Ende da natürlich jede Menge unfug drinne, aber nicht die Adresse meiner QueueList. Hat das Jemand von euch schon mal gemacht? Ich habe gesehen das dieses Prinzip der EndPointQueueList nicht auf LPC begrenzt ist.
Bei GCC mit aligned attibute:
1 | |
Damit sind die unteren 10 Bits von EndPointQueueList gleich null. Übrigens würde ich mich nach Beispielcode vom Hersteller umsehen, USB hat etliche Fallstricke bevor man das zu Fuß funktionierend programmiert hat.
Gast
#4267243
Ludwig S. schrieb: > USB Controller auf dem LPC1837... Erstmal eines: Lies das Manual nochmal gründlich. Manchmal hat es in den µC einen völlig separaten RAM-Bereich, der NUR für USB oder (evt. exclusiv) für Ethernet reserviert ist. Vielleicht ist SOWAS gemeint. Im normalen Programm so einen speziellen Puffer zu erwarten wäre m.E. viel zu unwahrscheinlich. Den von dir genannten µC hab ich noch nicht unter den Fingern gehabt, aber vielleicht hilft dir zum Verstehen einiger Dinge ein Blick auf nen Treiber, den ich für nen älteren LPC mal geschrieben hatte. Ich häng ihn die hier mal an. Aber: nur für verstehendes Lesen, nicht für copy&paste. W.S.
W.S. schrieb: > Aber: nur für verstehendes Lesen, nicht für copy&paste. Ich bin ja nicht doof ;) Danke Danke dein Beispiel wird mir denke ich, sehr weiterhelfen. Wegen der QueueList: Du meintest das deiner Meinung nach unwahrscheinlich ist das man so einen speicher selber machen soll. Ehrlich gesagt denke ich das auch. Aber es steht eigentlich unmissverständlich im Datenblatt! Nichtsdesotrotz werde ich mich morgen nocheinmal gründlich mit dem datenblatt auseinandersetzen. Heute schaff ich das nicht mehr. Ich werde die Community natürlich auf dem laufenden halten ;)
Ach und an Jim Meba: es gibt ein Beispiel vom Hersteller das ist allerdings mit den internen API Befehlen geschrieben. Die gibts bei dem Chip auf einem extra teil im ROM. Wenn ich allerdings die allgemeine Funktion des Controllers nicht kapiere, dann denk ich mal nutzen mir die API Befehle auch nix. Hab schon nach nem anderen Beispiel gesucht, aber bisher bin ich nich wirklich fündig geworden. Bin ehrlich gesagt was USB betrifft, auch Neueinsteiger! Das mit dem align is bestimmt praktisch aber wenn ich den register beschreibe werden wie ich jetzt herausgefunden hab, sowieso alle bits unten abgeschnitten, bzw nach links verschoben
W.S. schrieb: > Erstmal eines: Lies das Manual nochmal gründlich. Manchmal hat es in den > µC einen völlig separaten RAM-Bereich, der NUR für USB oder (evt. > exclusiv) für Ethernet reserviert ist. Vielleicht ist SOWAS gemeint. Definitiv nicht, wenn man das Manual liesst. Dort steht dann auch drin, dass untergeordnete Strukturen auf 64 Byte aligned sein müssen. NXP hat sich da ein paar Addressbits gespart, vermutlich weil das Peripherial auch High-Speed können soll. Ludwig S. schrieb: > es gibt ein Beispiel vom Hersteller das ist > allerdings mit den internen API Befehlen geschrieben. Die gibts bei dem > Chip auf einem extra teil im ROM. Dann nutze die doch! Habe ich beim LPC1343 für HID auch so gemacht, ist viel einfacher als den Mist selbst zu schreiben. Und der LPC18xx scheint sogar CDC im ROM zu unterstützen. USB auf low Level zu debuggen ist eher unangenehm, weil dabei der Host öfters mit Timeout oder Fehlern aussteigt.
problem is, ich weiß bei den APIs da nicht so richtig wo ich anfangen soll. Weil ich ja keine Ahnung hab, was der controller als erstes braucht. Ne Clock - das is klar! Dazu kommt, das sowie mein programmzeiger im ROM verschwunden ist, weiß ich ja dann auch nicht mehr richtig was er so tut. Ich weiß auch ehrlich gesagt nicht so richtig wie ich ihn dann zurückholen kann... im cdc beispiel gibts dafür callback funktionen aber woher weiß ich wie die aussehen müssen wenn ich keine ahnung hab wie die funkionen aussehen? Du siehst mit fehlt noch immer so'n bisschen ne Vorstellung von dem Ding.
Gast
#4268670
Ludwig S. schrieb: > Ne Clock - das is klar! Dazu kommt, das sowie mein > programmzeiger im ROM verschwunden ist, weiß ich ja dann auch nicht mehr > richtig was er so tut. O je, das blutet ja noch... Also, mal der Reihe nach: 1. Clock, Power, Portbeine, Interrupt aktivieren bzw. freischalten 2. Die Register für die gewünschten Endpoints einrichten Ich hab jetzt mal im UM10430 nachgesehen: Der USB-Core enthält RAM, und zwar 356 Words bzw. 128 Words pro Endpoint. Siehe 23.4.4 3. den 2k7 Widerstand am USB aktivieren 4. jetzt sollte das erste Setup-Paket vom Host eintrudeln und anschließend der zuständige Interrupt losgehen. 5. Denk bloß nicht mal im Traum daran, dort herumdebuggen zu wollen. Du wirst nach 3 ms vom Host herausgekickt und Ende der Vorstellung. Allenfalls kannst du dir ne Art Postmortem-Debugger schreiben: einfach das, was du dir selbst zu sagen hast, in einen bereitgestellten RAM-Puffer schreiben (aber hurri hurri Egon - alles getimed! Also kein sprintf und Konsorten) und später per UART zum PC schaufeln. W.S.
Ok Danke... das probiere ich jetzt mal so aus! Trotzdem würde mich schon interessieren was es mit diesem verfluchten ENDPOINTLISTADR Register auf sich hat. W.S. schrieb: > 2. Die Register für die gewünschten Endpoints einrichten > Ich hab jetzt mal im UM10430 nachgesehen: Der USB-Core enthält RAM, und > zwar 356 Words bzw. 128 Words pro Endpoint. Siehe 23.4.4 Aber wie komm ich da ran?
Ludwig S. schrieb: > W.S. schrieb: >> 2. Die Register für die gewünschten Endpoints einrichten >> Ich hab jetzt mal im UM10430 nachgesehen: Der USB-Core enthält RAM, und >> zwar 356 Words bzw. 128 Words pro Endpoint. Siehe 23.4.4 > > Aber wie komm ich da ran? Gar nicht. Der wird vom USB peripherial verwaltet und gefüttert. Dafür ist u.a. die oben genannte EndPointQueueList die Voraussetzung. Da USB ein AHB Master ist, läuft der Datenaustausch als DMA ab (direkt, ohne Verwendung des DMA peripherials). Hintergrund ist dass der USB RAM asynchron auf einer anderen Taktfrequenz laufen kann als der System RAM - bei High Speed muss der Zugriff sehr schnell erfolgen.
Ok Ok... Aber die Queue List wird schon von den API Befehlen selber angelegt oder was? Ich konnte bisher bei allen Beispielen keine QueueList finden.
Gast
#4271922
Ist in den LPCOpen Beispielen nichts brauchbares dabei? Da sind doch einige die LPCUSBLib benutzen (ohne ROM Unterstützung) und auch welche mit ROM: https://www.lpcware.com/content/nxpfile/lpcopen-software-development-platform-lpc18xx-packages-0
Gast
#4272001
Ludwig S. schrieb: > Aber wie komm ich da ran? durch das wirklich gründliche Lesen des Manuals. Sonst nicht. Glaube bitte nicht, daß ich den Treiber, den ich dir gepostet habe, mal eben so ohne x-maliges Durchlesen des RefMan's zuwege gekriegt habe. Wie ist das denn heute so (im Gegensatz zu früher) "ohne Preis kein Fleiß" ?-) W.S.
So ich bin zwar jetzt nicht viel weiter aber immerhin ein bisschen: also ich habe mich denn doch dazu entschieden die APIs zu benutzen. Aber das Rätsel um die QueueHeads sind dennoch ziemlich mysteriös. In der app_usbd_cfg.h steht folgendes geschrieben: /* On LPC18xx/43xx the USB controller requires endpoint queue heads to start on a 4KB aligned memory. Hence the mem_base value passed to USB stack init should be 4KB aligned. The following manifest constants are used to define this memory. */ #define USB_STACK_MEM_BASE 0x20000000 #define USB_STACK_MEM_SIZE 0x00002000 Also 0x2000 sind erstmal 8kb, daher gehe ich mal davon aus das er hier gerade den speicher für 2 endpoint also zwei queueheads definiert?! Woher kommen die 0x20000000? Das einzige was ich unter der adresse finden konnte ist, das dort der sram losgeht. Dann habe ich einfach mal losgelegt und nach und nach versucht mich durch zu fummeln. Mein Ziel ist es probehalber mein Device als MassStorageDevice am PC anzumelden. Problem ist jetzt, das ich nachdem ausführen der Funktion Init einen Wert zurückbekomme. Dies ist ein ErrorHandler und als Wert bekomme ich 0x40008 -> Bad InterfaceDescriptor Ich kann an meinem InterfaceDescriptor aber keinen Fehler erkennen?! (Quelltext folgt gleich)
Das ist der Quelltext
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.