LA PROGRAMMATION DES PICS PAR BIGONOFFusers.skynet.be/porcy/cours_16f877_part3.pdf · le pic, le...

86
LA PROGRAMMATION DES PICS PAR BIGONOFF TROISIEME PARTIE – Les secrets des 16F87x Techniques de bootloader - Révision 2b

Transcript of LA PROGRAMMATION DES PICS PAR BIGONOFFusers.skynet.be/porcy/cours_16f877_part3.pdf · le pic, le...

LA PROGRAMMATION DES PICS

PAR BIGONOFF

TROISIEME PARTIE – Les secrets des 16F87x

Techniques de bootloader - Révision 2b

2

3

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

1. LA DÉMARCHE .............................................................................................................................................. 6

1.1 LE RÔLE DU BOOTLOADER.............................................................................................................................. 61.2 QU’EST-CE QU’UN BOOTLOADER ?................................................................................................................. 61.3 INCONVÉNIENTS DU BOOTLOADER ................................................................................................................. 71.2 LE CAHIER DES CHARGES ............................................................................................................................... 7

2. LA RÉALISATION DE L’INTERFACE ....................................................................................................... 9

2.1 LA VERSION CLASSIQUE ................................................................................................................................. 92.2 L’INTERFACE BIGOPIC................................................................................................................................. 10

3. LA MISE EN ŒUVRE MATÉRIELLE ....................................................................................................... 15

3.1 CE QU’IL FAUT SAVOIR................................................................................................................................. 153.2 SCHÉMA D’APPLICATION TYPIQUE ............................................................................................................... 16

4. LA MISE EN ŒUVRE LOGICIELLE......................................................................................................... 18

4.1 LES QUESTIONS ............................................................................................................................................ 184.2 LA SÉQUENCE DE DÉMARRAGE DU BOOTLOADER......................................................................................... 184.3 GESTION DU DÉMARRAGE DU PROGRAMME ................................................................................................. 19

5. LE LOGICIEL PIC ........................................................................................................................................ 22

6. MISE EN PRATIQUE HARDWARE........................................................................................................... 55

7. UTILISATION PRATIQUE DU BOOTLOADER...................................................................................... 59

7.1 INTRODUCTION ............................................................................................................................................ 597.2 CUSTOMISATION DU BOOTLOADER .............................................................................................................. 59

8. UTILISATION PRATIQUE DE BIGOPIC ................................................................................................. 63

8.1 INSTALLATION DU LOGICIEL ........................................................................................................................ 638.2 PREMIER LANCEMENT DE BIGOPIC............................................................................................................... 638.3 PASSAGE EN MODE BOOTLOADER ................................................................................................................ 668.4 CHARGEMENT D’UN PROGRAMME D’APPLICATION....................................................................................... 698.5 RÉSOLUTION DES CONFLITS ......................................................................................................................... 718.6 EFFACEMENT DES ANCIENNES DONNÉES ...................................................................................................... 768.7 L’ENVOI DE NOTRE PREMIER PROGRAMME............................................................................................. 788.8 LANCEMENT DU PROGRAMME CHARGÉ ........................................................................................................ 80

9. CONCLUSIONS ............................................................................................................................................. 81

CONTRIBUTION SUR BASE VOLONTAIRE............................................................................................... 83

B. UTILISATION DU PRÉSENT DOCUMENT............................................................................................. 85

4

5

1. Introduction

Ce livre est la suite logique du livre « la programmation des pics – seconde partie – Lagamme mid-range par les 16F87x ».

Il s’adresse donc aux utilisateurs expérimentés, qui ont lu et assimilés les 2 ouvragespré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 techniqueque les précédents.

Je remercie de nouveau tous ceux qui m’ont témoigné leur confiance et leur soutien lorsde 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 desPICs 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 lademande se fait sentir concernant certains chapitres, il me sera toujours possible d’ajouterexplications complémentaires et exemples supplémentaires.

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

Je décline toute responsabilité, directe ou indirecte, pour toute conséquence fâcheuserésultant de l’utilisation de cet ouvrage, des interfaces décrites, ou des logiciels. Tout estfournis « tel quel », et l’utilisation est soumise à votre seule et unique responsabilité. Aucunrecours ne pourra être engagé contre moi. Si vous n’êtes pas d’accord, merci d’effacer cedocument, 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 jevous le conseille : expérimentez, expérimentez, et expérimentez encore !

… Et vive l’Internet libre !

BIGONOFF

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 foisvotre 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, enleverle pic, le placer dans le programmateur, le programmer, le remettre sur la platine, relancerl’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, à unmoment ou à un autre, vous allez oublier de couper l’alimentation, ou alors vous allez mettrevotre 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, carl’ICP utilise la programmation classique, et donc des tensions supérieures aux tensions defonctionnement normal du PIC.

De plus, l’ICP utilise plusieurs pins spécifiques du PIC, qui ne pourront facilement êtreutilisé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 devezplacer votre montage sur son lieu d’application.

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

Il nous faut donc trouver une solution pratique et flexible pour envoyer le programmedans 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 dubootloader.

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

Il suffit alors de se souvenir que le PIC 16F87x dispose de la possibilité d’écrire dans samémoire programme, pour comprendre qu’en fait, le PIC dispose de la possibilité de seprogrammer 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 queprogramme principal.

1.3 Inconvénients du bootloader

Maintenant que vous avez entrevu les avantages et la flexibilité du bootloader, il nous fauten 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’espaceen mémoire programme.

- Le bootloader est incapable de modifier la configuration du PIC, qui sera doncdéfinitivement figée sans l’utilisation d’un programmateur classique.

- Il faut réaliser un programme tournant sur votre ordinateur pour communiquer avec lebootloader. J’ai réalisé un programme pour Windows, je cherche des volontaires pourré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 allezvoir 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 enlecture empêche l’écriture en mémoire flash. Nous verrons cependant qu’il est possible decontinuer à 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 contraintesauxquelles 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é desapplications que vous trouverez sur le net.

- La pin utilisée ne devra pas être bloquée pour l’utilisation du bootloader, mais pourraservir 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 programmed’application.

- On doit pouvoir envoyer dans le PIC n’importe quel programme réalisé suivant lesdirectives données jusqu’à présent, sans imposer la réécriture ou la modification dusource, et même sans nécessiter de réassemblage. En sommes, on doit pouvoir prendre unexemple 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 entout cas que ce que vous trouverez généralement. Ceci fait de ce bootloader un véritable outilparfaitement opérationnel.

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

9

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 pournotre bootloader, et pour l’utilisation du debugger intégré. Ceci pour vous expliquer quecertaines 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 unordinateur. Autrement dit, nous aurons beaucoup de points communs.

La principale différence entre le bootloader et le debugger, c’est que le premier peut secontenter de communiquer en n’utilisant qu’une seule pin, alors que le second exigel’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 lePIC, le montage de destination étant sous tension.

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

10

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

2.2 L’interface BigoPic

La méthode qui vient alors à l’esprit est de se dire : il suffit d’ajouter un opto-coupleur parligne 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 cellealimentant le PIC, pour conserver l’isolation.

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

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

- Un opto-coupleur est également capable de convertir des tensions, il suffit de l’alimenteravec les dites tensions adéquates.

Partant de là, on peut alors se dire : on peut éliminer le max232, et ne conserver que lesopto-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 destensions de signaux qui soient compatibles avec le port série de l’ordinateur utilisé. En effet, ilest 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 del’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éellementpar 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 unprogrammateur 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 de13V nécessaire à la programmation du PIC. Cette tension est fixe, et ne peut être atteinte parles ports séries qui ne respectent pas les tensions standardisées.

11

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

Voyons donc l’interface en question, en gardant à l’esprit qu’on pouvait faire un peu plussimple, 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.

Bien évidemment, je vais vous commenter tout ça en détail.

