Je suis parti à la découverte des micros Cortex M4 lors de l'achat d'une carte de démonstration STM32F3 discovery pour une dizaine d'euros.
Cette "demo board" embarque plusieurs choses très intéressantes, notamment, un MCU STM32F303VCT6 32 bits Cortex M4, un ST-LINK v2 (outil de programmation et de debug), un Gyroscope, Un compas avec un accéléromètre, plusieurs leds et boutons et deux connecteurs mini USB. Bref, tout pour commencer à s’amuser.
Un programme de démonstration tourne déjà sur la carte et permet de s'amuser avec les différents composants (Chenillard, gyroscope et accéléromètre avec la roue de Leds).
Après lecture de la documentation téléchargeable sur le site de ST microelectronics. J'ai fait particulièrement attention aux différents outils de développement proposés avec la carte. 4 choix possibles :
Vous l'aurez compris, j'ai choisi la cinquième option. Elle consiste à utiliser des outils Open source pour toute la chaîne de développement.
Ce premier post sur le cortex M4 va consister à montrer les différents outils nécessaires au développement, à la programmation et au débogage.
Avant de répondre à cette questionexistentielle, on va revenir sur l'archive fournie par ST avec la démo board. Elle fournit les sources de la démo installée sur la carte ainsi que différents exemples sur l'utilisation et l'interfaçage des périphériques du micro.
Dans le dossier Libraries, contient le fameux dossier CMSIS, ainsi que le dossier STM32F30x_StdPeriph_Driv contenant les drivers (sources) des périphériques présents sur la carte et le dossier STM32_USB-FS-Device_Driv contenant la librairie de la pile de communication USB de la carte.
J'ai voulu m’intéresser plus particulièrement au dossier CMSIS parce qu'il a une particularité très intéressante.
CMSIS pour ARM Cortex Microcontroller Software Interface Standard est une couche d'abstraction bas niveau, comprenez hardware, indépendante du constructeur pour les séries de micro contrôleur Cortex. Ce qui signifie, que quelque soit le constructeur de micro contrôleur Cortex M0, Cortex M3 ou Cortex M4 (ST, NXP, etc ...), la couche d'abstraction CMSIS sera, à un ou deux détails près, la même.
Dans le cas de travaux hobbyistes, tels que les miens, ce n'est pas très important, mais pour des sociétés voulant changer de micro contrôleur sur leurs cartes en passant d'un fabricant à un autre pour des raisons de pérennité ou pour passer sur une série plus puissante, cela peut considérablement réduire les coûts de développement.
Dans le dossier CMSIS, se trouve les sous dossiers :
Pour construire notre chaîne de compilation, on va se servir de l'outil Crosstool-NG. Pour ceux qui suivent ce blog, il fait partie de la suite de logiciels contenue dans buildroot.
Cet outil a pour but de construire une chaîne de compilation croisée en fonction des différents paramètres donnés.
Je vous file le fichier de config.
L'archive de l'outil (crosstool-ng-1.18.0.tar.bz2) doit être téléchargée puis installée :
Puis dans le dossier d'installation de Crosstool-NG, lancer l'outil :
L'un des sous dossiers important est Target options :
Ce sous dossier permet de configurer l'architecture matérielle du micro contrôleur.
Le sous dossier Operating System :
bare-metal signifie que le software est exécuté directement depuis la mémoire vive, sur le système, au lieu d'être chargé en tant que tâche d'un OS.
Le sous dossier C compiler :
Après la configuration, il suffit de lancer la commande pour construire la chaîne de compilation :
(Attention, cette étape peut-être longue, quelques dizaines de minutes, en fonction des capacités de votre ordinateur)
Une fois la compilation faite, voici le dossier d'installation de cette nouvelle chaîne :
Le Template va permettre de créer un projet générique ou il n'y aura plus qu'à y insérer les sources du projet et à modifier le makefile. Il est basé sur un déjà existant, adapté pour l'occasion :
Voici l'arborescence de notre Template nécessaire pour la compilation :
Le dossier Libraries a volontairement disparu puisque je vais utiliser les librairies fournies avec la démo board de chez ST.
Voici l'arborescence après compilation :
La séquence de démarrage pour un système "bare-metal" de type ARM est contenu dans un fichier startup.s. Toutes les séquences d'initialisation bas niveau pour le CPU, la carte, écrite en C ou en assembleur, sont présents.
Le script de linkage regroupe les informations du code de démarrage, et définit la "map" mémoire du système cible. Il a comme extention .ld.
Pour les plus courageux, voici un peu de documentation (Building_bare-metal_ARM_with_GNU.pdf) sur le sujet.
Maintenant le fichier de compilation, Makefile. Il faut modifier les variables :
Deux étapes sont nécessaires pour la compilation du projet, la première, compilation des sources des drivers périphériques et création d'une librairie statique et la deuxième, compilation des sources du projet et linkage avec la librairie statique.
Différentes sous-commandes sont présentes, dans ce Makefile, pour faciliter la compilation du projet, la programmation du micro contrôleur et le débogage de celui-ci.
Compilation du projet :
Programmation de la cible :
Débogage de la cible :
Bien sur, il n'est pas nécessaire de créer sa propre chaîne de compilation, il est possible d'en télécharger une. Vous en trouverez sur le site de Launchpad.net, rubrique GNU Tools for ARM embedded processors. Les avantages de télécharger la chaîne sont, premièrement, de l'installer sur l'OS que vous souhaitez (Windows, Mac ou Linux), deuxièmement, de pouvoir l'utiliser sur de nombreux micros, tel que Cortex M0, M3, M4, etc ...
Pour connaître toutes les architectures supportées par la chaîne de compilation croisée, il suffit de lancer la commande :
Les différents types d'architectures sont :
Cependant, cela implique quelques modifications du Makefile du Template pour préciser le type de micro, ainsi que les options qui vont avec.
La sonde JTAG est directement intégrée sur la carte de démo via un micro stlink v2. Sous windows, les drivers de cette sonde sont directement téléchargeable sur le site de chez ST. Par contre sous linux, c'est un peu plus galère, surtout si vous utilisez, comme moi, une machine virtuelle.
Sur virtualbox, ça ne fonctionne juste pas !!! Par contre, sur VMWare, cela fonctionne moyennant un ajout dans les règles udev.
Dans le dossier /etc/udev/rules.d, il faut rajouter la règle S49-stlinkv2.rules :
et copier le texte ci-dessous :
Le logiciel windows s'appelle STM32 ST-LINK Utility et permet de programmer les cibles STM32 Cortex sans trop de soucis. Après avoir installer les drivers de la sonde JTAG, il suffit de lancer le logiciel.
L'onglet Target permet de connecter la carte puis de la programmer. Il accepte comme fichier d'entrée le binaire ".HEX".
Je ne vais pas trop m'attarder sur le logiciel Windows. Passons maintenant aux choses sérieuses.
Le premier outil utilisé pour la programmation du micro s'appelle stlink, du même nom que la sonde JTAG de la carte. Les sources disponibles sous github (ci-dessous) permettent de compiler les outils sous Linux.
Repository des utilitaires de programmation pour la sonde JTAG stlink v2 pour les micros cortex de chez STM32 :
Installation des outils :
Deux utilitaires sont compilés :
Voici quelques exemples de commandes pour le flashage du binaire fraîchement compilé :
Commande de lecture de 4096 octets de la flash du micro, à partir de l'adresse 0x8000000, dans le fichier out.bin
Commande d'écriture du fichier in.bin dans la flash du micro à l'adresse 0x8000000
PS : L'adresse 0x8000000 correspond à l'adresse de début de la plage mémoire (0x8000000 à 0x8040000 => 256 KOctets) de la flash interne du micro d'après le mapping mémoire de la datasheet.
OpenOCD est un logiciel qui permet de débugger/programmer un code s'exécutant sur un processeur en utilisant l'interface JTAG. Ce logiciel libre fait l'intermédiaire entre le logiciel de debug et l'interface matérielle qui permet l'accès au JTAG.
Il offre trois interfaces d'utilisation :
OpenOCD reconnait de nombreux adaptateur JTAG :
Récupération des sources d'openocd :
Compilation et installation :
On reprend en détail la partie programmation du micro avec le makefile :
Il lance l'utilitaire OpenOCD avec comme configuration de carte stm32f3discovery.cfg, comme directives de programmation stm32f3-openocd.cfg et deux commandes (première pour la programmation et la deuxième pour la fermeture de la communication).
le fichier stm32f3-openocd.cfg, on retrouve, comme sur l'autre outil, une écriture en flash à l'adresse de début 0x08000000 :
Pour programmer le micro avec le programme fraîchement compilé, on lance la commande :
Attention : Le débogage, pour le moment n'est possible que si on utilise la chaîne de compilation croisée téléchargée sur le site de Launchpad, suite à un bug sur la version de GDB de crosstool-NG.
On reprend en détail la partie débogage du micro avec le makefile :
Il lance la commande de débogage arm-none-eabi-gdb avec comme fichier de configuration gdb-cmds et le binaire à déboguer.
GDB communique avec OpenOCD de deux façons différentes :
Le fichier de configuration gdb-cmds :
La commande à lancer pour le débogage est la suivante :
La petite astuce qui tue pour avoir le multi-windows sous GDB : CTRL x puis a :
Cette "demo board" embarque plusieurs choses très intéressantes, notamment, un MCU STM32F303VCT6 32 bits Cortex M4, un ST-LINK v2 (outil de programmation et de debug), un Gyroscope, Un compas avec un accéléromètre, plusieurs leds et boutons et deux connecteurs mini USB. Bref, tout pour commencer à s’amuser.
Un programme de démonstration tourne déjà sur la carte et permet de s'amuser avec les différents composants (Chenillard, gyroscope et accéléromètre avec la roue de Leds).
Après lecture de la documentation téléchargeable sur le site de ST microelectronics. J'ai fait particulièrement attention aux différents outils de développement proposés avec la carte. 4 choix possibles :
- Altium®, TASKINGTM VX-toolset : Outil payant (environ 1500 euros) avec version d'essai.
- ARM®, Atollic TrueSTUDIO® : Outil payant avec version d'essai.
- IAR, EWARM (IAR Embedded Workbench®) : Outil payant avec version d'essai 30 jours.
- Keil, MDK-ARM : Outil payant avec version d'essai.
Vous l'aurez compris, j'ai choisi la cinquième option. Elle consiste à utiliser des outils Open source pour toute la chaîne de développement.
Ce premier post sur le cortex M4 va consister à montrer les différents outils nécessaires au développement, à la programmation et au débogage.
- Création d'une chaîne de compilation croisée GNU custom pour le micro.
- Création d'un Template de compilation (Makefile, etc ...).
- Utilisation et comparaison avec une chaîne de compilation croisée GNU téléchargeable.
- Installation et utilisation de l'outil de programmation sous linux (non-officiel) et sous windows (officiel)
- Installation et utilisation de l'outil OpenOCD pour le débogage.
CMSIS : Qu'est ce que c'est ?
Avant de répondre à cette question
# cd STM32F3-Discovery_FW_V1.1.0 # ls -al total 100 drwxrwxr-x 6 sinseman44 sinseman44 4096 2013-02-25 19:30 ./ drwxr-xr-x 17 sinseman44 sinseman44 4096 2013-02-27 21:27 ../ drwxrwxr-x 2 sinseman44 sinseman44 4096 2013-02-25 19:30 _htmresc/ drwxrwxr-x 5 sinseman44 sinseman44 4096 2013-02-25 19:28 Libraries/ -r--r--r-- 1 sinseman44 sinseman44 17797 2012-09-07 13:14 MCD-ST Liberty SW License Agreement V2.pdf drwxrwxr-x 5 sinseman44 sinseman44 4096 2013-02-25 19:28 Project/ -r--r--r-- 1 sinseman44 sinseman44 39158 2012-09-27 15:05 Release_Notes.html drwxrwxr-x 3 sinseman44 sinseman44 4096 2013-02-25 19:30 Utilities/
Dans le dossier Libraries, contient le fameux dossier CMSIS, ainsi que le dossier STM32F30x_StdPeriph_Driv contenant les drivers (sources) des périphériques présents sur la carte et le dossier STM32_USB-FS-Device_Driv contenant la librairie de la pile de communication USB de la carte.
# cd Libraries total 20 drwxrwxr-x 5 sinseman44 sinseman44 4096 2013-02-25 19:28 ./ drwxrwxr-x 6 sinseman44 sinseman44 4096 2013-02-25 19:30 ../ drwxrwxr-x 9 sinseman44 sinseman44 4096 2013-02-25 19:28 CMSIS/ drwxrwxr-x 4 sinseman44 sinseman44 4096 2013-02-25 19:28 STM32F30x_StdPeriph_Driver/ drwxrwxr-x 4 sinseman44 sinseman44 4096 2013-02-25 19:28 STM32_USB-FS-Device_Driver/
J'ai voulu m’intéresser plus particulièrement au dossier CMSIS parce qu'il a une particularité très intéressante.
CMSIS pour ARM Cortex Microcontroller Software Interface Standard est une couche d'abstraction bas niveau, comprenez hardware, indépendante du constructeur pour les séries de micro contrôleur Cortex. Ce qui signifie, que quelque soit le constructeur de micro contrôleur Cortex M0, Cortex M3 ou Cortex M4 (ST, NXP, etc ...), la couche d'abstraction CMSIS sera, à un ou deux détails près, la même.
Dans le cas de travaux hobbyistes, tels que les miens, ce n'est pas très important, mais pour des sociétés voulant changer de micro contrôleur sur leurs cartes en passant d'un fabricant à un autre pour des raisons de pérennité ou pour passer sur une série plus puissante, cela peut considérablement réduire les coûts de développement.
Dans le dossier CMSIS, se trouve les sous dossiers :
- CMSIS-CORE : offre une interface avec l'architecture matérielle du micro contrôleur ainsi que les registres, les définitions des noms, des adresses. Il contient, également, une interface indépendante pour les noyaux temps réel (RTOS) qui inclus des définitions de débogage.
- CMSIS-DSP : Suite de sources, codées en C, de nombreuses fonctions pour le traitement de signaux basée sur l'architecture Cortex.
- CMSIS-RTOS API : Interface de programmation standardisé pour les OS temps réel (Thread control, resource, time management, ...)
- CMSIS-SVD (System View Description) : Fichiers XML contenant une vue complete du micro contrôleur incluant les périphériques externes.
Chaîne de compilation croisée custom
Pour construire notre chaîne de compilation, on va se servir de l'outil Crosstool-NG. Pour ceux qui suivent ce blog, il fait partie de la suite de logiciels contenue dans buildroot.
Cet outil a pour but de construire une chaîne de compilation croisée en fonction des différents paramètres donnés.
Je vous file le fichier de config.
L'archive de l'outil (crosstool-ng-1.18.0.tar.bz2) doit être téléchargée puis installée :
# tar xvjf crosstool-ng-1.18.0.tar.bz2 # cd crosstool-ng-1.18.0 # ./bootstrap # ./configure # make # make install
Puis dans le dossier d'installation de Crosstool-NG, lancer l'outil :
# cd <CROSSTOOL_NG_INSTALL_PATH> # cd bin
=> Pour ceux qui ont téléchargé le fichier de config # mv cortexM4_config .config
# ./ct-ng menuconfig
L'un des sous dossiers important est Target options :
Ce sous dossier permet de configurer l'architecture matérielle du micro contrôleur.
Le sous dossier Operating System :
bare-metal signifie que le software est exécuté directement depuis la mémoire vive, sur le système, au lieu d'être chargé en tant que tâche d'un OS.
Le sous dossier C compiler :
Après la configuration, il suffit de lancer la commande pour construire la chaîne de compilation :
# ./ct-ng build
(Attention, cette étape peut-être longue, quelques dizaines de minutes, en fonction des capacités de votre ordinateur)
Une fois la compilation faite, voici le dossier d'installation de cette nouvelle chaîne :
# cd <x-tools> total 320 dr-xr-xr-x 8 sinseman44 sinseman44 4096 2013-02-27 18:40 ./ drwxr-xr-x 3 sinseman44 sinseman44 4096 2013-02-27 16:34 ../ dr-xr-xr-x 6 sinseman44 sinseman44 4096 2013-02-27 17:58 arm-unknown-eabi/ dr-xr-xr-x 2 sinseman44 sinseman44 12288 2013-02-27 18:40 bin/ -r--r--r-- 1 sinseman44 sinseman44 278144 2013-02-27 18:40 build.log.bz2 dr-xr-xr-x 3 sinseman44 sinseman44 4096 2013-02-27 18:40 include/ dr-xr-xr-x 4 sinseman44 sinseman44 4096 2013-02-27 18:40 lib/ dr-xr-xr-x 3 sinseman44 sinseman44 4096 2013-02-27 18:31 libexec/ dr-xr-xr-x 4 sinseman44 sinseman44 4096 2013-02-27 18:40 share/
Template de compilation
Le Template va permettre de créer un projet générique ou il n'y aura plus qu'à y insérer les sources du projet et à modifier le makefile. Il est basé sur un déjà existant, adapté pour l'occasion :
Voici l'arborescence de notre Template nécessaire pour la compilation :
- dossier Device : contient le code de démarrage de la carte ainsi que le script de linkage
- dossier extra : contient les utilitaires nécessaires pour le flashage et le débogage du projet
- dossier src : contient les fichiers sources du projet
- dossier inc : contient les headers des fichiers sources
- Makefile : fichier de compilation
Le dossier Libraries a volontairement disparu puisque je vais utiliser les librairies fournies avec la démo board de chez ST.
Voici l'arborescence après compilation :
- dossier Device : contient le code de démarrage de la carte ainsi que le script de linkage
- dossier extra : contient les utilitaires nécessaires pour le flashage et le débogage du projet
- dossier bins : contient les binaires (fichier HEX, fichier ELF, fichier BIN, fichier MAP, etc ...) générés du projet.
- dossier inc : contient les headers des fichiers sources
- dossier deps : contient les dépendances générées lors de la compilation
- dossier objs : contient les fichiers objets générés lors de la compilation
- dossier src : contient les fichiers sources du projet
- Makefile : fichier de compilation
- libstm32f3.a : librairie statique compilée des sources des périphériques du micro
Quelques explications sur le fichier de linkage et le code de démarrage :
La séquence de démarrage pour un système "bare-metal" de type ARM est contenu dans un fichier startup.s. Toutes les séquences d'initialisation bas niveau pour le CPU, la carte, écrite en C ou en assembleur, sont présents.
Le script de linkage regroupe les informations du code de démarrage, et définit la "map" mémoire du système cible. Il a comme extention .ld.
Pour les plus courageux, voici un peu de documentation (Building_bare-metal_ARM_with_GNU.pdf) sur le sujet.
Maintenant le fichier de compilation, Makefile. Il faut modifier les variables :
- SRCS : contient les noms des fichiers sources à compiler.
- SRCS_PERIPH : contient les noms des fichiers sources des drivers des différents périphériques de la démo board.
- PROJ_NAME : Le nom du projet qui sera utilisé comme nom de binaires.
- STD_PERIPH_LIB : Le chemin des librairies fournies avec la démo board.
- LDSCRIPT_INC : Le chemin du script de linkage.
- OPENOCD_BOARD_DIR : Le chemin des scripts de configuration de carte pour OpenOCD.
- OPENOCD_PROC_FILE : Le chemin des directives de lancement d'OpenOCD.
- TOOLCHAIN : Le chemin de la chaîne de compilation croisée.
- TOOLCHAIN_TARGET : Le préfixe de la chaîne de compilation croisée.
# put your *.c source files here, make should handle the rest! SRCS = main.c errno.c stm32f3_discovery.c system_stm32f30x.c # Periph driver sources SRCS_PERIPH = stm32f30x_adc.c stm32f30x_can.c stm32f30x_comp.c stm32f30x_crc.c \ stm32f30x_dac.c stm32f30x_dbgmcu.c stm32f30x_dma.c \ stm32f30x_exti.c stm32f30x_flash.c stm32f30x_gpio.c \ stm32f30x_i2c.c stm32f30x_iwdg.c stm32f30x_misc.c stm32f30x_opamp.c \ stm32f30x_pwr.c stm32f30x_rcc.c stm32f30x_rtc.c stm32f30x_spi.c \ stm32f30x_syscfg.c stm32f30x_tim.c stm32f30x_usart.c \ stm32f30x_wwdg.c usb_core.c usb_init.c usb_int.c usb_mem.c \ usb_regs.c usb_sil.c # all the files will be generated with this name (main.elf, main.bin, main.hex, etc) PROJ_NAME=blink_led # Location of the Libraries folder from the STM32F3 Standard Peripheral Library STD_PERIPH_LIB=<PATH_TO_LIBRARIES_FILES>/STM32F3-Discovery_FW_V1.1.0/Libraries # Location of the linker scripts LDSCRIPT_INC=Device/ldscripts # location of OpenOCD Board .cfg files (only used with 'make program') OPENOCD_BOARD_DIR=<PATH_TO_OPENOCD_BOARD_SCRIPT> # Configuration (cfg) file containing programming directives for OpenOCD OPENOCD_PROC_FILE=extra/stm32f3-openocd.cfg # toolchain path TOOLCHAIN=<PATH_TO_TOOLCHAIN>/gcc-arm-none-eabi-4_7-2012q4/bin TOOLCHAIN_TARGET=$(TOOLCHAIN)/arm-none-eabi- # that's it, no need to change anything below this line! ################################################### CC = $(TOOLCHAIN_TARGET)gcc GDB = $(TOOLCHAIN_TARGET)gdb OBJCOPY = $(TOOLCHAIN_TARGET)objcopy OBJDUMP = $(TOOLCHAIN_TARGET)objdump SIZE = $(TOOLCHAIN_TARGET)size LIB = libstm32f3.a CFLAGS = -Wall -g -std=c99 -Os #CFLAGS += -mlittle-endian -mcpu=cortex-m4 -march=armv7e-m -mthumb #CFLAGS += -mfpu=fpv4-sp-d16 -mfloat-abi=hard CFLAGS += -ffunction-sections -fdata-sections LDFLAGS += -Wl,--gc-sections -Wl,-Map=bins/$(PROJ_NAME).map ################################################### vpath %.a $(STD_PERIPH_LIB) vpath %.c $(STD_PERIPH_LIB)/STM32F30x_StdPeriph_Driver/src vpath %.c $(STD_PERIPH_LIB)/STM32_USB-FS-Device_Driver/src vpath %.c src ROOT=$(shell pwd) CFLAGS += -Iinc CFLAGS += -I$(STD_PERIPH_LIB) CFLAGS += -I$(STD_PERIPH_LIB)/CMSIS/Device/ST/STM32F30x/Include CFLAGS += -I$(STD_PERIPH_LIB)/CMSIS/Include CFLAGS += -I$(STD_PERIPH_LIB)/STM32F30x_StdPeriph_Driver/inc CFLAGS += -I$(STD_PERIPH_LIB)/STM32_USB-FS-Device_Driver/inc CFLAGS += -DUSE_STDPERIPH_DRIVER STARTUP = Device/startup_stm32f30x.s # add startup file to build OBJS = $(addprefix objs/,$(SRCS:.c=.o)) DEPS = $(addprefix deps/,$(SRCS:.c=.d)) OBJS_PERIPH = $(addprefix objs/,$(SRCS_PERIPH:.c=.o)) DEPS_PERIPH = $(addprefix deps/,$(SRCS_PERIPH:.c=.d)) ################################################### .PHONY: all lib proj program debug clean reallyclean all: $(LIB) proj -include $(DEPS) $(LIB): $(OBJS_PERIPH) @echo [AR] $@ @$(AR) -r $@ $(OBJS_PERIPH) proj: bins/$(PROJ_NAME).elf dirs: @mkdir -p deps objs bins @touch dirs objs/%.o : %.c dirs @echo [OBJ] $< @$(CC) $(CFLAGS) -c -o $@ $< -MMD -MF deps/$(*F).d bins/$(PROJ_NAME).elf: $(OBJS) @$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(STARTUP) -L$(STD_PERIPH_LIB) -L. -lstm32f3 -L$(LDSCRIPT_INC) -Tstm32f3.ld @$(OBJCOPY) -O ihex bins/$(PROJ_NAME).elf bins/$(PROJ_NAME).hex @$(OBJCOPY) -O binary bins/$(PROJ_NAME).elf bins/$(PROJ_NAME).bin @$(OBJDUMP) -St bins/$(PROJ_NAME).elf > bins/$(PROJ_NAME).lst @$(SIZE) bins/$(PROJ_NAME).elf program: all @openocd -f $(OPENOCD_BOARD_DIR)/stm32f3discovery.cfg -f $(OPENOCD_PROC_FILE) -c "stm_flash `pwd`/bins/$(PROJ_NAME).bin" -c shutdown debug: program @$(GDB) -x extra/gdb_cmds bins/$(PROJ_NAME).elf clean: @echo [CLEAN] @find ./ -name '*~' | xargs rm -f @rm -rf objs @rm -rf deps @rm -rf bins @rm -f dirs @rm -f $(LIB) reallyclean: clean @$(MAKE) -C $(STD_PERIPH_LIB) clean
Deux étapes sont nécessaires pour la compilation du projet, la première, compilation des sources des drivers périphériques et création d'une librairie statique et la deuxième, compilation des sources du projet et linkage avec la librairie statique.
Différentes sous-commandes sont présentes, dans ce Makefile, pour faciliter la compilation du projet, la programmation du micro contrôleur et le débogage de celui-ci.
Compilation du projet :
# make clean all
Programmation de la cible :
# make program
Débogage de la cible :
# make debug
Chaîne de compilation croisée GNU
Bien sur, il n'est pas nécessaire de créer sa propre chaîne de compilation, il est possible d'en télécharger une. Vous en trouverez sur le site de Launchpad.net, rubrique GNU Tools for ARM embedded processors. Les avantages de télécharger la chaîne sont, premièrement, de l'installer sur l'OS que vous souhaitez (Windows, Mac ou Linux), deuxièmement, de pouvoir l'utiliser sur de nombreux micros, tel que Cortex M0, M3, M4, etc ...
Pour connaître toutes les architectures supportées par la chaîne de compilation croisée, il suffit de lancer la commande :
./arm-none-eabi-gcc -print-multi-lib .; thumb;@mthumb fpu;@mfloat-abi=hard armv6-m;@mthumb@march=armv6s-m armv7-m;@mthumb@march=armv7-m armv7e-m;@mthumb@march=armv7e-m armv7-r/thumb;@mthumb@march=armv7-r armv7e-m/softfp;@mthumb@march=armv7e-m@mfloat-abi=softfp@mfpu=fpv4-sp-d16 armv7e-m/fpu;@mthumb@march=armv7e-m@mfloat-abi=hard@mfpu=fpv4-sp-d16 armv7-r/thumb/softfp;@mthumb@march=armv7-r@mfloat-abi=softfp@mfpu=vfpv3-d16 armv7-r/thumb/fpu;@mthumb@march=armv7-r@mfloat-abi=hard@mfpu=vfpv3-d16
Les différents types d'architectures sont :
- Architecture ARMv6-M : Cortex-M0, Cortex-M0+ et Cortex-M1
- Architecture ARMv7-M : Cortex-M3
- Architecture ARMv7E-M : Cortex-M4
- Architecture ARMv7-R : Cortex-R4 (processeur temps-réel)
Cependant, cela implique quelques modifications du Makefile du Template pour préciser le type de micro, ainsi que les options qui vont avec.
# put your *.c source files here, make should handle the rest! SRCS = main.c errno.c stm32f3_discovery.c system_stm32f30x.c # Periph driver sources SRCS_PERIPH = stm32f30x_adc.c stm32f30x_can.c stm32f30x_comp.c stm32f30x_crc.c \ stm32f30x_dac.c stm32f30x_dbgmcu.c stm32f30x_dma.c \ stm32f30x_exti.c stm32f30x_flash.c stm32f30x_gpio.c \ stm32f30x_i2c.c stm32f30x_iwdg.c stm32f30x_misc.c stm32f30x_opamp.c \ stm32f30x_pwr.c stm32f30x_rcc.c stm32f30x_rtc.c stm32f30x_spi.c \ stm32f30x_syscfg.c stm32f30x_tim.c stm32f30x_usart.c \ stm32f30x_wwdg.c usb_core.c usb_init.c usb_int.c usb_mem.c \ usb_regs.c usb_sil.c # all the files will be generated with this name (main.elf, main.bin, main.hex, etc) PROJ_NAME=blink_led # Location of the Libraries folder from the STM32F3 Standard Peripheral Library STD_PERIPH_LIB=<PATH_TO_LIBRARIES_FILES>/STM32F3-Discovery_FW_V1.1.0/Libraries # Location of the linker scripts LDSCRIPT_INC=Device/ldscripts # location of OpenOCD Board .cfg files (only used with 'make program') OPENOCD_BOARD_DIR=<PATH_TO_OPENOCD_BOARD_SCRIPT> # Configuration (cfg) file containing programming directives for OpenOCD OPENOCD_PROC_FILE=extra/stm32f3-openocd.cfg # toolchain path TOOLCHAIN=<PATH_TO_TOOLCHAIN>/gcc-arm-none-eabi-4_7-2012q4/bin TOOLCHAIN_TARGET=$(TOOLCHAIN)/arm-none-eabi- # that's it, no need to change anything below this line! ################################################### CC = $(TOOLCHAIN_TARGET)gcc GDB = $(TOOLCHAIN_TARGET)gdb OBJCOPY = $(TOOLCHAIN_TARGET)objcopy OBJDUMP = $(TOOLCHAIN_TARGET)objdump SIZE = $(TOOLCHAIN_TARGET)size LIB = libstm32f3.a CFLAGS = -Wall -g -std=c99 -Os CFLAGS += -mlittle-endian -mcpu=cortex-m4 -march=armv7e-m -mthumb CFLAGS += -mfpu=fpv4-sp-d16 -mfloat-abi=hard CFLAGS += -ffunction-sections -fdata-sections LDFLAGS += -Wl,--gc-sections -Wl,-Map=bins/$(PROJ_NAME).map ################################################### vpath %.a $(STD_PERIPH_LIB) vpath %.c $(STD_PERIPH_LIB)/STM32F30x_StdPeriph_Driver/src vpath %.c $(STD_PERIPH_LIB)/STM32_USB-FS-Device_Driver/src vpath %.c src ROOT=$(shell pwd) CFLAGS += -Iinc CFLAGS += -I$(STD_PERIPH_LIB) CFLAGS += -I$(STD_PERIPH_LIB)/CMSIS/Device/ST/STM32F30x/Include CFLAGS += -I$(STD_PERIPH_LIB)/CMSIS/Include CFLAGS += -I$(STD_PERIPH_LIB)/STM32F30x_StdPeriph_Driver/inc CFLAGS += -I$(STD_PERIPH_LIB)/STM32_USB-FS-Device_Driver/inc CFLAGS += -DUSE_STDPERIPH_DRIVER STARTUP = Device/startup_stm32f30x.s # add startup file to build OBJS = $(addprefix objs/,$(SRCS:.c=.o)) DEPS = $(addprefix deps/,$(SRCS:.c=.d)) OBJS_PERIPH = $(addprefix objs/,$(SRCS_PERIPH:.c=.o)) DEPS_PERIPH = $(addprefix deps/,$(SRCS_PERIPH:.c=.d)) ################################################### .PHONY: all lib proj program debug clean reallyclean all: $(LIB) proj -include $(DEPS) $(LIB): $(OBJS_PERIPH) @echo [AR] $@ @$(AR) -r $@ $(OBJS_PERIPH) proj: bins/$(PROJ_NAME).elf dirs: @mkdir -p deps objs bins @touch dirs objs/%.o : %.c dirs @echo [OBJ] $< @$(CC) $(CFLAGS) -c -o $@ $< -MMD -MF deps/$(*F).d bins/$(PROJ_NAME).elf: $(OBJS) @$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(STARTUP) -L$(STD_PERIPH_LIB) -L. -lstm32f3 -L$(LDSCRIPT_INC) -Tstm32f3.ld @$(OBJCOPY) -O ihex bins/$(PROJ_NAME).elf bins/$(PROJ_NAME).hex @$(OBJCOPY) -O binary bins/$(PROJ_NAME).elf bins/$(PROJ_NAME).bin @$(OBJDUMP) -St bins/$(PROJ_NAME).elf > bins/$(PROJ_NAME).lst @$(SIZE) bins/$(PROJ_NAME).elf program: all @openocd -f $(OPENOCD_BOARD_DIR)/stm32f3discovery.cfg -f $(OPENOCD_PROC_FILE) -c "stm_flash `pwd`/bins/$(PROJ_NAME).bin" -c shutdown debug: program @$(GDB) -x extra/gdb_cmds bins/$(PROJ_NAME).elf clean: @echo [CLEAN] @find ./ -name '*~' | xargs rm -f @rm -rf objs @rm -rf deps @rm -rf bins @rm -f dirs @rm -f $(LIB) reallyclean: clean @$(MAKE) -C $(STD_PERIPH_LIB) clean
Programmation du micro
La sonde JTAG est directement intégrée sur la carte de démo via un micro stlink v2. Sous windows, les drivers de cette sonde sont directement téléchargeable sur le site de chez ST. Par contre sous linux, c'est un peu plus galère, surtout si vous utilisez, comme moi, une machine virtuelle.
Sur virtualbox, ça ne fonctionne juste pas !!! Par contre, sur VMWare, cela fonctionne moyennant un ajout dans les règles udev.
Dans le dossier /etc/udev/rules.d, il faut rajouter la règle S49-stlinkv2.rules :
# cd /etc/udev/rules.d/ # sudo touch S49-stlinkv2.rules # vim touch S49-stlinkv2.rules
et copier le texte ci-dessous :
# stm32 discovery boards, with onboard st/linkv2 # ie, STM32L, STM32F4. # STM32VL has st/linkv1, which is quite different SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", \ MODE:="0666", \ SYMLINK+="stlinkv2_%n" # If you share your linux system with other users, or just don't like the # idea of write permission for everybody, you can replace MODE:="0666" with # OWNER:="yourusername" to create the device owned by you, or with # GROUP:="somegroupname" and mange access using standard unix groups.
Windows
Le logiciel windows s'appelle STM32 ST-LINK Utility et permet de programmer les cibles STM32 Cortex sans trop de soucis. Après avoir installer les drivers de la sonde JTAG, il suffit de lancer le logiciel.
L'onglet Target permet de connecter la carte puis de la programmer. Il accepte comme fichier d'entrée le binaire ".HEX".
Je ne vais pas trop m'attarder sur le logiciel Windows. Passons maintenant aux choses sérieuses.
Linux
Le premier outil utilisé pour la programmation du micro s'appelle stlink, du même nom que la sonde JTAG de la carte. Les sources disponibles sous github (ci-dessous) permettent de compiler les outils sous Linux.
Repository des utilitaires de programmation pour la sonde JTAG stlink v2 pour les micros cortex de chez STM32 :
Installation des outils :
# sudo apt-get install libusb-1.0 libusb-1.0-dev pkg-config autotools # git clone git://github.com/texane/stlink.git stlink # cd stlink # ./autogen.sh # ./configure # make
Deux utilitaires sont compilés :
- st-flash : un outil de manipulation de la flash
- st-utils : un serveur GDB (non abordé dans ce tutoriel)
Voici quelques exemples de commandes pour le flashage du binaire fraîchement compilé :
Commande de lecture de 4096 octets de la flash du micro, à partir de l'adresse 0x8000000, dans le fichier out.bin
# ./st−flash read out.bin 0x8000000 4096
Commande d'écriture du fichier in.bin dans la flash du micro à l'adresse 0x8000000
# ./st−flash write in.bin 0x8000000
PS : L'adresse 0x8000000 correspond à l'adresse de début de la plage mémoire (0x8000000 à 0x8040000 => 256 KOctets) de la flash interne du micro d'après le mapping mémoire de la datasheet.
OpenOCD (Open On-Chip Debugger)
OpenOCD est un logiciel qui permet de débugger/programmer un code s'exécutant sur un processeur en utilisant l'interface JTAG. Ce logiciel libre fait l'intermédiaire entre le logiciel de debug et l'interface matérielle qui permet l'accès au JTAG.
Il offre trois interfaces d'utilisation :
- Un serveur GDB, permettant l'utilisation de gnu debugger
- Une interface telnet pour passer directement des commandes
- Une interface TCL, permettant d'utiliser ce langage de script
OpenOCD reconnait de nombreux adaptateur JTAG :
- Interfaces parallèles
- Interface USB (FTDI, ...)
Installation de l'outil
Récupération des sources d'openocd :
# git clone git://git.code.sf.net/p/openocd/code openocd-code
Compilation et installation :
# ./bootstrap # ./configure --enable-maintainer-mode --enable-stlink # make # make install
Programmation grâce à OpenOCD et au Template du projet
On reprend en détail la partie programmation du micro avec le makefile :
program: all @openocd -f $(OPENOCD_BOARD_DIR)/stm32f3discovery.cfg -f $(OPENOCD_PROC_FILE) -c "stm_flash `pwd`/bins/$(PROJ_NAME).bin" -c shutdown
Il lance l'utilitaire OpenOCD avec comme configuration de carte stm32f3discovery.cfg, comme directives de programmation stm32f3-openocd.cfg et deux commandes (première pour la programmation et la deuxième pour la fermeture de la communication).
le fichier stm32f3-openocd.cfg, on retrouve, comme sur l'autre outil, une écriture en flash à l'adresse de début 0x08000000 :
init proc stm_flash {IMGFILE} { reset halt sleep 100 wait_halt 2 flash write_image erase $IMGFILE 0x08000000 sleep 100 verify_image $IMGFILE 0x08000000 sleep 100 reset run } proc stm_erase {} { reset halt sleep 100 stm32f1x mass_erase 0 sleep 100 }
Pour programmer le micro avec le programme fraîchement compilé, on lance la commande :
# make program Open On-Chip Debugger 0.7.0-dev-00167-g57aa19f (2013-03-04-14:27) Licensed under GNU GPL v2 For bug reports, read http://openocd.sourceforge.net/doc/doxygen/bugs.html srst_only separate srst_nogate srst_open_drain connect_deassert_srst Info : This adapter doesn't support configurable speed Info : STLINK v2 JTAG v16 API v2 SWIM v0 VID 0x0483 PID 0x3748 Info : Target voltage: 2.878032 Info : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints stm_erase target state: halted target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x0800040c msp: 0x20008000 auto erase enabled Info : device id = 0x10036422 Info : flash size = 256kbytes wrote 4096 bytes from file /home/sinseman44/cortex_M4/stm32f3_blink_led/bins/blink_led.bin in 0.938627s (4.262 KiB/s) verified 2216 bytes in 0.278803s (7.762 KiB/s) shutdown command invoked
Débogage grâce à OpenOCD et au Template du projet
Attention : Le débogage, pour le moment n'est possible que si on utilise la chaîne de compilation croisée téléchargée sur le site de Launchpad, suite à un bug sur la version de GDB de crosstool-NG.
On reprend en détail la partie débogage du micro avec le makefile :
debug: program @$(GDB) -x extra/gdb_cmds bins/$(PROJ_NAME).elf
Il lance la commande de débogage arm-none-eabi-gdb avec comme fichier de configuration gdb-cmds et le binaire à déboguer.
GDB communique avec OpenOCD de deux façons différentes :
- une connexion par socket TCP/IP.
- exemple : target remote localhost:3333
- une connexion par pipe. Ça a l'avantage que GDB à la main sur OpenOCD et peut l'arrêter à tout moment.
- exemple : target remote | openocd -c "gdb_port pipe; log_output openocd.log"
Le fichier de configuration gdb-cmds :
target remote | openocd -f /usr/share/openocd/scripts/board/stm32f0discovery.cfg -c "gdb_port pipe; log_output openocd.log" monitor reset halt load
La commande à lancer pour le débogage est la suivante :
#make debug Open On-Chip Debugger 0.7.0-dev-00167-g57aa19f (2013-03-04-14:27) Licensed under GNU GPL v2 For bug reports, read http://openocd.sourceforge.net/doc/doxygen/bugs.html srst_only separate srst_nogate srst_open_drain connect_deassert_srst Info : This adapter doesn't support configurable speed Info : STLINK v2 JTAG v16 API v2 SWIM v0 VID 0x0483 PID 0x3748 Info : Target voltage: 2.900648 Info : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints stm_erase target state: halted target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x08000458 msp: 0x20008000 auto erase enabled Info : device id = 0x10036422 Info : flash size = 256kbytes wrote 4096 bytes from file /home/sinseman44/cortex_M4/stm32f3_blink_led/bins/blink_led.bin in 1.038872s (3.850 KiB/s) verified 2216 bytes in 0.353893s (6.115 KiB/s) shutdown command invoked GNU gdb (GNU Tools for ARM Embedded Processors) 7.4.1.20121207-cvs Copyright (C) 2012 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "--host=i686-linux-gnu --target=arm-none-eabi". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /home/sinseman44/cortex_M4/stm32f3_blink_led/bins/blink_led.elf...done. Open On-Chip Debugger 0.7.0-dev-00167-g57aa19f (2013-03-04-14:27) Licensed under GNU GPL v2 For bug reports, read http://openocd.sourceforge.net/doc/doxygen/bugs.html srst_only separate srst_nogate srst_open_drain connect_deassert_srst 0x00000000 in ?? () target state: halted target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x0800040c msp: 0x20008000 Loading section .isr_vector, size 0x188 lma 0x8000000 Loading section .text, size 0x6d4 lma 0x8000188 Loading section .data, size 0x4c lma 0x800085c Start address 0x800040d, load size 2216 Transfer rate: 2 KB/sec, 738 bytes/write. (gdb) b main Breakpoint 1 at 0x80001a0: file src/main.c, line 30. (gdb) continue Continuing. Note: automatically using hardware breakpoints for read-only addresses. Breakpoint 1, main () at src/main.c:30 30 {
La petite astuce qui tue pour avoir le multi-windows sous GDB : CTRL x puis a :
┌──src/main.c───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ │22 } │ │23 │ │24 /** │ │25 * @brief Main program. │ │26 * @param None │ │27 * @retval None │ │28 */ │ │29 int main(void) │ B+>│30 { │ │31 /* SysTick end of count event each 10ms */ │ │32 RCC_GetClocksFreq(&RCC_Clocks); │ │33 SysTick_Config(RCC_Clocks.HCLK_Frequency / 100); │ │34 │ │35 /* Initialize LEDs and User Button available on STM32F3-Discovery board */ │ │36 STM_EVAL_LEDInit(LED3); │ │37 STM_EVAL_LEDInit(LED4); │ │38 STM_EVAL_LEDInit(LED5); │ │39 STM_EVAL_LEDInit(LED6); │ │40 STM_EVAL_LEDInit(LED7); │ └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ remote Remote target In: main Line: 30 PC: 0x80001a0 (gdb) cont Continuing. Note: automatically using hardware breakpoints for read-only addresses. Breakpoint 1, main () at src/main.c:30 (gdb)
Aucun commentaire:
Enregistrer un commentaire