Vous êtes sur la page 1sur 91

LA PROGRAMMATION DES PIC®

PAR BIGONOFF

TROISIEME PARTIE – Les secrets des 16F87x(A)

Techniques de bootloader - Révision 10


2
1. INTRODUCTION............................................................................................................................................. 5

1. LA DEMARCHE .............................................................................................................................................. 7
1.1 LE ROLE DU BOOTLOADER.............................................................................................................................. 7
1.2 QU’EST-CE QU’UN BOOTLOADER ?................................................................................................................. 7
1.3 INCONVENIENTS DU BOOTLOADER ................................................................................................................. 8
1.2 LE CAHIER DES CHARGES ............................................................................................................................... 8
2. LA REALISATION DE L’INTERFACE ..................................................................................................... 11
2.1 LA VERSION CLASSIQUE ............................................................................................................................... 11
2.2 L’INTERFACE BIGOPIC1 .............................................................................................................................. 12
3. LA MISE EN ŒUVRE MATERIELLE ....................................................................................................... 19
3.1 CE QU’IL FAUT SAVOIR ................................................................................................................................. 19
3.2 SCHEMA D’APPLICATION TYPIQUE ............................................................................................................... 20
4. LA MISE EN ŒUVRE LOGICIELLE......................................................................................................... 23
4.1 LES QUESTIONS ............................................................................................................................................ 23
4.2 LA SEQUENCE DE DEMARRAGE DU BOOTLOADER ......................................................................................... 23
4.3 GESTION DU DEMARRAGE DU PROGRAMME.................................................................................................. 24
5. LE LOGICIEL PIC® BGBOOT.ASM ......................................................................................................... 27
5.1 REMARQUE POUR L’UTILISATION DES PIC® VERSION « A » ........................................................................ 27
5.2 ETUDE DETAILLEE DU LOGICIEL BGBOOT .................................................................................................... 27
6. MISE EN PRATIQUE HARDWARE........................................................................................................... 59

7. UTILISATION PRATIQUE DU BOOTLOADER...................................................................................... 63


7.1 INTRODUCTION ............................................................................................................................................ 63
7.2 CUSTOMISATION DU BOOTLOADER............................................................................................................... 63
8. UTILISATION PRATIQUE DE BIGOPIC LIGHT ................................................................................... 67
8.1 INSTALLATION DU LOGICIEL ........................................................................................................................ 67
8.2 PREMIER LANCEMENT DE BIGOPIC LIGHT .................................................................................................. 67
8.3 PASSAGE EN MODE BOOTLOADER ................................................................................................................. 70
8.4 CHARGEMENT D’UN PROGRAMME D’APPLICATION ....................................................................................... 73
8.5 RESOLUTION DES CONFLITS ......................................................................................................................... 75
8.6 EFFACEMENT DES ANCIENNES DONNEES ...................................................................................................... 80
8.7 L’ENVOI DE NOTRE PREMIER PROGRAMME ............................................................................................. 82
8.8 LANCEMENT DU PROGRAMME CHARGE ........................................................................................................ 84
9. CONCLUSIONS ............................................................................................................................................. 85

CONTRIBUTION SUR BASE VOLONTAIRE .............................................................................................. 87

B. UTILISATION DU PRESENT DOCUMENT............................................................................................. 89

3
4
1. Introduction

Ce livre est la suite logique du livre « la programmation des PIC® – seconde partie – La
gamme mid-range par les 16F87x ».

Il s’adresse donc aux utilisateurs expérimentés, qui ont lu et assimilés les 2 ouvrages
précédents. Pour ceux qui n’en disposent pas, ils sont toujours disponibles sur mon site :
http://www.abcelectronique.com/bigonoff

Je ne reviendrai donc pas sur les notions de base, cet ouvrage étant un peu plus technique
que les précédents.

Je remercie de nouveau tous ceux qui m’ont témoigné leur confiance et leur soutien lors
de la réalisation des précédents ouvrages.

J’ai séparé cet ouvrage du précédent afin de permettre une mise à disponibilité plus rapide,
et une mise à jour plus efficace, le thème abordé étant très spécifique et sortant de l’étude des
PIC® en général.

Il sera suivi par une quatrième partie consacrée au debuggage sur circuit, le fameux
« ICD® » qui a fait couler pas mal d’encre.

Je suis toujours à l’écoute de tous, je réponds toujours au courrier reçu, et si la


demande se fait sentir concernant certains chapitres, il me sera toujours possible d’ajouter
explications complémentaires et exemples supplémentaires.

N’hésitez donc pas à me faire part de vos remarques et suggestions, et jetez de temps
en temps un œil sur les sites de téléchargement pour voir si une nouvelle révision n’est pas
disponible.

Je décline toute responsabilité, directe ou indirecte, pour toute conséquence fâcheuse


résultant de l’utilisation de cet ouvrage, des interfaces décrites, ou des logiciels. Tout est
fournis « tel quel », et l’utilisation est soumise à votre seule et unique responsabilité. Aucun
recours ne pourra être engagé contre moi. Si vous n’êtes pas d’accord, merci d’effacer ce
document, fichiers joints, et utilitaires, et de ne pas en tenir compte.

Tous les droits sur le contenu de ce livre et ses annexes restent ma propriété.

Je vous souhaite beaucoup de plaisir à la lecture de ce petit ouvrage sans prétention, et je


vous le conseille : expérimentez, expérimentez, et expérimentez encore !

… Et vive l’Internet libre !

BIGONOFF

5
6
1. La démarche

1.1 Le rôle du bootloader

Il vous est déjà probablement arrivé de devoir reprogrammer un grand nombre de fois
votre PIC®, pour corriger les erreurs, et améliorer le fonctionnement.

Quoi de plus énervant que de devoir sans arrêt couper l’alimentation du montage, enlever
le PIC®, le placer dans le programmateur, le programmer, le remettre sur la platine, relancer
l’alimentation… Pour s’apercevoir qu’il reste un problème, et tout recommencer.

Tout ceci est du travail non valorisant, et, de plus, présente un grand risque. En effet, à un
moment ou à un autre, vous allez oublier de couper l’alimentation, ou alors vous allez mettre
votre PIC® à l’envers. Ce seront alors quelques euros qui risquent de partir en fumée.

Vous vous êtes alors probablement intéressé à la méthode de programmation sur circuit,
ou « ICP » pour « In Circuit Programming » (ou ICSP®, avec le « S » pour Serial).

Malheureusement, ceci implique de construire spécifiquement sa platine d’application, car


l’ICP utilise la programmation classique, et donc des tensions supérieures aux tensions de
fonctionnement normal du PIC®.

De plus, l’ICP utilise plusieurs pins spécifiques du PIC®, qui ne pourront facilement être
utilisées dans n’importe quelle circonstance, et nécessite de couper l’alimentation du montage.

Et une fois votre circuit définitif construit, votre programme mis au point, vous devez
placer votre montage sur son lieu d’application.

Or, parfois, vous ne pouvez pas monter le circuit sur support, à cause de vibrations, par
exemple. La soudure du circuit sur sa platine, ou son éventuelle inaccessibilité (circuit
difficilement démontable, immersion dans de la résine etc.) peut vous empêcher de
reprogrammer votre PIC® pour une éventuelle mise à jour.

Il nous faut donc trouver une solution pratique et flexible pour envoyer le programme
dans le PIC®. La technique du bootloader constitue cette solution.

1.2 Qu’est-ce qu’un bootloader ?

Arrivés ici, il est grand temps que je vous explique ce que représente la technique du
bootloader.

L’idée de base est simple, envoyer un programme dans le PIC® sans utiliser de
programmateur.

Il suffit alors de se souvenir que le PIC16F87x(A) dispose de la possibilité d’écrire dans


sa mémoire programme, pour comprendre qu’en fait, le PIC® dispose de la possibilité de se
programmer lui-même.

7
Nous placerons donc dans le PIC® un programme chargé de communiquer avec
l’extérieur, en l’occurrence votre PC, afin de recevoir le nouveau programme à injecter en tant
que programme principal.

1.3 Inconvénients du bootloader

Maintenant que vous avez entrevu les avantages et la flexibilité du bootloader, il nous faut
en cerner inconvénients et limitations (nul n’est parfait en ce bas monde).

- Il s’agit d’un programme intégré dans le PIC®. Il va donc vous consommer un peu
d’espace en mémoire programme.

- Le bootloader est incapable de modifier la configuration du PIC®, qui sera donc


définitivement figée sans l’utilisation d’un programmateur classique.

- Il faut réaliser un programme tournant sur votre ordinateur pour communiquer avec le
bootloader. J’ai réalisé un programme pour Windows, je cherche des volontaires pour
réaliser le même sur d’autres machines.

- Il faut prévoir l’utilisation du bootloader lors de la réalisation de la carte, mais vous allez
voir que c’est beaucoup moins contraignant que pour la méthode d’ICP.

- Il est impossible de protéger l’intégralité de la mémoire du PIC®, puisque la protection en


lecture empêche l’écriture en mémoire flash. Nous verrons cependant qu’il est possible de
continuer à protéger vos programmes moyennant quelques astuces.

1.2 Le cahier des charges

Comme pour toute réalisation pratique, il nous faut maintenant définir les contraintes
auxquelles sera soumis notre bootloader.

- Le bootloader devra occuper une taille minimale dans le PIC®.

- On utilisera une seule pin pour communiquer, ce qui est une de moins que la majorité des
applications que vous trouverez sur le net.

- La pin utilisée ne devra pas être bloquée pour l’utilisation du bootloader, mais pourra
servir dans l’application réelle. Autrement dit, on ne sacrifie pas de pin pour le bootloader.

- L’interface devra être économique et simple à réaliser (disons de l’ordre de 5-6 euros).

- Aucune ressource du PIC® ne devra être sacrifiée (emplacements RAM, modules, etc.).

- Le bootloader pourra être logé où l’utilisateur le désire.

- Il devra communiquer à toutes les vitesses de transmission possible.

- La pin de communication pourra être librement choisie.

8
- Le bootloader devra vérifier qu’on ne tente pas de l’écraser avec le programme
d’application.

- On doit pouvoir envoyer dans le PIC® n’importe quel programme réalisé suivant les
directives données jusqu’à présent, sans imposer la réécriture ou la modification du
source, et même sans nécessiter de réassemblage. En sommes, on doit pouvoir prendre un
exemple réalisé précédemment, et envoyer directement son fichier « .hex » dans le PIC®.

Vous voyez donc que je me suis imposé un cahier des charges assez sévère, bien plus en
tout cas que ce que vous trouverez généralement. Ceci fait de ce bootloader un véritable outil
parfaitement opérationnel.

Maintenant, il va s’agir de respecter tout ça…

9
Notes :

10
2. La réalisation de l’interface

2.1 La version classique

Je vais vous proposer la réalisation d’une interface qui pourra être utilisée à la fois pour
notre bootloader, et pour l’utilisation du debugger intégré. Ceci pour vous expliquer que
certaines options peuvent paraître inutiles pour l’instant.

Pour les deux applications, il s’agit de communiquer en mode série entre un PIC® et un
ordinateur. Autrement dit, nous aurons beaucoup de points communs.

La principale différence entre le bootloader et le debugger, c’est que le premier peut se


contenter de communiquer en n’utilisant qu’une seule pin, alors que le second exige
l’utilisation de 2 pins spécifiques.

Voyons donc la méthode qui vient tout de suite à l’esprit, sachant qu’on veut pouvoir
émettre, recevoir, et provoquer le reset du PIC® à partir de l’ordinateur.

Nous retrouvons ici le classique Max232, accompagné de ses 4 condensateurs.

On pourrait se dire que cette version est tout à fait satisfaisante. Elle l’est, en effet, excepté
sur un point.

Il ne faut pas oublier que nous allons injecter notre programme depuis l’ordinateur vers le
PIC®, le montage de destination étant sous tension.

Or, rien ne dit que la platine d’application n’est pas portée à un potentiel dangereux par
rapport à la masse, par exemple si la masse de l’application est connectée au 220V.

11
Il nous faut donc, pour faire face à toutes les situations possibles, isoler galvaniquement
platine d’application et ordinateur. Ceci nous amène à la seconde solution.

2.2 L’interface BigoPIC1

La méthode qui vient alors à l’esprit est de se dire : il suffit d’ajouter un opto-coupleur par
ligne en communication avec le PIC®, c’est-à-dire, émission, réception, et reset.

Le montage devra cependant être alimenté avec une tension de 5V différente de celle
alimentant le PIC®, pour conserver l’isolation.

Cette méthode est tout à fait valable, mais un bon électronicien aura vite fait de faire les
réflexions suivantes :

- Le max 232 permet de convertir les niveaux 0/5V du PIC® en –12V/+12V du port série
du PC.

- Un opto-coupleur est également capable de convertir des tensions, il suffit de l’alimenter


avec les dites tensions adéquates.

Partant de là, on peut alors se dire : on peut éliminer le max232, et ne conserver que les
opto-coupleurs.

Il nous faudrait alors, une alimentation +12V/ -12V pour alimenter le montage.

Mais, en fait, on peut intelligemment se faire une seconde réflexion.

L’important n’est pas d’obtenir des tensions de signaux de +12V ou –12V, mais des
tensions de signaux qui soient compatibles avec le port série de l’ordinateur utilisé. En effet, il
est connu que les PC portables, par exemple, utilisent des tensions non standardisées.

L’important est donc de pouvoir gérer des niveaux 0 et 1 compatibles avec le port série de
l’ordinateur utilisé.

L’astuce consiste donc à créer ces niveaux directement par le port série lui-même. Ainsi,
on obtient les tensions correspondant à ces niveaux sur le port série.

Les tensions –12V et +12V seront de fait remplacées par les tensions utilisées réellement
par le port série de l’ordinateur utilisé, que celui-ci utilise ou non les tensions standardisées.
On obtient alors une parfaite compatibilité sans le recours d’une alimentation externe.

Vous allez me dire : « Oui, mais Bigonoff nous a bien dit de ne pas utiliser un
programmateur tirant son alimentation du port série, maintenant, il nous dit le contraire ».

Et bien, en fait, pas du tout. Pour le programmateur, nous avions besoin d’une tension de
13V nécessaire à la programmation du PIC®. Cette tension est fixe, et ne peut être atteinte par
les ports séries qui ne respectent pas les tensions standardisées.

12
Ici, au contraire, il n’est d’aucune importance d’avoir ou non une tension de 13V, il
importe simplement que les tensions générées pour un « 0 » et pour un « 1 », soient
compatibles avec le port série utilisé. Or comment être plus compatible qu’en utilisant le port
lui-même comme référence de tension ?

Voyons donc l’interface en question, en gardant à l’esprit qu’on pouvait faire un peu plus
simple, mais que j’ai réalisé cette interface pour qu’elle soit compatible avec le debugger, déjà
opérationnel dans sa première version à l’heure où j’écris ces lignes.

Cette interface est la troisième version. La première ne fonctionnait pas avec certains PC,
YC. s’est penché sur le problème et l’a résolu dans la seconde version, mais m’a communiqué
le schéma avec une erreur (R19). Voici qui est corrigé. Comme chez moi ça fonctionnait, je
n’ai pas pu mettre les problèmes en évidence, lui l’a fait.

Je vous livre ses commentaires. :

“Au départ le circuit ne fonctionnait malheureusement pas, j'ai donc dû trouver au moyen
d'un oscilloscope ce qui n'allait pas. En gros 2 problèmes : dans le sens PIC® vers PC le
signal arrivant au PC était trop faible en amplitude. Dans le sens PC vers PIC®, le transistor
restait saturé en permanence.” Voici donc les modifications apportées au schéma. Ces
modifications ont été testées sur divers PC et sur plusieurs cartes et cela fonctionne.

- Diminution de R5 à la valeur de 1,2K. Améliore le niveau « 1 » du read


- Placement d’une diode (1N4148 comme les autres) entre la pin 4 de U2 et la pin 3 du
RS232. Cela permet de mieux profiter du –12V en réception (Car augmentation du
courant dû à la modification précédente).
- Placement d’une résistance de 10K entre la pin 4 de U3 et la masse de sortie. Sans cette
résistance Q3 restait conducteur en permanence. »

13
J’ai placé un “!” sur les composants modifiés par rapport à la version originale, pour vous
faciliter la correction. Le schéma donné plus haut est le schéma corrigé.

Voyons maintenant comment fonctionne cette interface :

Vous remarquez la présence d’une ligne verticale pointillée, qui vous indique la séparation
galvanique complète entre le PIC® (à gauche), et l’ordinateur (à droite). La communication se
fait via les optocoupleurs, c’est-à-dire par une liaison lumineuse.

Vous constatez qu’au niveau du port RS232, on n’a plus besoin de la masse, mais qu’on a,
par contre, utilisé la pin DTR en supplément. En effet, un niveau « 0 » se reconnaît à sa
tension normalisée de +12V, un niveau « 1 » par sa tension normalisée de –12V. Autrement
dit, la masse ne joue aucun rôle de référence ici, on peut donc parfaitement s’en passer.

A gauche du schéma, vous voyez le connecteur destiné à connecter le PIC® au montage.

J’en arrive au fonctionnement proprement dit. Je commence les explications en partant de


la droite, c’est-à-dire au niveau du port série du PC.

En mode de fonctionnement normal, on envoie un niveau « 0 » sur DRT, et un niveau


« 1 » sur RTS. Autrement dit, pour un port RS232 standard, la tension sur DTR vaudra +12V,
et celle sur RTS –12V, mais ceci n’est absolument pas obligatoire. Tout au plus, dans les cas
les plus récalcitrants, pourrions-nous avoir besoin de diminuer les valeurs de R3 et R4.

Prenons le cas de l’émission par l’ordinateur d’un bit à « 1 » :

- La pin TD du port série se trouve alors portée au même potentiel que RTS, puisque celui-
ci est configuré justement pour envoyer un niveau « 1 ».

- Dans le circuit D4/R3/U3/D3 ne circule aucun courant, puisqu’il n’y a aucune différence
de potentiel.

- Le transistor de U3 est donc bloqué, ainsi que, par conséquence, le transistor Q3


(nécessaire pour obtenir un gain en courant).

- La PINT du PIC®, qui est le nom donné à la pin d’émission/réception (souvenez-vous que
dans le cahier des charges, on a imposé le recours à une seule pin), est alors porté à VDD
du PIC® via la résistance R6. En effet, les 2 broches du connecteur intitulés PINT sont
interconnectés ensemble par le câble de liaison.

- Autrement dit, on a sur le PIC® une tension VDD, donc un niveau « 1 », qui est bien le
niveau envoyé par l’ordinateur.

Prenez garde au fait que la connexion entre les 2 broches PINT ne doit se faire que par le
câble de liaison vers le PIC®. Si vous reliez directement ces deux connecteurs sur le circuit,
cela fonctionnera parfaitement en mode bootloader, mais votre interface sera inutilisable en
mode debugger.

14
Maintenant, étudions l’émission par l’ordinateur d’un bit à « 0 » :

- La pin TD se trouve portée à un potentiel supérieur à celui de la pin RTS (typiquement


24V de plus).

- Le circuit D4/R3/U3/D3 se voit parcouru par un courant qui allume la led interne de U3.

- Le phototransistor de U3 devient donc passant, ainsi que Q3.

