www.mikrocontroller.net

Forum: PC-Programmierung MPC5200B mit Linux, leicht planlos

Autor: gaston (Gast)
Datum: 09.06.2008 14:45

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
Autor: Timmo H. (masterfx)
Datum: 10.06.2008 08:38

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
Autor: gaston (Gast)
Datum: 12.06.2008 13:51

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
#define <linux/io.h>
...
int main()
{
unsigned int virt_base;
virt_base = (unsigned int) ioremap(0xf000000,0x4000); 
/*Hier wirft er mir vor ioremap impliziet zu deklarieren und das ioremap eine undefinierte Referenz ist*/
...
}

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.
Autor: Timmo H. (masterfx)
Datum: 12.06.2008 13:57

#define <linux/io.h>
Wie wärs mit #include anstatt #define?
Außerdem ist ioremap glaub ich in <linux/vmalloc.h> definiert
Autor: gaston (Gast)
Datum: 12.06.2008 14:08

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.
Autor: Ernst Bachmann (ernst)
Datum: 12.06.2008 14:56

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.
Autor: gaston (Gast)
Datum: 12.06.2008 16:16

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.
Autor: Berti (Gast)
Datum: 23.06.2008 22:50

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ß,
Autor: gaston (Gast)
Datum: 09.07.2008 13:52

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.
//read fifo
static int read_proc(char *page, char **start, off_t offset, int count, int *eof, void *data)
{
  //count want to read count byte
  int len =0;
  
  *start = page;
  *eof = 0;

  disable_writing =1;

  while (read_pos!=write_pos && len <= (count - MAX_STR_LEN))
  {
    buf[read_pos] = (long) read_databyte(); // MEINE LESEFUNKTION FÜLLT DEN PUFFER
    memcpy((*start)+len,&buf[read_pos],MAX_STR_LEN);
    len = len + MAX_STR_LEN;
    inc_read_pos();
  }
  if (read_pos == write_pos)
    *eof = 1; //read all data
  disable_writing = 0;
  return len;
}
Autor: Berti (Gast)
Datum: 12.07.2008 18:07

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ß,
Autor: Dave B. (gaston)
Datum: 14.07.2008 09:50

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
Autor: Berti (Gast)
Datum: 14.07.2008 22:23

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ß,
Autor: Dave B. (gaston)
Datum: 16.07.2008 14:39

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.

Antwort schreiben

Die Angabe einer Email-Adresse ist freiwillig. Wenn Sie automatisch per Email über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Suchfunktion und Betreffsuche benutzen - vielleicht gibt es schon einen ähnlichen Beitrag
  • Aussagekräftigen Betreff wählen
  • Im Betreff angeben um welchen Controllertyp es geht (AVR, PIC, ...)
  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
  • JPEG-Dateien (.jpg) nur für Fotos und Scans verwenden
  • Schaltpläne, Screenshots usw. als PNG oder GIF anhängen

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [pre]vorformatierter Text (z.B. Code in anderen Sprachen)[/pre]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel






webmaster@mikrocontroller.netImpressumWerbung auf Mikrocontroller.net