Vous remarquez la présence d’une ligne verticale pointillée, qui vous indique la séparationgalvanique complète entre le PIC (à gauche), et l’ordinateur (à droite). La communication sefait 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 à satension normalisée de +12V, un niveau « 1 » par sa tension normalisée de –12V. Autrementdit, 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 2 connecteurs, destinés à connecter le PIC au montage.Celui de l’extrême gauche, dénommé « bootloader » est celui qui nous intéresse dans ce livre,le second, dénommé « sonde » sera utilisé dans le cadre des techniques de debuggage surcircuit. Nous en reparlerons dans le livre suivant, ignorons-le pour l’instant.

J’en arrive au fonctionnement proprement dit. Je commence les explications en partant dela 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,

12

et celle sur RTS –12V, mais ceci n’est absolument pas obligatoire. Tout au plus, dans les casles 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érencede 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 quedans le cahier des charges, on a imposé le recours à une seule pin), est alors porté à VDDdu PIC via la résistance R6. En effet, les 2 broches du connecteur intitulés PINT sontinterconnecté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 leniveau envoyé par l’ordinateur.

Prenez garde au fait que la connexion entre les 2 broches PINT ne doit se faire que par lecâ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 enmode debugger.

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 (typiquement24V 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 niveauenvoyé par l’ordinateur.

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

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

13

- La diode D5 est bloquée, car la tension sur sa cathode est supérieure à celle présente surson 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 lecollecteur 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 uncourant 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 tensionreprésentant un niveau « 0 ».

- 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 eneffet que le port RS232, au lieu d’être au repos, envoie un niveau « 0 » vers le PIC (plantagedu 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 lamise à la masse de PINT. PINT que tente justement de mettre à +Vdd notre PIC tentantd’envoyer un « 1 ».

Nous avons la un parfait exemple de court-circuit, qui risque d’entraîner la destruction duPIC 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 unniveau Vdd sur PINT. Ceci est très simple, et sera résolu par une astuce d’utilisation duprogramme du PIC.

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

14

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

- 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 doncbloqué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 passantvia 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 decomposants, 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, estcomplètement opto-couplée, et donc utilisable sous tension. Elle est, de plus, adaptéeautomatiquement aux tensions utilisées par le port choisi, et donc universelle. Prenezcependant 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 devezgarantir votre sécurité et la sécurité de ceux qui emploieront l’interface Bigopic. Vousdevez donc garantir tout contact accidentel avec les sondes à destination du PIC, ainsiqu’avec la platine de l’interface. Un boîtier sera dès lors indispensable, et aucune pistedu circuit imprimé ne pourra passer entre les pins des opto-coupleurs. Vous vousengagez 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 petiteplatine d’expérimentation, ne mettant pas en œuvre des tensions supérieures à 5V. ClaudeGrini s’est proposé pour réaliser ce typon, il se trouve maintenant sur le site.

ATTENTION : SUR CERTAINS PC, CETTE INTERFACE NE FONCTIONNE PASCORRECTEMENT (ERREURS). CECI EST DU A L’IMPEDANCE TROP ELEVEEDU PORT SERIE. DANS CE CAS, IL VOUS FAUDRA REALISER L’INTERFACE

BIGOPIC2 DU COURS – PART4, EN CONNECTANT ENSEMBLE LES PINSD’EMISSION ET DE RECEPTION COTE PIC. IL VOUS APPARTIENT D’UTILISER UN

MAX232 OPTOCOUPLE SI BESOIN EST.

15

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 vamaintenant s’agir de voir comment concevoir une carte d’application permettant l’utilisationde l’interface.

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

Ensuite, nous ne devons pas connecter directement MCLR à Vdd, puisque nous devonspouvoir imposer un niveau « 0 » sur cette pin via notre interface. Ceci ne pose aucunproblè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 ledialogue. 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 entredémarrer le bootloader, ou démarrer le programme chargé, étant entendu que le bootloaderreste 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 latransmission 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) setrouve, même une fraction de seconde, au niveau « 0 », alors on lance le programmed’application.

- Si, par contre, durant un temps prolongé (du point de vue du PIC), ceci afin d’éviter unparasite, 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 0lors 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ésistancede 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 laré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 masseimposera à 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 toujoursen entrée au moment du reset. Attention, n’oubliez pas que l’application d’une tension surla pin de transmission appliquera également la tension sur le périphérique concerné. Encas de danger (moteur), utilisez un jumper pour passer du mode bootloader au modeutilisation normale.

16

- 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 travailleren sortie, ou une pin, inutilisée.

Remarquez une contrainte : Si vous utilisez une des pins du PORTB, et que vous avez misen service les résistances de rappel au +5V internes, alors il vous faudra vous arranger pourplacer une résistance suffisamment basse entre la pin et la masse pour garantir la lectureinfaillible d’un niveau « 0 ». Comme cette résistance interférera avec l’électronique del’interface, vous serez contraint d’utiliser un jumper (ce qui n’est guère contraignant), ou dechoisir une autre pin.

Vous constatez que l’utilisation de la pin de transmission ne prive pas votre montaged’une pin d’entrée/sortie. Il suffit en effet de la choisir judicieusement pour éviter les casdifficiles.

3.2 Schéma d’application typique

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

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

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

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. Cecine 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 dufonctionnement 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 etl’interface. La résistance de 10Kohms, présente après J2, permet de forcer le niveau 0 sur lapin lors d’un reset. Elle permet d’éviter d’entrer par accident en mode bootloader lors d’unreset du PIC.

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

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

17

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

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

18

4. La mise en œuvre logicielle

4.1 Les questions

Nous avons vu comment construire notre platine d’application pour qu’elle soitcompatible 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 denotre bootloader ?

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

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 unPIC.

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

19

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 devoirdé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 unbootloader. 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 resetPAGESEL 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 dePCLATH, 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’adresse0x02. Une fois l’exécution du bootloader terminée, on reviendra à l’adresse 0x03, premièreadresse libre pour caser notre programme d’application.

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

ORG 0x00 ; adresse de resetgoto init ; sauter au début du programme (0x00)

ORG 0x04 ; adresse des interruptionsxxxx ; début de la routine d’interruption

init

20

xxx ; première instruction du programme.

On voit tout de suite qu’il sera impossible de placer ce programme dans le PIC, puisquel’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 doncplus.

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çonsuivante :

ORG 0x03 ; adresse de resetgoto init ; sauter au début du programme (0x03)

ORG 0x04 ; adresse des interruptionsxxxx ; début de la routine d’interruption

initxxx ; première instruction du programme.

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

ORG 0x00 ; adresse sur resetPAGESEL 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)

initxxx ; première instruction du programme.

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

Bien entendu, pour pouvoir effectuer cette modification, il faut que l’adresse 0x03 soitlibre, afin de pouvoir y placer notre instruction de saut. Le programme BigoPic sur PC seracapable de gérer les cas suivants :

ORG 0x00 ; adresse de resetgoto init ; sauter au début du programme (0x00)

ORG 0x04 ; adresse des interruptionsxxxx ; début de la routine d’interruption

initxxx ; première instruction du programme.

Nous venons de le voir, c’est le cas classique d’utilisation de la maquette. L’instructiongoto sera simplement déplacée vers l’adresse 0x03.

ORG 0x00 ; adresse de resetgoto init ; sauter au début du programme (0x00)nop ; 0x01nop ; 0x02

21

nop ; 0x03xxxx ; début de la routine d’interruption (0x04)

initxxx ; première instruction du programme.

Certains utilisent cette méthode, qui, contrairement aux apparences n’est pas identique à lapré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 desvaleurs de 0x3FFF à ces adresses. Dans ce cas-ci, vous y lirez 0x00, puisque c’est le codehexadécimal d’une instruction « nop ».

Et bien, BigoPic va commencer par supprimer ces instructions « nop », ce qui fera revenirle 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, serontstructurés de la façon suivante :

ORG 0x00 ; adresse de resetxxx ; 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é duprogramme, ce que ne fait pas BigoPic. Il ne vous restera alors qu’à reprendre le fichiersource et à remplacer la directive « ORG 0x00 » par « ORG 0x03 » et de réassembler pourobtenir un nouveau fichier « .hex » compatible avec le bootloader.

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

22

5. Le logiciel PIC

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

Bien entendu, ce logiciel devra répondre à notre cahier des charges. Nous allons devoirrecourir 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. *;*****************************************************************************