- La tension présente précédemment sur PINT se voit donc ramenée à 0V (en réalité, 0,6V)

- Le PIC® reçoit donc un niveau « 0 » sur sa pin émission/réception, qui est bien le niveau
envoyé par l’ordinateur.

Voici donc réglé le problème du transfert RS232 vers PIC®. Voyons maintenant ce qui se
passe si le PIC® envoie un niveau « 1 » vers le PC. Nous avons affaire à une communication
sur une seule ligne, autrement dit « half-duplex ». Donc, durant la réception du côté de la
RS232, la ligne TD est au repos. Comme le niveau de repos pour une liaison RS232 est le
niveau « 1 », le transistor de U3, ainsi que Q3 sont bloqués et n’interfèrent pas dans la
transmission.

- Le PIC® place PINT à son niveau « 1 », c’est-à-dire à la tension VDD

- La diode D5 est bloquée, car la tension sur sa cathode est supérieure à celle présente sur
son anode.

- Dans R6 ne circule aucun courant, ses deux extrémités se retrouvant au même potentiel,
soit VDD

- Un courant peut donc circuler dans la led interne de U2, via R1 et D6.

- Le phototransistor de U2 devient donc passant, la tension positive présente sur le


collecteur de ce transistor, donc sur RD, se retrouve portée à la tension présente sur RTS,
autrement dit, la référence du niveau « 1 ».

- On a donc bien réception d’un niveau « 1 » sur la pin RD du port RS232.

Reste le cas de l’émission d’un niveau « 0 » du PIC® vers le port RS232 :

- Le PIC® place PINT à un niveau « 0 », c’est-à-dire à la tension de la masse.

- La diode D5 devient passante, ramenant la tension présente sur l’anode de D6 à 0,6V.

- La tension de seuil de D6, la même que celle de D5, ne permet plus de laisser passer un
courant dans la led interne de U2.

- Le phototransistor de U2 est donc bloqué.

- La tension appliquée sur RD est donc pratiquement celle présente sur DTR, soit la tension
représentant un niveau « 0 ».

15
- On a donc bien reçu un niveau 0 sur le port RS232.

Avant de poursuivre, revenons un peu à l’émission d’un bit « 1 » par le PIC®. Imaginons
en effet que le port RS232, au lieu d’être au repos, envoie un niveau « 0 » vers le PIC®
(plantage du programme sur l’ordi, erreur de l’utilisateur, etc.).

Dans ce cas, nous l’avons vu, le transistor de U3, ainsi que Q3 sont passants, entraînant la
mise à la masse de PINT. PINT que tente justement de mettre à +Vdd notre PIC® tentant
d’envoyer un « 1 ».

Nous avons la un parfait exemple de court-circuit, qui risque d’entraîner la destruction du


PIC® ou de U3, ou de Q3, à moins que ce ne soit de l’ensemble.

Il n’est pas question, pour un électronicien, de permettre la destruction du matériel suite à


un problème logiciel.

Nous devrons donc nous arranger pour que notre PIC® ne puisse JAMAIS envoyer un
niveau Vdd sur PINT. Ceci est très simple, et sera résolu par une astuce d’utilisation du
programme du PIC®.

Maintenant, quel est le rôle de U1, dont nous n’avons pas parlé ?

Et bien, U1 va permettre de générer un reset au niveau du PIC®. Voici comment cela se


passe :

- Dans le mode normal, la tension présente sur RTS est inférieure la celle présente sur DTR.
La diode D1, qui protège la LED de U1 d’une tension inverse trop importante, est donc
bloquée.

- Aucun courant ne circule dans la LED interne de U1.

- Son phototransistor est donc bloqué et n’a donc aucune influence sur le montage

- Si on inverse par logiciel les niveaux présents sur DTR et RTS, le circuit devient passant
via R4/U1/D1.

- Le phototransistor devient alors passant, et entraîne la pin MCLR du PIC® à la masse,


provoquant le reset de ce dernier.

Bien entendu, il ne faudra pas que le PIC® possède sa pin MCLR directement reliée au
+5V, sous peine d’un court-circuit. Je vais y revenir.

Voici donc, avec 3 opto-coupleurs à 25 cents, une fiche DB9, et une (petite) poignée de
composants, une interface de communication, ainsi qu’une interface de debuggage, pour,
disons, 6 euros.

Peut-on encore parler de prix de revient ?


De plus, cette interface, au contraire de la majorité de celles que vous trouverez, est
complètement opto-couplée, et donc utilisable sous tension. Elle est, de plus, adaptée

16
automatiquement aux tensions utilisées par le port choisi, et donc universelle. Prenez
cependant garde que la partie gauche du montage est connectée à votre platine d’application.

Autrement dit :

Si vous utilisez des tensions dangereuses sur votre platine d’application, vous devez
garantir votre sécurité et la sécurité de ceux qui emploieront l’interface BigoPIC1. Vous
devez donc garantir tout contact accidentel avec les sondes à destination du PIC®, ainsi
qu’avec la platine de l’interface. Un boîtier sera dès lors indispensable, et aucune piste
du circuit imprimé ne pourra passer entre les pins des opto-coupleurs. Vous vous
engagez de plus à obéir à toutes les normes de sécurité en vigueur dans votre pays.

Je n’ai pas réalisé de typon pour cette interface. Je l’ai réalisée pour ma part sur une petite
platine d’expérimentation, ne mettant pas en œuvre des tensions supérieures à 5V. Claude
Grini s’est proposé pour réaliser ce typon, il se trouve maintenant sur le site. Attention, ce
typon correspond à la permière version de l’interface, n’oubliez pas de modifier en
conséquence.

S’il s’avérait que ça ne fonctionne toujours pas sur votre PC, utilisez alors l’interface 2
disposant d’un MAX232. Dans ce cas, il vous faudra relier ensemble les pins 11 et 12 du max
par une résistance de 1K. PinT sera reliée à la pin 11 du max232. Attention que dans ce cas
votre interface n’est plus optocouplée, agissez en connaissance de cause.

17
Notes :

18
3. La mise en œuvre matérielle

3.1 Ce qu’il faut savoir

Nous venons de voir comment construire notre interface de communication. Il va


maintenant s’agir de voir comment concevoir une carte d’application permettant l’utilisation
de l’interface.

En fait, nous n’avons pas beaucoup de contraintes à respecter, c’est d’ailleurs voulu. Nous
aurons besoin tout d’abord d’un accès à Vdd et d’un accès à Vss, ce qui ne devrait poser
aucun problème.

Ensuite, nous ne devons pas connecter directement MCLR à Vdd, puisque nous devons
pouvoir imposer un niveau « 0 » sur cette pin via notre interface. Ceci ne pose aucun
problème, il suffit d’insérer une résistance.

Enfin, il nous faut un accès à une pin quelconque du PIC®, avec laquelle nous établirons
le dialogue. A ce niveau, il faut un peu plus de précision.

Notre PIC®, une fois son programme final chargé, va devoir « choisir » au démarrage
entre démarrer le bootloader, ou démarrer le programme chargé, étant entendu que le
bootloader reste en permanence à l’intérieur du PIC®, ce qui est son principal intérêt.

Comme, une fois le bootloader connecté, et en attente, le niveau de repos de la


transmission série est le niveau « 1 », j’ai donc choisi la procédure suivante :

- Si, au démarrage, la pin choisie, désignée sous le nom de PI NT (pin de transmission) se


trouve, même une fraction de seconde, au niveau « 0 », alors on lance le programme
d’application.

- Si, par contre, durant un temps prolongé (du point de vue du PIC®), ceci afin d’éviter un
parasite, le PIC®, au démarrage, constate un niveau « 1 » sur la pin de transmission, il en
«déduira » que le bootloader est connecté, et entreprendra la dialogue ».

Il vous incombe donc qu’en l’absence de bootloader, le niveau sur la pin soit un niveau 0
lors du reset. Il y a plusieurs façons d’y parvenir :

- Si la pin n’est pas utilisée par le montage (cas le plus simple), un jumper ou une résistance
de 10KOhms entre la pin et la masse garantira une détection de l’absence de bootloader.
Ne pas utiliser une résistance de moins de 10Kohms, pour ne pas interférer avec la
résistance de rappel de 1Kohms présente dans l’interface.

- Si la pin est utilisée en sortie, une simple résistance de 10K entre la pin choisie et la masse
imposera à coup sûr un niveau « 0 » lors du reset. Je rappelle que ce niveau n’est mesuré
qu’au reset, le reste du temps ce niveau peut varier sans problème. Or, une pin est toujours
en entrée au moment du reset. Attention, n’oubliez pas que l’application d’une tension sur
la pin de transmission appliquera également la tension sur le périphérique concerné. En
cas de danger (moteur), utilisez un jumper pour passer du mode bootloader au mode
utilisation normale.

19
- Si la pin est utilisée en entrée, il faudra gérer votre électronique pour avoir un niveau « 0 »
lors de chaque reset. Mais bon, c’est plus simple d’utiliser une pin prévue pour travailler
en sortie, ou une pin, inutilisée.

Vous constatez que l’utilisation de la pin de transmission ne prive pas votre montage
d’une pin d’entrée/sortie. Il suffit en effet de la choisir judicieusement pour éviter les cas
difficiles. C’est le cas de bien peu d’autres bootloaders proposés.

3.2 Schéma d’application typique

Partant du principe qu’un petit dessin vaut mieux qu’un long discours, je vais vous
montrer un schéma permettant l’utilisation du bootloader. Vous verrez qu’il est possible
d’adapter ce schéma.

Je vais choisir volontairement le cas le plus difficile, à savoir que la pin utilisée pour le
bootloader est une pin qui pilote un moteur, et qui donc, ne peut être alimenté au rythme de la
liaison série.

Vous pouvez constater que ce circuit ressemble tout à fait à un circuit d’application
classique.

Au niveau du reset, une résistance a simplement été ajoutée. Cette résistance vous permet,
de plus, d’ajouter un bouton de reset manuel sur le circuit entre la pin Mclr et la masse. Ceci
ne perturbera nullement le bootloader. Vous faites donc d’une pierre deux coups.

Un seul des 2 jumpers, naturellement, ne doit être placé à un instant donné. Lors du
fonctionnement normal, vous insérez J2. Lors de l’utilisation du bootloader, vous insérez J3.

Notez que la pin choisie sera connectée simultanément aux pins 1 et 3 de l’interface,
l’interconnexion des 2 pins s’effectuera donc via la câble de connexion entre le PIC® et
l’interface. La résistance de 10Kohms, présente après J2, permet de forcer le niveau 0 sur la
pin lors d’un reset. Elle permet d’éviter d’entrer par accident en mode bootloader lors d’un
reset du PIC®.

Les 2 autres pins utilisées ne sont rien d’autre que des connexions sur l’alimentation du
montage.

Il va de soi que si la pin choisie n’est pas utilisée dans le montage (en fait, il est plutôt rare
d’utiliser toutes les pins), les jumpers sont inutiles. On aura ainsi seulement besoin de
connecter la résistance directement entre la pin choisie et la masse, la connexion du
bootloader se faisant directement sur la pin.

20
Nous verrons un exemple pratique de la façon de procéder, pas de panique si vous n’avez
pas tout compris.

Remarquez simplement que le basculement du jumper permet de diriger la pin RB5, soit
sur la carte d’application, soit sur l’interface bootloader. Il s’agit ici du cas le plus
contraignant, puisque, comme expliqué, les jumpers peuvent être le plus souvent évités.

21
Notes :

22
4. La mise en œuvre logicielle

4.1 Les questions

Nous avons vu comment construire notre platine d’application pour qu’elle soit
compatible avec notre bootloader, mais qu’en est-il de notre programme d’application ?

Est-il possible dans tous les cas d’envoyer le fichier hexadécimal par l’intermédiaire de
notre bootloader ?

En fait, nous allons voir que je suis parvenu à résoudre la presque totalité des cas
pratiques.

Tout d’abord, voyons comment est organisé le bootloader :

4.2 La séquence de démarrage du bootloader

Regardons ce qui se passe au moment du reset, quand le bootloader est présent dans un
PIC®.

Nous constatons que la routine du bootloader est appelée d’office.

23
Ensuite la pin de transmission est testée :

- Si elle vaut 0, on revient à l’adresse de saut de départ du programme.


- Sinon on traiter le dialogue sous bootloader.

L’utilisateur dispose d’une possibilité de lancer le programme principal sans devoir


déconnecter l’interface.

Bien entendu, ceci laisse sous-entendre une organisation spéciale du début du programme.
Or, j’avais précisé dans le cahier des charges qu’on pourrait envoyer n’importe quel fichier
« .hex » construit d’après la maquette fournie avec les cours.

Et bien, rassurez-vous, j’ai prévu cette possibilité.

4.3 Gestion du démarrage du programme

Commençons par examiner le début de la mémoire programme d’un PIC® contenant un


bootloader. Imaginons que l’adresse de départ du bootloader soit l’étiquette « Bootloader».

Nous avons donc les contraintes suivantes :

- Le PIC® démarre toujours à l’adresse 0x00 après un reset.


- Bootloader peut se situer dans n’importe quelle page de la mémoire programme.

Le début de la mémoire programme sera donc de la forme :

ORG 0x00 ; adresse sur reset


PAGESEL Bootloader ; pointer sur la page du bootloader (0x00 et 0x01)
call Bootloader ; exécuter bootloader (0x02)
; première adresse libre = 0x03

Les valeurs entre parenthèses sont les adresses occupées par les instructions.

En effet, il faut se souvenir que la directive PAGESEL, qui positionne les bits 3 et 4 de
PCLATH, sera remplacée à l’assemblage par 2 instructions, et donc occupera 2 adresses
(0x00 et 0x01).

L’appel du bootloader, construit comme une sous-routine, s’effectuera donc à l’adresse


0x02. Une fois l’exécution du bootloader terminée, on reviendra à l’adresse 0x03, première
adresse libre pour caser notre programme d’application.

Or, un programme construit suivant les maquettes fournies est constitué de la façon
suivante :

ORG 0x00 ; adresse de reset


goto init ; sauter au début du programme (0x00)

ORG 0x04 ; adresse des interruptions


xxxx ; début de la routine d’interruption
init

24
xxx ; première instruction du programme.

On voit tout de suite qu’il sera impossible de placer ce programme dans le PIC®, puisque
l’instruction à l’adresse 0x00, « goto init » viendra écraser la première ligne de la directive
« PAGESEL Bootloader ». Lors du prochain reset, l’appel du bootloader ne fonctionnera donc
plus.

Quelle devrait donc être la structure correcte pour que tout ceci soit compatible ?

La solution est simple : on modifie le programme à envoyer dans le PIC® de la façon


suivante :

ORG 0x03 ; adresse de reset


goto init ; sauter au début du programme (0x03)

ORG 0x04 ; adresse des interruptions


xxxx ; début de la routine d’interruption
init
xxx ; première instruction du programme.

Autrement dit, on a simplement déplacé l’instruction « goto init » de l’adresse 0x00 vers
l’adresse 0x03. Le résultat final (bootloader + programme final) sera alors du style :

ORG 0x00 ; adresse sur reset


PAGESEL Bootloader ; pointer sur la page du bootloader (0x00 et 0x01)
call Bootloader ; exécuter bootloader (0x02)
goto init ; sauter au début du programme (0x03)
xxxx ; début de la routine d’interruption(0x04)
init
xxx ; première instruction du programme.

Mais, vous allez de nouveau me répéter que j’ai modifié le programme, ce qui était
contraire à mon cahier des charges. Et bien, oui et non, puisqu’en fait, vous n’aurez pas à vous
soucier de cette transformation, le programme que je vous ai construit sur PC, pour utiliser le
bootloader effectuera directement cette modification pour vous.

Bien entendu, pour pouvoir effectuer cette modification, il faut que l’adresse 0x03 soit
libre, afin de pouvoir y placer notre instruction de saut. Le programme BigoPIC light sur PC
sera capable de gérer les cas suivants :

ORG 0x00 ; adresse de reset


goto init ; sauter au début du programme (0x00)

ORG 0x04 ; adresse des interruptions


xxxx ; début de la routine d’interruption
init
xxx ; première instruction du programme.

Nous venons de le voir, c’est le cas classique d’utilisation de la maquette. L’instruction


goto sera simplement déplacée vers l’adresse 0x03.

ORG 0x00 ; adresse de reset


goto init ; sauter au début du programme (0x00)
nop ; 0x01
nop ; 0x02

25
nop ; 0x03
xxxx ; début de la routine d’interruption (0x04)
init
xxx ; première instruction du programme.

Certains utilisent cette méthode, qui, contrairement aux apparences n’est pas identique à la
précédente. En effet, dans le cas précédent, il n’y avait aucune instruction dans le fichier
« .hex » entre l’adresse 0x00 et l’adresse 0x04. Une relecture du PIC® vous donnerait des
valeurs de 0x3FFF à ces adresses. Dans ce cas-ci, vous y lirez 0x00, puisque c’est le code
hexadécimal d’une instruction « nop ».

Et bien, BigoPIC light va commencer par supprimer ces instructions « nop », ce qui fera
revenir le fichier au cas précédent, qui sera ensuite traité de la façon précédemment décrite.

Certains programme, principalement ceux n’utilisant pas les interruptions, seront


structurés de la façon suivante :

ORG 0x00 ; adresse de reset


xxx ; première instruction du programme (0x00)
xxx ; seconde instruction du programme (0x01)
xxx ; troisième instruction du programme (0x02)
xxx ; quatrième instruction du programme (0x03)
.. ..

Dans ce cas il n’y a pas d’instruction de saut, il faut donc déplacer l’intégralité du
programme, ce que ne fait pas BIGOPIC light. Il ne vous restera alors qu’à reprendre le
fichier source et à remplacer la directive « ORG 0x00 » par « ORG 0x03 » et de réassembler
pour obtenir un nouveau fichier « .hex » compatible avec le bootloader.

C’est le seul cas pour lequel vous devrez modifier votre fichier source. Nous allons
maintenant voir en détail ce que contient ce fameux programme bootloader.

26
5. Le logiciel PIC® BgBoot.asm

5.1 Remarque pour l’utilisation des PIC® version « A »

Nous allons décrire ici le logiciel PIC® dénommé BgBoot.asm. Ce logiciel ne fonctionne
qu’avec les versions 16F87x des PIC®.

Pour utiliser les versions 16F87xA, il vous faudra utiliser BgBootA, qui se trouve dans le
même répertoire, et qui prend en charge les différences entre les deux familles.

Je ne décrit pas en détails ce second logiciel, mais il est similaire à celui-ci, à l’exception
des routines d’écritures en mémoire flash qui sont différentes. L’utilisation en est en tout cas
parfaitement identique.

Une lecture du fichier source vous permettra d’étudier les différences.

Le programme BgBootA.asm a été créé par Torium sur base du fichier initialement prévu
pour les versions non « A » et qui est décrit dans ce chapitre.

5.2 Etude détaillée du logiciel BgBoot

Nous avons maintenant vu tout ce qui touche à la réalisation matérielle et logicielle, il est
temps de nous pencher sur le logiciel à insérer dans le PIC®.

Bien entendu, ce logiciel devra répondre à notre cahier des charges. Nous allons devoir
recourir aux macros, afin d’assurer la flexibilité exigée.

