Mahlzeit!
Ich bin gerade dabei, für meine Diplomarbeit ein LEON3-System
(www.gaisler.com) auf einen FPGA zu basteln und dafür irgendwelche
Software zu programmieren.
Nach 7 Monaten (!) harter Arbeit bin ich endlich soweit, dass meine Tool
Chain steht. Ich habe auf meinem FPGA-Board den LEON laufen und konnte
schon einfache C-Programme ausführen, die durch direkte
Register-Adressierung auf verschiedenen Ports (zB UART, Text-basierter
VGA-Ausgang) Zeichen ausgeben.
Nun soll ich jedoch die mitgelieferten C-Libraries (spezielles GCC für
den LEON gibts dazu) verwenden, um nicht mehr direkt in Register zu
schreiben sondern Funktionen wie printf zu nutzen.
printf("Hello World\n") hat schonmal funktioniert... das wird dann auch
auf UART ausgegeben. Aber wie komme ich jetzt an die anderen Ports?
Irgendwie kann man ja wohl Streams umleiten, davon verstehe ich aber
absolut nichts.
Mir fehlen einfach zu viele Grundlagen in Sachen C-Programmierung um
irgendwelche Toturials o.ä. im www zu verstehen.
Auch den entsprechenden Artikel hier
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Die_Nutzung_von_printf
verstehe ich gar nicht...
Ich weiß, wie schwer es für euch ist, mir eine passende Antwort zu
geben, da ich ja selbst kaum eine Frage formulieren kann...
Vielleicht kann mir ja einfach jemand den richtigen Weg zeigen, damit
ich den ganzen Kram mit StdIO verstehe.
Ich hoffe ihr habt ein bisschen Mitleid übrig für absolute Newbies.
Danke euch!!!
Du brauchst 7 Monate harte Arbeit um das erste Programm auf dem Ding
laufen zu lassen?! Da wundert es mich nicht, das du es nicht schaffst
die Worte "C stdio stream umleiten" bei google einzugeben. Aber das ist
nicht dein größtes Problem. Es wird für dich wahrscheinlich nicht so
leicht zu verstehen sein, aber glaub mir, um C programmieren zu können
muss man es wirklich vorher lernen. Kaum zu glauben, ist aber so. Mit
ein bisschen Glück kannst du dann sogar die Tutorials verstehen, die
hier zu finden sind. Ich denke aber du hast noch ein anderes großes
Problem. Es wird dir bisschen komisch vorkommen, aber die anderen Leute
können wirklich nicht deine Gedanken lesen. Was meinst du z.B. mit "den
anderen Ports"? Einen zweiten UART, TCP/IP oder CAN? Wenn du einen UART
meinst, dann ist es relativ einfach. Allerdings braucht man da auch
Ahnung von C.
Hi!
Das so eine Antwort kommt hab ich schon erwartet, deswegen hab ich mich
ja im Vorraus für meine Unwissenheit entschuldigt... Ich weiß, dass hier
niemand hellsehen kann.
Also google hab ich auch schon benutzt, sogar genau so, wie du es
vorschlägst;) Aber wie gesagt, wenn einem komplett die Grundlagen
fehlen, versteht man da halt nicht wirklich viel.
Das Problem ist halt einfach, dass mein Prof davon ausgeht, dass ich C
programmieren kann. Schliesslich gabs da im 1. Semester eine Vorlesung
zu. Da haben wir allerdings nur einfache Programme ins Visual Studio
getippt und uns gefreut, dass irgendwas in der Konsole von Windows
ausgegeben wurde...
Was ich die letzten 7 Monate gemacht habe, kann ich ja mal kurz
erklären:
Zunächst brauchte ich ein Linux-Betriebssystem für die Tool Chain. Linux
hatte ich vorher nie benutzt...
Dann die Geschichte mit Makefiles usw... wie schon in der GCC-Tutorial
beschrieben, ist das für einen Visual-Studio- und Windows-Benutzer alles
sehr verwirrend am Anfang. Sämtliche Dokumentation zum LEON setzen halt
auch schon sehr viele Grundlagen vorraus, die ich mir erstmal erarbeiten
musste.
Anfangs hat man schliesslich nur einen riesen Haufen VHDL-Dateien und
ein paar Makefiles. Also brauchte es schonmal knapp ein halbes Jahr, bis
der LEON auf dem FPGA war und Lebenszeichen von sich gab.
Aber ich wette, Du hättest das an 2 Tagen geschafft, oder?
Wie auch immer, es ist halt einfach so, dass mein Prof von mir Sachen
erwartet, für die mir bei weiten zu viele Grundlagen fehlen. Leider hat
er von der Sache auch keine Ahnung und stellt sich das alles ganz
einfach vor (genau wie Du ^^).
Und ich versuche jetzt halt irgendwie den Einstieg zu schaffen.
Vielleicht hat ja doch noch jemand Lust, mit mir heraus zu finden, WO
ich überhaupt einsteigen muss...
Also nochmal Danke!!!
Ich denke mal, das hier so zwischen null bis kaum einer was mit LEON
anfangen kann.
Wenn Du also LEON spezifische IO-Funktionen nutzen willst, mußt Du in
die LEON-Doku schauen.
Vielleicht steht ja auch was in den h-Files (z.B. stdio.h), aber das ist
in der Regel sehr kryptisch, wirklich nur was für C-Programmierer.
Ich stimme auch zu, C lernt man nicht mal so eben schnell.
Eine Sprache allein nützt auch garnichts, man muß außerdem die
Herangehensweise an eine Programmieraufgabe lernen, also wie man eine
Aufgabe plant, strukturiert und implementiert.
Peter
Hallo Peter,
erstmal Danke für Deine Antwort. Du versuchst wenigstens wirklich zu
helfen :)
Es ist klar, dass ich nicht "mal eben" C-Programmierung lernen kann.
Prinzipiell würde ich aber schon behaupten, dass ich systematisch an
Programmier-Aufgaben herangehen kann. Jedoch habe ich embedded-Systeme
bisher nur in ASM programmiert und Hochsprachen wie C oder JAVA nur für
kleine Windows-Applikationen benutzt. Für mich ist es einfach sehr
schwer, die Brücke zwischen hardwarenaher und abstrakter Programmierung
zu finden.
Zumindest hab ich ja schonmal herausgefunden, wie ich in C direkt
Register des LEON anspreche. Aber ich soll jetzt eine Abstraktionsebene
höher gehen.
Die Dokumentation zum LEON sagt zum StdIO nur das hier:
BCC applications uses Newlib, which is a posix compatible C-library with
full math support. However, no file or other I/O related functions will
work, with the exception of I/O to stdin/stdout. Stdin/stdout are mapped
on UART A, accessible via the usual stdio functions.
Das hilft mir nicht wirklich weiter...
Evtl. kann mir jemand eine gute Doku zur "Newlib" empfehlen, wo meine
Fragen (teilweise) beantwortet werden?!
In der stdio.h hab ich schonmal nachgeschaut, aber wie Du schon sagtest:
alles sehr kryptisch... Soweit ich das sehe, werden da nur jede Menge
Konstanten festgelegt.
Ich stelle mir das eigentlich so vor (wahrscheinlich völlig falsch...):
Mein UART liegt auf der Adresse 0x80000100. Jetzt müsste doch irgendwo
sowas stehen wie stdio=0x80000100. Das würde ich verstehen :) Aber so
einfach ist es ja nicht.
Also wo wird sowas idR festgelegt? Ist das irgendwo in der stdio.h
versteckt???
Ich kann mich nur nochmal für meine wahrscheinlich sehr blöden Fragen
entschuldigen. Aber irgendwo muss ich ja anfangen...
Im Prinzip funktioniert das so ähnlich. Du musst der Standardausgabe ein
neues Handle zuweisen. Es gibt dann eine Funktion in der Bibliothek, die
die Ausgabe von Daten über diese Handles macht und von dir implementiert
werden muss.In der Funktion kannst du nun je nach Handle das auf UART0,
UART1 oder wo auch immer ausgeben. Unter Windows oder Linux übernimmt
sowas das Betriebssystem. Auf einem Controller kann oder muss man das
selbst machen. Google findet dazu auch gute Anleitungen.
Robert S. wrote:
> However, no file or other I/O related functions will> work, with the exception of I/O to stdin/stdout. Stdin/stdout are mapped> on UART A, accessible via the usual stdio functions.
Na das ist ja schon mal ne Aussage. Es bedeutet, daß Du alles außer der
UART selber machen mußt.
In der Regel ruft printf putchar auf. Man kann also sein eigenes putchar
schreiben, was dann z.B. auf ein LCD ausgibt.
Auf MCs wird aber meist ein anderes Konzept verwendet:
Man benutzt nicht printf, sondern sprintf und schreibt damit in einen
Puffer. Und diesen Puffer übergibt man dann der LCD-Ausgabefunktion oder
wem auch immer. Damit ist man sehr flexibel.
Peter
Beim BCC funktionieren printf u.s.w. auf UART-A automatisch, quasi ab
Werk Gaisler. Wie auch in der Doku beschrieben. Er arbeitet mit 38400
Baud (wenn ich nicht irre).
> work, with the exception of I/O to stdin/stdout. Stdin/stdout are mapped> on UART A, accessible via the usual stdio functions.
Steht ja auch da: with the exception of
Die Doku ist leider ziemlich dürftig. Kostet dafür auch nichts.
Also dass hier sollte ohne weiteres funktioneren wenn du ein Terminal an
den UART klemmst:
1
#include<stdio.h>
2
#include<noch mehr, falls was fehlt>
3
4
intmain(void)
5
{
6
leonbare_init_ticks();
7
printf("Hello world\n");
8
return0;
9
}
Wie du wahrscheinlich weißt, gibt es ein spezielles LEON-Forum bei
YAHOO. Dort kann man einiges an Info bekommen.
Newlib Doku findest du bei RedHat. Gaisler hat da wenig gemacht.
Also Ihre eigene Implentierung ist kaum dokumentiert (leider).
Was auch hilft, die Sourcen und Beispiele von Gaisler durchzuwühlen. Sie
liefern die Newlib Sourcen ja auch. Da habe ich das meiste finden
können. Allerdings ist das sehr mühselig.
Es ist noch eine wichtige Funktion im Anfang der Main aufzurufen.
1
leonbare_init_ticks();
Diese initialisiert die Timerlib und die IRQs und noch mehr. Dann kann
man einen der beiden Timer schon so nutzen. Der läuft dann, wenn ich
jetzt nicht irre, mit 10ms. Damit betreiben sie auch dann u.a. die
pthreads-lib.
Interrupts nutzt man wie folgt:
1
catch_interrupt(IRQ-fFunc,uIrq);// register IRQ function
2
leonbare_enable_irq(uIrq);// enable IRQ
Zwei Makros, die den globalen IRQ EIN/AUS schalten
1
// Macros to enable/disable the global interrupts /traps)
2
#define CRITICAL_SECTION_START unsigned int old = leonbare_disable_traps();
Das Ganze geht auch unter Windows genauso bequem. Man kann von Gaisler
ein Eclipse für Windows mit der kompletten Toolchain und deren Plugin
für den LEON runterladen. Alles in einer EXE versteckt. Einfach starten
und glücklich sein. Damit hättest du dir 6 Monate für Linux sparen
können ;-)
Das gleiche Paket gibt es aber auch für Linux von Gaisler (er ist Linux
Verfechter) und funktioniert auch sehr gut.
So mehr fällt mir jetzt nicht ein. Ist schon 2 Jahre her :-)
Wie gesagt: YAHOO-Forum ist dein Ziel.
Ohne jemals mit der genannten Plattform gearbeitet zu haben...
Da newlib als libc genannt wurde sollte das Konzept zur Anpassung an die
Plattform analog zu anderen Plattformen sein (kenne es selbst nur von
diversen ARM-Experimenten). Leider finde ich im Quellcode der newlib
(hier 1.16) keine Verzeichnisse mit Namen leon, daher ist es etwas
knifflig zu helfen.
Wenn die "Umleitung" von stdin/stdout auf einen UART bereits
funktioniert, sind einige syscalls zumindest rudimentär bereits in der
libc enthalten. Möglicherweise wird es dann etwas kompliziert eigene
syscalls, die verschiedene Dateihandles verarbeiten "unterzuschieben".
Das geht evtl. mit "undef"-Linker-Optionen oder geänderter
Link-Reihenfolge, ist aber mglw. etwas knifflig. Einfacher die newlib so
zusammenbauen, dass keine default-syscalls enthalten sind (disable
newlib supplied syscalls), zumindest mache ich das so für meinen
ARM-Kram. Vorsicht: sehr wahrscheinlich wird dann die vorhandenen
Umleitung auf einen UART auch erstmal nicht funktionieren, gibt als eine
kleine Durststrecke.
Sind keine syscall in der libc, kann man sich diese später
projektspezifisch selbst erstellen und linken. Vorlagen für ganz
brauchbare und flexible syscall-Implementierungen auf Grundlage der
newlib-Schnittstellen: newlib-lpc von Aeolus und libsysbase von
DevkitPro. Das Prinzip hinter diesen Codes ist, dass man pro Geräte eine
Stuktur mit Funktionspointer zu hardwarespezifischen Funktionen (z.B.
Zeichen an UART0 senden, Zeichen von UART1 lesen etc.) füllt. Intern
wird eine Liste verwaltet, die Datei-Handle, Gerätebezeichung und
Funktionspointer-Strukturen enthält. Die syscalls-Implementierungen
(open, read, write, etc.) "finden" darin dann die zum Geräte/Handle
passenden Funktionspointer, die auf Funktionen verweisen, welche die
hardwarespezifischen Operationen ausführen.
Mein Text liest sich komplizierter als es ist... Einfach in den
Quellcode der genannten "support-libs" schauen. Die ganze
Listenverwaltung ist plattformunabhängiger C-Code, den man
wahrscheinlich einfach weitestgehend übernehmen kann. Die
hardwarespezifischen Funktionen kann man wahrscheinlich aus dem
vorhandenen Code für den einen UART ableiten und anpassen.
mthomas wrote:
> Ohne jemals mit der genannten Plattform gearbeitet zu haben...>> Da newlib als libc genannt wurde sollte das Konzept zur Anpassung an die> Plattform analog zu anderen Plattformen sein (kenne es selbst nur von> diversen ARM-Experimenten).
Newlib ist eine "modernere" libc.
> Leider finde ich im Quellcode der newlib> (hier 1.16) keine Verzeichnisse mit Namen leon, daher ist es etwas> knifflig zu helfen.
Hat Gaisler glaube ich selber unter seinen Pfoten. Darum hilft nur,
seine mitgeliefeten Sourcen durchzugraben.
900ss
Moin!
Erstmal schönen Dank an alle! Jetzt wirds ja doch noch interessant :)
Wenigstens bin ich nicht der einzige, der die Gaisler-Doku besch***
findet. Das schöne ist ja auch, dass es außer den Copyrights keinerlei
Beschreibungen in den Köpfen der mitgelieferten Libs bzw.
Beispielprogramme gibt. Kommentare sucht man meist vergeblich...
Also verstehe ich das jetzt richtig, dass es gar nicht möglich ist, das
StdOut mal eben umzuleiten?! Ich hatte den Satz der Doku so verstanden,
dass zwar nur ausschließlich StdIO-Befehle möglich sind, die ZUR ZEIT
auf UART A gemapped sind. Also muss man das doch ändern können!?
Das "Hello World" läuft wie gesagt. Und ich habe mir ja schon eigene
Funktionen geschrieben, die z.B. ein PS2-Keyboard auslesen oder Zeichen
auf VGA ausgeben. Mein Prof meint halt nur, dass es ja möglich sein
muss, die mitgelieferten Funktionen zu verwenden...
Die Yahoo-Group kenne ich natürlich schon. Hat mir aber bisher auch
nicht geholfen. Und auf meine absolute-beginner-Fragen hat da bisher
keiner reagiert ggg.
Na gut, ich werde nochmal tief in den Libs rumwühlen und versuchen zu
verstehen...
Nochmal zur Tool Chain: Ich habs natürlich erst mit Windows versucht.
Aber ganz so einfach wie "setup.exe und glücklich sein" wars dann doch
nicht. Dadurch, dass ich unter Linux jedes Tool manuell installieren
musste, hab ich mich wenigstens gleich mit jedem Tool auseinander setzen
müssen und weiß jetzt auch, welches wofür gut ist... Bei der
Win-Installation hatte ich mit einem Klick alle Tools auf einmal und
wußte nicht, wofür man das alles braucht. Von daher hab ich unter Linux
schonmal ne Menge gelernt :)
Danke euch erstmal!