Bon, ici je vous rappelle notamment que la configuration doit être écrite en fonction duprogramme 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 PICs 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. *; *

23

; 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 pasqu’un travail bénévole me rapporte des ennuis, ou qu’un autre se fasse de l’argent sur mondos.

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

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

Notez que le bootloader a été écrit pour être utilisé dans le 16F876 ou le 16F877. Pourd’autres processeurs, à vous de faire les modifications nécessaires, très simples et d’ailleursexpliqué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, êtrechargé à l’aide d’un programmateur classique. Ce n’est qu’une fois en place qu’on pourra sepasser 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 bootloaderou 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. *

24

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 vousseront utiles si vous créez votre propre programme de dialogue avec le PIC. Elles seronttransparentes pour vous si vous décidez d’utiliser BigoPic, l’utilitaire sous Windows que j’aicréé pour vous. Je détaillerai ces commandes lors de l’étude des routines correspondantes.

; 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 plusloin, que vous allez pouvoir modifier le fonctionnement du bootloader pour l’adapter à votrecas particulier. Voyons un peu plus en détails.

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

25

Si vous ne précisez aucun paramètre, l’adresse sera calculée automatiquement pour que lebootloader 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 votremontage d’application. Ceci est indispensable pour que les macros puissent calculercorrectement 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 tropgrandes valeurs, ça n’accélérerait pratiquement pas la vitesse de chargement, celle-ci étantplus limitée par le temps d’écriture en mémoire flash que par le temps nécessaire auxtransmissions.

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

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 quevous 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 lefaire. Dans ce cas, incrémentez successivement par pas de 1 jusqu’à obtenir la fin du messaged’erreur. Les messages peuvent être du type :

MESSAGE: (Débit trop faible pour votre quartz. Augmentez le baudrate ouaugmentez la valeur de BAUDRL)

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

26

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

Le second type de message concernant BAUDRL est le suivant :

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

Ici, lors du calcul du nombre de boucles, la valeur calculée ne « tombe pas juste ». Il endé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 messaged’erreur.

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

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

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 auminimum 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 duprogramme, 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é surle PORTA, et de laisser le bootloader à sa position par défaut, c’est-à-dire en fin de la page 3de la mémoire programme.

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

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

27

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 inclurecontient « 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 sommesencore 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 un16F877, il vous suffira de l’indiquer dans ces deux premières lignes. La configuration seracelle de votre programme d’application.

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

Prenez garde que vous ne pourrez pas modifier la configuration par l’intermédiaire dubootloader. Celle-ci sera donc définitive, à moins de reprogrammer le PIC par l’intermédiaired’un programmateur classique, et de lui réinjecter un nouveau programme de bootloader avecla configuration correcte.

Prenez également garde à la directive CP_OFF. Si vous décidez de protéger une partie dela mémoire PIC en lecture, vous ne pourrez pas écrire dans cette portion de mémoire. Il voussera 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 noncachée pourra être mise à jour par le bootloader. Soyez donc attentif à ce point si vousconstruisez des applications commerciales (pour lesquelles, je vous le rappelle, je conserve lesdroits).

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

BPORT EQU PORTB ; port de communicationBPIN 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

28

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. Cesvaleurs par défaut étant d’ailleurs celles indiquées après les « EQU », afin de vous permettrede vous en souvenir rapidement. D’autre part, les valeurs par défaut seront indiquées lors del’assemblage sous forme de messages.

En général, si vous utilisez un quartz de 20Mhz, vous laisserez tout tel quel, vouscontentant 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. Enpremier lieu, on va détecter si vous les avez précisé explicitement, sinon, on va leur affecterles valeurs par défaut :

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

errorlevel -302; valeurs par défaut; ------------------

IFNDEF FQUARTZ ; si fréquence non préciséeFQUARTZ = D'20000000' ; alors fréquence = 20MHz

MESSG "Fréquence de 20 Mhz prise par défaut" ; et messageendif

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 seconcentrer 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 ladirective « endif » ne sera interprété que si vous n’avez pas précédemment affecté une valeurau 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, carl’assembleur le considère comme une étiquette. Si vous ne le faites pas, vous aurez droit à unmessage « warning » qui vous préviendra que vous avez utilisé une étiquette hors de lacolonne « 1 ».

J’ai utilisé le symbole « = » au lieu de « EQU ». Vous allez me dire : c’est strictementidentique. En fait, pas tout à fait. Les nombreux tests que j’ai effectué avec cette directivemontre qu’elle ne réagit pas toujours comme on pourrait s’y attendre. Je vous conseille doncd’utiliser le symbole « = » lors d’affectations conditionnelles.

29

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 messageendif

IFNDEFBAUDRL ; 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éeTAILLEMAX = 0x2000 ; 8Kmots (16F876/877)

ENDIF

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

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

TAILLE = D'231' ; taille nominale du programme non situé en fin de page3TAILLE += BAUDRL ; ajouter les nop créées par BAUDRL

Ici, on définit la taille du programme comme étant de 231 octets. Il va de soi que si vousmodifiez quelque chose dans le programme bootloader, il vous appartiendra de modifier cetteligne en conséquence. Sans quoi vous risquez de déborder de la mémoire programme, vousserez 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 bouclede temporisation.

IF BPORT != PORTATAILLE -= 5

ENDIF

Ici, on indique que si le port choisi n’est pas le PORTA, alors on gagne 5 emplacementsmé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.

30

; adresse de début; ----------------

IFNDEF ADR ; si pas déjà définieTAILLE-= D'10' ; on gagne 10 instructions sur les tests.ADR = TAILLEMAX-TAILLE ; adresse de la routine en fin de page 3AUTOADD

MESSG"La routine de boot se trouve en fin de page 3" ; messageENDIF ; fin de l'assemblage conditionnel

Remarquez que si on a conservé l’adresse par défaut, on gagne 10 emplacementsmé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 cespré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 aconservé l’emplacement par défaut. Remarquez toujours les constantes en première colonne.

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 temporisationpour 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, puisquechaque instruction nécessite 4 cycles d’horloge. Nous obtenons alors le nombre d’instructionspar seconde.

Si nous divisons le nombre d’instructions par seconde par le débit (en nombre de bits parsecondes), nous obtenons le nombre d’instructions à attendre entre l’envoi ou la réception de2 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 2appels de la routine de temporisation.

En effet, si nous devons attendre 50 instructions entre l’émission de chaque bit, et quel’émission d’un bit nous prend 10 instructions, nous ne devrons plus attendre que 40instructions, 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 2appels consécutifs de la routine de temporisation., ce qui justifie le « -D’14’ ».

31

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 lavaleur obtenue. Mais, si nous avons défini une valeur pour BAURDL, nous ajouterons autantde « nop » à l’intérieur de la boucle de temporisation. Autrement dit, la durée d’une bouclesera de (3 + valeur de BAUDRL).

Groupez tout ceci, et vous arrivez à la formule que je viens de vous donner. C’est plussimple 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 leserreurs, nous reprendrons la formule précédente, en multipliant le résultat par 1.5. L’endroit leplus 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 desentiers, ceci nous donne (FQUARTZ * 3/8). La formule finale est donc :

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 soitcomprise entre 0 et 255. En effet, une valeur négative voudrait dire qu’on doit attendre untemps négatif, autrement dit qu’on n’a pas assez de temps, ou encore que le débit est tropimportant par rapport à la fréquence du quartz choisi.

Une valeur supérieure à 255 signifie qu’on doit attendre trop longtemps, donc que le débitest 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 courteMESSG "Impossible d'établir le débit, diminuez BAUDRL. Si déjà à 0, diminuez

le débit"ENDIF

If DUR1B5 >= 0x100 ; Si durée trop longueMESSG "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 calculssont arrondis à la valeur entière, il nous faut encore vérifier que l’erreur engendrée sur le débitne 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 PICs, 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%.

32

