Published on

Une boîte à histoire OpenSource - Partie 3

Authors
  • Name
    Anthony Rabine

La boîte à histoires Lunii, création française, est un objet électronique épatant pour les enfants : pas d'écran (quelques images seulement), une molette et un haut parleur suffisent pour écouter des histoires à créer. Les gosses sont accrocs ! Dans ce troisième chapitre, nous allons nous focalier sur les bases de l'électronique et du logiciel embarqué !

L'outillage

Je ne le dirais jamais assez : il faut s'outiller pour bien travailler. On parle ici aussi bien d'outil matériel que logiciel. Donc, puisque nous avons un port de d'émulation sur la carte, il faut utiliser un bon émulateur nous permettant de placer des points d'arrêt. Personnellement j'utilise les outils de la société Segger, à savoir les sondes JLink.

image

Je vous encourage à utiliser cette sonde pour tous vos développements à base d'ARM/PIC32/RISC-V : elle est performante, rapide et supporte beaucoup de points d'arrêts. Elle est supportée par beaucoup d'IDE (Eclipse, MPLAB X, Keil, Iar ...) dont Oxygen, leur outil maison gratuit ciblant le débogage uniquement. Un outil multi plateformes vraiment excellent.

Je vous invite à consulter mon article dédié à ce sujet : Solutions de débogage ARM sous Linux qui présente une autre sonde : la BlackMagic Probe.

Notre projet supportera ces deux sondes, à vous de choisir laquelle utiliser et de toutes façons nous ne serons pas liés à un IDE du commerce.

Choix de l'IDE

Pour le moment, l'IDE n'est pas encore fixé. Les deux candidats potentiels sont :

  • QtCreator : la meilleure intégration de GDB selon moi, il reste encore à bien supporter les cibles embarquées (nous en reparlerons)
  • Eclipse : pas de surprise ici, il dispose de plusieurs extensions pour l'embarqué et supporte toutes les principales sondes sans soucis
  • Oxygen : pas vraiment un IDE mais un débogueur propriétaire (Segger), qui fonctionne forcément très bien avec les sondes JLink. Réactif et léger, il est excellent !

Concernant la machinerie de construction : je partirai sur un CMake. Naturellement, je serais plutôt parti sur un système de construction à base de Makefile mais utiliser CMake me permettra de me former dessus et vu que c'est le système prévu pour la prochaine version de Qt (la 6), autant y passer le plus tôt possible.

Les bases du firmware, possibilité 1

C'est parti pour poser les bases du firmware. Notre but dans cet article sera de créer un "Hello world" de l'embarqué : faire clignoter une LED.

Je commence par récupérer la librairie ASF4 de Atmel. Chez Atmel, c'est un peu obscur, mais ça fonctionne : il faut aller sur le site start.atmel.com et se créer une carte fictive en choisissant ses périphériques. On peut ensuite télécharger une archive contenant un main() et de la librairie ASF4. Ouch, c'est épais, il y a beaucoup de fichiers, moi qui suis habitué aux librairies de ST je suis moyennement convaincu...

Ensuite, il y a plusieurs choix :

  • Soit on utilise le Makefile situé dans l'archive (pour GCC ou ARM), dans le sous répertoire /gcc qui lui utilise la toolchain ARM classique (et non MPLAB)
  • On peut aussi lancer MPLAB IDE : il est capable de convertir un projet START en projet natif, MPLAB est un environnement relativement simple à prendre en main et tout en un.

Après une rapide étude de l'exemple et après avoir passé du temps sur le site d'Atmel pour configurer mon firmware via leur clickodrome des enfers, je ne parviens pas à configurer le CPU à 48MHz. Bref, j'en ai marre de ces machins, une librairie toute simple et plein d'exemples (comme chez ST), c'est trop demander ?

Les bases du firmware, possibilité 2

Arduino c'est cool. C'est simple, j'aime bien. Et leur bootloader permettra de mettre à jour le firmware facilement. Par contre, l'IDE, c'est non. Au secours. Bon, au moment d'écrire cet article, ils proposent Arduino IDE PRO qui autorise beaucoup plus de souplesse dans la gestion du projet (plusieurs fichiers ...) et permet aussi de déboguer ! On verra ce que cela donne.

La fondation Arduino fournit le code source de toutes ses plateformes sur Github, c'est maintenu et le code est simple. Super, on va essayer cela, on récupère le code de la plateforme SAMD et on tente de construire notre CMake.

