SWO : un ARM Printf sous n’importe quel autre nom

Je vais avouer. Bien que printf-style débogage a une mauvaise réputation, je me tourne vers lui à l’occasion. Bien sûr, printf coûte cher et génère beaucoup de code, mais si vous avez l’espace et le temps de l’utiliser pendant le débogage, vous pouvez toujours le supprimer avant d’avoir terminé. Cependant, que se passe-t-il si vous n’avez pas de périphérique de sortie ou si vous l’utilisez pour autre chose ? Si vous utilisez la plupart des puces ARM modernes, vous avez une autre option – un canal de sortie dédié qui est utilisé pour plusieurs choses, y compris la sortie de débogage. J’ai décidé que je voulais essayer cela sur le Blackpill running mbed, et j’ai découvert que ce n’était pas aussi facile qu’on pourrait le penser. Mais c’est possible, et lorsque vous aurez fini de lire, vous pourrez également le faire.

J’écris ceci en utilisant le matériel ST-LINK spécifique à STM32. Si vous utilisez d’autres appareils JTAG comme la sonde BlackMagic, vous avez probablement déjà cette configuration pour vous.

Ce que vous obtenez

Je vais commencer en arrière avec le résultat final, puis parler du logiciel, de sorte que vous serez bon et motivé au moment où vous arriverez aux exigences matérielles. Alerte spoiler : votre matériel existant peut avoir besoin d’un piratage rapide pour le faire fonctionner, bien que vous puissiez acheter quelque chose dans le commerce si vous préférez.

Voici un programme de test très simple :


SWO_Channel debugport;  // requires #include "SWO.h"
int main() 
  {
  unsigned count=0;
  debugport.printf("rnHello World from SWOrn");
  debugport.printf("CPU SystemCoreClock is %d Hzrn", SystemCoreClock);

  while (1) 
    {
    led = !led; // flip LED if output is true
    ThisThread::sleep_for(rate); // sleepy time
    if (count % 10) debugport.putc('*'); else debugport.printf("%drn",count); 
    count++;
    }
}


Rien de difficile à imaginer ici. Vous pouvez utiliser putc ou alors printf pour écrire dans la sortie de débogage. Comme vous pouvez le voir sur la figure, vous obtenez une belle fenêtre qui affiche toute la sortie. Il y a en fait 32 canaux de sortie, mais le canal 0 est réservé à la sortie de débogage. Dans ce cas, j’ai choisi All parce que c’est la seule chose qui sort de l’appareil, de toute façon.

De quoi as-tu besoin

Le STM32CubeProgrammer de ST peut afficher les données SWO.

Tout d’abord, vous avez besoin d’une puce ARM compatible. Toutes les puces ARM ne prennent pas en charge ITM – la macrocellule de trace intégrée – mais c’est ce dont vous avez besoin. Il y aura une broche sur l’appareil marquée SWO (et probablement d’autres choses aussi). Puisque j’utilise le Blackpill avec un STM32F411CE, nous savons que cela devrait fonctionner et la broche de sortie sera PB3.

Vous avez également besoin d’un dongle ST-Link doté d’une broche SWO. Malheureusement, ceux bon marché qui ressemblent à un périphérique de mémoire USB que vous obtenez généralement n’ont pas la broche SWO. Cependant, vous pouvez facilement les pirater. Le ST-Link V2 « complet » a la broche sortie, mais est généralement beaucoup plus cher. Cependant, si vous magasinez dans les magasins chinois habituels, vous pouvez généralement en trouver un à un prix raisonnable. J’ai payé moins de 10 $.

Bien sûr, vous avez également besoin d’une sorte d’outil pour lire la sortie. Un terminal normal ne le fera pas, mais le STM32CubeProgrammer de ST peut facilement lire les données. Il y a, bien sûr, d’autres options aussi. De nombreux IDE et débogueurs peuvent lire la sortie SWO. Il existe également des outils open source, mais les packages Ubuntu sont trop anciens et les packages de publication ne fonctionnaient pas. Le construire à partir de zéro a cependant fonctionné.

Configuration du logiciel

Depuis que j’utilise Mbed, la première chose que j’ai faite a été de chercher une bibliothèque. Je n’ai pas été déçu. La bibliothèque est une mince enveloppe autour des fonctions ITM dans CMSIS, donc si vous n’utilisez pas Mbed, jetez simplement un coup d’œil à ces fonctions et vous pourrez le comprendre. Si vous préférez STM32Duino, vérifiez ceci pour quelque chose de similaire.

