2016-10-31 4 views
0

Ich habe bestehenden Code mit verschiedenen Debug-Meldungen. Unser Embedded-System hat keine externe Verbindung für ein Terminal. Ich möchte das printf so ändern, dass seine Ausgabe an einen Speicherort statt an STDOUT geht, der einem FIFO zugeordnet ist. Ich denke, ich muss mein eigenes Outbyte/Outnum schreiben. Ich kann einfach nicht den GNU Code finden, wo ich Dinge finden kann.C printf benutzerdefinierte Hardware

Ich betreibe einen Mikroprozessprozessor in einem Xilinx FPGA. Alle print-Anweisungen dienen zum Debuggen. Wir führen GNU-Tools (Xilinx SDK). Für die Entwicklung, konnte ein UART in das Design stecken und die UART auf ein paar Testpunkte verkabeln.

Während wir uns für die Bereitstellung bereit machen, habe ich diese Sichtbarkeit nicht mehr. Wir haben eine USB-zu-Seriell-Verbindung, aber es sieht wie ein Fifo aus, kein serieller Port zum eingebetteten System. Wir haben ein Protokoll zum Senden von Nachrichten über diesen Link. Ich dachte daran, unserem Protokoll eine Debug-Nachricht hinzuzufügen. Ich möchte meine print-Anweisung in einen Puffer umleiten und diesen Puffer dann verarbeiten.

Ich habe versucht, das vorhandene printf (xil_printf) zu nehmen und mein eigenes cc_printf zu erstellen, indem ich den Outbyte-Code umschrieb, aber einfach nicht in der Lage war, den Code weit genug zu durchforsten, um zu sehen, wie es geht. (Ehrlich gesagt, ich bin VHDL/Hardware-Typ).

Die Gesamtcodegröße beträgt Zehntausende Zeilen C-Code. Mein Abschnitt ist vielleicht 3-4 tausend Zeilen Code. Die Grundoperation besteht darin, dass Software-/Hardware-Updates des Systems über den USB-Port eingehen und in den FLASH-Speicher verschoben werden. Mein Code analysiert eingehende Pakete über die USB-zu-Seriell-Verbindung. Grundsätzlich gibt es ein Bit, das mir sagt, dass ein Paket in einem Empfangspuffer bereit ist. Ich verarbeite das Paket und schreibe nach FLASH. Als Teil des Protokolls gibt es ACK/NACKs/ABorts. Ich benutze derzeit den printf, um Status zu meiner Laborbankversion des Systems auszudrucken.

Wie gesagt, möchte ich diese Ausdrucke in unser Protokoll einbetten. Ich bin nicht mit printf verheiratet und würde eine andere Druckfunktion verwenden. Ich möchte Nachrichten und Daten ausdrucken. Wenn etwas anderes ein besserer Ausgangspunkt wäre, dann geht es mir gut. Es scheint, dass das größte Problem für mich ist, die Ausgabe des Druckes zu greifen und ihn wohin zu leiten.

+0

'fprintf'? 'dprintf'? –

+1

Es macht wenig Sinn, stdio.h auf eingebetteten Systemen zu verwenden. Sie verwenden wahrscheinlich eine generische UART-Druckroutine. Ihre MCU wird wahrscheinlich mit App-Notizen geliefert, die zeigen, wie Sie schnell einen UART-Treiber erstellen können. – Lundin

+0

Welche Art und Größe des Codes (Tausende von Quellcodezeilen)? Welches Embedded-System-Ziel? Wie kompilierst du es? Mit welchem ​​Compiler? Bitte ** bearbeiten Sie Ihre Frage **, um sie zu verbessern und zu motivieren! –

Antwort

1

Verwenden Sie nicht printfdirekt, für Debugging-Zwecke.

ein Makro verwenden, vielleicht so etwas wie

#define DEBUGPRINTF(Fmt,...) do \ 
    {printf("%s:%d: " Fmt "\n", __FILE__, __LINE__, __VA_ARGS__);} while(0) 

Dann, wenn Sie alle Ihre Debug printf umgewandelt haben (und nur diese) zu DEBUGPRINTF Sie nur die Definition dieses Makros ändern müssen (zB auf dem eingebetteten System, vielleicht mit snprintf ...).

