Wie kann ich Informationen aus Code in IAR Embedded Workbench in eine Protokolldatei protokollieren?

Ich versuche, eine Anwendung für den Mikrocontroller NXP LPC1788 zu entwickeln, und möchte formatierte Zeichenfolgen an beliebigen Stellen im Quellcode so in einer Protokolldatei protokollieren können, dass die Leistung des Programms vernachlässigbar ist. Im Wesentlichen möchte ich etwas, das den Logger-Dienstprogrammen, die Sie mit Java erhalten, so nahe wie möglich kommt.

ITM_EVENT8_WITH_PCDerzeit verwende ich einen iJet-Debugger und damit kann ich einzelne 8-Bit- oder 32-Bit-Zahlenwerte mit und ITM_EVENT32_WITH_PCzusammen mit dem Programmzähler und dem Zeitstempel in das IAR EW-Ereignisfenster drucken . Zahlen allein sind jedoch nicht aussagekräftig genug, und ich bin auf vier Kanäle beschränkt. Dies bedeutet, dass ich oft einen kleinen Teil des Programms auswählen muss, um ihn gleichzeitig zu protokollieren, Aufrufe ITM_EVENT...in nicht verwandten Teilen auskommentieren und neue hinzufügen oder vorhandene auskommentieren muss in dem Teil, den ich genau überwachen möchte. Dies ist nicht wirklich ein sehr effizienter Ansatz.

Eine Sache, die ich versucht habe, ist das Erstellen einer Makrodatei, die eine Funktion enthält, LogMessagedie eine Zeichenfolge als Parameter akzeptiert und an das integrierte __messageMakro übergibt. Ich bin mir jedoch nicht sicher, wie ich dieses Makro in das Programm einfügen kann, damit ich LogMessagees im Quellcode aufrufen kann - ich habe versucht, es in anzugeben , aber dies ist nicht mit dem Quellcode Debugger -> Setup Macrosverknüpft .LogMessage

Jede Hilfe wäre willkommen.

BEARBEITEN

Wie es in Java gemacht wird

Um ein Beispiel dafür zu geben, wie das Logger-Framework (insbesondere der SLF4J-Variante) in Java verwendet werden kann, nehme ich das aus dem SLF4J-Handbuch und erkläre, was passiert:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloWorld {
  public static void main(String[] args) {
    Logger logger = LoggerFactory.getLogger(HelloWorld.class);
    logger.info("Hello World");
  }
}

In diesem Fall erstellen wir eine Klasse mit einer statischen mainMethode, die als Einstiegspunkt für die Anwendung dient. Dann rufen wir eine Factory-Methode auf, getLoggerum ein Protokollierungsobjekt zu erzeugen, das wir auf die Klasse aufmerksam machen, in der wir es instanziieren - HelloWorld.class. Diese Informationen können so konfiguriert werden, dass sie in Protokollausgaben eingeschlossen werden.

Wir können dieses Protokollierungsobjekt dann verwenden, um Protokolle mit unterschiedlichen Protokollebenen zu erstellen , je nach Wichtigkeit und Art dessen, was wir protokollieren. In dem Beispiel geben wir „Hello World“ auf Protokollebene aus INFO, die zum Protokollieren relativ wichtiger Informationen verwendet wird, und das Protokollierungsframework behandelt diese Ausgabe entsprechend seiner Protokollebene und der Konfiguration des Frameworks – dies kann die Ausgabe an stdout umfassen oder in einer Datei speichern.

Wie ich es machen möchte

Es wäre schön, wenn ich etwas Ähnliches für die Arbeit mit IAR Embedded Workbench-Anwendungen bekommen könnte. I-jet/JTAGjet -> SWO Configuration...Ich habe das Problem mit einem Kollegen besprochen und festgestellt, dass wir Daten von den ITM-Stimulus-Ports über die Menüleiste oben zum Terminal-E/A-Fenster leiten und dann das Terminal-E/A-Fenster protokollieren können . Sie können sich direkt von den ITM-Ports in eine Protokolldatei einloggen, aber ich finde, dass es die Datei jedes Mal zu überschreiben scheint, wenn Sie aus irgendeinem Grund einen neuen Wert in einen ITM-Port schreiben.

Womit ich jetzt experimentiere, ist das Erstellen einer Methode wie logData(uint16_t logId, uint8_t logLevel, uint32_t value), die bewirkt, dass die Daten auf eine bestimmte Weise in einer Protokolldatei gespeichert werden:

  • logId ist eine Kennung, die für jede Protokollnachricht eindeutig ist
  • logLevel ist analog zu Protokollebenen in SLF4J (und sollte eventuell durch eine Aufzählung ersetzt werden)
  • value ist ein einzelner Wert, der der Protokollnachricht zugeordnet wird (und sollte schließlich durch einen variadischen Parameter ersetzt werden, um eine beliebige Anzahl von Werten zu akzeptieren).

Die erzeugte Protokolldatei ist nicht lesbar, aber ich könnte ein Python-Skript zusammenstellen, das die generierte Protokolldatei nimmt und eine schön formatierte, für Menschen lesbare Datei im gleichen Stil wie eine SLF4J-Protokolldatei erstellt.

Das ist zumindest die Idee.

BEARBEITEN 2

