Comment imprimer des messages de débogage sur la console gdb avec la carte de découverte STM32 à l'aide de GDB, OpenOCD et arm-none-eabi-gcc?

15

Je programme une carte de découverte STM32 Cortex M0 (32F0308DISCOVERY) en utilisant OpenOCD, arm-none-eabi-gcc et gdb. Je me demandais s'il existe un moyen simple de consigner les messages de débogage via SWD. J'ai lu sur l'option semihosting, mais cela semble nécessiter l'extraction de newlib ou d'autres grandes bibliothèques. (Il n'y a que 64 Ko de mémoire flash disponibles.) Existe-t-il un moyen plus léger de consigner du texte sur SWD, ou l'utilisation de l'UART est-elle la seule option pratique?

foldl
la source
1
Je vous suggère d'essayer l'option semi-hôte. À titre indicatif, les bibliothèques proposées par CooCox (un environnement Windows Cortex-M gratuit) pour M3 / 4 sont assez minimalistes, leur transfert sur un octet est de 17 instructions d'assemblage. Une reconstruction d'un ancien projet (STM32F4) avec leur semi-hôte et -O0 a ajouté 48 octets à la taille du code.
Markt
Votre éditeur de liens peut ne pas supprimer le code inutilisé. En ce qui concerne les alternatives, le dépôt github de texane pour la gestion des outils stlink a un schéma de boîte aux lettres simple, bien que je ne l'ai pas encore essayé.
Chris Stratton

Réponses:

15

Merci pour les pointeurs, Markt et Chris-Stratton. L'option de semi-hébergement s'est avérée assez simple. J'ai réussi à trouver la source de quelques routines de journalisation simples qui peuvent envoyer des messages à la console OpenOCD. Je les posterai ici car (i) ils ont nécessité quelques modifications pour fonctionner et (ii) je pense que cette information n'est pas super facile à trouver pour les personnes qui débutent.

Tout d'abord, le code D ici est facilement adapté pour fournir la fonction C suivante:

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");
}

Exemple d'appel de send_command pour écrire une chaîne dans la 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);

Deuxièmement, la fonction putChar donnée dans les commentaires ici fonctionne bien, sauf que j'ai dû ajouter un «#» avant 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"
    );
}

Pour regarder la sortie de ces fonctions, je démarre d'abord OpenOCD, puis je me connecte en utilisant arm-none-eabi-gdb comme suit:

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

Notez que les messages apparaissent sur la sortie standard du processus OpenOCD, pas sur la console GDB.

foldl
la source
1
Il y a un bug, la taille de () devrait être strlen ().
1
Merci user107642. En fait, il est possible d'utiliser sizeof ici si 's' est un tableau plutôt qu'un pointeur, donc je l'ai modifié de cette façon.
foldl
Très bonne réponse! Vous pouvez également écrire putcharaussi simplement quevoid putchar(char c) { send_command(3,&c); }
mvds
1
Le "sizeof" comptera le \ 0 de fin de la chaîne, contrairement à strlen. Si openocd imprime simplement sur stdout et une fenêtre de terminal xterm, cela ne fera probablement pas de différence notable car le terminal l'ignorera probablement. Mais si vous finissez par mettre des choses dans un fichier, je pense que vous serez surpris de trouver ces zéros là-dedans. Ou le protocole spécifie-t-il que vous devez envoyer des chaînes avec le terminateur de fin?
user242579
Ah, bon utilisateur point242579. J'ai ajouté un «-1» pour prendre en compte le \ 0 de fin.
foldl