[Actualité] [Raspberry Pi Pico][SDK C/C++] Session de débogage avec la sonde dans Visual Studio Code
par
, 02/06/2023 à 08h00 (3545 Affichages)
Mon #@¤* de code ne fonctionne pas ! Mais vous me croyez si je vous dis que je l'ai fait exprès ?
Parce qu'après avoir mis en place tout l'environnement avec ma sonde (voir Déboguer la Raspberry Pi Pico avec une sonde dans Visual Studio Code), il fallait bien mettre en place un scénario de débogage...
#@¤*-de-code.c
Code c : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 #include <stdio.h> #include "pico/stdlib.h" void four_digits(uint8_t *t, uint number); int main() { stdio_init_all(); sleep_ms(3000); uint8_t p[4], q[4]; four_digits(p, 5678u); four_digits(q, 124u); /* ----- débogage avec printf() ------ */ for (uint8_t i = 0; i < 4; i++) { printf("%d ", p[i]); } printf("\r\n"); for (uint8_t i = 0; i < 4; i++) { printf("%d ", q[i]); } printf("\r\n"); return 0; } void four_digits(uint8_t *t, uint number) { /* Remplit un tableau de 4 entiers passé en argument avec chaque chiffre du nombre 'number' (alignement à droite) exemple : avec four_digits(p, 124u) p[0]=0, p[1]=1, p[2]=2, p[3]=4 */ if (number > 9999u) number = 9999u; uint8_t i = 0; while (number) { t[3 - i] = number % 10u; number /= 10u; i++; } }
La fonction four_digits() doit compléter un tableau de taille 4 avec les différents chiffres qui constituent le nombre passé en paramètre (nombre < 9999).
Par exemple avec four_digits(p, 5678u), ont doit obtenir p[0]=5, p[1]=6, p[2]=7, et p[3]=8.
L'algorithme est simple, une histoire de division entière par 10 et de son reste... La fonction pourra servir plus tard à afficher un nombre entier sur un afficheur 7-segments à quatre digits.
Pourtant tout compile bien, mais mes printf() en retour dans un terminal m'affichent 100 1 2 4 pour l'appel four_digits(p, 124u) alors que j'ai bien 5 6 7 8 comme prévu pour l'appel four_digits(p, 5678u)... D'où vient cette valeur 100, qu'est-ce que c'est que ce bin's ?
Le lecteur averti a sans doute déjà trouvé ce qui clochait, mais le but du jeu est de voir comment on pourrait débusquer la boulette grâce à la sonde.
Quand on appuie sur l’icône du bouton Exécuter et déboguer à gauche (ou par Ctrl+Maj+d), et que l’on clique sur la flèche verte démarrer le débogage (F5) , la session de débogage débute avec une première pause à un point d’arrêt provisoire à l'entrée du main() :
En cliquant au début de la ligne 14, on rajoute un point d'arrêt (le point rouge) pour que le programme fasse une pause après la sortie de l'appel four_digits(p, 5678u). On sait qu'à cette étape, le résultat renvoyé est correct.
On doit cliquer ici sur le bouton Continuer (F5) pour dérouler le programme jusqu'au prochain point d'arrêt à la ligne 14. On voit en effet dans la section Variables à gauche que le tableau p est bien renseigné avec les valeurs 5, 6, 7 et 8, comme attendu.
Ici, il faut cliquer sur pas à pas détaillé (F11) pour justement rentrer dans le détail de la fonction. On aperçoit que l'argument 124 est bien passé en paramètre à la fonction. On peut d'ailleurs voir la valeur du paramètre number au passage de la souris sur la variable (number=124).
Ici, on avance un peu plus vite jusqu'au while. On rajoute un point d'arrêt à la ligne 44 à l'entrée de la boucle while, et on clique sur Continuer (F5).
Détailler entièrement les instructions de la boucle pas à pas à chaque passage dans la boucle serait un peu long. On peut accélérer les choses en modifiant les caractéristiques du point d'arrêt au niveau du while, avec une condition d'arrêt renseignée. Ici, le programme fera une pause quand la condition i==2 sera vérifiée.
En cliquant sur Continuer (F5), le programme stoppe à nouveau à l'entrée du while mais après deux tours dans la boucle, avec i=0 au 1er passage et i=1 au 2nd passage.
Le tableau local t commence à se remplir avec t[3]=4 puis t[2]=2 :
Comme number=1, il y a au moins un tour supplémentaire à effectuer dans la boucle. On peut cette fois dérouler les instructions jusqu'au retour au début du while avec des clics sur pas à pas (F10), et voir l'évolution du tableau t qui va être complété avec t[1].
On a bien t[1]=1, les chiffres du nombre 124 sont bien dans le tableau :
Mais maintenant number=0, donc on au prochain clic sur pas à pas (F10), on sort de la boucle while et on quitte la fonction.
On comprend que dans la fonction, t[0] n'a jamais été renseigné et que l'emplacement en mémoire est donc resté à sa valeur d'entrée non initialisée, c'est-à-dire ici la valeur 100 (code ASCII du caractère 'd'). La boucle while a bien traité un nombre à 3 chiffres, mais le 4è digit à gauche n'est pas mis à zéro.
Pour résoudre le problème, soit on initialise le tableau avec des zéros avant de boucler, soit on change la condition dans la boucle pour être sûr d'initialiser les quatre digits quelle que soit la taille du nombre passé en paramètre. Par exemple, while (number) peut simplement être remplacé par while (i < 4) sans rien changer d'autre par ailleurs.
Programme débogué
Conclusion
Nous avons, à travers un petit exemple tout simple, dégrossi les notions essentielles pour débuter le débogage du microcontrôleur Raspberry Pi Pico : point d'arrêt et ses propriétés, déroulement pas à pas du programme, et espionnage du contenu des variables. Pour être complet, il faudrait rentrer dans l'analyse des registres et des périphériques du Cortex M0, la pile des appels, etc.
Le fonctionnement du couple OpenOCD - GNU Debugger(GDB) est complexe : OpenOCD démarre entre autres un serveur GDB sur un port TCP, et un client GDB peut alors se connecter au port pour déboguer le microcontrôleur. Finalement, Visual Studio Code propose une interface graphique plus conviviale pour interagir avec le client, mais il est toujours possible de dialoguer en ligne de commande dans VS Code. Vous pouvez regarder cette discussion sur Stackoverflow avec un beau schéma pour comprendre le principe (avec un autre microcontrôleur).
À suivre...