Micro contrôleurs AVR/De la programmation des AVRs aux bootloaders

Leçons de niveau 14
Une page de Wikiversité, la communauté pédagogique libre.
Début de la boite de navigation du chapitre
De la programmation des AVRs aux bootloaders
Icône de la faculté
Chapitre no 8
Leçon : Micro contrôleurs AVR
Chap. préc. :Les communications en tout genre
Chap. suiv. :Arduino
fin de la boite de navigation du chapitre
En raison de limitations techniques, la typographie souhaitable du titre, « Micro contrôleurs AVR : De la programmation des AVRs aux bootloaders
Micro contrôleurs AVR/De la programmation des AVRs aux bootloaders
 », n'a pu être restituée correctement ci-dessus.

Ce chapitre s'intéresse à quelques méthodes de programmation des composants AVRs. Pour ne pas alourdir ce chapitre nous allons nous limiter à deux méthodes : ISP et le bootloader.

Le bootloader est une technique de programmation que l’on retrouve sur toutes les cartes AVR bon marché (en)Butterfly et Arduino. Nous rappelons que la traduction du mot bootloader est Chargeur d'amorçage. Nous utiliserons dans tout ce chapitre la terminologie anglaise : tant pis pour les puristes.

Le bootloader dans les AVR[modifier | modifier le wikicode]

L'idée est de réaliser ce que l’on trouve dans le petit système de développement appelé (en) Butterfly ou dans l’Arduino. Ces systèmes très bon marché sont architecturés autour d'un bootloader, c'est-à-dire un petit programme qui démarre le processeur en attendant qu'un ensemble de données lui arrive par la RS232. S'il y a des données, elles correspondent à un programme et le bootloader sera chargé de modifier la mémoire programme en conséquence. Tout ceci est bien plus facile à dire qu’à faire.

Pour faire fonctionner un bootloader il vous faudra donc faire communiquer deux programmes :

  • un programme dans le micro-contrôleur, c’est lui que l’on appellera bootloader
  • un programme sur la station de travail (en général un PC sous Windows ou sous Linux)

Bien comprendre le fonctionnement d'un bootloader nécessite une connaissance un peu technique que nous allons présenter maintenant.

Données techniques sur le bootloader[modifier | modifier le wikicode]

Nous voyons un certain nombre de questions auxquelles il nous faut répondre pour continuer ce travail :

  • le programme bootloader est-il dans un endroit particulier ?
  • peut-on envoyer directement un fichier hex ?

Pour la première question, oui le bootloader est dans un endroit particulier qui semble dépendre de la famille des AVR. Un bootloader trouvé sur Internet par exemple, utilisait la section

#define BootStart 0xFC00

dans son code, ce qui montre très clairement qu’il était à un endroit très précis.

Structure d'un programme et d'un bootloader (adresse 0 en haut)

Dans les AVR, cette section (bootloader) est gérée par les fusibles BOOTSZ0, BOOTSZ1 et BOOTRST qui doivent être positionnés correctement. Les deux premiers définissent la taille du bootloader tandis que le troisième autorise un RESET en début de bootloader (BOOTRST=1 RESET en 0, BOOTRST=0 RESET en debut bootloader réglé avec BOOTSZ0 et BOOTSZ1). C'est un peu compliqué, mais c’est un passage absolument obligé !

Pour la deuxième question nous avons trouvé une réponse sans lire le code source d'un programmateur. En effet, à la question : peut-on utiliser l'hyperterminal pour programmer un AVR ? Il est répondu qu’il faut alors transformer le fichier HEX en fichier binaire avant de l'envoyer.

Pour être un peu plus concret nous allons examiner les choses avec des figures explicatives.

Nous présentons dans la figure ci-dessus, à gauche, l'architecture d'un programme dans un AVR : il commence par une table des vecteurs d'interruptions (bleu clair) suivie par l’ensemble des données se trouvant en mémoire programme (en gris) pour finir par le programme proprement dit (bleu turquoise). Nous avons dessiné au centre un bootloader qui a exactement la même structure qu'un programme (sauf qu’il est plus petit). Contrairement à ce que laisse suggérer la figure, si le bootloader est plus petit, la taille de ses vecteurs d'interruption est identique. À droite nous avons montré comment un programme finit dans la mémoire flash du processeur (qui est représentée en jaune pâle).

La flèche noire représente le fait qu'un programme commence par un saut . En effet chaque vecteur d'interruption correspond à un saut vers le sous-programme d'interruption correspondant. Le premier vecteur d'interruption (en 0x0000) correspond au reset (en tout cas en utilisation normale). Une autre façon de dire les choses, chaque "reset" emmène le processeur à l'adresse 0 qui va lui permettre de retrouver le début du programme à l'aide de son premier saut.

Comment faire cohabiter un programme et son bootloader (bootloader en bas, programme en haut)

À ce point il est difficile de ne pas se poser la question : comment faire cohabiter pacifiquement un programme et un bootloader dans la mémoire flash du processeur ? Voilà la réponse en image (figure ci-contre).

Dans cette figure nous avons encore gardé la convention de placer l'adresse 0 en haut. Le bootloader est en bas, ce qui signifie qu’il se trouve en adresse haute.

