Forum: Compiler & IDEs WinAVR glibc I/O Funktionen


von Gerd Kautzmann (Gast)


Lesenswert?

Mir ist aufgefallen, dass die glibc in 'verschieden mächtigen'
Versionen vorliegt, also von 'kein printf' bis zu 'printf mit
float'

Was mir nicht ganz klar ist, sind die zugrunde liegenden Funktionen,
damit meine ich, dass printf(), scanf() immer irgendwie auf eine
getc()/getchar() putc()/putchar() zugreifen müssten.

Jetzt konnte ich aber keine Funktionen zur Initilisierung der UARTs
finden, d.h. ich weiß nicht ob und wie ich den UART richtig für die
glibc initialisiere oder ob ich die Funktionen einfach selber schreiben
muss.

Also bitte nicht falsch verstehen, ich will mir das KnowHow eigentlich
selber erarbeiten aber bevor ich ein eigenes helloworld.c schreiben
kann, muss ich wissen ob meine I/O Funktionen der glibc die Beine
wegziehen oder ob die glibc meine Funktionen benutzt so lange sie die
richtigen Namen haben.

Die glibc Versionen die ich so für andere µP kenne rufen zuerst
Routinen auf die z.B. den Speicher initialisieren, den Stack anlegen,
die vorbelegten statischen Variablen kopieren, den Mempool anlegen (für
malloc) die Timer und I/Os initialisieren und zum Schluss main()
aufrufen. Da felt mir noch etwas der Durchblick bei der glibc vom
WinAVR Packet.

cu Gerd

von Jörg Wunsch (Gast)


Lesenswert?

Erstmal kleine Korrektur: glibc ist die GNU libc, die du bei Linux
benutzt.  Hier heißt sie avr-libc.  Wesentlichste Unterschiede:
avr-libc ist viel kleiner und auf den AVR zugeschnitten, und sie steht
unter BSD-Lizenz weil wir denken, dass wir damit allen potenziellen
Anwendern die wenigsten Nutzungsprobleme mit auf den Weg geben.

Zweitens: sieh dir bitte die Doku zu "Standard IO facilities" in der
avr-libc-Dokumentation an, insbesondere die Funktion fdevopen().
stdio in der avr-libc kann auf allen möglichen Dingen aufsetzen, nicht
nur auf 'ner UART (LCD-Ausgabe ist sicher gleichermaßen sinnvoll),
die
dafür notwendigen Basisfunktionen musst du selbst schreiben und dem
stdio-System via fdevopen kund tun.

Ansonsten ist avr-libc ausdrücklich kein Betriebssystem, bietet also
keinerlei entsprechende Funktionalitäten wie eigene Timerverwaltung
oder so.  Es implementiert wirklich nur das Minimum, um ein
C-Laufzeitsystem gemäß C-Standard zu realisieren (dazu gehört aber die
Initialisierung des Stacks und der Variablen).

von Ger Kautzmann (Gast)


Lesenswert?

(Ach Mist immer wieder frisst dieser sch... Browser meine Beiträge ...)

Bei solchen Beispielen:
(Quellefile://C:\WinAVR\doc\avr-libc\avr-libc-user-manual\FAQ.html#faq_r 
om_array)

---------schnipp--------------
#include <inttypes.h>
#include <avr/io.h>
#include <avr/pgmspace.h>

void
uart_putchar(char c)
{
  if (c == '\n')
    uart_putchar('\r');
  loop_until_bit_is_set(USR, UDRE);
  UDR = c;
}
.............

---------schnapp--------------

fällt mir immer wieder auf dass keine Baudrate gesetzt wird.

Ist beim AVR irgendeine default Baudrate eingestellt oder hat man
diesen Teil des Programms einfach 'eingespart' ?

Falls es so was wie eine default Baudrate durch die libc giebt, wo kann
man diese konfigurieren ?


MfG Gerd Kautzmann

von Jörg Wunsch (Gast)


Lesenswert?

Nein, nein, die Bibliothek macht nichts, aber auch wirklich gar
nichts an deiner Hardware -- mit der einzigen bereits genannten
Ausnahme, dass der Stackpointer initialisiert wird.  Das ist aber
wirklich alles.  Um den Rest kümmerst du dich selbst.

Natürlich kümmerst du dich auch um die Initialisierung deiner UART.
Ich fasse dabei üblicherweise alle Peripherie-Initialisierung in einer
Funktion ioinit() zusammen, die am Anfang von main() gerufen wird.

Die zitierte Routine gibt ein Zeichen zur UART aus -- dabei willst du
natürlich die UART nicht jedesmal initialisieren, nicht wahr? ;-) Die
Routine dient nur als mögliches Beispiel, wie die entsprechende
callback-Funktion für fdevopen() aussehen sollte.  Übrigens als
schlechtes Beispiel, siehe den Eintrag zu fdevopen() selbst: die
Routine sollte vom Typ `int' sein und 0 zurückgeben, falls die
Ausgabe
erfolgreich war.  Wenn du obiges an den Compiler als callback in
fdevopen() übergibst, solltest du eine Warnung bekommen.  Aber das
entsprechende FAQ-Beispiel dient ja auch nicht als Beispiel für stdio
-- allerdings hast du Recht, da sollte zumindest andeutungsweise die
IO-Initialisierung erwähnt werden.

OK, habe beides repariert.  Das im Beispiel enthaltene uart_putchar()
ist jetzt auch stdio-fähig, und ioinit() habe ich angedeutet.

Btw., nicht bei allen AVRs heißen die Register so wie im Beispiel.

von Gerd Kautzmann (Gast)


Lesenswert?

Also erst mal vielen Dank für die Erklärungen und die Geduld.

Ich konnte mich einfach nicht damit abfinden dass das was nicht erwähnt
wird nicht da ist, vor allem nach dem mich einige Beispiele verwirrt
haben.

Ich denke ich kann mich jetzt mal darüber schlau machen wie die
Baudrate Generatoren etc. funktionieren, da findet sich hier bestimmt
einiges und es gibt bestimmt auch Doku die ich noch ausdrucken und
durcharbeiten sollte.


Dass putc() und getc() eventuell was zurückgeben sollten hab ich
kapiert, das stand so ähnlich in der Doku von fdevopen(). Ich weiß
nicht ob ich die stdio voll benutzen werde, dazu muss ich mir erst
einen Eindruck über ihre Fähigkeiten und meine Anforderungen machen.

---

Ehrlich gesagt ist es sogar von Vorteil wenn die glib jede mögliche
putc()/getc() Routine die der Anwender implementiert unterstützt.

MfG Gerd Kautzmann

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.