Hallo, auf einem Microcontroller (hier ARM Cortex M3 mit GCC und newlib) funktioniert printf ja nicht out-of-the-box, wenn der Controllerhersteller nicht schon passende Funktionen für _write, etc. zur Verfügung stellt. Ruft man dann printf auf, dann fliegen einem Fehlermeldungen bzgl fehlender Funktionen wie eben _write, _sbrk, etc um die Ohren. Diese Funktionen muss man dann selber passend für den µC implementieren. Hierzu hätte ich folgende Fragen: 1) mit sprintf landet die Ausgabe in einem Buffer, welchen man dann passend an die jeweilige Schnittstelle übergeben kann. Wenn ich nun davon ausgehe, dass die Software nicht auf einen PC portiert wird, dann gibt es eigentlich keinen Grund, die oben genannten Funktionen zu implementieren, oder? Falls die Software doch auf einem PC (oder generell auf einem völlig anderen System) laufen soll, dann sollte man es aber tun, damit man überall printf verwenden kann, korrekt? 2) Wie schwer ist die Implementierung, wenn man auf dem µC evtl mehrere Schnittstellen wie z.B. mehrere UARTs und ein Display hat, die man per printf ansprechen möchte? Neben den Zugriffsfunktionen (_write, etc.) müsste man dann ja noch die Schnittstellen selbst definieren, wie funktioniert das dann? Ralf
Benutze doch besser fprintf. Dort kannst du einen File-Control-Block angeben, der zur Ausgabe benutzt werden soll. Dann können beliebig viele UARTs angesprochen werden oder LCDs, deren Ausgabefunktionen du allerdings natürlich schreiben bzw. beistellen mußt. Im File-Control-Block stehen u.a. die Adressen der Ein/Ausgabefunktionen, die du dort reinschreiben mußt, ggf. durch Funktionen wie fopen. Siehe Doku.
Ne Art von '_write' mußt Du sowieso implementieren, irgendwie muß Du Deinen Buffer ja auch auf die Schnittstelle schreiben. Und sprintf geht auch auf dem PC problemlos. Der Portierungsaufwand zum PC ist nahezu derselbe, egal ob printf oder sprintf. sprintf könnte da sogar von Vorteil sein, eventuell will man ja auch am PC die Daten auf eine serielle Schnitstelle schreiben. Am flexibelsten dürfte die Variante von Günter sein.
printf ist ja offensichtlich untrennbar an die Funktionen _write, _sbrk etc. gekoppelt. Das bekommst Du nicht entkoppelt, und zur Laufzeit auf unterschiedliche Ausgabegeräte auch nicht umgelenkt. Mit fprintf ginge das eher, da es unterschiedliche Ausgabegeräte bedienen kann. Hat Günter schon beschrieben. Wenn Du dasselbe Modul auf unterschiedliche Geräte schreiben lassen möchtest, brauchst Du dafür ein Interface. Das Interface definiert die Funktionen. Das benutzt Du in diesem Modul und reichst von außen die gerätespezifische Implementierung dieses Interfaces hinein oder erfragst es per Callback. In C wäre das ein File Pointer, in C++ würde man sich für jedes Gerät einen eigenen Output Stream implementieren, in Java einen Writer. Zum printf-like Formatieren in C++ braucht es Zusatzklassen (sprintf könnte genügen), in Java gäbe es dazu den PrintWriter, der u.a. einen Writer formatiert beschreiben kann.
Der Nachteil an sprintf ist, dass Du die Größe des Puffers vorher festlegen musst. Mit printf bzw. fprintf kannst Du dagegen beliebig lange und kurze Daten effizient ausgeben, indem Du jedes Zeichen live rausschreibst. Von daher lohnt es sich imo schon, die benötigten Funktionen zu implementieren. Für die Variante mit sprintf brauchst Du ja am Ende auch eine Funktion, die den fertigen String ausgibt, typischerweise bestehend aus einer Schleife über alle Zeichen und der Ausgabe des Zeichens. Diesen Code in ein _write zu verpacken, dürfte kein großer Aufwand zu sein.
Beitrag "ARM - Probleme mit sprintf (Linkerfehler)" Beitrag "Re: ARM - Probleme mit sprintf (Linkerfehler)"
Hans schrieb: > Der Nachteil an sprintf ist, dass Du die Größe des Puffers vorher > festlegen musst. Und dass man überhaupt einen Puffer braucht, der so groß ist, daß die Ausgabe des sprintf-Aufrufs vollständig reinpasst. Dementsprechend viel Speicher verschwendet man damit ggf.
Die Anzahl auszugebender Bytes kann mit snprintf bestimmt werden, danach kann temporärer Speicher dafür zur Verfügung gestellt werden, z.B. per alloca auf dem Stack oder per malloc auf dem Heap. Schön ist das aber nicht; wenn man nicht aus anderen Gründen die Ausgabe als String benötigt, sollte man auf diesen Zwischenschritt verzichten. Fehlendes _sbrk deutet eher auf ein Fehlendes OS hin, printf durch sprintf ersetzen ändert nix daran. Stellt die libgloss kein _sbrk zur Verfügung? Oder verwendest du libnosys?
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.