À gauche, il est montré comment cela se passe. Mais nous y voyons deux points d'entrée (deux RESET en quelque sorte) : un pour le programme et un pour le bootloader. À droite nous voyons comment on peut accéder à ces deux points d'entrées grâce au fameux fusible BOOTRST, le RESET pour l'un et le "JMP 0x0000" ou le watchdog pour l'autre. À noter que certains AVR (jusqu'à ATMega8 compris) ne possèdent pas l'instruction "JMP" : vous êtes obligés de déclencher le watchdog pour aller en adresse 0x0000.

Programmation avec avrdude[modifier | modifier le wikicode]

Les fusibles sont modifiables par ISP ou JTAG. En ISP on peut utiliser avrdude ou uisp

Quelques commandes Avrdude[modifier | modifier le wikicode]

Lire la configuration des fusibles :

$avrdude −p m32 −c dapa −U hfuse:r:−:i −U lfuse:r:−:i

Ceci nécessite quelques explications (en plus du man avrdude indispensable) :

−U hfuse:r:−:i

On accède au HighByteFuse, en lecture (r), sans valeur (-), format hex intel (i)

-U lfuse:r:-:i

On accède au LowByteFuse, en lecture (r), sans valeur (-)

Configurer le bootloader[modifier | modifier le wikicode]

Puisque nous allons écrire un chapitre sur Arduino, nous allons nous intéresser essentiellement au logiciel "avrdude". En effet, c’est lui qui est installé pour programmer les cartes Arduino.

Programmer une carte Arduino en ligne de commande[modifier | modifier le wikicode]

Nous avons eu l’occasion d’utiliser abondamment une carte Arduino Mega2560 pour mettre au point un certain nombre de correction de ce livre. Voici le script que nous avons utilisé.

avr-gcc -g -mmcu=atmega2560 -Wall -Os -c Mega2560Demo1.c 
avr-gcc -g -mmcu=atmega2560 -o Mega2560Demo1.elf -Wl,-Map,Mega2560Demo1.map Mega2560Demo1.o 
#avr-objdump -h -S hello.elf > hello.lss
#avr-objcopy -O binary -R .eeprom hello.elf hello.bin
avr-objcopy -R .eeprom -O ihex Mega2560Demo1.elf Mega2560Demo1.hex

/usr/share/arduino/hardware/tools/avrdude -C/usr/share/arduino/hardware/tools/avrdude.conf -v -v -v -v -patmega2560 -cwiring -P/dev/ttyACM0 -b115200 -D -V -Uflash:w:Mega2560Demo1.hex:i 

#lecture fusible NOK 
#/usr/share/arduino/hardware/tools/avrdude -C/usr/share/arduino/hardware/tools/avrdude.conf -v -v -v -v -patmega2560 -cwiring -P/dev/ttyACM0 -b115200 -Uhfuse:r:-:i

Vous pouvez remarquer que la lecture de fusibles n’est pas opérationnelle. C'est absolument normal. La programmation ci-dessus utilise le bootloader de la carte Arduino et le bootloader ne peut pas lire les fusibles (à vérifier !).

Programmer la valeur d'un fusible[modifier | modifier le wikicode]

$avrdude −p m32 −c dapa −U lfuse:w:0x89:i

On place la valeur 0x89 dans le LowByteFuse.

Configurer les fusibles[modifier | modifier le wikicode]

La première question à laquelle il nous faut répondre est : quelle taille a notre bootloader ? Muni de cette information on va pouvoir en déduire comment positionner les fusibles.

Exercice[modifier | modifier le wikicode]

La commande avrdude de lecture de fusible est utilisée sur une carte Arduino MEGA2560 :

#lecture fusible avec cable Pololu (ICSP/USB) OK mais info retournée pas claire
/usr/share/arduino/hardware/tools/avrdude -C/usr/share/arduino/hardware/tools/avrdude.conf -v -v -v -v -patmega2560 -c avrispv2 -P/dev/ttyACM0 -b115200 -Uhfuse:r:-:i

Elle donne le résultat suivant :

AVR Part                      : ATMEGA2560
                 Chip Erase delay              : 9000 us
                 PAGEL                         : PD7
                 BS2                           : PA0
                 RESET disposition             : dedicated
                 RETRY pulse                   : SCK
                 serial program mode           : yes
                 parallel program mode         : yes
                 Timeout                       : 200
                 StabDelay                     : 100
                 CmdexeDelay                   : 25
                 SyncLoops                     : 32
                 ByteDelay                     : 0
                 PollIndex                     : 3
                 PollValue                     : 0x53
                 Memory Detail                 :

                                          Block Poll               Page                       Polled
                   Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
                   ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
                   eeprom        65    10     8    0 no       4096    8      0  9000  9000 0x00 0x00
                                          Block Poll               Page                       Polled
                   Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
                   ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
                   flash         65    10   256    0 yes    262144  256   1024  4500  4500 0x00 0x00
                                          Block Poll               Page                       Polled
                   Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
                   ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
                   lfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
                                          Block Poll               Page                       Polled
                   Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
                   ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
                   hfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
                                          Block Poll               Page                       Polled
                   Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
                   ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
                   efuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
                                          Block Poll               Page                       Polled
                   Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
                   ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
                   lock           0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
                                          Block Poll               Page                       Polled
                   Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
                   ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
                   calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
                                          Block Poll               Page                       Polled
                   Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
                   ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
                   signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

Pouvez-vous dire si la carte en question fonctionne avec un bootloader ou pas ?

Que faire si l’on ne connait ni l'assembleur ni le C ?[modifier | modifier le wikicode]

Il existe un système de développement qui utilise le BASIC et qui permet de travailler avec un bootloader. Il faut bien avoir à l'esprit que le bootloader n'est absolument pas lié au langage que l’on utilise pour réaliser des programmes. Ce qui fait que l’on pourra ou pas utiliser un bootloader est l'environnement de développement. Précisons un peu.

Si vous avez un IDE quelconque, il est pratiquement sûr que toute compilation produira un fichier d'extension hex. Le trouver n’est pas toujours simple mais sachez qu’il est quelque part. Si votre IDE n’est pas capable de dialoguer avec un bootloader, utilisez un programme externe. Nous utiliserons avrdude dans ce livre mais d'autres sont disponibles gratuitement.