ITM Meldungen ausgeben (Cortex-M3 und höher)

OP #8052992
Lesenswert?

Ich habe mir überlegt, wie ich bequem Debug Meldungen über ITM ausgeben kann. Das Konstrukt mit den variablen Argumenten (args) ist mir allerdings neu. Habe ich das so richtig umgesetzt?

1
#include "stm32g4xx.h"
2
#include <stdio.h>
3
#include <stdarg.h>
4

5
// Output an ITM message
6
void debug_print(const char *ptr) {
7
    while (*ptr) {
8
        ITM_SendChar((uint32_t)*ptr++);
9
    }
10
}
11

12
// Like printf() but using ITM. Max. 80 characters.
13
void debug_printf(const char* format, ...) {
14

15
    // Skip if ITM is not enabled
16
    if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) &&((ITM->TER & 1UL) != 0UL)) {
17

18
        char buffer[81]; // change the size if needed
19
        va_list args;
20
        va_start(args, format);
21
        vsnprintf(buffer, sizeof(buffer), format, args);
22
        va_end(args);
23
        debug_print(buffer);
24
    }
25
}
26

27
int main() {
28
    ...
29
    debug_print("Hello World! \n");
30
    int i=42;
31
    debug_printf("value of i is %d \n",i);
32
}

Es funktioniert, aber ist es so auch fachlich sauber?

#8053001
Lesenswert?

Der Code in den Zeilen 19 bis 22 ist soweit formal korrekt, so verwendet man va_list.

Unabhängig davon: Die Funktion belegt halt u.a. die Puffergröße auf dem Stack, das kann für eine Debugausgabe problematisch werden.

Günstiger könnte es sein, die Variante vfprintf zu verwenden, und die dort letztlich rausfallenden Zeichen direkt an ITM_SendChar zu übergeben. Dazu musst Du allerdings rausfinden, wie in Deiner Entwicklungsumgebung mit printf und Dateihandles wie stdio etc. umgegangen wird. Oft muss man nur eine lowlevel-Funktion wie _write ersetzen.

Und rein stilitisch: Was sollen die Leerzeichen vor den Zeilenumbrüchen in main()?

Könnte man doch eigentlich auch so schreiben, oder nicht?

Ja, das kann man.

: Bearbeitet durch User
OP #8053013
Lesenswert?

Harald K. schrieb:

Günstiger könnte es sein, die Variante vfprintf zu verwenden, und die dort letztlich rausfallenden Zeichen direkt an ITM_SendChar zu übergeben.

Ja das klappt.

Dazu musst Du allerdings rausfinden, wie in Deiner Entwicklungsumgebung mit printf und Dateihandles wie stdio etc. umgegangen wird. Oft muss man nur eine lowlevel-Funktion wie _write ersetzen.

Jawoll, den Punkt kenne ich. Im Fall von Arduino schien es mir naheliegender, einen kleinen Puffer zu verwenden. STM32duino saut eh schon herum, was den Speicherbedarf angeht. Da fallen die 81 Bytes nicht weiter auf :-)

Was sollen die Leerzeichen vor den Zeilenumbrüchen in main()?

Soll die Lesbarkeit des Beispiels erhöhen. In echt programmiere ich nicht so.

: Bearbeitet durch User
#8053038
Lesenswert?

Harald K. schrieb:

Günstiger könnte es sein, die Variante vfprintf zu verwenden, und die dort letztlich rausfallenden Zeichen direkt an ITM_SendChar zu übergeben. Dazu musst Du allerdings rausfinden, wie in Deiner Entwicklungsumgebung mit printf und Dateihandles wie stdio etc. umgegangen wird. Oft muss man nur eine lowlevel-Funktion wie _write ersetzen.

1
int __io_putchar(int ch) {
2
    ITM_SendChar(ch);
3
    return ch;
4
}
#8053044
Lesenswert?

Hans W. schrieb:

Harald K. schrieb:

Günstiger könnte es sein, die Variante vfprintf zu verwenden, und die dort letztlich rausfallenden Zeichen direkt an ITM_SendChar zu übergeben.

Im Fall von Arduino schien es mir naheliegender, einen kleinen Puffer zu verwenden. STM32duino saut eh schon herum, was den Speicherbedarf angeht. Da fallen die 81 Bytes nicht weiter auf :-)

Ein Kompromiss: der Puffer könnte static sein. So ein debug_print() möchte man irgendwann auch in einem fault handler benutzen, da fällt das auf dem Stack eher auf. Dafür lohnt sich evt. sogar Formatierung im Eigenbau. Wenn man auf Luxus wie %f, %*.*s verzichtet, braucht die nur ca. 12 Byte Puffer für beliebig lange Ausgaben. Und keine lib.

P.S. ich fände debug_printf mit 'f' schöner, gerade, wenn die die lib benutzt und alles kann.

Beitrag #8053046 wurde vom Autor gelöscht.
#8053052
Lesenswert?

Bauform B. schrieb:

Dafür lohnt sich evt. sogar Formatierung im Eigenbau. Wenn man auf Luxus wie %f, %*.*s verzichtet, braucht die nur ca. 12 Byte Puffer für beliebig lange Ausgaben. Und keine lib.

Ich frage mich, wieviel Lebenszeit schon sinnlos verschwendet wurde, um krampfhaft printf() & Co. zu vermeiden, nur weil es etwas Code einspart.

Damals, als die µCs wirklich noch keinen Programmspeicher hatten, da war das wirklich ein Argument, aber hier geht es um irgendeinen Cortex - und der hat nun wirklich keine Probleme damit, die wenigen kByte einer printf-Implementierung unterzubringen. Und auf float-Unterstützung kann man immer noch verzichten; die Runtime-Libraries üblicher Compiler bieten genau deswegen verschieden zurechtgekürzte printf-Libraries an.

#8053072
Lesenswert?

Harald K. schrieb:

Ich frage mich, wieviel Lebenszeit schon sinnlos verschwendet wurde, um krampfhaft printf() & Co. zu vermeiden, nur weil es etwas Code einspart.

Mir ging es drum, Abhängigkeiten zu vermeiden, Flash hat man, ausreichend. Mit einem printf(), das keinen Stack braucht, kann ich im fault handler immer noch "drucken", egal, wie groß das Chaos ist. OK, Hintergrund ist auch, ich lasse die Programme erstmal im RAM laufen und flashe selten.

Ich finde es auch angenehm, wenig bis keine fremden libs zu brauchen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren