Come stampare i messaggi di debug sulla console gdb con la scheda di rilevamento STM32 usando GDB, OpenOCD e arm-none-eabi-gcc?


15

Sto programmando una scheda di rilevamento STM32 Cortex M0 (32F0308DISCOVERY) utilizzando OpenOCD, arm-none-eabi-gcc e gdb. Mi chiedevo se esiste un modo semplice per registrare i messaggi di debug su SWD. Ho letto dell'opzione semihosting, ma questo sembra richiedere il pull di newlib o altre grandi librerie. (Sono disponibili solo 64k di flash.) Esiste un modo più leggero per registrare il testo su SWD o utilizzare UART è l'unica opzione pratica?


1
Ti suggerisco di provare l'opzione semihosting. A titolo indicativo, le librerie offerte da CooCox (un ambiente Windows Cortex-M gratuito) per M3 / 4 sono piuttosto minimaliste, il loro trasferimento a byte singolo è di 17 istruzioni di assemblaggio. Una ricostruzione di un vecchio progetto (STM32F4) con il loro semihosting e -O0 ha aggiunto 48 byte alla dimensione del codice.
Markt

Potresti non avere il tuo linker che elimina il codice inutilizzato. Per quanto riguarda le alternative, il repository github di texane per la guida degli strumenti stlink ha un semplice schema di cassette postali, anche se non l'ho ancora provato.
Chris Stratton,

Risposte:


15

Grazie per i puntatori, markt e chris-stratton. L'opzione semihosting si è rivelata abbastanza semplice. Sono riuscito a trovare l'origine per un paio di semplici routine di registrazione che possono inviare messaggi alla console OpenOCD. Li pubblicherò qui poiché (i) hanno richiesto alcune modifiche per funzionare e (ii) penso che queste informazioni non siano super facili da trovare per le persone che hanno appena iniziato.

Innanzitutto, il codice D qui è facilmente adattabile per fornire la seguente funzione C:

void send_command(int command, void *message)
{
   asm("mov r0, %[cmd];"
       "mov r1, %[msg];"
       "bkpt #0xAB"
         :
         : [cmd] "r" (command), [msg] "r" (message)
         : "r0", "r1", "memory");
}

Esempio di chiamata send_command per scrivere una stringa sulla console OpenOCD:

const char s[] = "Hello world\n";
uint32_t m[] = { 2/*stderr*/, (uint32_t)s, sizeof(s)/sizeof(char) - 1 };
send_command(0x05/* some interrupt ID */, m);

In secondo luogo, la funzione putChar fornita nei commenti qui funziona perfettamente, tranne per il fatto che ho dovuto aggiungere un '#' prima di 0x03:

void put_char(char c)
{
    asm (
    "mov r0, #0x03\n"   /* SYS_WRITEC */
    "mov r1, %[msg]\n"
    "bkpt #0xAB\n"
    :
    : [msg] "r" (&c)
    : "r0", "r1"
    );
}

Per guardare l'output di queste funzioni, prima avvio OpenOCD, quindi mi collego usando arm-none-eabi-gdb come segue:

target remote localhost:3333
monitor arm semihosting enable
monitor reset halt
load code.elf
continue

Si noti che i messaggi vengono visualizzati sullo stdout del processo OpenOCD, non sulla console GDB.


1
C'è un bug, sizeof () dovrebbe essere strlen ().

1
Grazie user107642. In effetti è possibile usare sizeof qui se 's' è un array piuttosto che un puntatore, quindi l'ho modificato in questo modo.
foldl

Bella risposta! Puoi anche scrivere putcharsemplice comevoid putchar(char c) { send_command(3,&c); }
mvds il

1
"Sizeof" conterà \ 0 finale della stringa, mentre strlen no. Se openocd stampa solo su stdout e su una finestra di terminale xterm, ciò probabilmente non farà una differenza evidente poiché il terminale probabilmente lo ignorerà. Ma se finisci per mettere le cose in un file, penso che sarai sorpreso di trovare quegli zero lì dentro. O il protocollo specifica che è necessario inviare stringhe con il terminatore finale?
user242579

Ah, buon punto user242579. Ho aggiunto un '-1' per tenere conto del trascinamento \ 0.
foldl
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.