Micro contrôleurs AVR/De la programmation des AVRs aux bootloaders
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
modifierL'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
modifierNous 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.
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.
À 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
modifierLes fusibles sont modifiables par ISP ou JTAG. En ISP on peut utiliser avrdude ou uisp
Quelques commandes Avrdude
modifierLire 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
modifierPuisque 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
modifierNous 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$avrdude −p m32 −c dapa −U lfuse:w:0x89:i
On place la valeur 0x89 dans le LowByteFuse.
Configurer les fusibles
modifierLa 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
modifierLa 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 ?
modifierIl 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.