So im Rest des Codes, ein printf("debugging x=%d\n", x); mit DEBUGPRINTF("debugging x=%d", x); ersetzen, sondern zu tun, dass nur für Debuggen druckt. BTWK 4KLOC (für Ihren Teil) ist wirklich winzig, und sogar 200KLOC (für die ganze Sache) ist klein genug, um diesen Ersatz "von Hand" machbar zu machen (z.B. Emacs "finde & interaktiv ersetzen").

(Ich vermute, dass Sie zunächst ein kleines Stück Code entwickeln -a paar tausend Lines- auf Ihrem Laptop, und später auf dem eingebetteten System zu portieren)

Sobald Sie konvertiert haben alle Ihre Debugprintf zu DEBUGPRINTF (und nur die Debugging-Drucke!) Sie dieses Makro neu definieren können, vielleicht von

inspiriert
#define DEBUGPRINTF(Fmt,...) do \ 
    {snprintf(debugbuffer, sizeof(debugbuffer), Fmt, __VA_ARGS__); } while(0) 

(Ich denke, dass Sie senden die Debug-Ausgabe tatsächlich benötigen, um etwas mehr in diesem Makro -wahrscheinlich vor dem Schließen brace- hinzufügen -Das ist der Gehalt an debugbuffer - irgendwo, aber wie man das macht ist & Implementierung systemspezifisch)

aber wahrscheinlicher werden Sie die Debug-printf mit

012 deaktivieren

BTW, könnte das eingebettete Zielsystem nicht einmal snprintf ...

Wenn Sie einige lesbar C Standard-Bibliothek Implementierung (unter Linux) betrachten Suche innerhalb musl-libc Quellcode zu studieren. Sie müssen verstehen, was system calls sind.

Eigentlich sollten Sie tatsächlich Ihren Code auf Ihrem Laptop schreiben und debuggen (z. B. unter Linux) und nur das eingebettete System etwas installieren, von dem Sie glauben, dass es keine Bugs hat. Vermeiden Sie in der Praxis die Implementierung von Code mit Debug-Printfs (oder denken Sie im Voraus an etwas viel Besseres). Siehe auch this.

Es scheint, dass das größte Problem für mich ist, die Ausgabe des Drucks zu ergreifen und es wohin zu gehen, zu lenken. Wahrscheinlich

verwenden snprintf „senden“ und dann die debugbuffer an der entsprechenden Stelle mit entsprechenden Primitiven. Mit snprintf kennen Sie die Größe der Nachricht (z. B. mit dem Rückgabewert von snprintf und/oder %n in der Formatsteuerungszeichenfolge). Oder haben Sie Ihre eigene Protokollierung oder Debugging variadic function (mit <stdarg.h> und va_start etc ....)

Verwechseln Sie nicht Nachrichten mit logging Debug-Meldungen. Wenn Sie protokollieren möchten, entwerfen Sie es sorgfältig. Debugging-Meldungen sollten jedoch wahrscheinlich zum Zeitpunkt der Bereitstellung entfernt werden.

+0

Es ist wahrscheinlich ein guter Rat, aber es beantwortet die Frage nicht, so dass die nächste Person diese Frage findet und vielleicht dieser Hinweis gilt nicht für seine Situation, vielleicht gute Info für einen Kommentar statt einer Antwort imo –

+0

@MarkAdelsberger: Das passt nicht in einen Kommentar, und ich habe keine Ahnung (nur Vermutungen) über den OP-Code und das Zielsystem. –

+0

Die wesentlichen Informationen in der ORIGINAL-Antwort (wie es aussah, als ich kommentierte) würden eigentlich in einen Kommentar passen, und unabhängig davon beantwortet es immer noch nicht qu Estion gefragt; Entschuldigung, wenn Sie nicht zustimmen. –

1

Die Posix-Funktion fmemopen ermöglicht es Ihnen, einen Speicherpuffer wie eine Datei zu öffnen und gibt eine FILE * zurück, die mit den Standard-IO-Funktionen wie fprintf verwendet werden kann. Was das Drucken auf einem Gerät betrifft, das kein serieller Port ist, weiß ich nicht, auf welchem ​​Betriebssystem (von denen) Sie laufen, aber wenn vorhanden, könnten Sie einen Stream-Gerätetreiber für dieses benutzerdefinierte Gerät schreiben und Ihre stdout und stderr (und vielleicht stdin) dazu. Wenn Sie ohne Betriebssystem arbeiten, dann hat jemand irgendwo eine FILE Struktur erstellt, die irgendwie mit der seriellen Schnittstelle in Verbindung steht, und printf verwendet diese.