www.mikrocontroller.net

Forum: GCC printf bei armgcc

Autor: Tilo Lutz (katagia)
Datum: 01.07.2008 15:20

Hallo

Ich will printf verwenden, um per Uart Daten auszugeben.

Die Datenausgabe mit meiner eigenen Funktion UartWrite() funktioniert
problemlos.

Leider hat mir google verschiedenste Lösungen angeboten, die alle nicht
taten.

Ich habe in meinem Hauptprogramm die Funktion int __putchar(int ch)
definiert. Sie wird allerdings von printf nicht aufgerufen.

Ich habe auch int putchar(int ch) versucht, dann erhalte ich folgende
Fehlermeldung, die ich gar nicht verstehe:

main.c:9: error: expected identifier or '(' before '--' token
make: *** [main.o] Error 1

Ich habe bisher mit printf etc. noch nicht gearbeitet und stehe ein
wenig auf dem Schlauch.

Wer weiß, wo mein Fehler liegt bzw. wo ich Hilfe finden könnte?

Vielen Dank,

Tilo
Autor: Sir alan Teplotaxl (t3plot4x1)
Datum: 01.07.2008 15:42

Da ich bedauerlicherweise nicht über eine Glaskugel verfüge, kann ich
dir auch nicht weiterhelfen. Zeig doch bitte mal den ganzen Code her.
Autor: Tilo Lutz (katagia)
Datum: 01.07.2008 15:53

#include "ADuC7020.h"
#include "uart.h"
#include <stdlib.h>
#include <stdio.h>

void IRQ_Function(void);      // IRQ Funktion

int __putchar(int ch) {
  return UartPutChar(ch);
}

int main (void)  {
  IRQ = IRQ_Function; // Weise IRQ Funkion zu
  UartInit(115200); // Initialisiere Uart mit 115200Baud

  while (1) {
    printf("Hallo printf test.");
  }
}

void IRQ_Function (void) {
  if (IRQSTA & UART_BIT) { // Uart
    UartIrq(); // Zeichen wurde empfangen
  }
}

Das ist der vollständige Code. Durch den Aufruf von UartPutChar() kann
direkt ein Zeichen gesendet werden.
Autor: Martin Thomas (mthomas) Benutzerseite
Datum: 01.07.2008 20:45

Üblicherweise werden die stdio-Funktionen der newlib, die in den meisten
Packeten mit arm-elf/eabi-gcc die libc ist, per sogen. syscalls mit der
Hardware verbunden. Vgl. newlib Dokumentation, Implementierungsbeispiel
z.B. newlib-lpc.
Autor: Tilo (Gast)
Datum: 02.07.2008 17:48
Dateianhang: newlib-lpc_rel_5a.zip (410,3 KB, 7 Downloads)

Danke für den Hinweis!

Ich habe mir die newlib-lpc angeschaut. Für jemanden, der die newlib
noch nie verwendet hat, ist das erst einmal ein ganz schöner Brocken.
Ich habe auch einiges an Dokumentation gefunden, nur die geht meist
davon aus, dass man schon weiß, wo man hin will.

Ich habe mal die newlib-lpc angehängt. Ich habe mich am Beispiel test3.c
orientiert.
  /**** Device table.  List of device drivers for newlib.  ****/
const struct device_table_entry *device_table[] = {
  &com1,  /* stdin  */
  &com1,  /* stdout */
  &com1,  /* stderr */
  0 };  /* end of list */

Es wird ein Array (Array aus Pointern) *device_table mit 4 Einträgen vom
Typ device_table_entry erzeugt. "com1" ist in der uart0_int.c definiert.
Dort sind die einzelnen Funktionen hinterlegt. device_table_entry ist in
dev_cntrl.h hinterlegt. Soweit habe ich auch verstanden, wie die
einzelnen Codeteile zusammenhängen.

Ein paar Dinge sind mir aber noch unklar:

1. Wo klinkt sich die newlib ein? Erwartet newlib, dass es ein Array mit
dem Namen *device_table gibt?

2. Der Eintrag in die Tabelle für den uart sieht in uart0_int.c so aus:
/************************** com1_int ************************************/
/*  Device table entry used to add this device.        */
const struct device_table_entry com1_int = {
  "com1",        /*  Device name.    */
  uart0_open,        /*  Open method.    */
  uart0_close,      /*  Close method.    */
  uart0_read,      /*  Read method.    */
  uart0_write,      /*  Write method.    */
  uart0_ioctl,      /*  Ioctl method.    */
  0 };        /*  No per-instance data.  */
static _ssize_t uart0_write (
    struct _reent *r,      /*  Re-entrancy structure, used to make  */
        /* thread safe.        */
    int file,       /*  File handle.  Used to distinguish  */
        /* multiple instances.      */
    const void *ptr,    /*  Pointer to data to write.    */
    size_t len,      /*  Amount of data to write.    */
    SUB_DEVICE_INFO *info)  /*  Per instance information, only one  */
            /* instance so not used.    */
{
[...]

In den Kommentaren zu dieser Funktion ist als Datentyp immer von "Byte"
die Rede. Wo ist das festgelegt? Könnte als Datentyp nicht auch short
oder long von der newlib verwendet werden?


3. In diesem Beispiel wird stdin, stdout und stderr auf "com1" gelegt.
Gehen wir davon aus, ich will zusätzlich ein Device per SPI ansprechen:
  /**** Device table.  List of device drivers for newlib.  ****/
const struct device_table_entry *device_table[] = {
  &com1,  /* stdin  */
  &com1,  /* stdout */
  &com1,  /* stderr */
        &spi1,
  0 };  /* end of list */

Wie kann die Ausgabe von newlib von stdout auf spi1 umgebogen werden?

Vielen Dank,

Tilo
Autor: mthomas (Gast)
Datum: 03.07.2008 12:34

zu 1: Die Implementierung der syscalls in newlib-lpc "erwart" ein Array
um zum hander die passenden Funktionen zu suchen. newlib-lpc (oder
libsysbase von devkitpro) bietet wahrscheinlich schon ein paar mehr
Möglichkeiten als benötigt. Man kann write etc. auch einfacher
implementierung v.a. wenn man nur stdio/printf nur dazu verwenden will
ein paar Ausgaben auf einen uart umzuleiten. Vgl. z.B. den Code zu
"uVision+Codesourcery" von keil.com oder ein paar meiner Bespiele auf
www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects

zu 2: verstehe die Frage wahrscheinlich nicht wirklich. Die syscalls
fuer stdio-support sind dazu gedacht, einen Bytestream
auszugeben/einzulesen.

zu 3: ja, "umbiegen" von stdout auf SPI (oder was auch immer)
funktioniert im Prinzip - habe das aber nie selbst ausprobiert.
Interface der Hardwarefunktionen fuer SPI-Ausgabe analog dem für UART
implementieren und Adressen in einer device_table_entry structure
eintragen.
Autor: Tilo Lutz (katagia)
Datum: 04.07.2008 15:04

zu 1:
Ich hab schon funktionierende Funktioenen. Wie geschrieben, ich würde es
jetzt gerne mal mit schon vorhandenen Libraries versuchen

zu 2:
OK, das wollte ich wissen. Hätte ja sein können, dass z.B. ein
Short-Stream zugelassen ist.

Nochmals Danke für deine Hilfe!

Tilo

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