Hallo, Ich bastele zu Zeit an nem MPC5200B(-tiny)-Board rum. Dadrauf läuft der passende/mitgelieferte powerpc-Linux-2.6.23.1-Kernel. Jetzt kenn ich nicht so wahnsinnig mit Linux aus und brauch wohl ein paar Hinweise. Das Board sollte eigentlich einige GPIOs haben. Da bei mir aber was größeres geplant ist brauch ich relativ viele Pins 8+3 aber weiß nicht so recht wie ich die mir konfigurieren soll bzw. wie ich auf die einzelnen Pins zugreife. Bin für jede Hilfe dankbar. gaston
Du hast 56 GPIOs. Um diese als normale Pins zu verwenden musst du in den entsprechenden Registern auch erstmal sagen, dass sie GPIOs sein sollen. Schau dir mal im Datenblatt die GPS Port Configuration Register an. In der Memorymap findest du dann die Register wo du die Pins lesen und schreiben kannst. Einfach mal Abschnitt 7.3 im Datenblatt ansehen, dafür sind sie schließlich da! Da du Linux verwendest musst du den physikalischen Speicher erstmal Mappen, damit du darauf zugreifen kannst. Das geht glaub ich mit mmap und mit ioremap. Einfach mal die entsprechenden Applications Notes von Freescale anschauen
Sorry für die späte Antwort. Ich hab auch schon ins Datenblatt geschaut aber nicht so richtig daraus schlau geworden wie ich denn das implementieren soll. Ich habe ja die MBAR-Registeradresse und dann eigentlich auch die Offsets um die Pins als GPIO zu setzen. Es hapert leider an der Umsetzung. Ich hab auch schon versucht bei Freescale was zu finden aber da kann man nur schwer durchsteigen, geschweige denn was zum Laufen bringen. Mir würde ja auch schon ein paar Hinweise reichen wie ich denn mmap oder ioremap verwenden muss umd die Register auszulesen bzw. zu schreiben. Momentan akzeptiert der Compiler gar nix und meckert nur
1 | #define <linux/io.h>
|
2 | ...
|
3 | int main() |
4 | {
|
5 | unsigned int virt_base; |
6 | virt_base = (unsigned int) ioremap(0xf000000,0x4000); |
7 | /*Hier wirft er mir vor ioremap impliziet zu deklarieren und das ioremap eine undefinierte Referenz ist*/
|
8 | ...
|
9 | }
|
Eine ganz andere Sache ist dann wieder wie ich die Daten von den Pins wieder runterlesen kann. Es soll mal in ferner Zukunft ein MPEG-Strom über die Pins auf das Board geleitet werden zum weiterverarbeiten.
1 | #define <linux/io.h>
|
Wie wärs mit #include anstatt #define? Außerdem ist ioremap glaub ich in <linux/vmalloc.h> definiert
Argh dusseliger Tippfehler beim Übertragen. Habe natürlich include genommen. Das linux/io.h included auch nur asm/io.h und da gibts dann die Funktion ioremap. Beim linux/io.h und vmalloc.h werden irgendwelche Fehler in den Headern gefunden. Include ich nur asm/io.h bekomme ich erst Fehlermeldungen bei ioremap.
Korrigiert mich, wenn ich daneben liege: "ioremap" geht nur im Kernel-Space, d.H. du musst deine Anwendung als Kernel-Modul schreiben, bzw statisch in den Kernel einbauen.
Hmm naja klingt ja nicht ganz so berauschend. Dann könnte ich ja auch gleich vorm kompilieren des kernels mit da durchwuseln und versuchen die Pins nach meiner Wahl umzustellen. Geht es denn nicht zur Laufzeit ein Register zu lesen und einzustellen. Wenn ja, dann bitte auch kleinen Hinweis wie genau. Wie bereits gesagt hab ich ja aus dem DS die Registeraddresse und wie das dann aussehen sollte. Ich brauch ja nur die Bitmanipulation vorzunehmen bzw. den Wert reinzuschreiben. Aber es fehlt mir halt der Weg des Reinschreibens, ich hab ja auch schon eine Weile gesucht aber nichts anständiges gefunden bzw. nichts Funktionierendes. Es gibt ja auch eine Funktion, die glaub ich ioctl() heißt, mit der man irgendwelche I/O-Operationen vornehmen könnte.
Hi, Ich beschäftige mich nun schon länger mit dem MPC5200 unter Linux. Was Du vorhast klingt einfach, ist es aber nicht. Zuerst einmal musst Du den Überblick bekommen, dazu sollte man auch einmal die ppc-Mailinglisten sich ansehen, um die Komplexität des Themas verstehen zu können. Auf www.denx.de gibt es das DULG auch für den MPC5200, das ist zwar speziell für die TQ-Module aber trotzdem lesenswert! Du möchtest also auf recht viele GPIOs zugreifen. Kein Problem, nur sind die Beine dieses Chips extrem stark gemultiplext und Du musst Dir die richtige Port-Konfiguration aus dem Datenblatt zusammensuchen. Dann sollte die Firmware (U-Boot?) die Portkonfiguration setzen (dabei solch Kleinigkeiten wie Bit0->most significant bit (MSB) etc. beachten!). Dann ist dabei noch darauf zu achten, durch die Portumkonfigurierung nicht irgendwelche Hardware (SIOs, USB, I2C etc.) ab- oder umzuschalten, die bestimmte Treiber vom Kernel erwarten. Firmware flashen, Kernel flashen. Für die Kommunikation mit den GPIOs benötigst Du einen Treiber. Das ist aber ein Thema für sich und Du musst Dir dafür zumindest "Linux Kernel Driver, 3.Auflage" zulegen um das zu verstehen (es gibt inzwischen auch ein deutsches Buch für den 2.6-Kernel, Name hab ich grad vergessen). Mit dem Treiber kommunizierst Du dann in Deiner Applikation. Entweder mit "normalen" read/write-Befehlen oder mit speziellen IOCTLs. Ein IOCTL ist die Schnittstelle zu Deinem Treiber. D.h. in der Applikation rufst Du einen bestimmten IOCTL auf und in Deinem Treiber wird dieser dann per Softwareinterrupt ausgeführt. Ohne Treiber kein IOCTL! Wenn Du mir sagst, was genau Du vorhast, dann kann ich Dir auch einen einfachen Treiber für Dein Vorhaben geben, den Du leicht anpassen kannst. Leider muss man für die ganze Sache so einiges an Arbeit investieren, wenn man die Funktionsweise von Treibern im Kernel verstehen möchte. Allerdings gibt es einige neue Ansätze Treiber im User Mode zu schreiben, damit habe ich mich noch nicht beschäftigt. Ich hoffe, das Alles schreckt Dich jetzt nicht ab, aber der MPC5200 ist ein ganz schön komplexes Teil, kann dafür aber auch viel. Gruß,
Tschuldigung für die abermals späte Antwort. Eigentlich ziele ich darauf ab einen anliegenden schnellen Datenstrom einzulesen (8 verschiedene Pins geben 1 Byte je Clock) und für andere Anwendungen zugänglich zu machen die dann die Bytes weiter verarbeiten sollen, ich brauch also nicht den ganzen Datenstrom sondern nur immer ausreichend große Pakete daraus die ich anderweitig verwende und dann wieder verwerfen kann. Habe jetzt schon etwas weiter daran gearbeitet. Momentan habe ich ein Modul gebastelt das beim init mir die Pins konfiguriert und einen /proc-Eintrag erstellt um einen Zugriff zu ermöglichen. Als Ansatz dafür habe ich mir FIFO-Puffer aus diesem Beispiel genommem [http://www.captain.at/howto-linux-kernel-module-fifo.php]. Damit kann ich erst einmal aus meiner Anwendung auf der User-Ebene heraus Lesevorgänge start (read_proc). Dies hab ich auch ersteinmal soweit wie möglich übernommen jedoch in der Lesefunktion im Modul rufe ich jedesmal meine Byte-Zusammenstellungsfunktion auf. In dieser mappe ich die GPIO-Register und schiebe mir dann die anliegenden Bits zu einem Byte zusammen und entmappe das ganze wieder. Das scheint auch soweit zu klappen das ich aus meiner "Anwendung" Daten lesen kann. Problematisch ist bei der ganze Sache jedoch das ich für das Datenbyte den PSC3-Bereich umbügele und damit auch meine UART-Schnittstelle beeinflusse. Bei der Initialisierung stelle ich alle dazugehörigen Pins als Inputs ein, aber ich habe keine Möglichkeit gefunden die serielle Ausgabe abzuklemmen. Das heißt ich erhalte wilden Datensalat auf der COM-Schnittstelle. Das ist zwar nicht weiter störend, da ich über telnet herangehe aber ich würde doch gern den Treiber dafür abstellen wollen um die serielle Ausgabe von ttyPSC0 und ttyPSC1 zu verhindern. Am originalen Kernel wollte ich dafür noch nicht herumpfuschen aber wenn es nicht anders geht würde ich auch das versuchen. Für die seriellen Treiber f0002400.serial und f0002c00.serial gibt es zwar ein bind/unbind aber das hat nach meinen "Versuchen" noch nicht so recht funktioniert. Meine 3 zusätzlichen Pins (aus PSC6) sollen mir den Status melden bzw. an einem liegt ein clock-Signal an für die Datenübertragung. Das clock-Signal habe ich auch erstmal an einen Interrupt-fähigen Pin gelegt in der Hoffnung, jedesmal einen Interrupt auszulösen und in der ISR den Status zu testen und ein Byte zusammenzulesen. Jedoch habe ich da noch so einige Bedenken wegen des Timings, ob das mappen der Register auch schnell genug erfolgen kann. Mit der Interrupt-Anforderung habe ich so meine Probleme dies zu mappen bzw. in Griff zu bekommen. Es gibt ja vielerlei Beispiele für einen Paralellport dieser hat ja aber seinen vordefinierten Interrupt und kann REQUEST_IRQ(...) aufrufen was mir bei mir noch nicht gelungen ist bzw. ich keinen rechten Ansatzpunkt dafür finde. Momentan läuft es bei mir nur durch ein Polling, ich lese aus meinem Puffer x Byte indem ich für jedes Byte die Pins lese und schreibe diese raus. Dadurch ist der anliegende Datenstrom natürlich kaum konsistent da ich ja zu beliebígen Zeiten nachschaue und nicht wenn mir die clock sagt das gerade etwas angekommen ist.
1 | //read fifo
|
2 | static int read_proc(char *page, char **start, off_t offset, int count, int *eof, void *data) |
3 | {
|
4 | //count want to read count byte
|
5 | int len =0; |
6 | |
7 | *start = page; |
8 | *eof = 0; |
9 | |
10 | disable_writing =1; |
11 | |
12 | while (read_pos!=write_pos && len <= (count - MAX_STR_LEN)) |
13 | {
|
14 | buf[read_pos] = (long) read_databyte(); // MEINE LESEFUNKTION FÜLLT DEN PUFFER |
15 | memcpy((*start)+len,&buf[read_pos],MAX_STR_LEN); |
16 | len = len + MAX_STR_LEN; |
17 | inc_read_pos(); |
18 | }
|
19 | if (read_pos == write_pos) |
20 | *eof = 1; //read all data |
21 | disable_writing = 0; |
22 | return len; |
23 | }
|
Hi nochmal, Ich würde Dir dringend empfehlen, bei der Treiberprogrammierung systematisch vorzugehen. Mal ein wenig Quellcode von irgendeinem Treiber anzusehen reicht einfach nicht aus. Ich habe hier einen Link für Dich: http://ezs.kr.hsnr.de/TreiberBuch/html/ Alternativ gibt es auch die "Treiberbibel" in english für den Kernel 2.4 online: http://www.xml.com/ldd/chapter/book/ Meiner bescheidenen Meinung nach brauchst Du einen Interruptgesteuerten Treiber, der dann die Daten zwischenspeichert (z.B. im Ringpuffer), bis du sie dann von Deiner Applikation abholst (also im Usermode). Du schreibst leider nicht, ob Du mit ARCH=ppc oder ARCH=powerpc compilierst, denn davon hängt es ab, wie man an die Nummer des Interrupts für Deinen GPIO-Pin kommt. Die modernere Form ist ARCH=powerpc, dort bildet sich die Hardware in einem s.g. Device-Tree ab, in dem kannst Du dann auch Deine seriellen Schnittstellen deaktivieren. Bei der älteren Architekur sind die zu verwendenen Schnittstellen meistens mit #ifdef hartcodiert, oft auch in den Treibern selbst. Finde heraus, mit welcher Architektur Dein Kernel läuft und dann sehen wir weiter. Gruß,
Hallo und danke schon mal für die Antwort. Ich weiß das meine Herangehensweise bisher nicht wirklich ordentlich war aber bin da auch wie die Jungfrau zum Kind gekommen und wollte erst einmal ausprobieren ob überhaupt etwas funktioniert. Ich verwende ARCH=powerpc. Den device-tree habe ich mir auch bereits einmal angeschaut, bin aber auch nicht 100% schlau daraus geworden, wie man diesen gefahrlos verändern bzw. seinen Nutzen daraus ziehen kann. Danke schon mal für die Bemühungen
Hallo, O.K., Du verwendest also ARCH=powerpc. Ich weiß jetzt nicht, ob es für Dein Board ein eigenes Device Tree File gibt (.dts - Datei), aber Du kannst auch z.B. das lite5200b.dts verwenden und modifizieren. Du findest darin z.B. die Definition für PSC1 (=/dev/ttyPSC0): serial@2000 { // PSC1 device_type = "serial"; compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart"; port-number = <0>; // Logical port assignment - reg = <2000 100>; + reg = <0x2000 0x100>; interrupts = <2 1 0>; interrupt-parent = <&mpc5200_pic>; }; Wenn Du die auskommentierst, dann sollte kein Treiber für PSC1 mehr geladen werden. Es gibt im Kernel unter "docs/booting-with-of.txt" ein Dokument, was mehr oder weniger gut die Struktur des DTS beschreibt. Leider verwende ich momentan noch aus bestimmten Gründen den 2.4-Kernel, sonst könnte ich Dir evtl. genauer verraten, was Du dort eintragen musst. Mit dem Device-Tree-Compiler (dtc genannt) kompilierst Du Dir eine dtb-Datei, die mit auf's Board geflasht wird und vom Kernel zur Laufzeit entpackt wird. Einzelheiten dazu sind, wie schon mal erwähnt, auf dem DULG unter www.denx.de beschrieben (tqm5200-Board auswählen). Nun zum Treiber: Diese ganze Device-Tree-Sache ist sehr neu, ändert sich momentan noch recht häufig und ist unglücklicherweise in keinem der von mir erwähnten Bücher aufgeführt. Vor allem die Funktionen "of_xxx", die die Anbindung der Treiber an das Device-Tree-File herstellen sind hierbei hervorzuheben. Wenn Du also bestimmte I/O-Adressen und Interrupts herausfinden willst, dann benötigst Du diese Funktionen (damit wird effektiv die .dtb-Datei geparst). Am besten, Du schaust Dir dazu einen Treiber, wie z.B. den der seriellen Schnittstellen an (drivers/serial/mpc52xx_uart.c). Ich würde Dir auch dringend dazu raten, einen neuen Kernel zu verwenden (auch von www.denx.de), da sich dort noch in letzter Zeit sehr viel geändert hat. Alternativ könntest Du aber auch auf den 2.4-Kernel zurückrüsten, falls das bei Dir möglich ist. Der Kernel ist zwar nicht so flexibel, die Treiberentwicklung dafür aber auch weniger aufwendig. Ich denke, als Einsteiger kommt man damit besser zurecht. Ich weiss, alles ganz schön aufwendig, und man will ja auch nicht gleich für jeden Mist Experte werden, aber wenn man erst einmal diese Ochsentour durchstanden hat, dann hat man auch jede Menge wertvolles Wissen für's nächste Projekt gesammelt :) Gruß,
Hmm hab jetzt schon so ein bisschen am Device-Tree herumgearbeitet und die seriellen Schnittstellen auskommentiert und Kernel damit kompiliert aber das bringt auch nicht so die Erleuchtung da dann mein Kernel beim entpacken des device tree sich aufängt. Den blob über uboot zu laden hat eben auch nicht so hingehauen. Ich sage mal, das die serielle Schnittstelle mit arbeitet ist zwar unschön aber damit kann ich vorerst mal noch leben. Was mir aber vordringlichst Sorgen macht ist der Interrupt. Wenn der schon einmal schalten würde bzw. ich den stellen könnte würde mir schon ein Stein vom Herzen fallen.
Hallo, ich habe derzeit dasselbe Problem (Kernel hängt sich auf beim Entpacken des device trees) Distribution: OpenSuse 11.1, IA-64 Kernel-Quellen: 2.6.29 ARCH = ppc CROSS_COMPILE = powerpc-603e-gnu-gcc Hardware-Revision: Phytec MPC5200B-tiny U-Boot Version 1.2 samt downloaded patches Ich habe es inzwischen mit verschiedensten Kernelversionen 2.4.x in Kombination mit U-Boot 1.1.4 ausprobiert. In diesem Zusammenhang hatte ich ein Thread gefunden von denx, wonach eine neue Uboot-Version unbedingt benutzt werden sollte und die dtb-Datei separat ins RAM kopiert werden sollte. Zum Erzeugen des Kernel-Images und das device-tree benutze ich: make uImage make filename.dtb mit den entsprechenden options für ARCH und CROSS_COMPILE Zwei Phytec-Module habe ich mittlerweile getestet - beide gehen nicht. Entweder hat die Hardware eine Macke oder das Kernel-Image... ich tippe eher auf das zweite, bin jedoch etw. ratlos, wo genau der Fehler liegt. Passt evtl. die Hardware Revision nicht zum Kernel oder fehlen weitere Patches hierzu ? Jedenfalls hängen sich sämtliche Images auf nach dem Entpacken (Wrapped Variante) oder nachdem versucht wurde, das device tree zu laden... bin für jeden Hinweis dankbar! Mit freundlichen Grüßen Nandini Hengen
Hi Nandini, was für einen Kernel setzt Du jetzt denn auf dem MPC ein? 2.6.29 oder einen 2.4er Kernel? 2.4er-Kernel und device trees passen ebensowenig zusammen wie ARCH=ppc und device trees! Oder anders herum gesagt: Beim 2.4er gibt es keinen device tree und man darf beim Booten ("bootm"-Kommando im U-Boot) auch auf keinen Fall eins angeben. Bei einem neuen 2.6er-Kernel geht aber ARCH=ppc nicht mehr. Das geht auch aus den vorherigen Posts hervor, bitte noch mal durchlesen! Gruß,
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.