Attention, à vos marques, prêts ? On commence …

;*****************************************************************************
; PROGRAMME BOOTLOADER POUR PIC 16F87x *
; A UTILISER AVEC LE PROGRAMME BGBOOT SUR PC *
; *
; Ce programme permet de programmer le PIC par technique de bootloader *
; Il peut rester résident dans le PIC pour toute application non critique *
; *
; Ce bootloader doit être chargé dans le PIC avec les bits de configuration*
; positionnés en fonction de l'application finale *
; *
; L'utilisateur décide de la pin utilisé pour le chargement au moment de *
; la programmation du bootloader dans le PIC. *
; *
; La requête de boot s'effectue en plaçant la pin concernée au niveau "1" *
; durant le reset du PIC. *
; *
; Pour toute application réelle, une résistance adéquate ou un jumper *
; devra être prévu sur la carte d'application entre la pin de *
; communication et la masse pour éviter une entrée non désirée en mode *
; de bootload. *
;*****************************************************************************

27
Bon, ici je vous rappelle notamment que la configuration doit être écrite en fonction du
programme qui sera finalisé dans le PIC®. C’est une des seules limitations du système.

;*****************************************************************************
; *
; NOM: BGBoot *
; Date: 23/10/2002 *
; Version: 1.0 *
; Circuit: Interface BIGOPIC *
; Auteur : Bigonoff *
; *
; Tous droits réservés, propriété intellectuelle de l'auteur *
; *
; Le présent logiciel ne peut être distribué sans le livre et *
; les fichiers auquel il fait référence, à savoir : *
; "La programmation des PIC par Bigonoff - Troisième partie - *
; Techniques du bootloader". Vous ne pouvez utiliser ce *
; programme qu'après avoir pris connaissance de cet ouvrage, *
; et d'en avoir accepté toutes les clauses. *
; *
; Toute utilisation sur des circuits présentant des tensions *
; à risque létal ne pourra se faire qu'en respectant les *
; législations en vigueur. L'utilisateur à l'obligation de se *
; renseigner et se conformer à ces législations. *
; *
; L'intégralité des fichiers est disponible uniquement sur le *
; site de Bigonoff. http://www.abcelectronique.com/bigonoff *
; Les webmasters sont autorisés à placer un lien sur leur site. *
; *
; Les droits relatifs à l'utilisation à des fins privées de *
; ce programme sont soumis aux mêmes conditions que celles *
; décrites dans l'ouvrage susmentionné. *
; *
; Toute utilisation commerciale est interdite sans l'accord *
; écrit de l'auteur. La modification de ce source n'est *
; autorisée qu'à des fins privées, toute distribution du code *
; modifié est interdite. *
; *
; L'auteur décline toute responsabilité quant aux conséquences *
; éventuelles résultant de l'utilisation de ce programme *
; et interfaces associées. *
; *
;*****************************************************************************

Eh oui, un petit coup de parapluie ! La vie m’a appris à être prudent. Je ne voudrais pas
qu’un travail bénévole me rapporte des ennuis, ou qu’un autre se fasse de l’argent sur mon
dos.

;*****************************************************************************
; *
; Fichier requis: P16F876.inc *
; *
;*****************************************************************************

Comme pour toute application standard, même si ça n’en n’est pas tout à fait une, le
fichier à inclure sera le fichier d’inclusion Microchip®.

28
Notez que les bootloaders ont été écrits pour être utilisé dans les 16F87x(A). Pour d’autres
processeurs, à vous de faire les modifications nécessaires, très simples et d’ailleurs expliquées
plus bas.

;*****************************************************************************
; *
; Fichier à charger dans le PIC à l'aide d'un programmateur classique *
; Le registre de configuration devra être programmé avec la valeur *
; définitive relative à l'application finale *
; *
; Au moment du reset, teste la pin choisie. Si elle est à "1", le PIC *
; exécute la routine de bootload et répond. Sinon, retour au *
; programme principal. *

Ici, un petit rappel au sujet de la programmation. Le bootloader devra, bien entendu, être
chargé à l’aide d’un programmateur classique. Ce n’est qu’une fois en place qu’on pourra se
passer d’un programmateur pour les chargements du programme définitif.

Je rappelle également que c’est au moment du reset que la décision de lancer le bootloader
ou le programme principal est prise.

; Le programme principal doit commencer exclusivement à l'adresse 0x03. *


; Les adresses 0x00 à 0x02 sont réservées par le bootloader. *
; Le bootloader PIC se charge de vérifier que l'utilisateur ne tente *
; pas de l'écraser. *

Inutile de commenter ceci plus avant, je viens juste de vous en parler.

; Le bootloader peut se placer à n'importe quel emplacement mémoire *


; selon les désirs de l'utilisateur. *

Nous allons voir un peu plus loin de quelle façon procéder pour choisir cet emplacement.

; Commandes acceptées : *
; *
; "P" + adresse (2 octets) : positionner le pointeur d'adresse *
; Réponse : 2 octets : valeur du pointeur *
; *
; "W" + donnée (2 octets) : écrit l'instruction et incrémente le ptr *
; Réponse : 4 octets : adresse + valeur effectivement lues *
; *
; "E" + donnée (1 octet) : écrit la donnée dans l'eeprom et incrémente *
; le pointeur. *
; Réponse : 2 octets : pointeur bas + donnée relue *
; *
; "G" : Retour au programme principal *
; Réponse : "GO" *
; *
; *
; Si commande inexistante, réponse "ERR" *

Nous avons ici la liste des commandes acceptées par le bootloader. Ces commandes vous
seront utiles si vous créez votre propre programme de dialogue avec le PIC®. Elles seront
transparentes pour vous si vous décidez d’utiliser BIGOPIC light, l’utilitaire sous Windows
que j’ai créé pour vous. Je détaillerai ces commandes lors de l’étude des routines
correspondantes.

29
; PARAMETRES POSSIBLES *
; -------------------- *
; *
; ADR : adresse de la routine bootloader *
; *
; FQUARTZ = V : avec V = fréquence du quartz utilisé en Hz *
; Par défaut : FQUARTZ = 20000000 (20Mhz) *
; *
; BAUDR = V : avec V = débit en bauds *
; par défaut : BAUDR = 19200 *
; *
; BAUDRL = V : à ne préciser qu'en cas d'erreur de débit *
; annoncé par un message. *
; par défaut : BAUDRL = 0 *
; *
; TAILLEMAX : Taille maximale de la mémoire flash *
; dépend du type de PIC. *
; Par défaut 0x2000 (8Kmots) *

C’est grâce à ces paramètres, en réalité des « Define » que vous allez trouver un peu plus
loin, que vous allez pouvoir modifier le fonctionnement du bootloader pour l’adapter à votre
cas particulier. Voyons un peu plus en détails.

Avec « ADR = adresse », vous allez pouvoir choisir à partir de quel emplacement
mémoire se trouvera le bootloader dans votre PIC®.

Si vous ne précisez aucun paramètre, l’adresse sera calculée automatiquement pour que le
bootloader se trouve dans les dernières adresses mémoire de la page 3.

Si vous avez l’intention d’utiliser ces emplacements pour votre programme d’application,
l’affectation d’une valeur précise forcera le bootloader à se charger ailleurs.

Par exemple :
ADR = 0x1800 ; Le bootloader commencera à l’adresse 0x1800.

FQUARTZ vous permet d’entrer la fréquence du quartz que vous allez utiliser sur votre
montage d’application. Ceci est indispensable pour que les macros puissent calculer
correctement les boucles de temporisation nécessaires pour établir le débit de transmission.

Si vous ne précisez rien, on supposera que vous travaillez avec un quartz de 20 MHz.

Exemple :

FQUARTZ = D’4000000’ ; Le quartz utilisé sera de 4MHz


; Ne pas oublier le « D », sinon on parle en hexa

BAUDR vous permet de préciser le débit de la communication. Inutile d’utiliser de trop


grandes valeurs, ça n’accélérerait pratiquement pas la vitesse de chargement, celle-ci étant
plus limitée par le temps d’écriture en mémoire flash que par le temps nécessaire aux
transmissions.

Si vous ne précisez rien, le débit par défaut sera de 19200 bauds.

30
Exemple :

BAUDR = D’9600’ ; débit de 9600 bauds.


; Ne pas oublier le « D », sinon on parle en hexadécimal

BAUDRL est un peu particulier. Vous ne devez modifier sa valeur que si le débit que
vous avez choisi n’est pas compatible avec la fréquence du quartz choisie.

En fait, le calcul du nombre de boucles de temporisation donne une erreur trop importante.
A l’aide de BAUDRL, vous ajoutez des « nop » à l’intérieur des routines de temporisation,
permettant de changer leur durée, et donc d’obtenir une erreur différente.

Vous ne devez modifier cette valeur que si vous obtenez un message vous précisant de le
faire. Dans ce cas, incrémentez successivement par pas de 1 jusqu’à obtenir la fin du message
d’erreur. Les messages peuvent être du type :

MESSAGE: (Débit trop faible pour votre quartz. Augmentez le baudrate ou


augmentez la valeur de BAUDRL)

Ce message indique que le débit est trop faible, donc que le nombre de boucles d’attente
dépasse 256. Dans ce cas, l’ajout de « nop » allonge la durée de la boucle, et donc en réduit le
nombre. La meilleure solution reste cependant d’augmenter le débit choisi.

Notez que la valeur de BAUDRL augmente d’autant la taille finale du programme de


bootloader.

Le second type de message concernant BAUDRL est le suivant :

MESSAGE: (Erreur de baudrate trop importante. Essayez de modifier la valeur de


BAUDRL)

Ici, lors du calcul du nombre de boucles, la valeur calculée ne « tombe pas juste ». Il en
découle que le débit réel obtenu par rapport au débit demandé entraîne une erreur supérieure à
4%, et donc ne garanti pas une transmission correcte avec le PC.

De nouveau, augmentez progressivement BAUDL jusqu’à disparition du message.

BAUDRL = D’1’ ; ajout d’un « nop » dans la boucle de temporisation

Je vous rappelle que vous laisserez la valeur par défaut en cas d’absence de message
d’erreur.

TAILLEMAX indique la taille de la mémoire flash sur le PIC® utilisé.

Par défaut, il s’agit de 0x2000, soit 8 Ki mots, comme sur le 16F876/877. Si vous utilisez,
par exemple, un PIC®16F873, ramenez la valeur à 0x1000 (4Ki mots).