Nous allons tout d’abord calculer le débit réel obtenu avec la valeur retenue, simplementen 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 enpossession 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 dudébit théorique. Comme il nous faut une valeur en %, nous multiplions par 100 avant ladivision (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 êtrenégative ou positive. Nous devons donc vérifier si l’erreur trouvée est supérieure à 4% ouinférieure à –4%. Dans ce cas, nous avertirons l’utilisateur pour qu’il puisse modifier la valeurde BAUDRL.

Si vous avez tout compris, sans BAUDRL, on divise la valeur trouvée par 3, avecBAUDRL = 1, on divise par 4, avec la valeur 2, on divise par 5 etc. Il arrivera forcément unmoment où l’erreur de division sera suffisamment faible pour obtenir une erreur acceptable.

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, voyonsmaintenant les variables utilisées.

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

CBLOCK0x70cmpt : 1 ; compteurtmps : 1 ; compteur pour temporisationbbyte : 1 ; octet reçu ou à envoyerptr : 2 ; pointeur reçucar1 : 1 ; caractère 1 reçucar2 : 1 ; caractère 2 reçuENDC

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 cesemplacements, 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 vousn’avez pas bien réfléchi. Sceptique ? Reprenons :

33

- 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’auprochain reset, pour lequel l’état des variables est de nouveau, par définition, inconnu.

Autrement dit, bootloader et programme d’application peuvent se partager desemplacements de variables communs, puisqu’ils ne tourneront jamais en même temps, et quel’un n’interrompra jamais l’autre.

Au reset, soit on utilise le bootloader, soit on utilise le programme principal. Leprogramme principal peut donc utiliser les emplacements RAM du bootloader etréciproquement.

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

Le seul cas où cela pourrait se révéler gênant, c’est le cas où, dans votre programmeprincipal, vous détectez le type de reset auquel vous avez affaire, et que vous décidiez de nepas 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 lepassage dans le bootloader avant le renvoi au programme principal, c’est-à-dire la variable« cmpt ».

Je suppose que dans ce cas extrême, il vous sera possible d’accepter un seul emplacementsusceptible d’être modifié après un reset, étant donné que vous disposez, de plus, de lapossibilité de déplacer « cmpt » n’importe où dans la zone RAM commune. Ceci ne constituedonc 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 commencerici. 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 resetPAGESEL ADR ; pointer sur la page du bootloadercall (ADR & 0x7FF) ; exécuter bootloader

Souvenez-vous que le programme sur PC, BigoPic, est capable de gérer plusieurs casapparents de conflits.

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

34

;*****************************************************************************; 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;-----------------------------------------------------------------------------

ORGADR ; début du bootloader

; gérer PORTA; -----------

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

; tester état de PINT; -------------------

clrf cmpt ; effacer compteurinloop

btfss PINT ; tester si PIN = 0goto sortir ; oui, rendre la main au programmemovlw DUR1B5 ; pour durée de 1,5 bitcall tempo ; attendredecfszcmpt,f ; décrémenter compteur de bouclesgoto inloop ; pas dernière, suivante

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

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

En l’occurrence, on teste si le port choisi par l’utilisateur est le PORTA. Dans ce cas, ceport étant en mode analogique par défaut, il faudra commencer par le positionner en modenumérique. Ceci explique déjà 4 des 5 instructions supplémentaires nécessaires si on utilise lePORTA, 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’étaitpas sécurisant.

J’ai trouvé dangereux qu’un simple parasite au moment d’un reset puisse faire basculerune application réelle en mode bootloader, bloquant ainsi le fonctionnement de la carte. Aulieu 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, unniveau 0, alors on quitte le mode bootloader et on passe en application normale.

35

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 travaillersur le PIC. Le reset sera renvoyé par le programme BigoPic, et tout sera corrigé en quelquesms.

Par contre, le PIC ne pourra pas entrer par accident en mode bootloader (ou alors, vousn’avez vraiment, mais alors vraiment pas de chance, pour avoir reçu 256 fois un parasitesynchronisé 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 doncvite 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 onpeut estimer à coup sûr que l’interface est connectée. Nous pouvons donc entrer dans le modebootloader 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èrecall send ; l'envoyermovlw "G" ; charger caractèrecall send ; l'envoyermovlw "B" ; charger caractèrecall send ; l'envoyermovlw HIGH(ADR) ; adresse haute du bootloadercall send ; envoyermovlw LOW(ADR) ; adresse basse du bootloadercall send ; envoyermovlw HIGH(TAILLE) ; taille haute du bootloadercall send ; envoyermovlw LOW(TAILLE) ; taille basse du booloadercall send ; envoyer

Vous voyez qu’une fois dans ce mode, le programme commence par envoyerl’identification « BGB » qui va servir au programme sur l’ordinateur distant qu’il se trouvebien 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 octetscodés de la même façon.

A partir de ce moment, le PC sait donc où commence et ou fini le bootloader. Ceci luipermettra de vérifier si le programme que vous tentez d’envoyer dans le PIC n’utilise pas lesmê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êmeeffectue cette vérification également. De la sorte, il vous est impossible de détruire lebootloader par inadvertance.

36

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 provenancede 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

; réception des 2 octets; ----------------------

call receive ; lire donnéemovwf ptr ; sauver dans poids fort pointeurcall receive ; lire donnéemovwf ptr+1 ; sauver dans poids faible pointeur

; renvoi de la valeur écrite; --------------------------

movf ptr,w ; charger poids fortcall sendtemp ; le renvoyermovf ptr+1,w ; charger poids faible

lastsendcall send ; le renvoyergoto boucle ; lire commande suivante

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

Cette commande permet de positionner le pointeur interne. En effet, afin d’éviter dedevoir 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 eninterne par le PIC.

37

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

Vous remarquerez que l’envoi du premier octet s’effectue par l’appel de « sendtemp » aulieu de « send » pour les envois suivants. Ceci est dû au fait que nous sortons de notre routinede 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 lescommandes 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 octetde la réponse, il recevra ainsi cet octet avant la fin du dernier stop-bit, ce qui ne manquera pasde poser problème. Nous ménagerons donc une pose entre la réception d’un octet et l’envoidu premier octet suivant, ce qui explique cette particularité que nous retrouverons donc dansles autres routines.

Si la commande reçue n’est pas « P », alors on arrive dans la routine suivante. Comme elleest 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); 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 lacomparaison 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çuxorlw "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 dele 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 :

38

xorlw "P" ; réinverser les bits précédemment inversésxorlw "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 », lavaleur 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éeXor B’0101 0000’ ; xorlw « P »= B’0000 0111’ ; résultat, les bits correspondants à « P » ont été inversés

Si maintenant on exécute

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

On obtientB’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 lesbits qui n’ont pas encore été inversés par « P », et réinverser ceux qui l’ont été sans que ce soitnécessaire.

En réalité, cela correspond simplement à dire qu’au lieu de comparer le contenu duregistre 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 » :

39

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 », sile 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 wXor 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çuxorlw "W" ; comparer avec commande "W"

Par

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

Et voilà, toutes ces explications pour arriver à gagner 1 octet par test. Vous constatez iciles méandres et les joies de l’optimisation. Poursuivons cette routine.

; réception des 2 octets de donnée; --------------------------------

call receive ; lire une donnéemovwf car1 ; la sauvercall receive ; lire la donnée suivantemovwf car2 ; la sauver

On réceptionne ici les 2 octets, qui, combinés ensemble, donneront la valeur del’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 onest en train d’écrire. C’est ici que nous trouvons tout ce qui concerne la sécurité dubootloader, c’est-à-dire le blocage de toute tentative d’écrasement de ce bootloader par leprogramme d’application.

; vérifier si adresse < 0x03; --------------------------

movf ptr,w ; charger pointeur hautbtfss STATUS,Z ; tester si >0goto testsuite ; oui, alors premier test OKmovlw 0x03 ; plus petite adresse validesubwf ptr+1,w ; comparer avec pointeur basbtfss STATUS,C ; tester si <3goto interdit ; oui, adresse interdite

40

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

Poursuivons nos vérifications :

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

testsuitemovlw HIGH(ADR) ; charger poids fort adresse routinesubwf ptr,w ; comparer avec pointeur fortbtfss STATUS,C ; tester si on est en dessousgoto testok ; oui, alors c'est bonbtfss STATUS,Z ; tester si poids forts identiquesgoto testsuite2 ; non, tester si on est après le bootloader

movlw LOW(ADR) ; charger poids faible adresse routinesubwf ptr+1,w ; comparer avec pointeur faiblebtfss STATUS,C ; tester si pointeur < adressegoto testok ; oui, alors c'est bon

Le bootloader se trouve chargé à partir de l’adresse « ADR » Autrement dit, si on tented’écrire après l’adresse 0x02 et avant l’adresse ADR, on n’a aucun risque d’écraser lebootloader. C’est ce que vérifie le code précédent.

Poursuivons :

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

testsuite2IFNDEFAUTOADD ; si pas adresse par défautmovf HIGH(ADR+TAILLE),w ; charger première adresse libre MSBsubwf ptr,w ; comparer avec pointeur hautbtfss STATUS,C ; tester si on est en dessousgoto interdit ; oui, interditbtfss STATUS,Z ; tester si égalité des poids fortsgoto testok ; non, alors c'est bon

movf LOW(ADR+TAILLE),w ; charger première adresse libre LSBsubwf ptr+1,w ; comparer avec pointeur basbtfsc STATUS,C ; tester si on est >=goto testok ; oui, OKENDIF ; 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 estpossible 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’unassemblage conditionnel, le rôle de « AUTOADD » a déjà été expliqué au moment de l’étudedes directives de début de programme. Si on a laissé l’adresse par défaut, on économise ainsices 10 instructions, et donc, autant de mémoire programme.

Vous noterez qu’on exploite ici judicieusement l’ordre des routines afin d’économiser dessauts. En effet, le traitement de l’interdiction va suivre directement cette routine, ce qui al’effet suivant :

41

- 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 dubootloader

- S’il n’a pas défini son adresse, l’instruction qui suit « testsuite2 » sera alorsautomatiquement 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’écrasementdu bootloader :

; traiter adresse pas autorisée; -----------------------------

interditmovf ptr,w ; charger pointeur MSBcall sendtemp ; envoyermovf ptr+1,w ; charger pointeur LSBcall send ; envoyercomf 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 octetsde l’instruction à écrire, mais dont le premier est inversé. Ainsi, le programme PC sait qu’uneerreur 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, etdonc, on économise quelques octets de mémoire programme.

Si tout s’est bien passé jusqu’à présent, il nous faut maintenant écrire l’instruction reçuesous forme de 2 octets dans la mémoire flash, à l’emplacement pointé par le pointeur interne :

; écrire instruction dans mémoire programme; -----------------------------------------

testokbsf STATUS,RP1 ; passer banque 2movf car1,w ; charger caractère 1movwf EEDATH ; sauver dans data MSBmovf car2,w ; charger caractère 2movwf EEDATA ; sauver dans data LSBmovf ptr,w ; charger pointeur hautmovwf EEADRH ; sauver dans pointeur MSBmovf ptr+1,w ; charger ptr basmovwf EEADR ; sauver dans pointeur LSB

bsf STATUS,RP0 ; pointer banque 3bsf EECON1,EEPGD ; pour écriture en mémoire programmebsf EECON1,WREN ; autorisation d'écriture

movlw 0x55 ; début de la séquence d'écrituremovwf EECON2 ; commande 0x55movlw 0xAA ; pour commande 0xAAmovwf EECON2 ; envoyer commandebsf EECON1,WR ; écrirenop ; instruction ignoréenop ; instruction ignoréebcf EECON1,WREN ; verrouiller écritures

42

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

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

; lire instruction en mémoire flash; ---------------------------------

bsf STATUS,RP0 ; pointer banque 3bsf EECON1,RD ; ordre de lecturenop ; attendre fin de lecturenop ; attendre

; récupérer les données; ----------------------

bcf STATUS,RP0 ; passer en banque2movf EEDATH,w ; charger data MSBmovwf car1 ; sauvermovf EEDATA,w ; charger data LSBmovwf car2 ; sauverbcf STATUS,RP1 ; repasser banque 0

De nouveau, rien que du classique. Nous allons maintenant envoyer le pointeur effectifvers 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 MSBcall sendtemp ; envoyermovf ptr+1,w ; charger pointeur LSBcall send ; envoyer

Puis, ensuite, les 2 octets de l’instruction :

; envoyer instruction; -------------------

movf car1,w ; charger instruction MSBenvinst

call send ; envoyermovf car2,w ; charger instruction LSB

Vous remarquez la présence de l’étiquette « envinst », qui permet de récupérer lesinstructions 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; --------------------

incptrincf ptr+1,f ; incrémenter pointeur poids faiblebtfsc STATUS,Z ; tester si débordementincf ptr,f ; oui, incrémenter poids fortgoto lastsend ; envoyer dernier octet

43

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

call send ; le renvoyergoto boucle ; lire commande suivante

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

Nous voici donc de nouveau en présence d’une optimisation en taille, au dépend del’optimisation en vitesse. Il va de soi que cette seconde n’a pas la moindre importance danscette application, au contraire de la première.

Après la routine d’écriture en mémoire flash, voyons la routine d’écriture en mémoireeeprom, 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

; réception octet de donnée; -------------------------

call receive ; réception octet de donnée

; écrire en eeprom; ----------------

bsf STATUS,RP1 ; passer banque 2movwf EEDATA ; placer dans registremovf ptr+1,w ; charger pointeurmovwf EEADR ; dans pointeur eeprom

bsf STATUS,RP0 ; passer banque 3bcf EECON1,EEPGD ; pour écriture en mémoire databsf EECON1,WREN ; autorisation d'écriture

movlw 0x55 ; début de la séquence d'écrituremovwf EECON2 ; commande 0x55movlw 0xAA ; pour commande 0xAAmovwf EECON2 ; envoyer commandebsf EECON1,WR ; écrire

; attendre fin d'écriture; -----------------------

clrwdt ; effacer watchdogbtfsc EECON1 , WR ; tester si écriture terminéegoto $-2 ; non, attendre

44

bcf EECON1,WREN ; verrouiller écritures

; relire donnée écrite; --------------------

bsf EECON1,RD ; ordre de lecturebcf STATUS,RP0 ; passer en banque2

; envoyer pointeur et donnée; --------------------------

bcf STATUS,RP1 ; passer banque 0movf ptr+1,w ; charger pointeurcall sendtemp ; envoyerbsf STATUS,RP1 ; passer banque2movf EEDATA,w ; charger donnée luebcf 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 pointeurbas. En effet, nous n’avons que 256 emplacements de mémoire eeprom, donc un octet noussuffit, ainsi qu’un seul octet de donnée. Nous relisons la valeur écrite et la renvoyons auprogramme, 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, quiincrémentera aussi le pointeur haut, ce qui ne nous gène en aucune façon, bien que nous nel’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émoireeeprom, il ne peut donc risquer de se faire écraser.

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

Nous pouvons maintenant positionner le pointeur, et écrire en mémoire flash et eeprom. Ilnous reste une dernière commande, certes pas indispensable, mais bien pratique : pouvoirlancer 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 pasbesoin, vous pouvez la supprimer, et gagner ainsi quelques octets supplémentaires. Cettecommande 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"; ------------------

45

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 ; envoyermovlw "O" ; charger "O"call send ; envoyer

Vous voyez que le bootloader renvoie « GO » pour confirmer le retour au programme del’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’onn’a pas non plus, par conséquence, été en présence d’une autre commande valide, onexé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 1IF (BPORT == PORTA) ; si PORTAclrf ADCON1 ; ADCON1 dans l'état d'origineENDIF ; fin d'assemblage conditionnelmovlw 0xFF ; pour port en entréemovwf BPORT ; remettre PORT en entréebcf STATUS,RP0 ; repasser banque 0clrf PCLATH ; repointer en page 0return ; 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 effetque le programme n’avait pas besoin d’être écrit spécifiquement pour être chargé par unbootloader.

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

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 pagedans 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 dela page de notre bootloader.

46

A ce moment de l’explication, je vous précise donc que le bootloader ne peut pas setrouver à cheval entre 2 pages du PIC. C’est la seule contrainte concernant sa localisation. Sivous tentez de le faire, vous verrez des messages d’avertissement de changement de page lorsde l’assemblage.

Remarquez l’assemblage conditionnel concernant le PORTA, qui nous impose une lignesupplémentaire pour remettre ACON1 à 0 si nous avons utilisé une pin de ce port comme pinde 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 commandeincorrecte :

;*****************************************************************************; 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 lecturesmovwf cmpt ; dans compteur

commerrlclrwdt ; effacer watchdogbtfss PINT ; lire si pin entrée est au repos (=1)goto commErr ; non, on recommencemovlw DUR1B/2 ; pour une tempo de +- un demi bitcall tempo ; attendredecfszcmpt,f ; décrémenter compteur de bitsgoto commerrl ; pas dernière lecture, suivante

; répondre "ERR"; --------------

comrepmovlw "E" ; charger "E"call sendtemp ; l'envoyermovlw "R" ; charger "R"call send ; l'envoyermovlw "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 quesa 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 êtreinterprétée comme correcte.

Vous voyez que cette routine est composées de 2 parties. En effet, si on reçoit unecommande erronée, on ne peut pas savoir si l’utilisateur ne tente pas de passer des autresoctets 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 derépondre, afin d’être certain que notre message d’erreur sera effectivement reçu par le PC.

47

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 compteurclrwdt ; effacer watchdog

tempoli

WHILE i < BAUDRL ; tant que i < BAUDRLnop ; ajouter nop

i+=1 ; incrémenter iENDW

decfsztmps,f ; décrémenter compteurgoto tempol ; pas 0, recommencerreturn ; 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 parle paramètre « BAUDRL ». Vous voyez donc ici comment est utilisé ce paramètre.

Que dure l’exécution totale de cette boucle ? En effet, ceci est un paramètre importantpour expliquer les précédents calculs effectués dans nos directives initiales.

Le cœur de cette boucle est constitué des instructions suivantes :

tempolnop ; un certain nombres de nop, éventuellement « 0 »decfsztmps,f ; décrémenter compteurgoto 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 :

48

- 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 dureune 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 cyclede 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 compteurclrwdt ; 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édentcalcul, ce qui nous fait donc 4 cycles de moins à perdre dans la boucle. Notre calcul devientdonc :

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 auprogramme 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;-----------------------------------------------------------------------------

49

sendtempmovwf bbyte ; sauver octet à envoyermovlw DUR1B5 ; pour durée d'un bit et demicall tempo ; attendremovf 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 quicorrespond 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’attendreun demi-bit, j’ai choisi d’attendre un peu plus, par sécurité. Nous entrons maintenant dans laréception classique :

; envoyer start-bit; -----------------

sendmovwf bbyte ; sauver octet à envoyerbcf PINT ; pin = 0bsf STATUS,RP0 ; passer en banque1bcf PINT ; générer start-bitmovlw DUR1B ; pour durée d'un bitcall tempo ; attendremovlw 0x08 ; 8 bits à envoyermovwf cmpt ; dans compteur de bitsnop ; correction de timing

; envoyer 8 bits de data; ----------------------

sendlrrf bbyte,f ; lire bit poids faiblebtfss STATUS,C ; tester si bit = 0bcfPINT ; oui, envoyer 0btfsc STATUS,C ; tester si bit = 1bsfPINT ; oui, envoyer 1movlw DUR1B ; pour durée d'un bitcall tempo ; attendredecfszcmpt,f ; décrémenter compteur de bitsgoto sendl ; pas dernier, suivant

; envoyer stop-bit; ----------------

nop ; attendre fin délai bit 7nopnopbsf PINT ; passer en entrée = stop-bitbcf STATUS,RP0 ; repasser banque 0movlw DUR1B ; durée d'un bitgoto 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 ». Ongénère les « 1 » et les « 0 » en la faisant respectivement passer en entrée et en sortie. Cecinous permet de ne jamais générer un niveau « 1 », celui-ci s’effectuant par la résistance derappel de l’interface. Ainsi, nous ne générerons jamais de court-circuit, comme expliqué lorsde l’étude de l’interface.

Cette méthode s’apparente donc à celle, en électronique, d’un collecteur ouvert, nepouvant forcer que le niveau « 0 ». Vous voyez que vous pouvez imiter un comportementhardware uniquement en jouant sur le logiciel, il suffit d’avoir de l’imagination… et j’en ai ☺

50

Ici, les gestions de timing sont assez complexes, plus quelles n’en ont l’air. Je vais doncvous les expliquer en détails. Il importe de commencer par la boucle centrale, afin de calculerprécisément le temps complet d’une boucle. Ce temps est celui séparant l’émission de 2 bitsconsécutifs.

Je commence, pourquoi pas, par l’instruction d’appel de la routine de temporisation. Jeréécris ici la boucle centrale précédente en commençant par l’appel de la routine detemporisation :

call tempo ; 2 cycles en plus de la tempo (saut)decfszcmpt,f ; 1 cycle, car pas de sautgoto sendl ; 2 cycles, on revient en début de boucle

sendlrrf bbyte,f ; 1 cyclebtfss STATUS,C ; toujours 2 cycles pour l’ensemble de ces 2bcf PINT ; instructionsbtfsc STATUS,C ; encore 2 cycles pour ces 2 instructionsbsf PINT ;movlw DUR1B ; 1 cycle

Si nous faisons le total, cette boucle nous consomme 11 cycles, qu’il faudra déduire dutemps à 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 detemporisation.

Revenons en arrière, pour voir ce qui se passe pour l’émission du start-bit. Ce start-bit estcaractérisé par la mise à « 0 » de la pint. Ce start-bit doit durer également le même tempsqu’un bit classique.

On ne remarquera la fin du start-bit que si le bit suivant est à « 1 », sans quoi, « 0 » suivide « 0 » ne se remarquera pas. Voyons donc le temps que va durer notre start-bit :

bcf PINT ; ici, la ligne passe à 0movlw DUR1B ; 1 cycle écoulécall tempo ; 2 cycles + tempomovlw 0x08 ; 1 cyclemovwf cmpt ; 1 cyclenop ; 1 cycle

; envoyer 8 bits de data; ----------------------

sendlrrf bbyte,f ; 1 cyclebtfss STATUS,C ; 2 cyclesbcf PINT ; 0 cycle (sauté)btfsc STATUS,C ; 1 cyclebsf PINT ; la pin sera mise à 1 ici : 1 cycle nécessaire

51

Soit, un total de 11 cycles en plus de la routine de temporisation, soit exactement le tempsséparant l’émission de 2 bits calculé précédemment. Evidemment, le « nop » ajouté dans cetteroutine 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-bitest le passage à « 1 » de la pint. Autrement dit, si le dernier bit était à « 1 », on ne verra pas latransition. 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 cyclebtfsc STATUS,C ; 2 cyclesbsf PINT ; 0 cyclemovlw DUR1B ; 1 cyclecall tempo ; 2 cycles + tempodecfszcmpt,f ; 2 cycles (on saute)goto sendl ; 0 cycle

; envoyer stop-bit; ----------------

nop ; 1 cyclenop ; 1 cyclenop ; 1 cyclebsf 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 tempsstrictement 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 peumoins longtemps, mais cela ne se remarquerait pas, puisque la transition entre dernier bit etstop-bit serait invisible. L’important c’est qu’il n’y ai pas d’erreur cumulative.

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

bsf PINT ; stop-bit : nécessite 1 cyclebcf STATUS,RP0 ; 1 cyclemovlw DUR1B ; 1 cyclegoto 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 neprendra 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 uneinstruction. On économise également un niveau de sous-routine, mais ceci n’a aucuneimportance ici.

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

52

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

movf car2,w ; 1 cyclecall send ; 2 cycles

Ce qui nous donne encore 3 cycles supplémentaires. On en arrive donc à 8. Il nous fautencore entrer dans la routine d’envoi, qui va effectuer les opérations suivantes avant decommencer l’envoi du start-bit suivant :

sendmovwf bbyte ; 1 cyclebcf PINT ; 1 cyclebsf STATUS,RP0 ; 1 cyclebcf PINT ; générer start-bit (prend un cycle)

Ceci nous consomme donc encore 4 cycles supplémentaires, portant le total à 12. Notrestop-bit respecte donc le temps minimal qui lui est imparti. Vous voyez qu’il faut vraimentpenser à 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, cequi é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 watchdogbtfsc PINT ; pin réception = 0?goto $-2 ; non, attendremovlw DUR1B5 ; pour durée de 1.5 bitcall tempo ; attendremovlw 0x08 ; pour 8 bitsmovwf cmpt ; dans compteur de bits

reclbcf STATUS,C ; par défaut, bit = 0btfsc PINT ; bit reçu = 1?bsf STATUS,C ; oui, positionner carrynop ; pour correction du tempsrrf bbyte,f ; faire entrer bit reçumovlw DUR1B ; pour durée de 1 bitcall tempo ; attendredecfszcmpt,f ; décrémenter compteur de bitsgoto recl ; pas dernier, suivantmovf bbyte,w ; charger octet reçureturn ; fini, retourEND

53

Je ne vous recommence pas toute la démonstration, faites-la si vous le voulez. Concernantl’instant exact de l’arrivée du start-bit généré par l’ordinateur, elle s’effectue quelque partdans cette routine :

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

Autrement dit, on prendra un compromis entre temps minimum et temps maximumséparant l’instant présumé du start-bit et la lecture du premier bit. Il s’agit d’une erreurabsolue 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, dumoins si vous avez pris la peine de chercher à comprendre, ce dont je ne peux que vousféliciter.

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

54

Notes…

55

6. Mise en pratique hardware

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

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

Je choisis arbitrairement la pin RB7, étant entendu que le programme de destinationn’utilise que la pin RA2 pour faire clignoter la LED. La double utilisation d’une pin n’estdonc pas d’application, car il reste des pins inutilisées sur le PIC, autant donc utiliser une decelles-là.

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

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

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 pinsMclr, Vss,Vdd, et RB7. En sommes, rien qu’une petite “pinoche” sur le circuit, si vous nevoulez pas placer un connecteur spécifique, la liaison s’effectuant alors à l’aide de petitespinces “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.

56

N’oubliez pas, si vous avez mis en service les résistances de rappel au +5V pour lePORTB, 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 del’interface du bootloader pouvant s’effectuer directement par un pontage sur le connecteurrelié à vos sondes destinées à la carte d’application.

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

57

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.

58

Notes : …

59

7. Utilisation pratique du bootloader

7.1 Introduction

Nous avons maintenant notre circuit d’application et notre interface bootloader. Avant depouvoir définitivement placer notre PIC sur notre platine d’application, il nous faudra, une etune 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 lafrancisation 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 choisid’utiliser l’application avec laquelle j’ai mis au point le bootloader. Il est doncautomatiquement adapté à cette application.

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

La bonne méthode est d’effectuer un copier/coller du fichier « bgboot.asm » et derenommer 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 serale bootloader spécifique à l’application concernée.

Une fois fait, ouvrons notre fichier d’application (Led-tmr0.asm). La configuration duprogramme 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 seravisible 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 serezdans le même embarras.

60

Nous allons maintenant vérifier s’il n’existe pas d’incompatibilité avec le bootloader. Laprincipale é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ésirezmettre à jour à l’aide du bootloader.

Une protection partielle peut être envisagée, à condition d’être conscient que la partiesitué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 ». Eneffet, « WRT_ENABLE_OFF » empêche toute écriture en mémoire flash. Vous devrez doncmodifier ce bit obligatoirement.

Un oubli à ce niveau engendrera ainsi une erreur de vérification à chaque tentatived’écriture.

Le plus compliqué est fait. Eh oui, rien de bien difficile. Il nous suffit maintenant devérifier si les paramètres par défaut nous conviennent dans le bootloader, et, sinon, lesmodifier. 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. Attendonsl’assemblage.

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

- Nous utilisons un PIC 16F876, la taille mémoire flash est bien de 0x2000. Pas deproblè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 pardéfaut)

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

