Forum: PC-Programmierung MPC5200B mit Linux, leicht planlos


von gaston (Gast)


Lesenswert?

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

von Timmo H. (masterfx)


Lesenswert?

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

von gaston (Gast)


Lesenswert?

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.

von Timmo H. (masterfx)


Lesenswert?

1
#define <linux/io.h>
Wie wärs mit #include anstatt #define?
Außerdem ist ioremap glaub ich in <linux/vmalloc.h> definiert

von gaston (Gast)


Lesenswert?

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.

von Εrnst B. (ernst)


Lesenswert?

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.

von gaston (Gast)


Lesenswert?

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.

von Berti (Gast)


Lesenswert?

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ß,

von gaston (Gast)


Lesenswert?

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
}

von Berti (Gast)


Lesenswert?

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ß,

von Dave B. (gaston)


Lesenswert?

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

von Berti (Gast)


Lesenswert?

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ß,

von Dave B. (gaston)


Lesenswert?

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.

von Nandini Hengen (Gast)


Lesenswert?

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

von Superberti (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.