31
ATTENTION : Sur les 873 et 874 il n’y a pas de banque commune. Dès lors,
l’utilisation d’un de ces composants implique d’ajouter des changements de banques là
où c’est nécessaire (ce qui implique de recalculer les durées des routines), soit de
changer l’emplacement des variables utilisées. L’utilisation du logiciel tel quel pour ces
composants ne fonctionnera pas.
TAILLEMAX = 0x1000
; RESSOURCES UTILISEES *
; -------------------- *
; FLASH : de 216 mots à 231 mots + BAUDRL *
; *
; PIN : BPIN (à définir par l'utilisateur) *
; PORT : BPORT (idem) *
;*****************************************************************************

Je vous précise ici les ressources utilisées. Le programme bootloader occupera au


minimum 216 mots, et au plus 231 mots augmentés de la valeur que vous aurez affectée
éventuellement à BAUDRL.

Le choix d’une pin du port A comme pin de communication augmente la taille du


programme, de même que le fait de préciser une adresse explicite pour « ADR ».

La taille minimale est donc obtenue en choisissant une pin quelconque du PIC®, excepté
sur le PORTA, et de laisser le bootloader à sa position par défaut, c’est-à-dire en fin de la
page 3 de la mémoire programme.

PIN précisera le numéro de la pin dédicacée au transfert, tandis que PORT définira le port
utilisé, de la façon suivante :

PIN EQU 7 ; pin 7


PORT EQU PORTB ; sur le PORTB, donc, il s’agira de RB7

Notez qu’il peut paraître curieux d’utiliser « EQU » et non « DEFINE » pour « PORT »,
puisque ce qui suit est du texte et non une valeur.

En fait, il s’agit bien d’une valeur, puisque le fichier P16F876.inc que vous allez inclure
contient « PORTB EQU 0x06 ». La ligne « PORT » sera donc remplacée à l’assemblage par
« PORT EQU 6 ».

Nous en avons fini… avec notre commentaire de début, c’est dire que nous ne sommes
encore nulle part. Commençons les choses sérieuses.

LIST p=16F876 ; Définition de processeur


#include <p16F876.inc> ; fichier include

__CONFIG _CP_OFF & _DEBUG_OFF & _WRT_ENABLE_ON & _CPD_OFF & _LVP_OFF &
_BODEN_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC

Ici, vous voyez que j’ai précisé qu’il s’agissait d’un PIC16F876. Si vous utilisez un
16F877, il vous suffira de l’indiquer dans ces deux premières lignes. La configuration sera
celle de votre programme d’application.

32
A vous donc de décider, par exemple, si vous mettrez ou non le watchdog en service, le
bootloader s’en accommodant fort bien.

Prenez garde que vous ne pourrez pas modifier la configuration par l’intermédiaire du
bootloader. Celle-ci sera donc définitive, à moins de reprogrammer le PIC® par
l’intermédiaire d’un programmateur classique, et de lui réinjecter un nouveau programme de
bootloader avec la configuration correcte.
Prenez également garde à la directive CP_OFF. Si vous décidez de protéger une partie de
la mémoire PIC® en lecture, vous ne pourrez pas écrire dans cette portion de mémoire. Il
vous sera donc impossible de la modifier en utilisant le bootloader.

Si vous avez besoin d’une protection, cachez une partie du code (qui ne pourra donc plus
être modifiée) dans une partie protégée de la mémoire. Bien entendu, seule la partie non
cachée pourra être mise à jour par le bootloader. Soyez donc attentif à ce point si vous
construisez des applications commerciales (pour lesquelles, je vous le rappelle, je conserve les
droits).

;*****************************************************************************
; PARAMETRES *
;*****************************************************************************

BPORT EQU PORTB ; port de communication


BPIN EQU 7 ; pin de communication

;FQUARTZ EQU D'20000000' ; fréquence quartz


;BAUDR EQU D'19200' ; débit en bauds
;BAUDRL EQU D'0' ; Permet de diminuer le taux d'erreur
; Augmente la taille du programme
; conserver la plus faible valeur
; possible. Ne pas dépasser D'5'
;ADR EQU 0x1800 ; adresse forcée de départ de la routine
;TAILLEMAX EQU 0x2000 ; taille maximale du programme

Ici, vous pouvez entrer les paramètres dont nous avons parlé, inutile donc d’y revenir.
Notez les « ; » devant les paramètres dont vous désirez conserver les valeurs par défaut. Ces
valeurs par défaut étant d’ailleurs celles indiquées après les « EQU », afin de vous permettre
de vous en souvenir rapidement. D’autre part, les valeurs par défaut seront indiquées lors de
l’assemblage sous forme de messages.

En général, si vous utilisez un quartz de 20Mhz, vous laisserez tout tel quel, vous
contentant d’indiquer quelle pin et quel port vous utilisez pour la communication avec le PC.
Pour ces paramètres, il n’y a pas de valeur par défaut.

Tous ces paramètres, vous vous en doutez peut-être, vont être traités par des directives. En
premier lieu, on va détecter si vous les avez précisé explicitement, sinon, on va leur affecter
les valeurs par défaut :

;*****************************************************************************
; ACTIONS SELON PARAMETRES *
;*****************************************************************************

errorlevel -302
; valeurs par défaut

33
; ------------------
IFNDEF FQUARTZ ; si fréquence non précisée
FQUARTZ = D'20000000' ; alors fréquence = 20MHz
MESSG "Fréquence de 20 Mhz prise par défaut" ; et message
endif

Nous commençons par la directive « errorlevel » qui évite les warnings de type « 302 »
concernant les banques. Ceci évite d’avoir une tonne de messages inutiles, et permet de se
concentrer sur les messages réellement utiles.

Je vous donne un petit mot de précision sur ces directives. Tout d’abord la directive
« IFNDEF » signifie « IF No DEFine », autrement dit, « si pas défini ». Ce qui suit, jusque la
directive « endif » ne sera interprété que si vous n’avez pas précédemment affecté une valeur
au paramètre concerné. Autrement dit, si vous avez précisé « FQUART EQU … »,
l’affectation qui suit « IFNDEF » ne sera pas exécutée.

Notez que le contraire de « IFNDEF » est « IFDEF », pour « si défini ».

Ensuite, concernant la ligne :


FQUARTZ = D'20000000' ; alors fréquence = 20MHz

Remarquez que le symbole « FQUARTZ » doit se trouver en première colonne, car


l’assembleur le considère comme une étiquette. Si vous ne le faites pas, vous aurez droit à un
message « warning » qui vous préviendra que vous avez utilisé une étiquette hors de la
colonne « 1 ».

J’ai utilisé le symbole « = » au lieu de « EQU ». Vous allez me dire : c’est strictement
identique. En fait, pas tout à fait. Les nombreux tests que j’ai effectué avec cette directive
montre qu’elle ne réagit pas toujours comme on pourrait s’y attendre. Je vous conseille donc
d’utiliser le symbole « = » lors d’affectations conditionnelles.
IFNDEF BAUDR ; si débit non précisé
BAUDR = D'19200' ; alors débit = 19200 bauds
MESSG "Débit de 19200 bauds pris par défaut" ; et message
endif

IFNDEF BAUDRL ; si BAUDRL non précisé


BAUDRL = 0 ; alors BAUDRL = 0. Message possible
endif ; en cas d'erreur importante

IFNDEF TAILLEMAX ; si taille max non précisée


TAILLEMAX = 0x2000 ; 8Kmots (16F876/877)
ENDIF

Après avoir assigné les valeurs par défaut, nous allons nous intéresser à la taille du
programme. Tout d’abord, la taille « standard » de ce programme.

; taille du programme
; -------------------

TAILLE = D'231' ; taille nominale du programme non situé en fin de page3


TAILLE += BAUDRL ; ajouter les nop créées par BAUDRL

34
Ici, on définit la taille du programme comme étant de 231 octets. Il va de soi que si vous
modifiez quelque chose dans le programme bootloader, il vous appartiendra de modifier cette
ligne en conséquence. Sans quoi vous risquez de déborder de la mémoire programme, vous
serez alors gratifiés d’autant d’erreurs que d’instructions impossibles à caser.
Ecrire

TAILLE += BAUDRL

équivaut à écrire

TAILLE = TAILLE+BAUDRL

On ajoute à cette taille standard la valeur que vous avez éventuellement affectée à
«BAUDRL », puisque cette constante provoquera l’ajout d’autant de « nop » dans la boucle
de temporisation.

IF BPORT != PORTA
TAILLE -= 5
ENDIF

Ici, on indique que si le port choisi n’est pas le PORTA, alors on gagne 5 emplacements
mémoire. Nous verrons plus loin la raison de cette différence.

#DEFINE PINT BPORT,BPIN ; facilité d'écriture

Cette ligne est simplement destinée à raccourcir l’écriture. Au lieu d’écrire partout
« BPORT,BPIN », nous pourrons écrire « PINT ».

Nous allons maintenant calculer l’emplacement du début du programme, dans le cas où


l’utilisateur, bien entendu, n’a pas précisé explicitement la valeur.

; adresse de début
; ----------------
IFNDEF ADR ; si pas déjà définie
TAILLE-= D'10' ; on gagne 10 instructions sur les tests.
ADR = TAILLEMAX-TAILLE ; adresse de la routine en fin de page 3
AUTOADD
MESSG"La routine de boot se trouve en fin de page 3" ; message
ENDIF ; fin de l'assemblage conditionnel

Remarquez que si on a conservé l’adresse par défaut, on gagne 10 emplacements


mémoire. Nous verrons également pourquoi.

L’étiquette « AUTADD » ne sera définie que si on travaille avec l’adresse par défaut.
Ceci nous sera utile dans le programme principal. En effet, nous ne pourrons plus utiliser
« IFNDEF ADR », puisque, si celle-ci n’a pas été définie par l’utilisateur, elle l’a été par ces
précédentes directives. Autrement dit, à ce stade du programme, elle sera toujours définie.

Par contre, en procédant de la suite, si « AUTOADD » est défini, c’est que l’utilisateur a
conservé l’emplacement par défaut. Remarquez toujours les constantes en première colonne.

35
Bon, à partir d’ici, ça devient un peu plus corsé .

; Calcul de la constante de temporisation


; ---------------------------------------

DUR1B EQU (((FQUARTZ/4)/BAUDR)-D'14')/(3+BAUDRL)


Cette directive calcule le nombre de boucles à effectuer dans la routine de temporisation
pour obtenir une durée équivalente à celle d’un bit à émettre ou à recevoir. Je vous explique :

« FQUARTZ / 4 » représente la fréquence des instructions qu’exécute le PIC®, puisque


chaque instruction nécessite 4 cycles d’horloge. Nous obtenons alors le nombre d’instructions
par seconde.

Si nous divisons le nombre d’instructions par seconde par le débit (en nombre de bits par
secondes), nous obtenons le nombre d’instructions à attendre entre l’envoi ou la réception de
2 bits.

Comme « BAUDR » représente le dit débit, ceci nous donne :


Nombre d’instructions à attendre = (FQUARTZ/4)/BAUDR

Maintenant, il nous faut déduire, de ce temps d’attente, le temps qui va s’écouler entre 2
appels de la routine de temporisation.

En effet, si nous devons attendre 50 instructions entre l’émission de chaque bit, et que
l’émission d’un bit nous prend 10 instructions, nous ne devrons plus attendre que 40
instructions, 10 étant déjà consommées en instructions utiles.

Il se trouve, nous le verrons plus loin, que 14 cycles d’instructions sont utilisés entre 2
appels consécutifs de la routine de temporisation., ce qui justifie le « -D’14’ ».

Nous avons maintenant le nombre de cycles à perdre dans la routine de temporisation. Or,
ce que nous voulons, c’est le nombre de boucles à effectuer dans la dite routine.

Sachant que chaque boucle de la routine consomme 3 cycles, nous diviserons par 3 la
valeur obtenue. Mais, si nous avons défini une valeur pour BAURDL, nous ajouterons autant
de « nop » à l’intérieur de la boucle de temporisation. Autrement dit, la durée d’une boucle
sera de (3 + valeur de BAUDRL).

Groupez tout ceci, et vous arrivez à la formule que je viens de vous donner. C’est plus
simple une fois expliqué, n’est-ce pas ? Je reviendrai en détails sur la fameuse valeur
« D’14’ ». Nous allons également avoir besoin d’une durée équivalente à la durée d’un bit et
demi (nous verrons pourquoi). Il suffit donc de multiplier la valeur précédemment obtenue par
1.5.

Seulement, les valeurs sont toujours arrondies en valeurs entières, aussi, pour limiter les
erreurs, nous reprendrons la formule précédente, en multipliant le résultat par 1.5. L’endroit le
plus approprié pour effectuer cette opération est (FQUARTZ/4).

Si nous multiplions ceci par 1,5, c’est-à-dire « 3/2 », puisqu’on ne peut utiliser que des
entiers, ceci nous donne (FQUARTZ * 3/8). La formule finale est donc :

36
DUR1B5 EQU (((FQUARTZ*3/8)/BAUDR)-D'14')/(3+BAUDRL)

Il reste encore à vérifier que la valeur trouvée tienne bien sur un octet, c’est-à-dire soit
comprise entre 0 et 255. En effet, une valeur négative voudrait dire qu’on doit attendre un
temps négatif, autrement dit qu’on n’a pas assez de temps, ou encore que le débit est trop
important par rapport à la fréquence du quartz choisi.

Une valeur supérieure à 255 signifie qu’on doit attendre trop longtemps, donc que le débit
est trop faible. Vous aurez alors 2 possibilités : Soit augmenter le débit, soit ajouter des
« nop » en augmentant la valeur de BAURL.

IF DUR1B5 < 0 ; Si durée trop courte


MESSG "Impossible d'établir le débit, diminuez BAUDRL. Si déjà à 0, diminuez
le débit"
ENDIF

If DUR1B5 >= 0x100 ; Si durée trop longue


MESSG "Débit trop faible pour votre quartz. Augmentez le baudrate ou
augmentez la valeur de BAUDRL"
endif

Nous avons calculé un nombre de boucles à effectuer. Seulement, comme tous les calculs
sont arrondis à la valeur entière, il nous faut encore vérifier que l’erreur engendrée sur le débit
ne soit pas trop importante. Il nous est de plus impossible d’exécuter une fraction de boucle.

Souvenez-vous, en effet, comme étudié dans le chapitre sur les liaisons série asynchrones,
seconde partie du cours sur les PIC®, qu’une erreur de plus de 5% entraîne une impossibilité
de communiquer. Nous allons maintenant vérifier que l’erreur reste sous la barre des 4%.

Nous allons tout d’abord calculer le débit réel obtenu avec la valeur retenue, simplement
en inversant la formule du calcul de DUR1B.

; calcul du débit réel et de l'erreur obtenus


; -------------------------------------------
DURBR EQU FQUARTZ/((((3+BAUDRL)*DUR1B)+D'14')*4)

Je vous passe la démonstration, qui est extrêmement simple. Nous voici maintenant en
possession du débit réel et du débit théorique.

L’erreur, est représentée par la valeur absolue de la différence divisée par la valeur du
débit théorique. Comme il nous faut une valeur en %, nous multiplions par 100 avant la
division (sinon, le résultat sera arrondi erronément).

DURERR EQU (BAUDR-DURBR)*100/BAUDR

Nous voici en possession de l’erreur, mais pas en valeur absolue. L’erreur peut donc être
négative ou positive. Nous devons donc vérifier si l’erreur trouvée est supérieure à 4% ou
inférieure à –4%. Dans ce cas, nous avertirons l’utilisateur pour qu’il puisse modifier la valeur
de BAUDRL.
Si vous avez tout compris, sans BAUDRL, on divise la valeur trouvée par 3, avec
BAUDRL = 1, on divise par 4, avec la valeur 2, on divise par 5 etc. Il arrivera forcément un
moment où l’erreur de division sera suffisamment faible pour obtenir une erreur acceptable.

37
IF (DURERR>4 | DURERR <-4) ; Si erreur > 4%
MESSG "Erreur de baudrate trop importante. Essayez de modifier la valeur de
BAUDRL"
ENDIF

Le symbole « | » signifie « ou ». Nous en avons fini avec nos directives initiales, voyons
maintenant les variables utilisées.

;*****************************************************************************
; VARIABLE ZONE COMMUNE *
;*****************************************************************************

CBLOCK 0x70
cmpt : 1 ; compteur
tmps : 1 ; compteur pour temporisation
bbyte : 1 ; octet reçu ou à envoyer
ptr : 2 ; pointeur reçu
car1 : 1 ; caractère 1 reçu
car2 : 1 ; caractère 2 reçu
ENDC

Alors là, j’en vois d’ici qui disent : « ben zut alors (ben oui, je vous imagine polis) ,
Bigonoff monopolise des variables pour son bootloader. Mais moi, j’en avais besoin, de ces
emplacements, et en plus il s’est réservé la plus intéressante des zones, la zone commune ».

Si vous vous êtes dit ça (je suis certain que certains sont dans ce cas), c’est que vous
n’avez pas bien réfléchi. Sceptique ? Reprenons :

- Le bootloader est activé au reset : Le contenu des variables est donc inconnu

- Une fois le retour au programme effectué, le bootloader ne tournera plus jusqu’au


prochain reset, pour lequel l’état des variables est de nouveau, par définition, inconnu.

Autrement dit, bootloader et programme d’application peuvent se partager des


emplacements de variables communs, puisqu’ils ne tourneront jamais en même temps, et que
l’un n’interrompra jamais l’autre.

Au reset, soit on utilise le bootloader, soit on utilise le programme principal. Le


programme principal peut donc utiliser les emplacements RAM du bootloader et
réciproquement.

Comme je voulais économiser sur la taille du programme bootloader, j’ai placé toutes mes
variables dans la zone commune, m’économisant ainsi des instructions de changement de
banques.

Le seul cas où cela pourrait se révéler gênant, c’est le cas où, dans votre programme
principal, vous détectez le type de reset auquel vous avez affaire, et que vous décidiez de ne
pas réinitialiser vos variables lors d’un reset de type manuel.

Dans ce cas, très rare, il vous suffira de tenir compte de la seule variable modifiée par le
passage dans le bootloader avant le renvoi au programme principal, c’est-à-dire la variable
« cmpt ».

38
Je suppose que dans ce cas extrême, il vous sera possible d’accepter un seul emplacement
susceptible d’être modifié après un reset, étant donné que vous disposez, de plus, de la
possibilité de déplacer « cmpt » n’importe où dans la zone RAM commune. Ceci ne constitue
donc pas, non plus, une limitation. Je tenais cependant à envisager toutes les possibilités.

Nous rentrons enfin dans le vif du sujet. Notre programme PIC® va réellement
commencer ici. Nous allons trouver en premier le saut vers notre routine bootloader, dont
nous avons déjà parlé.

;*****************************************************************************
; DEMARRAGE SUR RESET *
;*****************************************************************************
;-----------------------------------------------------------------------------
; les adresses 0x00 à 0x02 sont réservées pour le bootloader
; le programme réel devra donc commencer à l'adresse 0x03
;-----------------------------------------------------------------------------

ORG 0x00 ; adresse sur reset


PAGESEL ADR ; pointer sur la page du bootloader
call (ADR & 0x7FF) ; exécuter bootloader

Souvenez-vous que le programme sur PC, BIGOPIC light, est capable de gérer plusieurs
cas apparents de conflits.

Nous allons maintenant tester la pin de transmission, pour savoir si l’interface bootloader
est oui ou non connectée au montage.

;*****************************************************************************
; TESTER SI REQUETE DE BOOT *
;*****************************************************************************
;-----------------------------------------------------------------------------
; Teste si PINT est à "1". Si oui, on entre dans le bootloader
; Sinon, on revient au programme principal
; Par sécurité, on fait 256 tests. Si un seul donne la pin à "0", on revient
; au programme principal
;-----------------------------------------------------------------------------

ORG ADR ; début du bootloader

; gérer PORTA
; -----------
IF (BPORT == PORTA) ; si PORTA
bsf STATUS,RP0 ; passer en banque 1
movlw 0x06 ; valeur pour mode " numérique "
movwf ADCON1 ; PORTA en mode numérique
bcf STATUS,RP0 ; repasser en banque 0
ENDIF ; fin d'assemblage conditionnel

; tester état de PINT


; -------------------
clrf cmpt ; effacer compteur
inloop
btfss PINT ; tester si PIN = 0
goto sortir ; oui, rendre la main au programme
movlw DUR1B5 ; pour durée de 1,5 bit
call tempo ; attendre
decfsz cmpt,f ; décrémenter compteur de boucles
goto inloop ; pas dernière, suivante

39
Vous voyez que nous commençons par la directive « ORG ADR », puisque le bootloader
sera chargé à partir de cette adresse.

Ensuite, vous voyez un assemblage conditionnel (IF…), c’est-à-dire que les instructions
comprises entre le « IF » et le « ENDIF » ne seront écrites dans le PIC® que si la condition
est réalisée.

En l’occurrence, on teste si le port choisi par l’utilisateur est le PORTA. Dans ce cas, ce
port étant en mode analogique par défaut, il faudra commencer par le positionner en mode
numérique. Ceci explique déjà 4 des 5 instructions supplémentaires nécessaires si on utilise le
PORTA, comme nous l’avons vu lors des directives de calcul de la taille du programme.

Ensuite, nous allons tester si la pin choisie est à l’état haut (présence du bootloader) ou à
l’état bas (démarrage du programme classique). Un simple test aurait pu suffire, mais n’était
pas sécurisant.

J’ai trouvé dangereux qu’un simple parasite au moment d’un reset puisse faire basculer
une application réelle en mode bootloader, bloquant ainsi le fonctionnement de la carte. Au
lieu de ça, j’ai testé pendant l’équivalent de 256 fois la durée de transmission d’un bit et demi.

Si, au cours de ce laps de temps, la pin ne présente ne serait-ce qu’une seule fois, un
niveau 0, alors on quitte le mode bootloader et on passe en application normale.

Un parasite aura alors comme seul risque de ne pas lancer le bootloader au moment voulu,
ce qui n’a aucune importance, l’utilisateur étant à ce moment présent et en train de travailler
sur le PIC®. Le reset sera renvoyé par le programme BIGOPIC light, et tout sera corrigé en
quelques ms.

Par contre, le PIC® ne pourra pas entrer par accident en mode bootloader (ou alors, vous
n’avez vraiment, mais alors vraiment pas de chance, pour avoir reçu 256 fois un parasite
synchronisé avec une fréquence égale à celle du débit choisi multiplié par 1,5).

Dans ce cas, ça relève de la malédiction Vaudou, plus que de la malchance. Courez donc
vite consulter un spécialiste en la matière, je ne peux plus rien pour vous.

Si la pin de transmission est restée au niveau « 1 » tout au long du test précédent, alors on
peut estimer à coup sûr que l’interface est connectée. Nous pouvons donc entrer dans le mode
bootloader proprement dit.

;*****************************************************************************
; ENTRER DANS LE MODE BOOTLOADER *
;*****************************************************************************
;-----------------------------------------------------------------------------
; Envoie la séquence "BGB"
; ensuite envoie l'adresse du bootloader et sa taille (2 + 2 octets)
; ensuite, attends la commande
;-----------------------------------------------------------------------------
movlw "B" ; charger caractère
call send ; l'envoyer
movlw "G" ; charger caractère
call send ; l'envoyer
movlw "B" ; charger caractère

40
call send ; l'envoyer
movlw HIGH(ADR) ; adresse haute du bootloader
call send ; envoyer
movlw LOW(ADR) ; adresse basse du bootloader
call send ; envoyer
movlw HIGH(TAILLE) ; taille haute du bootloader
call send ; envoyer
movlw LOW(TAILLE) ; taille basse du booloader
call send ; envoyer

Vous voyez qu’une fois dans ce mode, le programme commence par envoyer
l’identification « BGB » qui va servir au programme sur l’ordinateur distant qu’il se trouve
bien en train de dialoguer avec le bootloader du PIC®.

Ensuite, le programme PIC® va envoyer au PC 2 octets contenant l’adresse du bootloader,


dans l’ordre poids fort puis poids faible, et ensuite la taille du programme, en deux octets
codés de la même façon.

A partir de ce moment, le PC sait donc où commence et ou fini le bootloader. Ceci lui


permettra de vérifier si le programme que vous tentez d’envoyer dans le PIC® n’utilise pas
les mêmes adresses que le bootloader. Bref, si vous ne tentez pas d’écraser le bootloader.

Notez que le programme PC vérifie cette condition, mais le bootloader en lui-même


effectue cette vérification également. De la sorte, il vous est impossible de détruire le
bootloader par inadvertance.

Nous entrons alors dans la boucle principale :

;*****************************************************************************
; BOUCLE PRINCIPALE *
;*****************************************************************************
;-----------------------------------------------------------------------------
; On attend la commande
; ensuite, on teste pour voir de laquelle il s'agit
;-----------------------------------------------------------------------------
boucle
call receive ; attendre et recevoir commande

Le bootloader passe alors en mode de réception, et attend une commande en provenance


de l’ordinateur. Il va alors pouvoir identifier et traiter la commande.

;*****************************************************************************
; TRAITER COMMANDE "P" *
;*****************************************************************************
;-----------------------------------------------------------------------------
; Positionne le pointeur qui sera utilisé pour l'écriture et la lecture en
; mémoire eeprom et flash
; On reçoit le poids fort puis le poids faible
; Réponse : 2 octets : les 2 octets reçus
;-----------------------------------------------------------------------------

; tester si reçu "P"


; ------------------
xorlw "P" ; comparer avec commande "P"
btfss STATUS,Z ; tester si égalité
goto commW ; non, tester commande suivante

41
; réception des 2 octets
; ----------------------
call receive ; lire donnée
movwf ptr ; sauver dans poids fort pointeur
call receive ; lire donnée
movwf ptr+1 ; sauver dans poids faible pointeur

; renvoi de la valeur écrite


; --------------------------
movf ptr,w ; charger poids fort
call sendtemp ; le renvoyer
movf ptr+1,w ; charger poids faible
lastsend
call send ; le renvoyer
goto boucle ; lire commande suivante

Que fait cette routine ? Elle compare l’octet reçu avec « P ». Si on a correspondance, on
traite la commande, sinon, on compare avec la commande suivante.

Cette commande permet de positionner le pointeur interne. En effet, afin d’éviter de


devoir envoyer l’adresse suivie de la valeur pour chaque instruction à écrire en mémoire flash,
j’ai choisi de travailler avec un pointeur. On initialise le pointeur avec la première adresse à
écrire, puis on envoie les valeurs à écrire, le pointeur étant incrémenté automatiquement en
interne par le PIC®.

Une fois la commande « P » reçue, on attend les 2 octets suivants. On réceptionne alors le
poids fort suivi du poids faible, le tout constituant une adresse sur 16 bits. On sauve la valeur
dans le pointeur interne, et on retourne les 2 octets mémorisés, pour que le programme PC
puisse vérifier l’intégrité de la transmission.

Vous remarquerez que l’envoi du premier octet s’effectue par l’appel de « sendtemp » au
lieu de « send » pour les envois suivants. Ceci est dû au fait que nous sortons de notre routine
de réception dès le milieu de stop-bit.

Il faut alors se souvenir qu’au niveau de l’ordinateur, celui-ci reçoit en écho les
commandes qu’il envoie, du fait de la construction de l’interface.

Il a donc reçu le dernier octet qu’il a envoyé. Si vous envoyez directement le premier octet
de la réponse, il recevra ainsi cet octet avant la fin du dernier stop-bit, ce qui ne manquera pas
de poser problème. Nous ménagerons donc une pose entre la réception d’un octet et l’envoi
du premier octet suivant, ce qui explique cette particularité que nous retrouverons donc dans
les autres routines.

Si la commande reçue n’est pas « P », alors on arrive dans la routine suivante. Comme elle
est nettement plus longue, je vais détailler d’avantage.

;*****************************************************************************
; TRAITER COMMANDE "W" - ECRITURE FLASH *
;*****************************************************************************
;-----------------------------------------------------------------------------
; reçoit l'instruction à placer en mémoire programme(2 octets)

42
; Réponse : 4 octets : adresse (2 octets) + instruction (2 octets)
; Après écriture, on pointe sur l'emplacement suivant
; Si on tente d'écrire en mémoire interdite, on renvoie l'adresse
; avec le premier octet de l'instruction inversés
;-----------------------------------------------------------------------------
commW
; tester si reçu "W"
; ------------------
xorlw "P"^"W" ; comparer avec commande "W"
btfss STATUS,Z ; tester si égalité
goto commE ; non, tester commande suivante

Examinons la première ligne. « Qu’est-ce donc ceci ? », allez vous probablement dire.
Vous devez comparer l’octet reçu avec « W » .

Or, l’octet présent dans « w » a déjà été détruit par le test précédent, lors de la
comparaison avec « P ». Si je vous dit que l’octet reçu se trouve également dans la variable
« bbyte », vous penserez immédiatement à écrire :

movf bbyte,w ; charger octet reçu


xorlw "W" ; comparer avec « W ».

En fait, c’est la façon « intuitive » de procéder, mais ce n’est pas une façon optimisée de
le faire. En effet, il vous faut 2 instructions pour exécuter ce test.

On peut se dire également que le contenu du registre W n’est pas détruit. En effet,
simplement les bits correspondants à « P » ont été inversés. Autrement dit si j’écris :

xorlw "P" ; réinverser les bits précédemment inversés


xorlw "W" ; comparer avec commande "W"

La première instruction réinverse le contenu de « W » de façon à retrouver le contenu de


« W » d’origine, donc la valeur de bbyte. Jusqu’ici, c’est très beau, mais on ne gagne rien.

Imaginons que l’utilisateur envoie « W ».

Le code ASCII de « W » vaut 0x57, le code ASCII de « P » vaut 0x50

On a donc, au moment du test dans la routine de traitement de la commande « P », la


valeur du registre w est 0x57, soit B’0101 0111’

On va, dans cette routine exécuter


xorlw "P" ; comparer avec commande "P"
btfsc STATUS,Z ; tester si commande "P"

On a donc dans le registre w , la valeur « W » xor « P », donc :

B’0101 0111’ ; valeur de la commande envoyée


Xor B’0101 0000’ ; xorlw « P »
= B’0000 0111’ ; résultat, les bits correspondants à « P » ont été inversés

Si maintenant on exécute

43
xorlw "P" ; réinverser les bits précédemment inversés
xorlw "W" ; comparer avec commande "W"

On obtient
B’0000 0111’ ; registre w
Xor B’0101 0000’ ; xor « P »
= B’0101 0111’ ; on retrouve la valeur envoyée = « W »
Xor B’0101 0111’ ; xor « W»
= B’0000 0000’ ; = 0 , notre test fonctionne.

On se dit alors qu’on peut aussi imaginer l’astuce suivante :

Au lieu d’inverser les bits du registre w correspondants à « W », on ne va réinverser que les


bits qui n’ont pas encore été inversés par « P », et réinverser ceux qui l’ont été sans que ce soit
nécessaire.

En réalité, cela correspond simplement à dire qu’au lieu de comparer le contenu du


registre w avec la valeur « W », on le teste avec « P » XOR « W ». Pas convaincus ?
Regardez :

Après le test de « P », j’ai B’0000 0111’ dans mon registre « W ».

Si je calcule ce que donne « P » XOR « W » :

B’0101 0000’ ;«P»


Xor B’0101 0111’ ; xor « W »
= B’0000 0111’ ; = 0x07

Maintenant, il me reste à tester, dans ma routine de traitement de la commande « W », si


le registre w est égal à ( « P » XOR « W »).Dans toutes ces explications, ne confondez pas
« W » qui est le code ascii correspondant à la lettre « W » et le registre w.

B’0000 0111’ ; contenu du registre w


Xor B’000 0111’ ; xor (P xor W)
= B’0000 0000’ ; = 0, test réussi.

Or, l’avantage de cette façon de procéder, c’est que (« P » xor « W ») est une constante,
qu’on peut calculer une fois pour toute au moment de l’assemblage. D’ailleurs MPASM®
fera ça très bien tout seul. Il suffit de savoir que la directive pour un ou exclusif est « ^ ».

On peut alors remplacer

movf bbyte,w ; charger octet reçu


xorlw "W" ; comparer avec commande "W"

Par

xorlw "P"^"W" ; comparer avec commande "W"

44
Et voilà, toutes ces explications pour arriver à gagner 1 octet par test. Vous constatez ici
les méandres et les joies de l’optimisation. Poursuivons cette routine.
; réception des 2 octets de donnée
; --------------------------------
call receive ; lire une donnée
movwf car1 ; la sauver
call receive ; lire la donnée suivante
movwf car2 ; la sauver

On réceptionne ici les 2 octets, qui, combinés ensemble, donneront la valeur de


l’instruction à écrire en mémoire flash à l’emplacement désigné par le pointeur.

Nous allons ensuite procéder à différents contrôles de la validité de l’adresse à laquelle on


est en train d’écrire. C’est ici que nous trouvons tout ce qui concerne la sécurité du
bootloader, c’est-à-dire le blocage de toute tentative d’écrasement de ce bootloader par le
programme d’application.

; vérifier si adresse < 0x03


; --------------------------
movf ptr,w ; charger pointeur haut
btfss STATUS,Z ; tester si >0
goto testsuite ; oui, alors premier test OK
movlw 0x03 ; plus petite adresse valide
subwf ptr+1,w ; comparer avec pointeur bas
btfss STATUS,C ; tester si <3
goto interdit ; oui, adresse interdite

Nous avons déjà vu que les adresses 0x00 à 0x02 contenaient le saut initial vers le
bootloader, il n’est donc pas question d’autoriser l’écriture de ces adresses, quel que soit
l’emplacement auquel se trouve le bootloader.

Poursuivons nos vérifications :

; vérifier si adresse < début de routine


; --------------------------------------
testsuite
movlw HIGH(ADR) ; charger poids fort adresse routine
subwf ptr,w ; comparer avec pointeur fort
btfss STATUS,C ; tester si on est en dessous
goto testok ; oui, alors c'est bon
btfss STATUS,Z ; tester si poids forts identiques
goto testsuite2 ; non, tester si on est après le bootloader

movlw LOW(ADR) ; charger poids faible adresse routine


subwf ptr+1,w ; comparer avec pointeur faible
btfss STATUS,C ; tester si pointeur < adresse
goto testok ; oui, alors c'est bon

Le bootloader se trouve chargé à partir de l’adresse « ADR » Autrement dit, si on tente


d’écrire après l’adresse 0x02 et avant l’adresse ADR, on n’a aucun risque d’écraser le
bootloader. C’est ce que vérifie le code précédent.

Poursuivons :
; vérifier si adresse > fin de routine
; ------------------------------------

45
testsuite2
IFNDEF AUTOADD ; si pas adresse par défaut
movf HIGH(ADR+TAILLE),w ; charger première adresse libre MSB
subwf ptr,w ; comparer avec pointeur haut
btfss STATUS,C ; tester si on est en dessous
goto interdit ; oui, interdit
btfss STATUS,Z ; tester si égalité des poids forts
goto testok ; non, alors c'est bon

movf LOW(ADR+TAILLE),w ; charger première adresse libre LSB


subwf ptr+1,w ; comparer avec pointeur bas
btfsc STATUS,C ; tester si on est >=
goto testok ; oui, OK
ENDIF ; fin d'assemblage conditionnel

Vous vous souvenez que le bootloader peut être placé, soit en fin de mémoire programme
(par défaut), soit à un emplacement que vous avez fixé vous-même. Dans ce dernier cas, il est
possible de placer du code programme derrière la fin du bootloader.

Dans le cas contraire, cette vérification est inutile, ce qui justifie qu’il s’agit ici d’un
assemblage conditionnel, le rôle de « AUTOADD » a déjà été expliqué au moment de l’étude
des directives de début de programme. Si on a laissé l’adresse par défaut, on économise ainsi
ces 10 instructions, et donc, autant de mémoire programme.

Vous noterez qu’on exploite ici judicieusement l’ordre des routines afin d’économiser des
sauts. En effet, le traitement de l’interdiction va suivre directement cette routine, ce qui a
l’effet suivant :
- Si le pointeur pointe avant le début du bootloader, on peut traiter

- Sinon, si l’utilisateur a défini sa propre adresse, on teste si on ne pointe pas après la fin du
bootloader

- S’il n’a pas défini son adresse, l’instruction qui suit « testsuite2 » sera alors
automatiquement la première instruction d’une non validité du pointeur.

Voici d’ailleurs maintenant le traitement de l’erreur résultant de la tentative d’écrasement


du bootloader :

; traiter adresse pas autorisée


; -----------------------------
interdit
movf ptr,w ; charger pointeur MSB
call sendtemp ; envoyer
movf ptr+1,w ; charger pointeur LSB
call send ; envoyer
comf car1,w ; charger caractère 1 inversé
goto envinst ; envoyer caractère inversé

Que fait-on ici ? Simplement on réenvoie les 2 octets du pointeur, suivis par les 2 octets
de l’instruction à écrire, mais dont le premier est inversé. Ainsi, le programme PC sait qu’une
erreur s’est produite, puisque la valeur reçue n’est pas celle envoyée. Notez que par l’appel de
« goto envinst », on récupère quelques instructions utilisées plus loin dans le programme, et
donc, on économise quelques octets de mémoire programme.

46
Si tout s’est bien passé jusqu’à présent, il nous faut maintenant écrire l’instruction reçue
sous forme de 2 octets dans la mémoire flash, à l’emplacement pointé par le pointeur interne :
; écrire instruction dans mémoire programme
; -----------------------------------------
testok
bsf STATUS,RP1 ; passer banque 2
movf car1,w ; charger caractère 1
movwf EEDATH ; sauver dans data MSB
movf car2,w ; charger caractère 2
movwf EEDATA ; sauver dans data LSB
movf ptr,w ; charger pointeur haut
movwf EEADRH ; sauver dans pointeur MSB
movf ptr+1,w ; charger ptr bas
movwf EEADR ; sauver dans pointeur LSB

bsf STATUS,RP0 ; pointer banque 3


bsf EECON1,EEPGD ; pour écriture en mémoire programme
bsf EECON1,WREN ; autorisation d'écriture

movlw 0x55 ; début de la séquence d'écriture


movwf EECON2 ; commande 0x55
movlw 0xAA ; pour commande 0xAA
movwf EECON2 ; envoyer commande
bsf EECON1,WR ; écrire
nop ; instruction ignorée
nop ; instruction ignorée
bcf EECON1,WREN ; verrouiller écritures

Cette routine n’est rien d’autre que la transposition de la routine standard d’écriture en
mémoire flash, que nous avons déjà eu l’opportunité d’étudier dans la seconde partie du
cours.

Ensuite, nous allons relire les valeurs effectivement écrites dans la mémoire flash, ce qui
nous servira de vérification.

; lire instruction en mémoire flash


; ---------------------------------
bsf STATUS,RP0 ; pointer banque 3
bsf EECON1,RD ; ordre de lecture
nop ; attendre fin de lecture
nop ; attendre

; récupérer les données


; ----------------------
bcf STATUS,RP0 ; passer en banque2
movf EEDATH,w ; charger data MSB
movwf car1 ; sauver
movf EEDATA,w ; charger data LSB
movwf car2 ; sauver
bcf STATUS,RP1 ; repasser banque 0

De nouveau, rien que du classique. Nous allons maintenant envoyer le pointeur effectif
vers l’ordinateur distant, de façon à ce qu’il puisse vérifier que l’adresse écrite est bien celle à
laquelle il s’attend :
; envoyer pointeur
; ----------------
movf ptr,w ; charger pointeur MSB

47
call sendtemp ; envoyer
movf ptr+1,w ; charger pointeur LSB
call send ; envoyer
Puis, ensuite, les 2 octets de l’instruction :

; envoyer instruction
; -------------------
movf car1,w ; charger instruction MSB
envinst
call send ; envoyer
movf car2,w ; charger instruction LSB

Vous remarquez la présence de l’étiquette « envinst », qui permet de récupérer les


instructions suivantes lors du saut situé après l’étiquette « interdit » vu un peu plus haut.

Il ne reste plus qu’à incrémenter le pointeur pour se préparer à la prochaine écriture :

; incrémenter pointeur
; --------------------
incptr
incf ptr+1,f ; incrémenter pointeur poids faible
btfsc STATUS,Z ; tester si débordement
incf ptr,f ; oui, incrémenter poids fort
goto lastsend ; envoyer dernier octet

Vous constaterez que la routine se termine par « goto lastsend » au lieu de la séquence
attendue suivante :

call send ; le renvoyer


goto boucle ; lire commande suivante

Ceci nous fait consommer 2 cycles d’instructions supplémentaires, mais nous fait gagner
un emplacement mémoire en récupérant ces deux instructions qui existent déjà dans la routine
de traitement de la commande « P ».

Nous voici donc de nouveau en présence d’une optimisation en taille, au dépend de


l’optimisation en vitesse. Il va de soi que cette seconde n’a pas la moindre importance dans
cette application, au contraire de la première.

Après la routine d’écriture en mémoire flash, voyons la routine d’écriture en mémoire


eeprom, beaucoup plus simple :

;*****************************************************************************
; TRAITER COMMANDE "E" *
;*****************************************************************************
;-----------------------------------------------------------------------------
; Ecriture dans la zone eeprom. Attend la fin de l'opération avant de
; continuer.
; Réponse : 2 octets : adresse + valeur relue
;-----------------------------------------------------------------------------
commE
; tester si reçu "E"
; ------------------
xorlw "W"^"E" ; comparer avec commande "E"
btfss STATUS,Z ; tester si égalité
goto commG ; non, tester commande suivante

48
; réception octet de donnée
; -------------------------
call receive ; réception octet de donnée

; écrire en eeprom
; ----------------
bsf STATUS,RP1 ; passer banque 2
movwf EEDATA ; placer dans registre
movf ptr+1,w ; charger pointeur
movwf EEADR ; dans pointeur eeprom

bsf STATUS,RP0 ; passer banque 3


bcf EECON1,EEPGD ; pour écriture en mémoire data
bsf EECON1,WREN ; autorisation d'écriture

movlw 0x55 ; début de la séquence d'écriture


movwf EECON2 ; commande 0x55
movlw 0xAA ; pour commande 0xAA
movwf EECON2 ; envoyer commande
bsf EECON1,WR ; écrire

; attendre fin d'écriture


; -----------------------
clrwdt ; effacer watchdog
btfsc EECON1 , WR ; tester si écriture terminée
goto $-2 ; non, attendre
bcf EECON1,WREN ; verrouiller écritures

; relire donnée écrite


; --------------------
bsf EECON1,RD ; ordre de lecture
bcf STATUS,RP0 ; passer en banque2

; envoyer pointeur et donnée


; --------------------------
bcf STATUS,RP1 ; passer banque 0
movf ptr+1,w ; charger pointeur
call sendtemp ; envoyer
bsf STATUS,RP1 ; passer banque2
movf EEDATA,w ; charger donnée lue
bcf STATUS,RP1 ; repasser banque0

; incrémenter pointeur
; --------------------
goto incptr ; envoyer, incrémenter ptr et com suivante

Rien que du très classique : on écrit l’octet reçu dans l’emplacement pointé par le pointeur
bas. En effet, nous n’avons que 256 emplacements de mémoire eeprom, donc un octet nous
suffit, ainsi qu’un seul octet de donnée. Nous relisons la valeur écrite et la renvoyons au
programme, en même temps que le pointeur.

La dernière ligne permet de récupérer une partie du code de la routine précédente, qui
incrémentera aussi le pointeur haut, ce qui ne nous gène en aucune façon, bien que nous ne
l’utilisions pas. De nouveau, perte de temps se fait de pair avec gain de place.

Il n’y a ici rien à vérifier, puisque le bootloader n’utilise aucune ressource en mémoire
eeprom, il ne peut donc risquer de se faire écraser.

49
Dernière remarque, la présence du « clrwdt » dans la boucle d’attente de la fin d’écriture
eeprom vous montre que le watchdog est géré, et qu’il vous est loisible de l’utiliser ou non
dans la configuration finale de votre bootloader (en fonction, je vous le rappelle, du
programme d’application).

Nous pouvons maintenant positionner le pointeur, et écrire en mémoire flash et eeprom. Il


nous reste une dernière commande, certes pas indispensable, mais bien pratique : pouvoir
lancer le programme principal sans devoir déconnecter l’interface bootolader.

Vous apprécierez cette option lors de la phase de développement. Si vous n’en avez pas
besoin, vous pouvez la supprimer, et gagner ainsi quelques octets supplémentaires. Cette
commande est la commande « G », qui n’est suivie d’aucun paramètre.

;*****************************************************************************
; TRAITER COMMANDE "G" *
;*****************************************************************************
;-----------------------------------------------------------------------------
; Retour au programme principal
; Réponse : 2 octets : "GO"
; puis renvoie la main au programme principal
;-----------------------------------------------------------------------------
commG
; tester si reçu "G"
; ------------------
xorlw "E"^"G" ; comparer avec commande "G"
btfss STATUS,Z ; tester si égalité
goto commErr ; non, alors commande inconnue

; envoyer message
; ---------------
movlw "G" ; charger "G"
call sendtemp ; envoyer
movlw "O" ; charger "O"
call send ; envoyer

Vous voyez que le bootloader renvoie « GO » pour confirmer le retour au programme de


l’application. Un simple reset permettra de revenir en mode bootloader.

Remarquez le test sur la commande. Si on n’a pas affaire à une commande « G », et qu’on
n’a pas non plus, par conséquence, été en présence d’une autre commande valide, on
exécutera une procédure d’erreur.
;*****************************************************************************
; REVENIR AU PROGRAMME PRINCIPAL *
;*****************************************************************************
;-----------------------------------------------------------------------------
; Remet les registres dans l'état où ils doivent être après un reset, puis
; rend la main au programme principal
;-----------------------------------------------------------------------------
sortir
bsf STATUS,RP0 ; passer en banque 1
IF (BPORT == PORTA) ; si PORTA
clrf ADCON1 ; ADCON1 dans l'état d'origine
ENDIF ; fin d'assemblage conditionnel
movlw 0xFF ; pour port en entrée
movwf BPORT ; remettre PORT en entrée

50
bcf STATUS,RP0 ; repasser banque 0
clrf PCLATH ; repointer en page 0
return ; retour au programme principal
Vous pourriez penser qu’un simple « return » suffirait à revenir au programme principal .
En fait, ceci reviendrait à ignorer deux problèmes.

Le premier est une conséquence de notre cahier des charges. Nous avons précisé en effet
que le programme n’avait pas besoin d’être écrit spécifiquement pour être chargé par un
bootloader.

Il en découle que le programme d’application suppose qu’il est exécuté après un reset du
PIC®, et donc que ses registres se trouvent dans l’état qu’ils sont supposés avoir après le dit
reset.

Or, nous avons placé la PINT en sortie, il convient donc de la remettre en entrée.

Le second problème est que notre programme a modifié PCLATH pour pointer sur la page
dans laquelle se trouve notre bootloader. Nous devons le remettre dans son état d’origine, à
défaut de quoi le premier saut de notre programme d’application s’effectuerais en direction de
la page de notre bootloader.

A ce moment de l’explication, je vous précise donc que le bootloader ne peut pas se


trouver à cheval entre 2 pages du PIC®. C’est la seule contrainte concernant sa localisation.
Si vous tentez de le faire, vous verrez des messages d’avertissement de changement de page
lors de l’assemblage.

Remarquez l’assemblage conditionnel concernant le PORTA, qui nous impose une ligne
supplémentaire pour remettre ACON1 à 0 si nous avons utilisé une pin de ce port comme pin
de transmission. Voici donc le 5ème octet supplémentaire dont nous avons déjà parlé au début.

Il nous reste, pour ce qui est du programme principal, à traiter le cas d’une commande
incorrecte :
;*****************************************************************************
; TRAITER COMMANDE ERRONNEE *
;*****************************************************************************
;-----------------------------------------------------------------------------
; Renvoie "ERR" en cas de commande erronée
; attend la fin de l'émission avant de répondre
; ON effectue 30 mesures à intervalles d'un demi-bit. Si toutes valident le
; repos, alors on peut répondre.
;-----------------------------------------------------------------------------
commErr
; attendre fin de réception
; -------------------------
movlw D'30' ; pour 30 lectures
movwf cmpt ; dans compteur
commerrl
clrwdt ; effacer watchdog
btfss PINT ; lire si pin entrée est au repos (=1)
goto commErr ; non, on recommence
movlw DUR1B/2 ; pour une tempo de +- un demi bit
call tempo ; attendre
decfsz cmpt,f ; décrémenter compteur de bits
goto commerrl ; pas dernière lecture, suivante

51
; répondre "ERR"
; --------------
comrep
movlw "E" ; charger "E"
call sendtemp ; l'envoyer
movlw "R" ; charger "R"
call send ; l'envoyer
movlw "R" ; charger "R"
goto lastsend ; envoyer, puis commande suivante

En cas d’erreur, on renverra à l’ordinateur la séquence « ERR », qui est choisie parce que
sa longueur est de 3 octets, et la distingue de ce fait de tout autre réponse valide. Ainsi, on
évite que le message d’erreur ne corresponde par accident à une autre réponse pouvant être
interprétée comme correcte.

Vous voyez que cette routine est composées de 2 parties. En effet, si on reçoit une
commande erronée, on ne peut pas savoir si l’utilisateur ne tente pas de passer des autres
octets suite à cette commande. Or, c’est la même pin qui sert pour l’émission et la réception.

Nous devons être certains que l’ordinateur a fini d’envoyer sa fausse commande, avant de
répondre, afin d’être certain que notre message d’erreur sera effectivement reçu par le PC.

On s’assure de ceci en vérifiant que la liaison série reste inactive pendant une durée
équivalant à la durée de 15 bits, ce qui est amplement suffisant.

C’est est fini du programme principal, voyons les sous-routines, et tout d’abord

Commençons par notre routine de temporisation :


;*****************************************************************************
; ROUTINE DE TEMPORISATION *
;*****************************************************************************
;-----------------------------------------------------------------------------
; La longueur de la temporisation est passée dans W, qui contient le nombre
; de boucles à effectuer. Ce nombre a été calculé par les directives en
; fonction des vitesses demandées et de la fréquence du quartz
;-----------------------------------------------------------------------------
tempo
movwf tmps ; sauver dans compteur
clrwdt ; effacer watchdog

tempol
i
WHILE i < BAUDRL ; tant que i < BAUDRL
nop ; ajouter nop
i+=1 ; incrémenter i
ENDW

decfsz tmps,f ; décrémenter compteur


goto tempol ; pas 0, recommencer
return ; sinon, return

Vous remarquerez la boucle « WHILE », qui ajoute à la boucle comprise entre WHILE
(tant que) et ENW (END WHILE) autant d’instructions « nop » que de valeurs précisées par
le paramètre « BAUDRL ». Vous voyez donc ici comment est utilisé ce paramètre.

52
Que dure l’exécution totale de cette boucle ? En effet, ceci est un paramètre important
pour expliquer les précédents calculs effectués dans nos directives initiales.
Le cœur de cette boucle est constitué des instructions suivantes :

tempol
nop ; un certain nombres de nop, éventuellement « 0 »
decfsz tmps,f ; décrémenter compteur
goto tempol ; pas 0, recommencer

Autrement dit, chaque boucle pour laquelle la valeur de tmps est >1 durera :

- 1 cycle par « nop » présent


- 1 cycle pour le decfsz (pas de saut)
- 2 cycles pour le goto (saut)

Le nombre de cycles total était donc de 3 + le nombre de « nop », soit « 3+BAUDRL »

Lors du dernier passage dans la boucle, lorsque tmps vaut 1, nous aurons :

- 1 cycle par « nop » présent


- 2 cycles pour le decfsz (car on saute, puisque 1-1 = 0)
- 0 cycle pour le « goto », qui est sauté et n’est donc pas exécuté.

Le nombre de cycles total est donc de « 2+BAUDRL » pour ce dernier passage.

Or, le cœur de notre formule de base était de la forme :

Nombre de boucles à attendre = nombre de cycles à attendre / (3+BAUDRL).

On considérait donc que chaque boucle durait (3+BAUDRL), alors que la dernière en dure
une de moins. Autrement dit, il nous faut effectuer une première correction de notre calcul.

Comme la temporisation dure un cycle de moins que prévu, nous devons attendre un cycle
de plus.

Nombre de boucles à attendre = (nombre de cycles à attendre + 1) / (3+BAUDRL).

Mais notre routine comporte également une partie d’initialisation :

movwf tmps ; sauver dans compteur


clrwdt ; effacer watchdog

qui nous consomme 2 cycles, ainsi que l’instruction de retour

return ; sinon, return

qui nous en consomme 2.

Autrement dit, la routine nous consomme 4 cycles de plus que prévu dans notre précédent
calcul, ce qui nous fait donc 4 cycles de moins à perdre dans la boucle. Notre calcul devient
donc :

53
Nombre de boucles à attendre = (nombre de cycles à attendre + 1- 4) / (3+BAUDRL).

Autrement dit :

Nombre de boucles à attendre = (nombre de cycles à attendre -3) / (3+BAUDRL).

Ceci représente le temps nécessaire pour exécuter la routine de temporisation et revenir au


programme d’appel. Examinons maintenant notre routine d’émission d’un octet :

;*****************************************************************************
; Envoi d'un octet *
;*****************************************************************************
;-----------------------------------------------------------------------------
; envoie l'octet contenu dans w - entrée normale = send
; on envoie en faisant passer en sortie, la pin étant bloquée sur 0
; ainsi, on évite les court-circuit par forçage à 1 de la pinT
; Si on entre par sendtemp, on attend d'abord la fin de la réception
; précédente avant de répondre (on sort de réception avant la fin du dernier
; stop-bit
;-----------------------------------------------------------------------------
sendtemp
movwf bbyte ; sauver octet à envoyer
movlw DUR1B5 ; pour durée d'un bit et demi
call tempo ; attendre
movf bbyte,w ; récupérer octet à envoyer

Nous sommes ici en présence du premier point d’entrée de notre routine. C’est celui qui
correspond au cas où nous venons de recevoir un octet de l’ordinateur. Comme je l’ai déjà
expliqué, il nous faut attendre un peu avant de répondre. On pouvait se contenter d’attendre
un demi-bit, j’ai choisi d’attendre un peu plus, par sécurité. Nous entrons maintenant dans la
réception classique :

; envoyer start-bit
; -----------------
send
movwf bbyte ; sauver octet à envoyer
bcf PINT ; pin = 0
bsf STATUS,RP0 ; passer en banque1
bcf PINT ; générer start-bit
movlw DUR1B ; pour durée d'un bit
call tempo ; attendre
movlw 0x08 ; 8 bits à envoyer
movwf cmpt ; dans compteur de bits
nop ; correction de timing

; envoyer 8 bits de data


; ----------------------
sendl
rrf bbyte,f ; lire bit poids faible
btfss STATUS,C ; tester si bit = 0
bcf PINT ; oui, envoyer 0
btfsc STATUS,C ; tester si bit = 1
bsf PINT ; oui, envoyer 1
movlw DUR1B ; pour durée d'un bit
call tempo ; attendre
decfsz cmpt,f ; décrémenter compteur de bits
goto sendl ; pas dernier, suivant

54
; envoyer stop-bit
; ----------------
nop ; attendre fin délai bit 7
nop
nop
bsf PINT ; passer en entrée = stop-bit
bcf STATUS,RP0 ; repasser banque 0
movlw DUR1B ; durée d'un bit
goto tempo ; pour longueur du stop-bit et retour

La première chose à vous faire remarquer, c’est que la pin est toujours à l’état « 0 ». On
génère les « 1 » et les « 0 » en la faisant respectivement passer en entrée et en sortie. Ceci
nous permet de ne jamais générer un niveau « 1 », celui-ci s’effectuant par la résistance de
rappel de l’interface. Ainsi, nous ne générerons jamais de court-circuit, comme expliqué lors
de l’étude de l’interface.

Cette méthode s’apparente donc à celle, en électronique, d’un collecteur ouvert, ne


pouvant forcer que le niveau « 0 ». Vous voyez que vous pouvez imiter un comportement
hardware uniquement en jouant sur le logiciel, il suffit d’avoir de l’imagination… et j’en ai 
Ici, les gestions de timing sont assez complexes, plus quelles n’en ont l’air. Je vais donc
vous les expliquer en détails. Il importe de commencer par la boucle centrale, afin de calculer
précisément le temps complet d’une boucle. Ce temps est celui séparant l’émission de 2 bits
consécutifs.

Je commence, pourquoi pas, par l’instruction d’appel de la routine de temporisation. Je


réécris ici la boucle centrale précédente en commençant par l’appel de la routine de
temporisation :

call tempo ; 2 cycles en plus de la tempo (saut)


decfsz cmpt,f ; 1 cycle, car pas de saut
goto sendl ; 2 cycles, on revient en début de boucle

sendl
rrf bbyte,f ; 1 cycle
btfss STATUS,C ; toujours 2 cycles pour l’ensemble de ces 2
bcf PINT ; instructions
btfsc STATUS,C ; encore 2 cycles pour ces 2 instructions
bsf PINT ;
movlw DUR1B ; 1 cycle

Si nous faisons le total, cette boucle nous consomme 11 cycles, qu’il faudra déduire du
temps à attendre entre l’émission de 2 bits. Si nous reprenons notre formule :

Nombre de boucles à attendre = (nombre de cycles à attendre -3) / (3+BAUDRL).

Nous voyons que nous devons encore soustraire 11 cycles du temps à attendre, soit :

Nombre de boucles à attendre = (nombre de cycles à attendre -14) / (3+BAUDRL).

Vous voyez maintenant d’où provient ce fameux « -D ‘14’ » de notre calcul de


temporisation.

55
Revenons en arrière, pour voir ce qui se passe pour l’émission du start-bit. Ce start-bit est
caractérisé par la mise à « 0 » de la pint. Ce start-bit doit durer également le même temps
qu’un bit classique.
On ne remarquera la fin du start-bit que si le bit suivant est à « 1 », sans quoi, « 0 » suivi
de « 0 » ne se remarquera pas. Voyons donc le temps que va durer notre start-bit :

bcf PINT ; ici, la ligne passe à 0


movlw DUR1B ; 1 cycle écoulé
call tempo ; 2 cycles + tempo
movlw 0x08 ; 1 cycle
movwf cmpt ; 1 cycle
nop ; 1 cycle

; envoyer 8 bits de data


; ----------------------
sendl
rrf bbyte,f ; 1 cycle
btfss STATUS,C ; 2 cycles
bcf PINT ; 0 cycle (sauté)
btfsc STATUS,C ; 1 cycle
bsf PINT ; la pin sera mise à 1 ici : 1 cycle nécessaire

Soit, un total de 11 cycles en plus de la routine de temporisation, soit exactement le temps


séparant l’émission de 2 bits calculé précédemment. Evidemment, le « nop » ajouté dans cette
routine est bel et bien là pour effectuer cette correspondance.

Le dernier bit doit également présenter la même durée, avant de générer le stop-bit.

L’émission du dernier bit ne provoquera pas le bouclage de la boucle centrale. Le stop-bit


est le passage à « 1 » de la pint. Autrement dit, si le dernier bit était à « 1 », on ne verra pas la
transition. Comptons donc le temps séparant le dernier bit, si celui-ci vaut « 0 » du stop-bit.

bcf PINT ; on génère le dernier bit à 0 : prend un cycle


btfsc STATUS,C ; 2 cycles
bsf PINT ; 0 cycle
movlw DUR1B ; 1 cycle
call tempo ; 2 cycles + tempo
decfsz cmpt,f ; 2 cycles (on saute)
goto sendl ; 0 cycle

; envoyer stop-bit
; ----------------
nop ; 1 cycle
nop ; 1 cycle
nop ; 1 cycle
bsf PINT ; ici, on génère le stop-bit

De nouveau, le dernier bit dure 11 cycles + la durée de la tempo, donc un temps


strictement identique aux précédents. Les « nop » sont de nouveau là pour corriger le timing.

Remarquez que si le dernier bit valait « 1 », le calcul serait strictement identique.


Simplement, le bit aurait été positionné à 1 un peu plus tard, et durerait un tout petit peu
moins longtemps, mais cela ne se remarquerait pas, puisque la transition entre dernier bit et
stop-bit serait invisible. L’important c’est qu’il n’y ai pas d’erreur cumulative.

56
Reste à déterminer le temps du stop-bit en lui-même, qui doit durer, au minimum le temps
d’un bit.

bsf PINT ; stop-bit : nécessite 1 cycle


bcf STATUS,RP0 ; 1 cycle
movlw DUR1B ; 1 cycle
goto tempo ; 2 cycles + tempo

Vous allez me dire : il n’y a que 5 cycles au lieu de 11. En fait, pas du tout. Le stop-bit ne
prendra fin qu’au moment de la génération du start-bit suivant. Remarquez le « goto temp »
au lieu du « call tempo », suivi de « return ». Cela revient au même mais économise une
instruction. On économise également un niveau de sous-routine, mais ceci n’a aucune
importance ici.

Revenons à notre stop-bit : Après la temporisation, notre routine de tempo revient à notre
routine qui a appelé l’émission de l’octet.

Soit c’était le dernier octet, et dans ce cas, notre stop-bit durera plus que nécessaire, soit ça
ne l’est pas, et on devra charger l’octet suivant avant de l’envoyer. On trouvera donc une
séquence du style :

movf car2,w ; 1 cycle


call send ; 2 cycles

Ce qui nous donne encore 3 cycles supplémentaires. On en arrive donc à 8. Il nous faut
encore entrer dans la routine d’envoi, qui va effectuer les opérations suivantes avant de
commencer l’envoi du start-bit suivant :
send
movwf bbyte ; 1 cycle
bcf PINT ; 1 cycle
bsf STATUS,RP0 ; 1 cycle
bcf PINT ; générer start-bit (prend un cycle)

Ceci nous consomme donc encore 4 cycles supplémentaires, portant le total à 12. Notre
stop-bit respecte donc le temps minimal qui lui est imparti. Vous voyez qu’il faut vraiment
penser à tout quand on décide de gérer soi-même les liaisons série.

Utiliser l’USART vous obligeait à recourir à une pin bien précise pour le bootloader, ce
qui était en contradiction avec mon cahier des charges. C’était cependant bien plus simple,
mais, de toute façon, c’est moi qui ai fait le boulot, pas vrai ?

Il nous reste à voir la routine de réception d’un octet :

;*****************************************************************************
; Réception d'un octet *
;*****************************************************************************
;-----------------------------------------------------------------------------
; Reçoit un octet, le retourne dans w et dans bbyte
;-----------------------------------------------------------------------------
receive
clrwdt ; effacer watchdog
btfsc PINT ; pin réception = 0?
goto $-2 ; non, attendre
movlw DUR1B5 ; pour durée de 1.5 bit
call tempo ; attendre

57
movlw 0x08 ; pour 8 bits
movwf cmpt ; dans compteur de bits

recl
bcf STATUS,C ; par défaut, bit = 0
btfsc PINT ; bit reçu = 1?
bsf STATUS,C ; oui, positionner carry
nop ; pour correction du temps
rrf bbyte,f ; faire entrer bit reçu
movlw DUR1B ; pour durée de 1 bit
call tempo ; attendre
decfsz cmpt,f ; décrémenter compteur de bits
goto recl ; pas dernier, suivant
movf bbyte,w ; charger octet reçu
return ; fini, retour
END

Je ne vous recommence pas toute la démonstration, faites-la si vous le voulez. Concernant


l’instant exact de l’arrivée du start-bit généré par l’ordinateur, elle s’effectue quelque part
dans cette routine :

clrwdt ; effacer watchdog


btfsc PINT ; pin réception = 0?
goto $-2 ; non, attendre

Autrement dit, on prendra un compromis entre temps minimum et temps maximum


séparant l’instant présumé du start-bit et la lecture du premier bit. Il s’agit d’une erreur
absolue et non cumulative, qui ne pose pas de problème dans la pratique.

Remarquez avec plaisir la directive « END » qui indique que votre calvaire est fini, du
moins si vous avez pris la peine de chercher à comprendre, ce dont je ne peux que vous
féliciter.

Nous allons maintenant passer à la mise en pratique de tout ceci.

58
6. Mise en pratique hardware

Je vais partir d’un petit montage destiné à faire clignoter une LED. Pour ceci, je reprends
un exemple précédent, led_tmr0.asm, dont je vous fournis le source et le fichier « .hex » tel
qu’assemblé dans le précédent livre.

Il convient de commencer par établir notre schéma de travail, en tenant compte de l’accès
au bootloader sur une pin de notre choix.

Je choisis arbitrairement la pin RB7, étant entendu que le programme de destination


n’utilise que la pin RA2 pour faire clignoter la LED. La double utilisation d’une pin n’est
donc pas d’application, car il reste des pins inutilisées sur le PIC®, autant donc utiliser une de
celles-là.

Commençons par revoir le schéma que nous avions retenu pour ce montage, avant que
nous ne décidions d’utiliser le bootloader :

En sommes, un montage des plus classiques. Que faire pour le rendre compatible avec notre
bootoloader?

Presque rien, en définitive :

- Remplacer la liaison directe de mclr au +5V par une résistance.

- Placer la résistance de rappel à la masse sur la pin de transmission

- Ajouter des pins de connexion ou des petits connecteurs pour permettre l’accès aux pins
Mclr, Vss,Vdd, et RB7. En sommes, rien qu’une petite “pinoche” sur le circuit, si vous ne
voulez pas placer un connecteur spécifique, la liaison s’effectuant alors à l’aide de petites
pinces “grip-fil”.

L’idéal, pour une réalisation “pro”, est cependant de prévoir un petit connecteur, qui vous
évitera les erreurs de branchement.

59
N’oubliez pas, si vous avez mis en service les résistances de rappel au +5V pour le
PORTB, d’en tenir compte lors du calcul de la résistance de rappel de la pin de transmission,
ou de choisir une autre pin, ce que je vous conseille. Ce ne sera pas le cas ici.

Voyons donc ce que ceci nous donne :

Autrement dit, en termes de composants, le supplément se limite à 2 résistances.

Concernant les connexions, si on excepte l’alimentation, toujours disponible quelque part,


2 pins de connexion sont simplement nécessaires. La connexion entre les pins 1 et 3 de
l’interface du bootloader pouvant s’effectuer directement par un pontage sur le connecteur
relié à vos sondes destinées à la carte d’application.

Afin de bien visualiser l’ensemble, voici ce que cela donne de façon schématique :

60
Et voilà : une alimentation, et 2 fils suffisent pour utiliser le bootloader sur votre platine,
sans plus jamais devoir démonter votre PIC® de son circuit d’application.

61
Notes : …

62
7. Utilisation pratique du bootloader

7.1 Introduction

Nous avons maintenant notre circuit d’application et notre interface bootloader. Avant de
pouvoir définitivement placer notre PIC® sur notre platine d’application, il nous faudra, une
et une seule fois, la programmer avec un programmateur classique.

7.2 Customisation du bootloader

Je conserve ce terme anglais, car il est bien plus explicite que tout terme français
équivalant. Et puis, je suis Belge, et en Belgique, nous n’avons pas de loi imposant la
francisation de tout terme anglais. Je ne vais donc pas me gêner…

Customisation, donc, ai-je dit. Pourquoi ?

Tout simplement parce que nous allons devoir adapter notre programme de bootloader à
l’application particulière à laquelle il va être lié.

Dans ce cas particulier, nous n’aurons rien à faire, mais c’est parce que j’ai choisi
d’utiliser l’application avec laquelle j’ai mis au point le bootloader. Il est donc
automatiquement adapté à cette application.

Néanmoins, ceci ne sera pas toujours le cas, ce qui impliquera de vérifier et modifier le
bootloader en fonction de votre application. Vous allez voir cependant que ceci est
extrêmement simple.

La bonne méthode est d’effectuer un copier/coller du fichier « bgboot.asm » et de


renommer cette copie avec un nom explicite : « boot_led .asm » par exemple.

Nous allons maintenant créer un nouveau projet, pour le fichier « boot_led.asm » qui sera
le bootloader spécifique à l’application concernée.

Une fois fait, ouvrons notre fichier d’application (Led-tmr0.asm). La configuration du


programme d’application devra être, je vous le rappelle, celle du programme de bootloader.
Cette directive est :

__CONFIG _CP_OFF & _DEBUG_OFF & _WRT_ENABLE_OFF & _CPD_OFF & _LVP_OFF &
_BODEN_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC

Remplacez la ligne _CONFIG du bootloader par celle de votre application.

Notez que si vous n’avez pas le source, cela n’a aucune importance, la configuration sera
visible une fois le fichier « .hex » chargé avec un programme comme IC-Prog (http://www.ic-
prog.com), ou alors le propriétaire du fichier vous aura fourni les directives.

Dans le cas contraire, de toute façon, même avec un programmateur classique, vous serez
dans le même embarras.

63
Nous allons maintenant vérifier s’il n’existe pas d’incompatibilité avec le bootloader. La
principale étant la présence d’une directive de protection de la zone du programme, du style
« CP_ALL ». Souvenez-vous que vous ne pouvez pas protéger la zone que vous désirez
mettre à jour à l’aide du bootloader.

Une protection partielle peut être envisagée, à condition d’être conscient que la partie
située dans la zone protégée ne pourra pas être modifiée avec le bootloader.

Dans ce cas-ci, aucune incompatibilité n’est à craindre, puisque le PIC® n’est pas protégé.

La seconde chose est que vous devez toujours indiquer « WRT_ENABLE_ON ». En


effet, « WRT_ENABLE_OFF » empêche toute écriture en mémoire flash. Vous devrez donc
modifier ce bit obligatoirement.

Un oubli à ce niveau engendrera ainsi une erreur de vérification à chaque tentative


d’écriture.

Le plus compliqué est fait. Eh oui, rien de bien difficile. Il nous suffit maintenant de
vérifier si les paramètres par défaut nous conviennent dans le bootloader, et, sinon, les
modifier. Pour rappel, ici :

;FQUARTZ EQU D'20000000' ; fréquence quartz


;BAUDR EQU D'19200' ; débit en bauds
;BAUDRL EQU D'0' ; Permet de diminuer le taux d'erreur
; Augmente la taille du programme
; conserver la plus faible valeur
; possible. Ne pas dépasser D'5'
;ADR EQU 0x1800 ; adresse forcée de départ de la routine
;TAILLEMAX EQU 0x2000 ; taille maximale du programme

- La fréquence du quartz , 20Mhz, nous convient, inutile de la changer.

- Le débit de 19200 bauds sera très bien également. Rien à changer

- BAUDRL ne sera changé qu’en cas de message d’erreur explicite. Attendons


l’assemblage.

- Inutile de changer ADR, le bootloader casé en fin de mémoire programme est l’endroit le
plus approprié, et nous économise de l’espace mémoire.

- Nous utilisons un PIC16F876, la taille mémoire flash est bien de 0x2000. Pas de
problème.

Ne reste qu’à lancer l’assemblage, nous recevons les messages suivants :

Message[301] chemin\ boot_led.asm 165 : MESSAGE: (Fréquence de 20 Mhz prise par


défaut)

Message[301] chemin\ boot_led.asm 170 : MESSAGE: (Débit de 19200 bauds pris par
défaut)

Message[301] chemin\ boot_led.asm 201 : MESSAGE: (La routine de boot se trouve


en fin de page 3)

64
Autrement dit, rappel des valeurs par défaut, tout s’est bien passé, inutile de changer
BAUDRL ni BAUDR.

Programmez le PIC® avec le fichier « .hex » obtenu et placez le PIC® sur la platine
d’application. Il ne sera plus jamais utile de l’ôter (dans le cas d’une application réelle).

65
Notes : …

66
8. Utilisation pratique de BIGOPIC light

8.1 Installation du logiciel

La première chose à faire est d’aller charger, si ce n’est déjà fait, l’utilitaire « BIGOPIC
light » présent sur mon site : http://www.abcelectronique.com/bigonoff

Il s’agit d’un petit programme que j’ai développé pour vous, afin de permettre la
communication avec le bootloader. Il contient également d’autres fonctions, relatives au
debugger, et que nous verrons plus tard.

Malheureusement, ce programme est écrit pour Windows. Je manque de temps pour le


développer pour une autre plate-forme.

L’idéal serait de le réécrire en java, il serait ainsi multi plates-formes. Si cette aventure
vous intéresse, contactez-moi, je vous fournirais tout ce dont vous avez besoin pour réaliser ce
programme, afin qu’il soit ensuite librement accessible à tous. Il m’est en effet impossible, par
manque de temps, de tout faire tout seul, vous pouvez le comprendre.

La version de BIGOPIC light que je vais utiliser ici est la version 1.0. Lorsque vous lirez
cet ouvrage, une nouvelle version sera peut-être en ligne, ce qui pourrait expliquer quelques
différences éventuelles dans les captures d’écrans et les explications. Je présume que ceci ne
devrait pas poser de problèmes insurmontables.

Une fois en possession des fichiers décompactés, il vous suffit de lancer « setup.exe »
pour vous retrouver avec le programme BIGOPIC light disponible depuis votre menu
démarrer.

Il n’y a pas d’aide pour ce programme, car cette aide est constituée par le présent
document. Je vais donc vous expliquer en détails les différentes procédures.

8.2 Premier lancement de BIGOPIC light

La première chose à savoir, c’est qu’à la fermeture du programme, un fichier


« BIGOPICL.cfg » est enregistré dans le répertoire du logiciel, qui est, par défaut,
« c:\program files\BIGOPIC ».

Tous vos paramètres sont enregistrés dans ce fichier, dernier mode utilisé, langue, tailles
et positions des différentes fenêtres, chemins vers les fichiers, etc.

Si vous souhaitez revenir aux paramètres par défaut, tels qu’expliqués ici, il vous suffira
de fermer le programme, et d’effacer le fichier « BIGOPICL.cfg ». Le prochain redémarrage
de BIGOPIC light s’effectuera avec les paramètres par défaut.

Assez de paroles, alimentez votre montage, puis lancez le programme, à partir du menu
démarrer. Vous voici alors en présence de la fenêtre suivante :

67
Vous vous trouvez par défaut en mode « DTRA », pour « Debugger Temps Réel Ascii ».
Il s’agit ni plus ni moins d’un programme de dialogue en ascii pour communiquer entre le
PIC® et le PC.

En fait, c’est l’équivalant du programme « BSCP » que vous avez vu dans la seconde
partie du cours. La différence étant que ce programme est spécifiquement conçu pour piloter
l’interface BIGOPIC, que celui-ci soit réalisé à partir d’un max232, BIGOPIC2 (auquel cas il
gère le reset), ou à partir des 3 opto-coupleurs, BIGOPIC1 (auquel cas il gère le reset et
l’alimentation).

Je fais l’impasse sur ce mode ici, car nous en reparlerons au moment de l’étude du
debugger ASCII.

Vous avez la possibilité de travailler en anglais, en choisissant votre langue dans le menu
préférences.

La première chose à faire, est de configurer le port série en fonction de votre


configuration. Cliquez donc sur la seconde petite icône de la barre d’outils, celle représentant
une fiche DB9 avec un point d’interrogation.

Désolé, le dessin est loin d’être mon point fort, aussi, il faudra vous contenter de ces
icônes. La fenêtre suivante apparaît :

68
Le bootloader, comme nous l’avons vu, utilise toujours 8 bits de données, et un stop-bit. Il
ne gère pas la parité. J’ai cependant permis la modification de ces paramètres, ainsi vous
pourrez utiliser ce programme pour toutes vos applications personnelles.

Vous choisirez donc uniquement votre numéro de port série. Le débit de 19200 bauds
étant celui par défaut du bootloader (que nous avons conservé), de même que celui de
BIGOPIC light.

Cliquez « Accepter » pour valider votre choix. Vous n’aurez à faire cette opération qu’une
seule fois, les paramètres du port série faisant évidemment partie de ceux sauvegardés dans le
fichier de configuration.

Par curiosité, et pour vérifier que tout fonctionne bien, nous allons lancer notre port série,
en cliquant sur la première icône de la barre d’outils, représentant 2 fiches DB9 disjointes.
Ces fiches sont maintenant jointes, indiquant que le port série est en service.

Nous allons maintenant provoquer un reset, en cliquant sur l’icône représentant une fiche
DB9 accompagnée d’un grand « R » rouge.

Si tout s’est bien passé, vous avez maintenant un message dans la fenêtre de droite,
intitulée « Depuis le PIC® ». Ce message est BGB accompagné de plusieurs caractères non
alphabétiques, dont plusieurs sont même invisibles. Si vous n’avez rien obtenu, vérifier
interface et connexions.

Si tout se passe comme prévu, vous savez déjà que votre bootloader est bien chargé, qu’il
fonctionne, que votre PIC® tourne, que votre interface BIGOPIC1 ou BIGOPIC2 reçoit, et
que le reset fonctionne. Félicitations.

En fait, si vous vous souvenez, le bootloader du PIC® a envoyé, au reset, la séquence


« BGB » en ascii, suivie de la position du bootloader et de sa taille. Or, le mode DTRA tente

69
de tout afficher en ASCII . Comme position et taille ne sont pas forcément des caractères
ascii, il est normal de ne pas pouvoir tout visualiser.

8.3 Passage en mode bootloader

Après cette sommaire vérification, il est temps maintenant de passer dans le mode
bootloader qui nous intéresse.

Choisissez « Téléchargement (Bootloader) » dans le menu « Mode ».

70
Nous voici dans une fenêtre qui ressemble beaucoup à celles qu’on rencontre dans les
programmes de programmateurs.

En fait, c’est logique, puisqu’il s’agit ici de remplir la même fonction. Notez que les 2
dernières icônes de la barre d’outils sont maintenant opérationnelles.

La fenêtre principale est librement redimensionnable, les 2 fenêtres internes le sont


uniquement en hauteur et en position, leur largeur est fixe.

Les fenêtres intérieures représentent le contenu de ce que vous allez envoyer dans le
PIC®. Il ne s’agit pas du contenu du PIC®, mais bien de ce que vous allez envoyer.

A ce niveau, ceci diffère d’un programmateur classique. Pour ce dernier, toute adresse non
utilisée sera effacée, et aura donc le contenu 0x3FFF (regardez IC-Prog pour vous en
convaincre).

Ici, au contraire, vous avez 3 possibilités :

- Soit l’emplacement mémoire est représenté par des « - », et dans ce cas, l’emplacement de
destination ne sera pas affecté

71
- Soit l’emplacement mémoire est représenté par « 3FFF », et dans ce cas, l’emplacement
de destination sera effacé

- Soit on a une valeur quelconque, qui sera envoyée au PIC®.

La fenêtre supérieure représente la mémoire flash du PIC® et la fenêtre inférieure la


mémoire eeprom.

Chacune de ces 2 fenêtres est séparée en 3 zones, en se souvenant que tous les nombres
sont représentés en notation hexadécimale :

- En bleu, à gauche, l’adresse concernée

- Au centre, la valeur, qui passe en vert si vous l’avez modifiée manuellement

- A droite, la représentation ASCII de la valeur correspondante, à condition que cette


représentation existe. Dans le cas contraire, un point sera affiché.

Vous pouvez vous exercer à écrire des valeurs dans la fenêtre flash et dans la fenêtre
eeprom. Le programme surveille en permanence votre saisie, et vous empêche d’entrer une
valeur incorrecte. Par exemple, vous ne pouvez entrer une valeur supérieure à 3FFF dans la
mémoire flash.

Les touches « del » et « backspace » permettent d’effacer le contenu de la mémoire


concernée, qui ne sera donc pas envoyée au PIC®.

Dans la fenêtre « eeprom », vous pouvez entrer directement des caractères ascii en
utilisant la touche « tabulation ».

72
Vous voyez que toutes les modifications sont inscrites en vert à l’emplacement des
données.

Les zones représentées le sont pour des PIC® qui comportent 8Ki mots de mémoire
programme et 256 octets de mémoire eeprom. Si vous utilisez des PIC® plus petits, il suffit
de ne pas utiliser manuellement ces zones.

Lors du chargement d’un fichier « .hex », les dites zones ne seront d’ailleurs pas utilisées,
n’entraînant pas d’erreur au niveau du programme. Il est donc automatiquement universel, au
contraire des programmateurs classiques.

8.4 Chargement d’un programme d’application

Nous allons maintenant charger notre programme d’application, « Led_Tmr0.hex »,


destiné à notre application. Ceci effacera bien évidemment les modifications manuelles que
nous venons d’effectuer. Il restera cependant possible d’effectuer des modifications manuelles
une fois le fichier réel téléchargé.

Cliquez sur la 4ème icône, qui représente un dossier ouvert. Cherchez après votre fichier
« Led-tmr0.hex » et chargez-le.

73
Le programme effectue une vérification du format du fichier et vous signale en détail tout
type d’erreur possible (format incorrect, mauvaise longueur, checksum etc.). Ceci peut être
utile si vous avez l’habitude de bricoler manuellement vos fichiers « .hex ».

Une fois chargé, les fenêtres précédentes vous indiquent la représentation du contenu de
votre fichier « .hex ».

Vous voyez que la fenêtre inférieure est vide, et c’est logique, puisque notre programme
ne contient aucune directive d’initialisation de la zone eeprom.

La fenêtre mémoire programme est très instructive. Ce que vous y voyez est en fait la
représentation hexadécimale des instructions que nous allons envoyer dans notre PIC®.

Remarquez qu’à l’adresse 0x00, nous avons 0x2891. Si vous vous souvenez de ce que
nous avons déjà vu, il s’agit d’un saut (goto). En réalité, c’est le « goto init » de notre
programme d’application.

Effectivement, il n’a pas été écrit en tenant compte du bootloader, mais vous allez voir
que cela ne pose aucun problème.

74
A la suite, nous avons 3 instructions vides. On peut donc directement en tirer comme
conclusion qu’un fichier « .hex » ne contient que les adresses qui sont effectivement utilisées,
les autres ne sont pas remplies par des « 0 », ni pas des « 3FFF », elles sont tout simplement
inexistantes. Notre programme en tient évidemment le plus grand compte.

En voyant la structure de début du programme, on en déduit qu’il doit être de la forme :

ORG 0x00
goto init

ORG 0x04
Début de la routine d’interruption.

Dans ce cas, effectivement, les adresses 0x01 à 0x03 sont inutilisées.

8.5 Résolution des conflits

Plus on avance, plus on arrive aux points sensibles. Nous allons passer à l’étape suivante,
en cliquant sur l’icône représentant un fichier avec une flèche pointant vers le PIC®. J’espère
que l’icône est suffisamment parlante.

Notez que pour pouvoir passer dans ce mode, il faut 2 conditions :

- Le port série doit être ouvert

- Il doit au moins y avoir une valeur dans une des deux fenêtres.

Dans le cas contraire, un message d’erreur vous rappellera à l’ordre.

75
Si, au lieu d’avoir cette fenêtre, vous avez un message d’erreur, vérifiez interface et
montage.

Cette fenêtre est la représentation graphique du contenu de votre PIC®. Vous trouvez ici
énormément de renseignements.

Tout au dessus, en bleu, vous avez un message qui vous avertit que le bootloader a bien
été trouvé, et qu’il est compatible avec celui que je vous ai fourni. En bref, ceci signifie que le
PIC® a bien envoyé la séquence « BGB » suivie de la position et de la taille de la routine
bootloader intégrée dans le PIC®.

Suit l’information précisant les emplacements utilisés par le bootloader. Dans notre cas, 2
zones :

- La zone 0x00 à 0x02, qui contient le saut vers le programme bootloader

- La zone 0x1F28 à 0x1FFF, qui contient la routine bootloader.

Ceci vous indique donc que :

- Le bootloader est présent


- Les vitesses de transmissions sont bien celles paramétrées
- Il est situé en fin de page 3 de la mémoire
- Il occupe 216 octets en plus des 3 octets de saut (0x1FFF+1-0x1F28)

76
Directement dessous, nous avons la légende des couleurs des LEDs :

- Les Leds en vert représentent une zone occupée par des données à envoyer au PIC®.

- Une LED orange indique une zone contenant des instructions bootloader et des
instructions du programme d’application, mais à des emplacements différents.

- Une LED rouge indique qu’un même emplacement mémoire contient une instruction
bootloader et une instruction du programme d’application, ce qui est impossible.

La LED orange s’explique parce que chaque LED de la mémoire programme représente
32 adresses de mémoire. Autrement dit, on peut avoir, dans la zone de 32 emplacements,
différents types de donnée, sans qu’il n’y ai conflit. Nous allons d’ailleurs voir tout ceci.

Voyons la zone intitulée « flash ». La première chose à remarquer, c’est que vous avez 4
rangées de Led, contenant chacune 64 LED. Chaque rangée représente donc une page de
mémoire. Vous pouvez donc instantanément visualiser les pages utilisées par votre
programme.

Vous voyez 3 types de LEDs dans notre cas :

- Une LED rouge, qui indique un conflit d’adresse dans les 32 premiers emplacements de
mémoire programme. C’est logique, il s’agit de notre « goto init » qui interfère avec la
directive « PAGESEL » de notre bootloader

- Des LEDs vertes, qui représentent chacune 32 emplacements de mémoire programme


utilisés par notre programme d’application. Vous voyez que ce programme est
ridiculement petit comparé à la place disponible.

- Des LEDs bleues, qui représentent la place occupée par notre bootloader. Vous voyez que
je vous ai laissé suffisamment de place pour écrire un beau programme.

Maintenant, nous allons voir que ces indicateurs sont également interactifs. Nous voulons
savoir quelles sont les zones qui posent problème. Pour ceci, nous avons plusieurs méthodes.

Cliquez sur le texte sur fond rouge « superposition » :

77
Vous savez maintenant avec précision quelles adresses posent problème. Dans notre cas,
nous n’en avons qu’une, tant mieux. Cliquez <OK> pour fermer cette fenêtre.

Vous pouvez aussi avoir le détail d’une zone représentée par une led. Cliquez donc sur la
LED rouge, pour voir ce que contiennent les adresses 0x00 à 0x01F (32 adresses).

Le menu déroulant permet d’explorer toute la zone. Vous voyez qu’à l’adresse 0x00, vous
avez un conflit entre bootloader et programme.

Aux adresses 0x00 à 0x02 se trouvent le saut vers la routine bootloader, à l’adresse 0x00
le saut vers le début du programme d’application, lequel se poursuit à partir de l’adresse 0x04
(routine d’interruption)

Vous avez de la sorte la représentation détaillée du contenu de la zone représentée par une
LED.

Vous pouvez également cliquer sur la zone texte « données à envoyer » pour savoir les
emplacements concernés par le programme d’application :

78
Vous voyez que notre programme occupe l’emplacement 0x00, puis les emplacements de
0x04 à 0xB4 inclus. Vous aviez les mêmes informations en regardant la fenêtre de
représentation hexadécimale de la mémoire flash. Fermez la fenêtre en cliquant sur <OK>

Voyons maintenant la méthode de vérification la plus efficace. Cliquez sur le bouton


<Vérifier> situé en haut à droite dans la zone des boutons :

Ici, non seulement le programme vous indique qu’il s’agit bien d’une instruction
« goto », mais également vous propose de résoudre le problème. Cliquez donc sur <Oui>.

Le problème est résolu. Cliquez sur <OK> pour fermer la fenêtre, et la suivante, qui vous
indique qu’il n’y a pas d’autre problème. Vous constatez maintenant que la LED rouge est
devenue orange. Cliquez dessus pour vérifier ce qui s’est passé.

Vous constatez que l’adresse de saut du programme principal, qui se trouvait à


l’adresse 0x00 a été déplacée à l’adresse 0x03, où elle ne pose plus le moindre problème,

79
et continue d’être prise en compte dès le retour de la routine de bootloader. On en revient
donc à notre ordinogramme de traitement du démarrage du programme.

Fermez cette fenêtre, puis cliquez sur <Quitter> pour revenir provisoirement à notre
fenêtre de contenu du fichier « .hex ».

Vous constatez que notre instruction « 0x2891 » a bien été déplacée à l’adresse 0x03.
Le programme est maintenant compatible avec notre bootloader.

8.6 Effacement des anciennes données

Retournez maintenant à la fenêtre d’envoi.

Nous avons vu que notre programme n’envoyait au PIC® que les données explicitement
présentes dans le fichier « .hex », ou celles qui ont été ajoutées manuellement par l’utilisateur.

Or, ceci n’efface pas d’éventuelles données qui se trouvent ailleurs dans le PIC®, et dont
vous désirez peut-être vous débarrasser avant d’envoyer un nouveau programme.

80
Je vous ai donné accès à cette possibilité, sous forme de 2 boutons. Un pour l’effacement
intégral de la mémoire flash, et un autre pour celui de la mémoire eeprom.

Concernant l’effacement de la mémoire flash, il va de soi que le programme ne tente pas


d’effacer la zone contenant le bootloader. Ceci est d’ailleurs impossible, le bootloader lui-
même vérifiant, nous l’avons vu, que vous ne tentez pas de nuire à son intégrité. Cela se
traduirait donc par un message d’erreur renvoyé par ce dernier.

L’effacement de la mémoire programme revient à envoyer des valeurs 0x3FFF dans tout
emplacement non occupé par le bootloader. Pour ce qui est de la mémoire eeprom, on enverra
0xFF dans tous les emplacements.

Si vous utilisez un PIC® avec une taille inférieure à celle d’un 16F876, vous aurez une
erreur de vérification à la première adresse rencontrée non présente dans le PIC®.
L’effacement s’arrêtera alors à cette valeur.

Vous allez me dire : « Et si je ne veux effacer qu’une partie ? ». Je vous répondrai bien
« vous êtes exigeants, puisqu’un programmateur classique ne le permet pas ».

Mais, en fait, vous avez cette possibilité très facilement. Il vous suffit d’écrire
des « 3FFF » dans tous les emplacements de la mémoire flash et des « FF » dans tous les
emplacements de la mémoire eeprom, que vous voulez effacer.

Ainsi, inutile de cliquer sur les boutons <effacer>, les emplacements seront
automatiquement effacés au moment de l’envoi des données vers le PIC®, puisque ces
emplacements ne seront plus considérés comme emplacements non utilisés.

BIGOPIC light fait donc parfaitement la différence entre une donnée non utilisée,
représentée par des tirets, et un emplacement à effacer, représenté par sa valeur 0x3FFF pour
la mémoire flash, ou 0xFF pour la mémoire eeprom. Ceci vous laisse une très grande liberté
d’action.

Effaçons donc la zone flash à titre d’essai. Cliquez donc sur <Effacer flash>.

Les LEDs s’allument progressivement en blanc, vous signalant l’avancée de l’opération.

Chaque Led représente 32 emplacements, alors que pour la zone eeprom, chaque led ne
représente qu’une seule adresse. Ceci explique pourquoi l’effacement eeprom semblera plus
rapide.

81
A tout moment, vous pouvez stopper l’opération avec le bouton <Stop>. N’oubliez pas
d’économiser votre mémoire flash. Inutile donc de passer son temps à effacer sans arrêt
inutilement.

Une fois dépassée la zone que vous désirez effacer, cliquez <Stop>, ou laissez poursuivre
l’effacement jusqu’au début.

Fermez cette fenêtre, et passons au but de tout cet ouvrage.

8.7 L’envoi de notre premier programme

Bon, nous avons vu toutes les facettes de BIGOPIC light en mode bootloader, sauf la plus
intéressante, l’envoi du programme vers le PIC®.

82
Cet envoi est scindé en 2 parties, l’envoi des instructions en mémoire flash, et l’envoi des
données en mémoire eeprom. Dans notre cas, nous n’avons pas de données à envoyer en
mémoire eeprom. Cliquez donc sur <envoyer flash>.

Au fur et à mesure de la programmation, les LEDs s’allument en jaune, signalant


l’évolution du transfert.

BIGOPIC light vérifie, pour chaque instruction envoyée (ou groupe de 4 instructions pour
le cas des 16F87xA, l’adresse retournée, et la valeur effectivement relue en mémoire flash.

Autrement dit, si BIGOPIC vous indique que tout s’est bien passé, c’est que votre
programme est effectivement correctement écrit dans votre PIC®.

83
Fermez la fenêtre, et félicitez-vous : vous venez de charger votre premier programme en
utilisant la technique du bootloader. Je suis certain que vous ne pourrez plus vous en passer.

8.8 Lancement du programme chargé

Il nous reste à lancer le programme chargé dans le bootloader. Vous avez 2 méthodes,
suivant qu’il s’agisse d’un chargement sur une platine opérationnelle, ou sur une platine en
cours de développement.

Pour une platine opérationnelle, sur laquelle vous venez de charger une nouvelle version
de votre programme, il est temps de débrancher l’interface, et d’effectuer un reset du
montage, après avoir éventuellement repositionné les jumpers dans la position d’une
application réelle.

Lorsque vous développez une application, en cours de tests, il n’est pas pratique de devoir
déconnecter sans arrêt le bootloader. Pour votre confort, j’ai donc ajouté une fonction sous
forme d’un bouton <Démarrer programme PIC®> qui vous permet de lancer l’application
tout en laissant l’interface connectée.

Cliquez ce bouton :

Votre programme est lancé. Un coup d’œil vous permettra de vous rendre compte que
votre LED clignote, ce qui vous prouve que votre programme d’application est parfaitement
opérationnel, après son passage dans le bootloader.

Une fois la fenêtre fermée, le programme continuera de tourner. Toutes les options,
excepté <quitter> sont en grisé. C’est logique, puisque, pour pouvoir envoyer une autre
donnée, il faudra d’abord la charger, et donc revenir à la fenêtre précédente.

Pour faire repasser votre PIC® en mode bootloader, il vous suffira, soit de cliquer sur le
bouton « reset » de la barre d’outils, soit de repasser en mode « envoi vers PIC® », ce qui
générera automatiquement un reset. La led s’arrête de clignoter, votre PIC® dialogue de
nouveau en mode bootloader. Vous pouvez relancer le programme par le bouton que nous
venons de voir.

Vous pouvez également tenter de générer des conflits, pour voir comment BIGOPIC light
se comporte.

84
Si vous entrez une instruction 0x0000 (nop) à l’adresse 0x01, par exemple, vous verrez
qu’en tentant la vérification, ceci ne pose aucun problème au logiciel, celui-ci s’aperçoit
qu’une instruction « nop » à cet emplacement peut être tout simplement supprimée.

Si, par contre, vous tentez d’inscrire une autre instruction, le problème ne pourra être
résolu, et vous aurez droit à un message d’erreur.

9. Conclusions

Nous voici déjà arrivés au terme de cette troisième partie, courte pour vous, mais
longue pour moi, car, avant de pouvoir écrire ce petit livre, il m’a fallut concevoir les
logiciels, ce qui m’a pris un certain temps, pour ne pas dire un temps certain.

Vous pouvez utiliser cette technique avec toutes vos cartes d’applications futures,
moyennant des aménagements dérisoires. Il est même relativement facile de modifier une
carte déjà existante.

Je suis certain que cette technique vous dépannera dans bien des situations, et
améliorera le confort de la phase de développement de vos projets.

Le cours suivant, consacré au ICD® (In Circuit Debugger) vous rendra encore bien
d’autres services, les 2 modules étant prévus pour cohabiter.

Je remercie Torium de m’avoir aidé en adaptant BIGOPIC light et BgBoot.asm pour


pouvoir utiliser le bootloader sur les versions « A » des PIC®. Nul doute que vous lui en
serez reconnaissants.

Je vous souhaite bon travail avec ce bootloader 

85
86
Contribution sur base volontaire
La réalisation de ces cours m’a demandé beaucoup de temps et d’investissements
(documentations, matériel, abonnements, etc.).

Aussi, pour me permettre de poursuivre, je vous demande, si cela est dans vos possibilités, et
si vous appréciez ce que je fais, de contribuer un peu, chacun selon ses possibilités et ses
désirs.

J'ai donc besoin de votre aide pour continuer l'aventure. En effet, je ne dispose plus vraiment
de la capacité de consacrer l'intégralité de mon temps libre à écrire des cours et des
programmes sans recevoir un petit "coup de pouce".

Cependant, je ne voulais pas tomber dans le travers en verrouillant l'accès aux fichiers, et en
imposant un payement pour les obtenir. En effet, je tiens à ce qu'ils restent disponibles pour
tous.

J'ai donc décidé d'instaurer un système de contribution sur base volontaire en permettant à
celui qui le désire, et en fonction de ses propres critères, de m'aider financièrement. Le but
n'étant pas de me faire riche, mais plutôt de m'aider à "joindre les 2 bouts".

Il ne s'agit donc pas d'un payement, ni d'une obligation. Il s'agit simplement d'une assistance
sans promesse d'aucun sorte, et sans contrainte. Je continuerai à répondre au courrier de tout
le monde, sans distinction, et sans interrogation à ce sujet.

Une bonne méthode consiste donc, pour celui qui le désire, à télécharger le document choisi,
le lire ou l'utiliser, puis décider si cela vaut ou non la peine de m'aider sur base de l'usage que
vous en faites.

Si oui, vous vous rendez sur mon site : www.abcelectronique.com/bigonoff ou


www.bigonoff.org, et vous suivez le lien « cours-part1 ». Vous y trouverez, dans la page
« contributions », la procédure à suivre. Pensez que ces contributions me sont très utiles, et
contribuent à me permettre de continuer à travailler pour vous.

Pour remercier ceux qui ont contribué, soit par l’envoi d’une lettre, soit par la création d’un
site d’utilité publique, j’offrirai le logiciel BIGOPIC V2.0.

N’oubliez pas de mettre votre email en caractère d’imprimerie, pour que je puisse vous
répondre.

Je réponds toujours au courrier reçu. Aussi, si vous n’obtenez pas de réponse, n’hésitez
surtout pas à me contacter pour vérifier s’il n’y a pas de nouveau un problème.

Merci d’avance à tous ceux qui m’ont aidé ou m’aideront à poursuivre ce travail de longue
haleine.

87
Notes :

88
B. Utilisation du présent document

Le présent ouvrage est une annexe des deux précédents ouvrages. Il décrit la mise en
œuvre de la technologie de téléchargement dénommée « bootloader ».

Communiquez à l’auteur (avec politesse) toute erreur constatée afin que la mise à jour
puisse être effectuée dans l’intérêt de tous, si possible en utilisant le livre de report
d’information présent sur la page de téléchargement du cours.

Pour ces raisons, et par facilité de maintenance pour moi, j’ai décidé que ce cours serait
disponible uniquement sur mon site : www.abcelectronique.com/bigonoff ou
www.bigonoff.org

Aussi, si vous trouvez mon cours ailleurs, merci de m’en avertir.

Bien entendu, j’autorise (et j’encourage) les webmasters à placer un lien sur le site,
inutile d’en faire la demande. Bien entendu, je ferai de même en retour si la requête m’en est
faite. Ainsi, j’espère toucher le maximum d’utilisateurs.

Le présent ouvrage peut être utilisé par tous, la modification et la distribution sont
interdites sans le consentement écrit de l’auteur.

Tous les droits sur le contenu de ce cours, et sur les programmes qui l’accompagnent
demeurent propriété de l’auteur.

L’auteur ne pourra être tenu pour responsable d’aucune conséquence directe ou indirecte
résultant de la lecture et de l’application du cours ou des programmes.

Toute utilisation commerciale est interdite sans le consentement écrit de l’auteur. Tout
extrait ou citation dans un but d’exemple doit être accompagné de la référence de l’ouvrage.

J’espère n’avoir enfreint aucun droit d’auteur en réalisant cet ouvrage, je n’ai utilisé que
les programmes mis gracieusement à la disposition du public par la société Microchip®. Les
datasheets sont également disponibles gracieusement sur le site de cette société, à savoir :
http://www.Microchip.com

Si vous avez aimé cet ouvrage, si vous l’utilisez, ou si vous avez des critiques, merci de
m’envoyer un petit mail, ou mieux, de poster un message sur mon site. Ceci me permettra de
savoir si je dois ou non continuer cette aventure avec les parties suivantes.

Certains continuent à envoyer des messages sur mon ancienne adresse. Prenez
connaissance de la bonne adresse, pour de pas encombrer des adresses non concernées. Vous
risquez de plus d’attendre longtemps votre réponse.

Sachez que je réponds toujours au courrier reçu, mais notez que :

- Je ne réalise pas les programmes de fin d’étude pour les étudiants (même en payant), c’est
une demande qui revient toutes les semaines dans mon courrier. Tout d’abord je n’ai pas

89
le temps, et ensuite je ne pense pas que ce soit un bon service. Enfin, pour faire un peu
d’humour, si je donnais mes tarifs, ces étudiants risqueraient un infarctus.

- Je n’ai malheureusement pas le temps de débuguer des programmes complets. Inutile donc
de m’envoyer vos programmes avec un message du style « Ca ne fonctionne pas, vous
pouvez me dire pourquoi ? ». En effet, je passe plus de 2 heures par jour pour répondre au
courrier, si, en plus, je devais débuguer, j’y passerais la journée. Vous comprenez bien que
c’est impossible, pensez que vous n’êtes pas seul à poser des questions. Posez plutôt une
question précise sur la partie qui vous semble inexacte.

- Si vous avez des applications personnelles, n’hésitez pas à les faire partager par tous. Pour
ce faire, vous pouvez me les envoyer. Attention cependant, faites précéder votre envoi
d’une demande, je vous redirigerai alors sur une autre boîte, celle-ci étant limitée à 512K.

- Avec cette version, j’essaye de répondre aux demandes légitimes des personnes qui
travaillent sur différentes plates-formes (Mac, Linux, Windows, etc.). Si, cependant, la
version fournie est inexploitable sur votre machine, merci de me le faire savoir. Notez
cependant que ce cours utilise MPLAB® pour les exercices, il faudra donc éventuellement
adapter ces exercices en fonction du logiciel qu’il vous sera possible d’utiliser.

Je remercie tous ceux qui m’ont soutenu tout au long de cette aventure, et qui se
reconnaîtront. Nul doute que sans les nombreux encouragements reçus, ce livre n’aurait
jamais vu le jour.

Merci au webmaster de www.abcelectronique.com, pour son hébergement gratuit.

Merci à Byte, pour sa proposition d’hébergement gratuit.

Merci à Grosvince pour sa proposition d’hébergement gratuit.

Merci à Bonny Gijzen pour la modification de IC-Prog qui servira pour la suite de l’aventure :
www.ic-prog.com

Dernière remarque : il est impossible que vous trouviez trace d’un plagiat ici, étant donné
que je n’ai lu aucun ouvrage sur le sujet, autre que le datasheet de Microchip®. Tout est donc
issu de mes propres expériences.

- Edition terminée en révision beta le 03/11/2002.

- Révision 1 le 23/03/2003 : Ajout d’un avertissement concernant l’interface, page 14.

- Révision 2 le 09/06/04 : Modification de mon adresse courrier

- Révision 3 le 28/10/04 : correctif page 16 + ajout d’un fichier provisoire d’adaptation au


16F877A par Alain (alainper@club-internet.fr)

- Révision 4 le 10/11/2004 : Prise en compte définitive des PIC16F87xA, grâce à la


modification de BIGOPIC1 (qui devient BIGOPIC light V2.0) et à la création de
BgBootA.asm créé à partir de BgBoot.asm. Merci à TORIUM pour ce travail
d’adaptation.

90
- Révision 5 le 05/01/2004 : Modification de l’interface optocouplée pour qu’elle
fonctionne avec tous les types de PC, modification par YC.

- Révision 6 le : 27/03/2006 : Seconde modification du schéma par YC.

- Révision 7 le 13/10/2006 : Remarque sur l’utilisation des versions 873 et 874 page 31 par
Alloui Tahar.

- Révision 8 le 25/11/2007 : Ajout des mentions ® à la demande de Microchip®.

- Révision 9 le 24/02/2009 : Adoption définitive du terme Kibi

- Révision 10 le 05/10/2010 : Correctif page 14.

Réalisation : Bigonoff

Email : bigocours@hotmail.com (Attention BIGOCOURS, PAS BIGONOFF)

91

Vous aimerez peut-être aussi