Message[301] chemin\ boot_led.asm 201 : MESSAGE: (La routine de boot se trouveen fin de page 3)

61

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

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

62

Notes : …

63

8. Utilisation pratique de BigoPic

8.1 Installation du logiciel

La première chose à faire est d’aller charger, si ce n’est déjà fait, l’utilitaire « BigoPic »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 lacommunication avec le bootloader. Il contient également d’autres fonctions, relatives audebugger, et que nous verrons plus tard.

Malheureusement, ce programme est écrit pour Windows. Je manque de temps pour ledévelopper pour une autre plate-forme.

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

La version de BigoPic que je vais utiliser ici est la version 1.0. Lorsque vous lirez cetouvrage, une nouvelle version sera peut-être en ligne, ce qui pourrait expliquer quelquesdifférences éventuelles dans les captures d’écrans et les explications. Je présume que ceci nedevrait 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 V1.0 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ésentdocument. Je vais donc vous expliquer en détails les différentes procédures.

8.2 Premier lancement de BigoPic

La première chose à savoir, c’est qu’à la fermeture du programme, un fichier« Bigopic.cfg » est enregistré dans le répertoire du logiciel, qui est, par défaut, « c:\programfiles\BigoPic ».

Tous vos paramètres sont enregistrés dans ce fichier, dernier mode utilisé, langue, tailleset 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 suffirade fermer le programme, et d’effacer le fichier « BigoPic.cfg ». Le prochain redémarrage deBigoPic s’effectuera avec les paramètres par défaut.

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