Ich habe ein scheinbar anständiges Protokollierungs-Framework für meine Anforderungen zusammengestellt, obwohl ich noch nicht versucht habe, es ausgiebig zu verwenden, um zu sehen, wie es sich unter Druck hält.

In der Methode meiner Mikrocontroller-Anwendung mainkann ich einen Aufruf wie durchführen LOGGER_Init(LOG_LEVEL_DEBUG, 5);, wobei das erste Argument die Logger-Protokollebene und das zweite Argument der ITM-Stimulus-Port zum Drucken von Protokolldaten ist. Der Logger druckt nur Log-Meldungen, deren Log-Level gleich oder höher als sein eigener ist (z. B. druckt ein Logger LOG_LEVEL_INFOMeldungen LOG_LEVEL_WARNund LOG_LEVEL_INFOMeldungen, aber keine LOG_LEVEL_DEBUGMeldungen).

Ich kann dann Daten auf folgende Weise protokollieren:

LOGGER_Info(0x1, 0x20);
LOGGER_Debug(0x2, 0x3A, 0xFF);

Diese Methoden behandeln den ersten Wert als Protokollkennung und die verbleibenden Argumente werden auf unterschiedliche Weise als Protokolldaten behandelt.

In einer 'log map'-Datei verwalte ich eine Zuordnung von Protokollkennungen zu Platzhalter-Protokollausgabemeldungen, wobei '{}' einen Platzhalterwert wie in SLF4J darstellt:

static const LOG_MAP_T logMappings[] = {
  {1, "The first log message in main provides {}"},
  {2, "The second log message provides {} and also {}"}
};

Der Logger druckt Protokollmeldungen der entsprechenden Ebenen an den konfigurierten ITM-Stimulus-Port aus, der sie dann an das Terminal-E/A-Fenster weiterleitet, wo sie in einer Protokolldatei gespeichert werden.

Ich habe dann ein Python-Skript, das sowohl die Protokollausgaben als auch die Zuordnungsdatei durchgeht und alles zusammenfügt, um so etwas zu produzieren:

>>> 
INFO  The first log message in main provides 32
DEBUG The second log message provides 58 and also 255
Können Sie Standard-E/A-Funktionen mit dem Terminal-E/A-Fenster verwenden (Beachten Sie, dass Sie möglicherweise mit Semihosting-Optionen in den Projekteinstellungen herumspielen müssen.). Hast du eine serielle Schnittstelle zur Verfügung? Bei 176x habe ich normalerweise UART0 als Debugging-Port, weil es die gleichen Pins wie die ISP-Schnittstelle verwendet. Sie sollten wahrscheinlich ein kleines Codebeispiel hinzufügen, wie Sie dies verwenden würden, da die Leute möglicherweise nicht mit Logger von Java vertraut sind (ich eingeschlossen).
@user694733 Hallo, ich habe Semihosting konfiguriert, aber es ist wirklich langsam. Ich habe das Problem jedoch mit einem Kollegen besprochen und wir haben festgestellt, dass wir Daten von den ITM-Ports zum Terminal-E/A-Fenster (Seite 10: iar.com/Global/Resources/Developers_Toolbox/… ) leiten und dann das Terminal protokollieren können E/A-Fenster. Es ist möglich, Daten von ITM-Ports direkt in einer Protokolldatei zu speichern, aber ich finde, dass dies aus irgendeinem Grund nicht sehr gut funktioniert. Ich werde das OP mit einem Logger ex aktualisieren.
Diese Frage ist ein wenig relevant.
@ user694733 Danke für die Informationen, aber ich habe jetzt etwas am Laufen, mit dem ich vorerst zufrieden bin (siehe letzte Bearbeitung). Ich werde morgen testen, was ich habe, um sicherzustellen, dass es unter Druck mithalten kann, und wenn nicht, werde ich hierher zurückkommen und mir das, was Sie verlinkt haben, genauer ansehen, um zu sehen, ob es helfen kann.
Ein sehr gutes Protokollierungssystem ist Segger RTT (Real Time Transfer). Aber es erfordert einen Segger-Debugger. Wie auch immer, vielleicht einen Blick wert?

Antworten (1)

Ich würde empfehlen, dass Sie die ETM-Funktion des von Ihnen verwendeten LPC-Chips aktivieren. Die Embedded Trace Macrocell ist im Wesentlichen ein Speicherort, in den Sie Zeichen schreiben können, die über die JTAG/SWD-Verbindung zu Ihrem EWARM in die Terminalfenster (oder sogar in das Eclipse-Plugin) gelangen.

Sie können einfach ein Makro schreiben, um die Zeichen direkt in die Mem-Adresse zu schreiben, oder Sie können das verwenden, was IAR "Host-Modus" nennt, ich denke, wo sie Ihre Standardausgabe hacken und es für Sie tun. Verwenden Sie dann einfach printf eines beliebigen Wrappers, den Sie mögen.

Suchen Sie auf ihrer Website nach der Appnote und ignorieren Sie alle ausgefallenen Trace-Funktionen, die ETM bietet (wenn Sie sie nicht benötigen), und suchen Sie einfach nach den Debug-Ausgaben.

Wenn Sie gewartet werden, rufen Sie das nächste IAR-Büro an und fragen Sie nach einem FAE, und sie werden Sie Schritt für Schritt durchgehen.