Forum: Compiler & IDEs C-Programmierung für LEON3-Prozessor (StdIO)


von Robert S. (efyzz)


Lesenswert?

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!!!

von ... (Gast)


Lesenswert?

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.

von Robert S. (efyzz)


Lesenswert?

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!!!

von Peter D. (peda)


Lesenswert?

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

von Robert S. (efyzz)


Lesenswert?

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...

von ... (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von 900ss (900ss)


Lesenswert?

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
int main( void )
5
{ 
6
  leonbare_init_ticks();
7
  printf("Hello world\n");
8
  return 0;
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();
3
#define CRITICAL_SECTION_END   leonbare_enable_traps(old);

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.

von mthomas (Gast)


Lesenswert?

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.

von 900ss (900ss)


Lesenswert?

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

von Robert S. (efyzz)


Lesenswert?

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!

von 900ss (900ss)


Lesenswert?

Gerade d'rüber gestolpert. Vielleicht hilft dir dieser Artikel noch ein 
wenig.
http://venus.billgatliff.com/node/3

Poting and using Newlib.

900ss

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.