64

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 PICet le PC.

En fait, c’est l’équivalant du programme « BSCP » que vous avez vu dans la secondepartie du cours. La différence étant que ce programme est spécifiquement conçu pour piloterl’interface BigoPic, que celui-ci soit réalisé à partir d’un max232 (auquel cas il gère le reset),ou à partir des 3 opto-coupleurs (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 dudebugger ASCII.

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

La première chose à faire, est de configurer le port série en fonction de votreconfiguration. Cliquez donc sur la seconde petite icône de la barre d’outils, celle représentantune fiche DB9 avec un point d’interrogation.

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

65

Le bootloader, comme nous l’avons vu, utilise toujours 8 bits de données, et un stop-bit. Ilne gère pas la parité. J’ai cependant permis la modification de ces paramètres, ainsi vouspourrez 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 deBigoPic.

Cliquez « Accepter » pour valider votre choix. Vous n’aurez à faire cette opération qu’uneseule fois, les paramètres du port série faisant évidemment partie de ceux sauvegardés dans lefichier 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 ficheDB9 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 nonalphabétiques, dont plusieurs sont même invisibles. Si vous n’avez rien obtenu, vérifierinterface et connexions.

Si tout se passe comme prévu, vous savez déjà que votre bootloader est bien chargé, qu’ilfonctionne, que votre PIC tourne, que votre interface BigoPic reçoit, et que le resetfonctionne. 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 tentede tout afficher en ASCII . Comme position et taille ne sont pas forcément des caractèresascii, il est normal de ne pas pouvoir tout visualiser.

66

8.3 Passage en mode bootloader

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

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

67

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

En fait, c’est logique, puisqu’il s’agit ici de remplir la même fonction. Notez que les 2derniè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 sontuniquement 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 nonutilisée sera effacée, et aura donc le contenu 0x3FFF (regardez IC-Prog pour vous enconvaincre).

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

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

68

- Soit l’emplacement mémoire est représenté par « 3FFF », et dans ce cas, l’emplacementde 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 lamémoire eeprom.

Chacune de ces 2 fenêtres est séparée en 3 zones, en se souvenant que tous les nombressont 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 cetterepré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êtreeeprom. Le programme surveille en permanence votre saisie, et vous empêche d’entrer unevaleur incorrecte. Par exemple, vous ne pouvez entrer une valeur supérieure à 3FFF dans lamémoire flash.

Les touches « del » et « backspace » permettent d’effacer le contenu de la mémoireconcernée, qui ne sera donc pas envoyée au PIC.

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

69

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

Les zones représentées le sont pour des PIC qui comportent 8Kmots de mémoireprogramme et 256 octets de mémoire eeprom. Si vous utilisez des PICs plus petits, il suffit dene 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, aucontraire 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 quenous venons d’effectuer. Il restera cependant possible d’effectuer des modifications manuellesune 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.

70

Le programme effectue une vérification du format du fichier et vous signale en détail touttype d’erreur possible (format incorrect, mauvaise longueur, checksum etc.). Ceci peut êtreutile 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 devotre fichier « .hex ».

Vous voyez que la fenêtre inférieure est vide, et c’est logique, puisque notre programmene 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 larepré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 quenous avons déjà vu, il s’agit d’un saut (goto). En réalité, c’est le « goto init » de notreprogramme d’application.

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

71

A la suite, nous avons 3 instructions vides. On peut donc directement en tirer commeconclusion 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 simplementinexistantes. 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 0x00goto init

ORG 0x04Dé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èreque 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.

72

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

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 lePIC a bien envoyé la séquence « BGB » suivie de la position et de la taille de la routinebootloader intégrée dans le PIC.

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

- 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)

