Bonjour à toutes et à tous !
Après tant de temps, je me suis enfin décidé à partager ma progression concernant ce projet de développement. Cela à deux fins : partager avec vous des informations sur la programmation de microcontrôleurs PICs et la manière d’implémenter la méthode ICSP sur une carte de type Arduino et, par ce biais, vous en apprendre également plus sur le fonctionnement d’un microcontrôleur.
Historique des méthodes de programmation
À l’origine, la méthode utilisée pour programmer un microcontrôleur était d’utiliser un programmateur comportant un emplacement prévu pour y insérer le microcontrôleur. On écrit le programme dans la mémoire du microcontrôleur avant de retirer ce dernier et de l’intégrer au système qu’il doit piloter. Inutile de préciser que c’est une méthode fastidieuse qui impose, pour chaque modification du logiciel embarqué, de devoir retirer puis insérer le microcontrôleur à plusieurs reprises pour pouvoir le programmer puis le tester. Cela au risque d’abîmer plus rapidement et plus facilement les broches du microcontrôleur. Mais, plus encore, un problème se pose dans le cas d’une modification majeure du logiciel d’un produit fini et vendu en masse. On ne peut décemment pas exiger de rappeler tous les exemplaires sous le prétexte d’une mise à jour du logiciel, aussi majeure soit-elle, qu’il faudra effectuer pour chaque microcontrôleur.
C’est là qu’apparaît la méthode ISP, pour In-System Programming – Programmation In-Situ en français. Elle permet la programmation d’un microcontrôleur déjà intégré à un système. Cette fois, nous pouvons consulter ou modifier le programme d’un microcontrôleur via un connecteur relié à des broches dédiées de ce microcontrôleur, le tout directement intégré dans le système à piloter. Les programmateurs les plus aboutis permettent même le débogage du logiciel embarqué en temps réel. Elle permet aussi la mise en place de procédures plus simples pour la mise à jour du logiciel embarqué, comme la reprogrammation directe du microcontrôleur ou la mise en place d’un microcontrôleur secondaire sur la carte faisant office de programmateur in-situ.
Microchip fut le premier à implémenter cette méthode de programmation in-situ, nommé alors ICSP pour In Circuit Serial Programming, pour ses microcontrôleurs PIC et dsPIC. Par la suite, de nombreux fabricants ont implémenté leur propre version de cette méthode de programmation.
Description
Selon le fabricant, l’implémentation de la méthode peut différer. Aussi, pour cet article, nous nous concentrons uniquement sur ICSP tel qu’implémenté par Microchip.
De plus, le microcontrôleur utilisé dans cette étude de cas est le PIC18F2550. Il est donc possible que certaines fonctionnalités diffèrent voire sont inexistantes pour d’autres modèles de microcontrôleurs – même provenant de chez Microchip.
Ces points étant explicitement établis, passons maintenant à la description technique de la méthode ICSP.
Brochage
Le connecteur ICSP comprend 6 broches qui se décrivent comme suit :
- MCLR/VPP : Il s’agit de la tension de programmation. L’état de la broche permet d’entrer ou de sortir du mode de programmation. Dans le cas qui nous intéresse, la tension varie en fonction du mode de programmation : « High-Voltage » = 12 V et « Low-Voltage » = 5 V.
- VDD : La tension d’alimentation du microcontrôleur, ici 5 V.
- VSS : Il s’agit tout simplement de la masse. Le PIC18F2550 dispose de deux broches à relier à la masse.
- PGM : utilisée uniquement dans le cas d’une programmation « Low-Voltage », autrement elle n’est qu’une entrée/sortie comme une autre (RB5). Lors de l’entrée en mode de programmation, elle est la première broche placée à l’état haut, avant la tension de programmation. De même, elle est la dernière à être placée à l’état bas lors de la sortie du mode de programmation.
- PGC : C’est l’horloge utilisée lors de la transmission de données. Comme dans la plupart des protocoles de transmission, c’est le maître – ici le programmateur – qui donne la cadence de l’horloge.
- PGD : C’est par cette broche que les données transitent, en little endian – i.e. le bit de poids faible est transmis en premier et le bit de poids fort en dernier.
Organisation des zones mémoire
La mémoire du PIC18F2550 est organisée en différentes zones. Les adresses en mémoire sont exprimées en hexadécimal et chaque adresse correspond à un octet de mémoire.
- La mémoire dédiée au code exécutable, de l’adresse 0x00000 à l’adresse 0x007FFF, soit 32 Kio divisés en 5 blocs :
- Le bloc de démarrage (ou Boot Block) sur les 2048 premiers octets, contenant les instructions du programme exécutées en premier au démarrage du microcontrôleur ;
- Le bloc 0, de 6 Kio, soit 6144 octets ;
- et trois blocs, numérotés de 1 à 3, de 8 Kio chacun.
- Les ID locations – des registres dédiés à l’écriture de divers numéros d’identification – de 0x200000 à 0x200007, soit 8 octets au total ;
- Les registres de configuration, de 0x300000 à 30000D, soit 16 octets organisés en 8 paires de registres (CONFIGxH pour le regitre de poids fort et CONFIGxL pour le registre de poids faible) ;
- Et enfin, l’identifiant du périphérique (Device ID) sur deux octets, aux adresses 0x3FFFFE et 0x3FFFFF. Il permet au programmateur d’identifier le modèle et le numéro de version du microcontrôleur présent.
Processus de programmation
Le processus de programmation se déroule comme suit :
- Entrée en mode de programmation/vérification (Program/Verify mode)
- Effacement partiel ou complet de la mémoire du microcontrôleur
- Écriture du programme dans la zone mémoire dédiée au code
- Écriture des ID Locations
- Écriture de données dans la mémoire EEPROM
- Vérification du programme
- Vérification des ID Locations
- Vérification des données EEPROM
- Écriture des bits de configuration
- Vérification des bits de configuration
- Sortie du mode de programmation/vérification
Pour chaque opération, hormis pour l’entrée et la sortie du mode de programmation/vérification, le programmateur doit envoyer des trames au microcontrôleur. Ces trames se composent toutes de 4 bits de commande et de 16 bits de payload – le contenu du payload dépend essentiellement de la commande.
Tout le processus consiste à manipuler un pointeur nommé TABLPTR au travers de trois registres dédiés : TABLPTRU, TABLPTRH, TABLPTRL. Ces registres vont chacun contenir une partie de l’adresse mémoire vers laquelle TABLPTR doit pointer et à laquelle on souhaite opérer.
Parmi les commandes utilisées par le programmateur, on peut trouver essentiellement :
- Core Instruction (0b0000) : Elle sert essentiellement à exécuter des instructions du processeur du microcontrôleur. Le payload correspond ici à une instruction en assembleur sur 16 bits (une instruction et son argument). La plupart du temps, cette commande servira à initialiser la valeur de TABLPTR avant d’opérer sur l’octet pointé.
- Table Read (0b1000) : Une des deux principales opérations que l’on peut effectuer sur l’adresse mémoire pointée par TABLPTR. Elle consiste à lire les données qui se trouve à l’emplacement mémoire pointé. Le payload est constitué uniquement de 0, les données lues étant transmises à la suite de cette commande.
- Table Write (0b1100) : La seconde principale opération que l’on peut effectuer à l’adresse mémoire pointée par TABLPTR. Par opposition à la précédente, il s’agit ici d’écrire des données à l’emplacement mémoire pointé. Le payload est ici constitué des données à inscrire. L’adresse mémoire pointant vers un octet, soit 8 bits, le payload de 16 bits contient en fait deux fois l’octet à écrire, probablement pour vérifier de manière simpliste l’intégrité des données transmises – i.e. vérifier que toute la donnée à inscrire a bien été transmise et n’a donc pas été perdue ou corrompue.
Les autres commandes sont des variantes des deux dernières présentées avec, par exemple, la possibilité d’incrémenter le pointeur directement pour qu’il pointe vers l’adresse suivante ou de démarrer la programmation suite à l’écriture. Nous les verrons plus en détail au fil des articles traitant des différentes étapes de la programmation.
Et ensuite ?
Toute cette présentation est censée poser les bases du programmateur et vous donner les informations élémentaires pour comprendre la suite. Le prochain article, à paraître fin février 2017, traitera de la première procédure du processus, à savoir l’effacement de la mémoire du microcontrôleur.
Sur ce je vous laisse et vous dis à bientôt.
Nicolas SAN AGUSTIN
Sources :
- Wikipedia, page ICSP (fr/en)
- Datasheet PIC18F2550
- Spécification de programmation