Le projet CMake est indépendant de tout IDE. J'utilise personnellement QtCreator pour ouvrir car le C++ est particulièrement bien géré (et nous verrons plus tard que le débogage aussi).

La seule chose qu'il faudra spécifier est une variable d'environnement spécifiant où se trouve le compilateur.

shell
ARM_FIND_ROOT_PATH définit à /opt/gcc-arm-none-eabi-2020/bin/

Avec QtCreator c'est ici que ça se passe :

image

Un peu d'électronique

Voici le schéma de principe que nous allons utiliser. Attention, à la lecture de la datasheet, nous voyons que le SAMD21G18A ne peut fournir que 7mA par GPIO. Vous pouvez brancher une LED 5mm classique dessus mais attention à utiliser la bonne résistance en série (généralement on utilise 10mA ou 15mA pour allumer ce type de LED).

Dans notre cas, pour jouer la sécurité, nous allons piloter la LED via un transistor type MOSFET canal N et une résistance de 330 Ohms. Ce type de transistor est pratique car il se contrôle en tension : une tension positive entre la gate et la source permet de le rendre passant.

À quoi pourra bien servir cette LED ? Eh bien, à plein d'usages :

  • Voir rapidement que le programme vie, ou est démarré
  • Signifier des erreurs (par des clignotements)
  • Avoir un GPIO dédié à des tests de mesure de temps, que l'on pourra visualiser avec un oscilloscope

Donc, on va garder ce schéma pour notre montage final.

Nous allons brancher cette LED sur un port numérique, PA22 en notation Atmel, et D0 en notation Arduino. Comment connaître la relation entre les deux ?

C'est très simple : ouvrez le fichier variant.cpp correspondant à votre carte électronique (ici la MKR Zero), un joli tableau vous liste toutes les broches et leur différent nommage :

image

Faire clignoter une LED

Alors en Arduino c'est très simple, ils fournissent un exemple :

c++
#include "Arduino.h"

// the setup function runs once when you press reset or power the board
void setup() {
    // initialize digital pin LED_BUILTIN as an output.
    pinMode(0, OUTPUT);
}

// the loop function runs over and over again forever
void loop()
{
    digitalWrite(0, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(1000);                       // wait for a second
    digitalWrite(0, LOW);    // turn the LED off by making the voltage LOW
    delay(1000);                       // wait for a second
}

J'ai changé la proche par la numéro '0', correspondant à la broche D0 (PA22).

Au niveau du CMake, il suffit d'inclure progressivement les fichiers C++ du projet Arduino jusqu'à ce que le projet compile complètement. Si vous avez des références inconnues à l'étape du linkage c'est qu'il vous manque un fichier.

On flash le fichier .elf avec le débogueur Ozone de Segger :

image

Deuxième outillage : le port série

Vous savez qu'avec Arduino vous disposez généralement d'un port série vous permettant d'afficher des informations de débogage. Nous avons un émulateur, c'est génial pour placer des points d'arrêt, mais avoir une console permet de rapidement voir que tout tourne bien ou au contraire imprimer des messages d'erreur. Lorsque votre application est très grosse, c'est essentiel pour surveiller toute l'application.

Avec la plateforme SAMD21, nous disposons d'un port USB natif. Nous allons donc l'utiliser, cela va nous épargner de prendre des broches pour le débogage. Attention cependant, il y a un petit défaut comparé à un UART natif : à chaque arrêt ou redémarrage, le port série /dev/ttyACM0 sera re-créé et donc tout terminal ouvert dessus générera une erreur. Un port UART natif connecté au PC via un dongle USB/Série n'aura pas ce problème.

c++
#include "Arduino.h"

// the setup function runs once when you press reset or power the board
void setup() {
    // initialize digital pin LED_BUILTIN as an output.
    pinMode(0, OUTPUT);

    SerialUSB.begin(9600);
}

// the loop function runs over and over again forever
void loop()
{
    digitalWrite(0, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(1000);                       // wait for a second
    digitalWrite(0, LOW);    // turn the LED off by making the voltage LOW
    delay(1000);                       // wait for a second
    SerialUSB.println("Hello, Arduino!");
}

Et voilà !

image

Conclusion

Nous avons semble-t-il une plateforme logicielle complète, compatible Arduino mais sans les limitations (nous pouvons modifier les fichiers comme bon nous semble). Au niveau de notre artillerie logicielle, nous avons tout ce qu'il faut :

  • Un débogueur in-situ
  • Une LED à usage générique
  • Une console de sortie