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
Da ich bedauerlicherweise nicht über eine Glaskugel verfüge, kann ich dir auch nicht weiterhelfen. Zeig doch bitte mal den ganzen Code her.
1 | #include "ADuC7020.h" |
2 | #include "uart.h" |
3 | #include <stdlib.h> |
4 | #include <stdio.h> |
5 | |
6 | void IRQ_Function(void); // IRQ Funktion |
7 | |
8 | int __putchar(int ch) { |
9 | return UartPutChar(ch); |
10 | }
|
11 | |
12 | int main (void) { |
13 | IRQ = IRQ_Function; // Weise IRQ Funkion zu |
14 | UartInit(115200); // Initialisiere Uart mit 115200Baud |
15 | |
16 | while (1) { |
17 | printf("Hallo printf test."); |
18 | }
|
19 | }
|
20 | |
21 | void IRQ_Function (void) { |
22 | if (IRQSTA & UART_BIT) { // Uart |
23 | UartIrq(); // Zeichen wurde empfangen |
24 | }
|
25 | }
|
Das ist der vollständige Code. Durch den Aufruf von UartPutChar() kann direkt ein Zeichen gesendet werden.
Ü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.
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.
1 | /**** Device table. List of device drivers for newlib. ****/
|
2 | const struct device_table_entry *device_table[] = { |
3 | &com1, /* stdin */ |
4 | &com1, /* stdout */ |
5 | &com1, /* stderr */ |
6 | 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:
1 | /************************** com1_int ************************************/
|
2 | /* Device table entry used to add this device. */
|
3 | const struct device_table_entry com1_int = { |
4 | "com1", /* Device name. */ |
5 | uart0_open, /* Open method. */ |
6 | uart0_close, /* Close method. */ |
7 | uart0_read, /* Read method. */ |
8 | uart0_write, /* Write method. */ |
9 | uart0_ioctl, /* Ioctl method. */ |
10 | 0 }; /* No per-instance data. */ |
1 | static _ssize_t uart0_write ( |
2 | struct _reent *r, /* Re-entrancy structure, used to make */ |
3 | /* thread safe. */
|
4 | int file, /* File handle. Used to distinguish */ |
5 | /* multiple instances. */
|
6 | const void *ptr, /* Pointer to data to write. */ |
7 | size_t len, /* Amount of data to write. */ |
8 | SUB_DEVICE_INFO *info) /* Per instance information, only one */ |
9 | /* instance so not used. */
|
10 | {
|
11 | [...]
|
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:
1 | /**** Device table. List of device drivers for newlib. ****/
|
2 | const struct device_table_entry *device_table[] = { |
3 | &com1, /* stdin */ |
4 | &com1, /* stdout */ |
5 | &com1, /* stderr */ |
6 | &spi1, |
7 | 0 }; /* end of list */ |
Wie kann die Ausgabe von newlib von stdout auf spi1 umgebogen werden? Vielen Dank, Tilo
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.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.