73

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 desinstructions du programme d’application, mais à des emplacements différents.

- Une LED rouge indique qu’un même emplacement mémoire contient une instructionbootloader 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ésente32 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 4rangées de Led, contenant chacune 64 LED. Chaque rangée représente donc une page demémoire. Vous pouvez donc instantanément visualiser les pages utilisées par votreprogramme.

Vous voyez 3 types de LEDs dans notre cas :

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

- Des LEDs vertes, qui représentent chacune 32 emplacements de mémoire programmeutilisés par notre programme d’application. Vous voyez que ce programme estridiculement petit comparé à la place disponible.

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

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

Cliquez sur le texte sur fond rouge « superposition » :

74

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 laLED 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, vousavez un conflit entre bootloader et programme.

Aux adresses 0x00 à 0x02 se trouvent le saut vers la routine bootloader, à l’adresse 0x00le 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 uneLED.

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

75

Vous voyez que notre programme occupe l’emplacement 0x00, puis les emplacements de0x04 à 0xB4 inclus. Vous aviez les mêmes informations en regardant la fenêtre derepré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 vousindique qu’il n’y a pas d’autre problème. Vous constatez maintenant que la LED rouge estdevenue 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,

76

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

Fermez cette fenêtre, puis cliquez sur <Quitter> pour revenir provisoirement à notrefenê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 explicitementpré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 dontvous désirez peut-être vous débarrasser avant d’envoyer un nouveau programme.

