Forum: Mikrocontroller und Digitale Elektronik RTOS, UART, printf


von tan delta (Gast)


Lesenswert?

Hallo,
ich habe hier ein kleines selbst entworfenes ARM9-Board. Dieses verfügt 
über eine serielle RS-232 Verbindung zum PC, und ich möchte da einer Art 
Konsole entwerfen, um z.B. für Debug-Zwecke bestimmte Funktionen zu 
starten usw.
Da ich ein RTOS einsetze, wird zwar vieles einfacher zum Programmieren, 
anderes ist dafür ein Krampf...

Ich möchte gerne eine Ausgabe von Debug-Meldungen realisieren über die 
RS-232. Dabei soll jedoch derjenige Task, welcher eine Meldung ausgibt, 
so wenig wie nur irgend möglich gebremst werden, z.B. durch ein 
kompliziertes printf. Denn die Tasks führen z.T. 
Datenübertragungsprotokolle aus oder sollen Messwerte möglichst in 
Echtzeit verarbeiten. Wenn da ein Task eine Meldung ausgeben soll wie 
"Messwert 34: 3.25V", und dazu printf braucht, dann wird der Task 
erstens mal unnötig lange von diesem printf gebremst (das kann ja leider 
nur Zeichen für Zeichen verarbeiten) und dann wird auch noch ein 
unnötiger Buffer erstellt, wo der zu sendende String erst 
zwischengespeichert wird, bevor man damit auf den UART los kann.
Mir will das nicht so recht gefallen; gibt es keine elegantere Lösung? 
Wie kann ich auf einfache Weise eine möglichst schnelle, einigermassen 
Speicher sparende Ausgabe formatierter Daten über UART ermöglichen, die 
RTOS tauglich ist?

von holger (Gast)


Lesenswert?

>Wie kann ich auf einfache Weise eine möglichst schnelle, einigermassen
>Speicher sparende Ausgabe formatierter Daten über UART ermöglichen, die
>RTOS tauglich ist?

Ganz einfach: Du überlegst dir wieviele Daten du wirklich zum
debuggen brauchst. Du nimmst eine hohe Datenrate für deinen
UART, zb. 115kBaud. Dann ein Sendepuffer der per
Interrupt verschickt wird. Wenn der UART die Daten mit 115kBaud
nicht schnell genug senden kann weil die eingehenden Daten schneller
kommen hast du sowieso schon verloren.

von holger (Gast)


Lesenswert?

Kleiner Nachtrag:

>Wenn da ein Task eine Meldung ausgeben soll wie
>"Messwert 34: 3.25V", und dazu printf braucht, dann wird der Task
>erstens mal unnötig lange von diesem printf gebremst (das kann ja leider
>nur Zeichen für Zeichen verarbeiten) und dann wird auch noch ein
>unnötiger Buffer erstellt, wo der zu sendende String erst

Ich glaube der ARM9 lacht sich tot über deine Vorstellungen
von Verarbeitungszeit und Speicherbedarf von einem printf().

von tan delta (Gast)


Lesenswert?

Hmm, okay... ist es denn auch eine elegante Lösung, wenn in diesem 
printf() jedes Zeichen einzeln ausgegeben wird? Toll wäre ja, wenn man 
den String erst in einen Buffer schreiben könnte, der dann in einem 
Rutsch gesendet wird. Aber dann muss ich wieder einen Buffer 
alloziieren, von dem ich im Vornherein ja sowieso nicht wissen kann, wie 
gross er sein muss. Hmm...

von holger (Gast)


Lesenswert?

>ist es denn auch eine elegante Lösung, wenn in diesem
>printf() jedes Zeichen einzeln ausgegeben wird?

Was? Wie die Zeichen gesendet werden hängt nicht von deinem
printf ab. printf benutzt normalerweise (oder auch nicht?)
eine putchar Routine. Dort wird festgelegt wie die Zeichen
gesendet werden. putchar kann die Zeichen von printf in einen
UART Ringpuffer kopieren und gesendet werden sie dann per
UART Interrupt. Wie effektiv printf ist hängt also unter
Umständen von der Implementierung von putchar ab. Evtl. musst du dir
ein putchar selber schreiben. Genaues kann man aber so nicht
sagen.

von JojoS (Gast)


Lesenswert?

Ein RTOS hat aber auch Queues, Mailboxen usw und auch Threads mit 
verschiedenen Prioritäten. Statt mit printf() zu arbeiten kann man auch 
mit sprintf() in einen Buffer schreiben und in eine Mailbox schreiben. 
Die Buffer einmal allozieren damit der Speicher nicht zerfranst wird. 
Und aufpassen das nicht langsames lesen das Schreiben blockiert.

von Lutz (Gast)


Lesenswert?

tan delta schrieb:
> Aber dann muss ich wieder einen Buffer
> alloziieren, von dem ich im Vornherein ja sowieso nicht wissen kann, wie
> gross er sein muss.

Na wenn du als der Programmierer der Software nicht weißt, wie groß die 
Werte sind, dann hast du an viel früherer Stelle schon ein Problem. Du 
kennst bzw. schreibst den Debugstring selbst. Du legst auch den Datentyp 
darin fest. Sogar die Zahl eventueller Nachkommastellen.

Debuggen über UART etc. hat halt seinen Preis; nicht umsonst gibt es 
"richtige" Debugschnittstellen (na ja, z.B. JTAG), teure Debugger und 
vor allem Breakpoints.

Ein ARM9 sollte schon massig Reserven haben, aber das kommt natürlich 
ganz auf die Anwendung an.
Wenn z.B. eine Sequenz wegen Timern etc. nicht vernüftig mit Breakpoints 
debuggt werden kann, kann man auch einen Sequenzbuffer einrichten, in 
dem die minimalsten Daten gespeichert werden. Dann nach der Sequenz 
einen Breakpoint und hier die Daten am Stück ausgeben und analysieren.

von Purzel H. (hacky)


Lesenswert?

Printf() hat mit Echtzeit eh nichts zu suchen. Allenfalls eine feste 
Anzahl Stellen, zb 8 Hexziffern fuer eine 32bit Zahl.

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.