J’ai pas mal d’heures de recherches et de manips sur le sujet, donc je fait un CR. Pour l’instant je suis arrivé à compiler des programmes qui utilisent Mbed avec gcc. J’écris ce post en février 2017.
Grâce à un confrère de l’Electrolab, j’ai trouvé un article de blog qui m’a donné les éléments qui me manquaient pour réussir mon premier pas vers l’indépendance developatrice vis à vis des cartes ST Nucleo. Mais tout d’abord un peu de contexte.
Contexte
Je suis un grand fan des cartes Nucleo de ST. Elles sont pas chères, ont des connecteurs compatibles Arduino (donc on peut utiliser les shields, ce qui est éminament pratique), ont des MCUs performants (ARM 32 bits jusqu’à plus que 100MHz), sont correctement documentés et intègrent un programmateur qui permet de s’en servir “out of the box”. D’ailleurs, les cartes Discovery de ST sont du même niveau et tout à fait recommandables.
Pour programmer et mettre en oeuvre au niveau hardware, pas de souci. Pour ce qui est de programmaer, c’est moins clair. Pour simplifier grossièrement, voici les voies que j’ai identifié:
- Mbed online : directement sur l’IDE en ligne Mbed
- Mbed offline : en utilisant la lib Mbed mais en compilant offline, avec gcc, eclipse ou autre
- Bare-metal : pas de lib, the hard way, compilation offline
- Bare-metal avec les codes générés par STM32Cube : en offline, mais en s’aidant de code pré-généré
- Bare-metal avec la lib Standard Peripheral Libraries Expansions de ST
On va voir chaque cas.
Mbed online, le côté obscur de la force
Plus rapide, plus facile, plus séduisant. Mbed est une lib très accessible et performante … tant qu’on ne créé pas de conflits et que ça rentre dans la flash du MCU. Et l’IDE en ligne est très pratique … quand elle marche.
La lib Mbed est pratique:
- Elle inclut des mécanismes pour faire l’abstraction hardware des cartes supportées, ce qui fait gagner un max de temps. Préparer un environnement pour une carte ? Nouveau projet -> Clic sur le modèle de carte. Fin. Facile. Toutes les spécificités des cartes sont intégrées en #include dans la lib. Très très très pratique.
- L’API est très facile d’accès. Je trouve que le C++ est bien utilisé pour faciliter la mise en place des fonctionalités des cartes.
La lib Mbed a tout de même certains gros défauts:
- Elle est mise à jour un peu quand elle veut, ou plutôt quand ARM veut bien, et c’est pas souvent. Et quand une fonctionalité d’un MCU n’est pas suportée à la sortie de la carte qui la propose, et bien il faut être patient pour que la fonctionalité soit disponible. Généralement ça se compte en mois d’attente.
- Les mises à jour sont centralisées par ARM. Donc forcément ça avance pas vite. On peut fork, ouais ouais. Heureusement d’ailleurs.
- Je n’aime pas trop la tendance de l’API à utiliser les float à tout bout de champ. A un moment il y aura un passage en integer, et un arrondi. Où ? Quand ? Comment ? Pffffuit …
- Cette lib est monstrueusement grosse. Sur les petites cartes, genre Nucleo STM32F042K6, 32kB de flash, si on essaye de mettre autre chose que des GPIO, genre de la SPI ou des ADC, le code ne tient plus en flash. Voilà voilà. Et de toutes façons sur les pages dédiées aux petites cartes, ils disent qu’on ne peut pas utiliser leur OS MbedOS dessus because pas assez de flash.
- Si on compile offline, on voit bien que la lib est conçue pour fonctionner avec l’IDE en ligne
J’oublie sûrement plein de choses, mais en gros c’est ma vision bien / pas bien.
Pour ce qui est de l’IDE c’est un peu pareil:
- Très pratique, on a tout accessible en permanence
- Gestion de version intégrée (Mercurial) très pratique
- On peut exporter les projets, pratique pour les backups et pour passer offline … quand ça accepte de compiler
- Quand le site est en maintenance, tu ne bosses pas.
- C’est buggé à MORT ! Des fois je ne peux pas taper de texte dans l’éditeur. Ou ctrl-c / ctrl-v ne marche pas. Ou l’export. Méga-relou.
- Et ce n’est pas vraiment open-source, quand-même, il faut bien le dire à un moment.
Jusqu’à maintenant j’étais content d’utiliser l’IDE Mbed, mais je n’arrive plus à faire abstraction des problèmes, surtout les bugs qui la rendent inutilisable. Donc il me faut une autre méthode. Dans un premier temps je compte juste me débarrasser de l’IDE pour ne pas subir un site “exterieur”.
Mbed offline
J’ai passé beaucoup de temps à essayer de faire du gcc pour Nucleo, pour me former. J’ai rencontré deux problèmes principaux : je suis une trompette en makefile, et la lib Mbed ne compile pas en offline. Ces deux points ont été brutalement résolus grâce à l’aide d’un confrère de l’Electrolab, qui m’a donné un lien qui m’a débloqué, indirectement. Celui-là:
http://www.josho.org/blog/blog/2014/11/30/nucleo-gcc/
Aujourd’hui, il y a quelques choses à ajouter à ce tutoriel:
- Sur la compilation de stlink, il n’y a plus de script autogen.sh et configure. Il faut suivre les indications dans doc/compiling.md, à savoir faire, tout simplement
make release
et ne pas hésiter à faire unmake clean
avant dans le doute. - Dans la lib Mbed en ce moment il y a une erreur de #define sur les couches CAN de Mbed. Très pro. J’ai trouvé la solution en cherchant l’erreur sur gogol. Et il faut aller dans le makefile, et chercher les deux lignes qui définissent le switch de compil’ DDEVICE_CAN et les mettre à 0:
C_FLAGS += -DDEVICE_CAN=0
CXX_FLAGS += -DDEVICE_CAN=0
- La lib USB, c’est libusb-1.0-0-dev, hein, libusb-tiret-un-point-zero-tiret-zero-tiret-dev
- Et ne pas oublier d’adapter la version de GCC. Aujourd’hui on est en 4.9.3, pas 4.8, donc dans les include du Makefile, remplacer 4.8 par la version installée de GCC
Et là ça compile.
Bare-metal sans aucune lib
http://regalis.com.pl/en/arm-cortex-stm32-gnulinux/
Bare-metal avec les libs ST
Il y a un truc qui m’a grandement choqué quand je me suis plongé dans les libs ST et STM32Cube il y a deux ans : les codes générés par STM32Cube ne sont pas compatibles de la lib standard ST. L’architecture est quasi-identique, mais les noms des modules, des fonctions et des variables sont différents et suivent des normes de nomage différentes. Voilà voilà. Très sérieux tout ça. Donc soit on utilise du code généré par STM32Cube, soit on utilise la lib standard, mais ce n’est pas trop possible de mélanger les deux.
Bon, maintenant je vherche un IDE pour me faciliter le travail, parce que Vim c’est bien, mais je ne maitrise pas encore assez pour avoir un développement fluide. Et modifier les makefile à la main systématiquement c’est pénible à force.
Avec un IDE
J’oublie à dessein les IDE payantes. On est en démocratie, bordel. Plusieurs solutions:
- Eclipse + module C/C++ + gcc-arm
- L’IDE workbench AC6, qui est en fait un Eclipse pré-configuré pour les STM32, donc en gros la même chose que le précédent
- Em::blocks / Embitz: ça a bien évolué, mais c’est assez mal documenté je trouve. Et c’est bien quon puisse créer un projet sur beaucoup de cibles, mais il manque certains MCUs. Genre, je prend la première Nucleo qui traine sur mon bureau, pas de bol le MCU n’est pas dans la liste. Faich’
Le plus gros problème là-dedans, c’est Java. Ce truc s’installe toujorus pas comme il faut, et c’est la merde à faire marcher.
Eclipse + Mbed sous Linux
On peut exporter les projets Mbed pour GNU ARM GCC Eclipse. Faisons donc ça.
Dans le Linux il faut installer les package eclipse et eclipse-cdt. Les outils de compil en eux-mêmes sont installés en suivant les indications précédentes. Dans Eclipse on peut importer le projet exporté de Mbed. Comme on peut s’y atendre, il faut tout de même modifier le makefile (qui est à la racine du projet) avec les modifications proposées par Josj Stone:
- Modifier le flag de compil
nano.spec
ennosys.specs
- Mettre à 0 les define
C_FLAGS += -DDEVICE_CAN=0
etCXX_FLAGS += -DDEVICE_CAN=0
Là ça compile. Youpi !
Eclipse + Mbed sous Windows
Là ça se complique. Le fait d’installer Eclipse requiert Java. Or, le problème que je rencontre systématiquement est qu’il ne se lance pas avec un message d’erreur pas poss’. A chaque fois c’était parce qu’il y avait incohérence entre le type d’install d’Eclipse et du JRE de Java, 32 ou 64 bits. Il faut que les deux soient du même type. Or, pour je ne sais quelle raison, il semble que les installations “automatiques” de java - genre quand on a un warning navigateur pour un applet et qu’on installe le plugin - se fasse systématiquement en 32 bits, même sur un OS 64 bits. Donc commencer par désinstaller Java, puis réinstaller la déclinaison qui va bien. Le JRE suffit. Ensuite il faut chopper le chemin d’accès aux binaires de Java pour le copier dans le fichier eclipse.ini, pour avoir un truc du style:
--launcher.defaultAction
openFile
-vm
C:/Program Files/Java/jre1.8.0_121/bin/javaw.exe
--launcher.appendVmargs
-vmargs
Une fois qu’Eclipse daigne démarrer, il faut installer le plug-in gnuarmeclipse. J’ai choisi de travailler avec ça, il doit y avoir d’autres solutions, mais bon, au moins sur cet outil il y a de la doc. Donc d’abord la toolchain:
http://gnuarmeclipse.github.io/toolchain/install/
Puis les outils de build:
http://gnuarmeclipse.github.io/windows-build-tools/install
Puis le plug-in gnuarmeclipse:
http://gnuarmeclipse.github.io/plugins/install/
Là normalement en essayant avec le “download button” ça met un message d’erreur comme quoi le repository n’est pa slisible (ou un truc du style). Solution :
http://gnuarmeclipse.github.io/blog/2017/01/29/plugins-install-issue/
Télécharger le package, écraser les deux fichisers dans le répertoire de Java, et redémarrer Eclipse pour que la modif soit prise en compte. Là ça doit fonctionner et s’installer.
Par contre, ça ne compile pas, bien entendu.
Encore un problème : sur les outils installés, les chemins d’accès contiennent des espaces. Bien entendu, le parsing dans le makefile va merder. Fuuuu
La solution que j’ai trouvé est d’échapper les espaces dans les chemins d’INCLUDE:
INCLUDE_PATHS += -I'\"d:/dev/GNU ARM Eclipse/Build Tools/2.8-201611221915/bin\"'
INCLUDE_PATHS += -I'\"d:/dev/GNU Tools ARM Embedded/5.4 2016q3/bin\"'
Les ” ” inclus dans des ‘ ‘ permettent de forcer les guillemets. On échappe les espaces avec
Avec ça, ça devrait compiler. Youpiii !
Eclipse sans Mbed sous Windows
Avec gnuarmeclipse, c’est plutôt facile. On peut installer des packs qui permettent de faire du debug avec le support QEMU (que j’ai installé). Ca marche bien avec les MCUs en M0 jusqu’à M4, mais les M7 ça merde grave. J’ai du mal à voir si c’est que ces MCUs ne sont pas encore supportés, ou bien si c’est un bug.