77

Je vous ai donné accès à cette possibilité, sous forme de 2 boutons. Un pour l’effacementinté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 pasd’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 setraduirait donc par un message d’erreur renvoyé par ce dernier.

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

Si vous utilisez un PIC avec une taille inférieure à celle d’un 16F876, vous aurez uneerreur de vérification à la première adresse rencontrée non présente dans le PIC. L’effacements’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’écriredes « 3FFF » dans tous les emplacements de la mémoire flash et des « FF » dans tous lesemplacements de la mémoire eeprom, que vous voulez effacer.

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

BigoPic fait donc parfaitement la différence entre une donnée non utilisée, représentée pardes tirets, et un emplacement à effacer, représenté par sa valeur 0x3FFF pour la mémoireflash, 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 nereprésente qu’une seule adresse. Ceci explique pourquoi l’effacement eeprom semblera plusrapide.

78

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

Une fois dépassée la zone que vous désirez effacer, cliquez <Stop>, ou laissez poursuivrel’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 en mode bootloader, sauf la plusintéressante, l’envoi du programme vers le PIC.

79

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

Au fur et à mesure de la programmation, les LEDs s’allument en jaune, signalantl’évolution du transfert.

BigoPic vérifie, pour chaque instruction envoyée, l’adresse retournée, et la valeureffectivement relue en mémoire flash. Autrement dit, si BigoPic vous indique que tout s’estbien passé, c’est que votre programme est effectivement correctement écrit dans votre PIC.

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

80

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 encours de développement.

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

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

Cliquez ce bouton :

Votre programme est lancé. Un coup d’œil vous permettra de vous rendre compte quevotre LED clignote, ce qui vous prouve que votre programme d’application est parfaitementopé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 autredonné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 lebouton « reset » de la barre d’outils, soit de repasser en mode « envoi vers pic », ce quigénérera automatiquement un reset. La led s’arrête de clignoter, votre PIC dialogue denouveau en mode bootloader. Vous pouvez relancer le programme par le bouton que nousvenons de voir.

Vous pouvez également tenter de générer des conflits, pour voir comment BigoPic secomporte.

Si vous entrez une instruction 0x0000 (nop) à l’adresse 0x01, par exemple, vous verrezqu’en tentant la vérification, ceci ne pose aucun problème au logiciel, celui-ci s’aperçoitqu’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 êtrerésolu, et vous aurez droit à un message d’erreur.

81

9. Conclusions

Nous voici déjà arrivés au terme de cette troisième partie, courte pour vous, maislongue pour moi, car, avant de pouvoir écrire ce petit livre, il m’a fallut concevoir leslogiciels, 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 unecarte déjà existante.

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

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

Je vous souhaite bon travail avec ce bootloader ☺

82

83

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, etsi vous appréciez ce que je fais, de contribuer un peu, chacun selon ses possibilités et sesdésirs.

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

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

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 butn'é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 assistancesans promesse d'aucun sorte, et sans contrainte. Je continuerai à répondre au courrier de toutle 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 quevous en faites.

Si oui, vous vous rendez sur mon site : www.abcelectronique.com/bigonoff ouwww.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, etcontribuent à 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’unsite 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 vousrépondre.

Je réponds toujours au courrier reçu. Aussi, si vous n’obtenez pas de réponse, n’hésitezsurtout 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 longuehaleine.

84

85

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 à jourpuisse être effectuée dans l’intérêt de tous, si possible en utilisant le livre de reportd’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 seraitdisponible uniquement sur mon site : www.abcelectronique.com/bigonoff ouwww.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 estfaite. Ainsi, j’espère toucher le maximum d’utilisateurs.

Le présent ouvrage peut être utilisé par tous, la modification et la distribution sontinterdites sans le consentement écrit de l’auteur.

Tous les droits sur le contenu de ce cours, et sur les programmes qui l’accompagnentdemeurent propriété de l’auteur.

L’auteur ne pourra être tenu pour responsable d’aucune conséquence directe ou indirecteré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. Toutextrait 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é queles programmes mis gracieusement à la disposition du public par la société Microchip. Lesdatasheets 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 dem’envoyer un petit mail, ou mieux, de poster un message sur mon site. Ceci me permettra desavoir si je dois ou non continuer cette aventure avec les parties suivantes.

Certains continuent à envoyer des messages sur mon ancienne adresse. Prenezconnaissance de la bonne adresse, pour de pas encombrer des adresses non concernées. Vousrisquez 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’estune demande qui revient toutes les semaines dans mon courrier. Tout d’abord je n’ai pas

86

le temps, et ensuite je ne pense pas que ce soit un bon service. Enfin, pour faire un peud’humour, si je donnais mes tarifs, ces étudiants risqueraient un infarctus.

- Je n’ai malheureusement pas le temps de debugger des programmes complets. Inutile doncde m’envoyer vos programmes avec un message du style « Ca ne fonctionne pas, vouspouvez me dire pourquoi ? ». En effet, je passe plus de 2 heures par jour pour répondre aucourrier, si, en plus, je devais debugger, j’y passerais la journée. Vous comprenez bien quec’est impossible, pensez que vous n’êtes pas seul à poser des questions. Posez plutôt unequestion précise sur la partie qui vous semble inexacte.

- Si vous avez des applications personnelles, n’hésitez pas à les faire partager par tous. Pource faire, vous pouvez me les envoyer. Attention cependant, faites précéder votre envoid’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 quitravaillent sur différentes plates-formes (Mac, Linux, Windows, etc.). Si, cependant, laversion fournie est inexploitable sur votre machine, merci de me le faire savoir. Notezcependant que ce cours utilise MPLAB pour les exercices, il faudra donc éventuellementadapter 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 sereconnaîtront. Nul doute que sans les nombreux encouragements reçus, ce livre n’auraitjamais 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 doncissu 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éalisation : Bigonoff

Email : [email protected] (Attention BIGOCOURS, PAS BIGONOFF)