fprintf ohne stdio?

OP #7080565
Lesenswert?
• ▲
▼
Servus!

mal angenommen, man meint -ffreestanding ernst, es gibt keine libc und 
selbst "Simply the best printf around the net"¹ ist noch zu fett. Ein 
kleines printf(), z.B. aus einem alten ChibiOS, gönnt man sich trotzdem.

So ein printf() kann seine Ausgabe ungepuffert über ein extrem einfaches 
putchar() machen. Für ein UART reichen 2 Zeilen. Für ein LCD mit HD44780 
braucht es kaum mehr. Alles trivial, solange es nur UART oder LCD 
gibt.

Damit man so ein printf() für UART und LCD nutzen kann, baut man 
einfach ein putchar(), das seinerseits über einen Pointer entweder 
uart_put() oder lcd_put() aufruft. Im Unterschied zu fprintf() und 
fputc() muss man nicht überall den FILE Pointer mitgeben. Stattdessen 
braucht man eine Funktion, mit der man zwischen den Ausgabekanälen 
umschalten kann. Also ungefähr etwas wie freopen() für stdout, nur 
einfacher, weil es kein close() und open() gibt (geben soll).

Natürlich nimmt man für größere uC stdio, aber für kleinere scheint mir 
diese Lösung geradezu elegant zu sein (mal abgesehen von einem besseren 
Namen statt reopen). Andererseits finde ich praktisch nur Beiträge, die 
entweder mit "nimm stdio" oder mit sprintf() enden. Wo ist der Fehler?
1
// putchar.h
2
typedef int putchar_ptr (int);
3
int putchar (int c);
4
int uart2_put (int c);
5
int lcd_put (int c);
6

7
// putchar.c
8
static putchar_ptr  *do_putchar = uart2_put;
9

10
void
11
reopen (putchar_ptr *fun)
12
{
13
   do_putchar = fun;
14
   return;
15
}
16

17
int
18
putchar (int c)
19
{
20
   assert (do_putchar != NULL);
21
   if (c == '\n' && no_nlcr == 0) {
22
      do_putchar ('\r');
23
   }
24
   return do_putchar (c);
25
}
1) https://github.com/mpaland/printf
Gast #7080680
Lesenswert?
• ▲
▼
> also eine Lösung mit FILE *; genau das wollte ich doch vermeiden.

Hast du dir das Beispiel mal angeschaut?
1
static int
2
myputchar(char c, FILE *stream)
3
{
4
  if (c == '\n')
5
    do_putchar('\r');
6
  do_putchar(c);
7
  return 0;
8
}
9

10
static FILE uart = FDEV_SETUP_STREAM(myputchar, NULL, _FDEV_SETUP_WRITE);
11

12
int
13
main(void)
14
{
15
  ... init ...
16
  stdout = &uart;  // dein reopen
17
  printf("Hello, world!\n");
18

19
  return 0;
20
}

Im avr-libc ist das FILE-Handling extrem mager - ein FILE ist nur ein 
paar Bytes größer als dein vergleichbarer putchar_ptr.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 4 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.