Vous avez un microcontrôleur mais pas de débogueur ? Ou peut-être un microcontrôleur qui ne supporte pas de débogueur ? Alors ces conseils sont pour vous ! Bien que les débogueurs et leurs environnements de développement intégrés (IDE) soient intelligents et exceptionnellement utiles, il arrive parfois qu'ils ne soient d'aucune aide ou presque. Ces conseils de débogage fournissent quelques idées sur la façon de savoir ce qui se passe à l'intérieur de votre microcontrôleur lorsqu'il n'y a pas d'autre moyen de voir.

Bien que la plupart des cartes de développement pour microcontrôleurs soient équipées d'un débogueur intégré, il y en a encore beaucoup qui ne le sont pas. L'un des avantages d'un débogueur est la possibilité d'arrêter l'exécution du code, d'examiner le contenu des variables et de parcourir le code ligne par ligne. Cependant, certaines cartes, comme l'Arduino Uno et Mega, n'ont pas de support de débogage intégré. Il existe également de minuscules microcontrôleurs 8 bits à faible nombre de broches, tels que ceux de la série PIC10/12/16 de Microchip, qui ne prennent même pas en charge un débogueur (il existe une solution de contournement en utilisant une carte d'en-tête de débogage).

Même avec un débogueur, certaines applications ne peuvent pas être arrêtées en cours de fonctionnement. Les appareils communiquant via USB ou Ethernet ne peuvent pas être interrompus en cours de communication par un débogueur, car cela rompt la liaison établie. Il en va de même pour la commande de moteurs ou les alimentations numériques, où la mise en pause du processeur pourrait entraîner un court-circuit ou une forte consommation de courant dans un MOSFET.

    Avez-vous déjà débogué sans débogueur ?


    La LED clignotante

    L'outil de débogage de loin le plus simple est une résistance et une LED de votre choix. Connectées à une broche d'E/S polyvalente (GPIO), elles peuvent être utilisées comme un drapeau à un endroit stratégique du code pour laisser un fil d'Ariane électronique. Il y a quelques exemples où cela peut être utile :

    • Routines d'interruption : Les fiches techniques sont notoirement difficiles à interpréter, et tout ce qui concerne les interruptions l'est particulièrement. De nombreux périphériques ont plusieurs interruptions. Une interface série peut générer une interruption lorsque des données sont envoyées, lorsqu'elles sont reçues, lorsque sa mémoire tampon est pleine, en cas de dépassement de la mémoire tampon, et dans de nombreuses autres conditions. Il n'est pas étonnant qu'il soit si difficile d'activer le bon signal et d'y attacher du code. Alterner l'état d'une broche GPIO dans la routine d'interruption cible peut confirmer si votre code est appelé.
    • Les instructions switch et if/else : l'écriture de la logique en C/C++ est sujette aux erreurs. Qui n'a pas accidentellement utilisé & au lieu de && ? Sans débogueur, vous pouvez vous demander si une branche du code est atteinte ou si une décision est décodée. Là encore, le fait d'activer une broche GPIO peut révéler si le code a été atteint.
     
    Une LED suffit à indiquer si une section du code a été atteinte.

    L'avantage de se limiter à la configuration d'une GPIO est la simplicité et la rapidité du code. La plupart des processeurs peuvent effectuer cette tâche en un ou deux cycles d'instruction, ce qui garantit que le temps d'exécution de votre code n'est pas affecté de manière significative.

    Malheureusement, certains problèmes de débogage sont plus complexes. Dans de tels cas, vous pourriez commencer à basculer la broche utilisée à plusieurs endroits. Cependant, il est peu probable que vous puissiez toujours voir la LED s'éteindre et s'allumer. Si vous avez la chance d'avoir un oscilloscope ou un analyseur logique, reliez-le à la broche, et vous pourrez voir ce qui se passe.

    L'approche du modem, câblé pour le son !

    En fonction de la complexité du problème, vous pouvez être tenté de commencer à basculer d'autres broches pour déterminer le problème. Cependant, avec les micros à faible nombre de broches, il se peut qu'il n'y en ait aucune de disponible. Mais, si votre dispositif comporte un périphérique de modulation de largeur d'impulsion (PWM), vous avez peut-être une alternative.

    Les PWM disposent généralement de deux options de configuration clés : la fréquence et le rapport d'espacement. Une fois activées, elles font basculer une GPIO indépendamment du processeur à une fréquence liée à l'oscillateur du micro. La modification de la fréquence nécessite généralement une écriture dans un seul registre, de sorte que l'ajout de ce code de débogage a un impact minimal sur le temps d'exécution du code, tout comme l'approche par LED. Le taux d'espacement des marques peut être laissé à 50% ou varier si ce paramètre supplémentaire aide le processus de débogage.

    Une sirène piézoélectrique peut être connectée à une broche du microcontrôleur via un petit condensateur.
    Sinon, un haut-parleur ou un écouteur peut être connecté via un transistor.

    Pour déboguer votre code, vous devrez attacher un ronfleur piézoélectrique à la broche PWM, ou vous pouvez utiliser un transistor pour augmenter la sortie afin de piloter un haut-parleur ou un écouteur de casque. En ajoutant une ligne de code pour changer la fréquence aux endroits stratégiques où vous pensez qu'il y a un problème, votre code créera une mélodie pendant son exécution. Le fait de passer par différentes sections du code modifie la « musique », et vous apprendrez avec le temps ce qui sonne bien ou mal. Pour ceux qui sont assez âgés, cela peut vous rappeler les vieux modems que nous utilisions pour accéder à l'Internet avant l'ère de la DSL 

    Contrôlez le temps

    Avec certains microcontrôleurs, il est facile de déterminer combien de temps une section de code doit prendre pour s'exécuter. Par exemple, la plupart des instructions assembleur d'un PIC10/12 ne nécessitent qu'un cycle d'horloge, à l'exception des instructions qui modifient le compteur de programme. Grâce à ces connaissances, vous pouvez calculer le temps d'exécution d'une section de code dans vos conditions de test et le comparer avec un oscilloscope ou un analyseur logique.

    La configuration matérielle pour cette approche est la même que pour la LED, qui n'est pas nécessaire. La seule différence est la préparation pour déterminer le temps d'exécution du code.

    Le basculement des broches dans les sections du code peut être capturé à l'aide d'un analyseur logique pour retracer le chemin d'exécution du code.

    Si vous n'avez pas envie de décoder l'assembleur, vous pouvez plutôt mesurer le temps d'exécution du code entre différents points. En testant différents chemins dans votre code, vous devriez avoir une idée de ce qui ne va pas. Par exemple, si une boucle for ou while est exceptionnellement longue ou courte, il se peut qu'une variable soit mal initialisée ou qu'une décision qui devrait mettre fin à une boucle soit mal codée.

    Sortie des messages

    Si votre microcontrôleur est suffisamment évolué, il peut disposer d'une interface série, telle qu'un U(S)ART ou un SPI. Comme le PWM, il suffit de les initialiser. Pour éviter de devoir mettre les données en mémoire tampon, l'interface doit être configurée pour fonctionner à sa fréquence la plus élevée, même s'il s'agit d'un débit en bauds ou d'un taux de signalisation excentrique et non standard. La raison pour laquelle cela n'a pas d'importance est que nous ne la connecterons pas à un autre périphérique. Au lieu de cela, nous allons simplement utiliser un analyseur logique.

    Les analyseurs logiques USB sont aujourd'hui très bon marché et le logiciel fourni peut être configuré pour décoder les données série. Si vous n'en avez pas sous la main, vous pouvez même concevoir le vôtre pour supporter cette approche de débogage en utilisant un Arduino avec un processeur ARM rapide et puissant.

    Ces interfaces ne nécessitent généralement que l'écriture d'un octet de données dans un registre de transmission, ce qui, là encore, est généralement fait en un seul cycle d'horloge. Après cela, les bits sont décalés en fonction du débit de données configuré. Tout ce qu'il reste à faire est d'attribuer différentes valeurs à écrire à différents points de votre code. Au fur et à mesure que les données sont transmises, vous obtenez une trace du chemin d'exécution de votre code. Si l'interface est suffisamment rapide, aucune donnée ne devrait être perdue.

    Le Serial Monitor de l'Arduino IDE peut également horodater les messages reçus, ce qui peut aider à déterminer les sections d'exécution de code d'une longueur inattendue. Cependant, la résolution du timer utilisé peut ne pas être suffisante pour résoudre les courtes sections d'exécution de code.

    Le Serial Monitor d'Arduino peut horodater les messages. Ici nous voyons une longue période entre '2' et '0' qui peut indiquer un problème d'exécution de code.

    Cette approche pourrait également être utilisée pour sortir des valeurs stockées dans des variables ou des registres, bien que la sortie puisse rapidement devenir confuse à décoder en raison des informations limitées.

    Pas de débogueur ? Il y a toujours un moyen

    Ce n'est pas parce que vous n'avez pas de débogueur que vous ne pouvez pas déboguer votre code. Vous devez simplement faire preuve d'un peu d'imagination. Les méthodes décrites ici, associées à une bonne compréhension de votre code et du microcontrôleur utilisé, peuvent aider à résoudre un large éventail de problèmes. Elles peuvent même aider lorsqu'un débogueur ne peut pas le faire ! Et, si aucune de ces méthodes ne vous convient, peut-être trouverez-vous un autre périphérique ou une autre fonction qui peut être réorientée pour servir d'outil d'aide au débogage.

     
    VF : Maxime Valens