Une fois que je l’ai ajouté au projet, j’ai dû corriger une petite chose. Cela n’avait probablement pas d’importance, mais il existe un cas où un tableau est alloué pour un nom de fichier, puis supprimé de manière incorrecte. Noter la delete dans le code ci-dessous :


bool SWO_Channel::claim (FILE *stream) {
  if ( FileBase::getName() == NULL) {
  error("claim requires a name to be given in the instantiator of the SWO instance!rn");
  }

//Add '/' before name:
  char *path = new char[strlen(FileBase::getName()) + 2];
  sprintf(path, "/%s", FileBase::getName());

  if (freopen(path, "w", stream) == NULL) {
// Failed, should not happen
  return false;
}

  delete [] path;   //  fixed

//No buffering
  setvbuf(stream, NULL, _IONBF, 32);
  return true;
}


Une fois que c’est fait, vous êtes prêt à partir. Vous avez juste besoin de matériel.

configuration materielle

Si vous avez le dongle ST « normal » comme le blanc dans l’image ci-dessous, la configuration est juste la configuration normale. Connectez l’alimentation, la masse et les deux broches de débogage au connecteur arrière du Blackpill, puis faites passer un fil de SWO à la broche B4 de l’appareil.

Si vous avez l’un des clones bon marché comme le violet assis à côté de l’appareil blanc, vous devrez faire une intervention chirurgicale pour faire ressortir une épingle supplémentaire.

Chargez un programme qui fait une sortie SWO simple, puis lancez tout. Vous devrez peut-être mettre à niveau le micrologiciel du ST-Link – le logiciel STM32CubeProgrammer peut également le faire.

Lors de la connexion au matériel avec le programmeur, j’ai constaté que le dongle blanc ne se connectait pas de manière fiable à 4000 kHz, j’ai donc dû sélectionner 1800 kHz. C’est peut-être juste cet appareil ou mon câblage aléatoire. Vous pouvez voir les informations de connexion que j’utilise dans la capture d’écran adjacente. Appuyez sur Connecter pour commencer.

Lorsque vous sélectionnez l’élément SWV, vous devrez régler une horloge de 96 MHz pour cette configuration. Vraisemblablement, si vous utilisez une fréquence différente, vous connaîtrez la bonne valeur pour votre configuration. Lorsque vous appuyez sur Démarrer, vous devriez voir la sortie du programme.

La seule chose à retenir est que votre logiciel se battra pour le dongle à moins qu’il n’ait été fait fonctionner en mode « partagé ». Dans mon cas, Mbed Studio ne semblait pas se soucier de ce paramètre, vous devez donc vous déconnecter si vous voulez qu’il reprogramme la puce. Bien sûr, vous pouvez utiliser le programmeur pour tout faire. Tout dépendra de vos outils et de votre configuration.

Bien sûr, une fois que vous l’avez lancé une fois, il est assez facile de le reproduire pour de futurs projets. Vous n’avez qu’un seul fil supplémentaire et deux fichiers supplémentaires dans votre programme.

Aller plus loin

Vous pouvez cependant aller plus loin. Tout d’abord, il y a une sortie colorée. Si votre chaîne de débogage contient #RED#, #GRN# ou #ORG#, les caractères restants seront dans cette couleur (rouge, vert ou orange) pour le reste de la ligne. En supposant, bien sûr, que le spectateur comprenne cela et que vous l’ayez activé. C’est pratique de pouvoir afficher les messages importants en rouge, par exemple.

Cependant, c’est un gaspillage qu’il y ait tant de canaux supplémentaires que nous n’utilisons pas. Par exemple, pourquoi ne pas avoir des messages de progression sur le canal 0 et des informations de débogage détaillées sur le canal 1 ? Vous pouvez avoir un vidage de ce qui arrive d’un périphérique externe sur le canal 5. Bien sûr, vous pouvez écrire un préfixe sur la ligne et extraire les données de cette façon, mais c’est plus amusant.

J’ai réécrit une toute petite partie de la classe SWO existante et, grâce aux arguments optionnels, cela fonctionne toujours de la même manière. La seule différence est que vous pouvez ajouter un numéro de canal au constructeur afin qu’il soit possible de créer plusieurs flux de débogage :


SWO_Channel debugport;
SWO_Channel dbg2("second",1);


Il y a très peu de changements dans le code, mais je laisserai tout le projet sur GitHub.

Si vous ne pouvez pas le dire, j’aime travailler avec le STM32 et le Mbed. Bien sûr, vous pouvez obtenir de meilleures performances en évitant Mbed, mais la bonne chose est que vous le pouvez. Curieusement, envoyer des données sur un port vers plusieurs canaux est quelque chose que j’ai déjà fait d’une manière complètement différente.