samedi 23 juillet 2016

Silvercard : le PIC16F876


Nous avons vu qu'une Silvercard est composée d'un PIC16F876 (ou PIC16F877 selon les sources) et d'une EEPROM 24LC64. Etre capable de programmer une Silvercard, c'est être capable de programmer un PIC16F876, donc allons faire le tour des fonctionnalités intéressantes de la bête dans cet article.

Tout ce qui y à savoir sur un PIC16F876 est écrit dans sa datasheet. Néanmoins il n'est nul besoin d'étudier les 218 pages du document pour apprendre à le programmer dans le cadre d'une silvercard. En effet, dans une silvercard, le PIC est câblé de manière particulière (peu de pattes connectées) de sorte que seules peu de fonctionnalités nous intéressent.

Rappelons le câblage interne d'une Silvercard :

Le PIC16F876 comporte :
Une zone pour le programme de 8 Ko
De la RAM pour stocker des valeurs volatiles de 368 octets
Une zone EEPROM interne de 256 octets

Prenons chacun des ces éléments dans l'ordre.

La zone pour le programme


La figure ci-dessus montre la zone pour le programme. On y voit en bas les 0x2000 adresses (soit 8K) numérotées de 0x0000 à 0x1FFF. On notera que pour pouvoir adresser toute cette plage d'adresses il faut 13 bits (0x1FFF est codé sur 13 bits).

Chaque adresse peut comporter une instruction de 14 bits de large. On regardera le jeu d'instruction dans un autre article.

Revenons à l'adressage car il comporte une astuce qu'il convient de bien comprendre. En effet, comme dans un micro-processeur normal, dans un micro-contrôleur il y a des registres.

Le premier, celui qui nous intéresse dans le cadre de l'adressage, s'appelle PC (Program Counter). C'est le registre qui contient l'adresse de l'instruction que le micro-contrôleur est en train d'exécuter. Vous voyez tout de suite le problème : comment parcourir un espace d'adressage sur 13 bits avec un registre qui ne contient que 8 bits ? C'est impossible. C'est pourquoi apparaît cette notion de page que l'on voit sur le schéma.


Comme on peut le voir ci-dessus un registre en RAM appelé PCLATH intervient dans la construction de l'adresse complète de 13 bits : [les 5 bits de poids faible de PCLATH][les 8 bits de PC] ce qui au final fait bien une adresse sur 13 bits.

La conséquence de ce point est qu'il faut normalement faire attention quand on fait un GOTO ou un CALL à ce que la destination soit bien dans la même page. Si ce n'est pas le cas, il faut faire attention à ce que les bits 4 et 3 de PCLATH contiennent bien le numéro de la page dans laquelle se situe la destination du GOTO ou du CALL.


Normalement c'est le genre de détail qui doit être pris en compte par le compilateur, sauf que je ne sais pas encore à ce stade si gpasm le fait. En fait, on n'est pas confronté au problème tant que notre code n'a pas atteint la taille minimale de 2K. Je ne sais pas encore si mon programme atteindra cette taille ; il faut juste avoir en tête que si cela se produit, il faudra vérifier que cette subtilité est bien gérée par le compilo. Si ce n'est pas le cas, il faudra faire attention, selon un exemple donné dans le datasheet :

 

Il faut faire attention au fait que l'adresse 0x0000 et l'adresse 0x0004 contiennent deux « vecteurs », l'un pour le reset du PIC, l'autre pour l'interruption. Je mets « vecteur » entre guillemets car c'est un abus de langage. En effet, traditionnellement un vecteur contient une adresse à laquelle se brancher. Ici, ces cases comportent bien une instruction qui sera exécutée.

En clair, au boot, le PIC commence par exécuter l'instruction présente à l'adresse 0, et lors d'une interruption il se branche à l'adresse 4. Autant dire qu'il est quasiment impératif de commencer son programme par un GOTO sinon on exécute le programme d'interruption dès l'adresse 4.

L'interruption sera un mécanisme du PIC non utilisé dans le cadre de la Silvercard car … la patte correspondante n'est branchée à rien.

A noter que le PIC comporte aussi une zone de pile de 8 emplacements mémoire. Cette pile est située dans une zone particulière du PIC qui n'empiète pas sur l'espace d'adressage du programme. Cette zone de pile contient les adresses de retour lors des CALL. En effet, lorsqu'on fait un CALL on se branche ailleurs dans le programme, et on exécute jusqu'à ce qu'on rencontre l'instruction RETURN. A ce moment-là, on est censé revenir à l'instruction qui suivait immédiatement le CALL (ce qu'on appelle l'adresse de retour). Il faut donc avoir mémorisé cette adresse. C'est dans la pile que le micro-contrôleur mémorise l'adresse de retour.

La gestion de la pile est indépendante du programmeur. Quand on fait des CALL on empile, quand on fait des RETURN on dépile. C'est aussi simple que cela. Sauf que, comme il n'y a que 8 emplacements de pile, il faut faire attention de ne pas faire plus de 8 CALL imbriqués dans ses programmes. Le risque c'est que, si on fait des CALL vers des routines qui elles-mêmes font des CALL vers d'autres routines qui font des CALL, etc. on va vite avoir plus de 8 niveaux de CALL imbriqués. Et comme la pile est cyclique, l'adresse de retour du 9ème CALL vient écraser l'adresse de retour du 1er CALL et ainsi de suite. Donc si l'on dépasse 8 CALL imbriqués, le programme part assurément en cacahuète.

Bon bien, voilà, on a fait le tour de tout ce qu'il y a à savoir sur la zone de programme. Après, il faut pratiquer.

La zone de RAM de 368 octets


La figure ci-dessus montre l'organisation des 368 octets de RAM dans le PIC. On voit que la RAM est organisée en 4 banques de 128 octets chacune. On pourrait croire à tort que toute cette RAM est à disposition du programmeur. C'est faux car toutes les cases qui ont un nom sont des registres, et chaque bit de ces registres a un rôle bien particulier qui est documenté dans le datasheet. Les cases grises correspondent à des cases inaccessibles donc inutilisables. Reste à la disposition du programmeur seulement les « general purpose registers ».

Dieu merci, il n'y a pas besoin de bosser la signification de tous les bits de tous les registres pour utiliser notre PIC dans sa carte à puce.

Un des registres les plus important est le registre STATUS (accessible aux adresses RAM 0x03, 0x83, 0x103 ou 0x183). Ce registre contient le bit Z qui se met à 1 quand une opération a généré un résultat égal à 0, et le bit C (Carry) qui se met à un quand un calcul a donné lieu à un débordement. Les bits 5 (RP0) et 6 (RP1) du registre STATUS permettent de choisir dans laquelle des 4 banques on travaille selon le tableau suivant :


Les deux autres registres importants pour nous sont PORTB et TRISB. En effet, notre PIC a sa plusieurs ports d'entrées/sorties, dont l'un, le PORT B de 8 bits, a sa patte 7 connectée à la patte I/O de la puce de la carte à puce.

Le bit 7 du port B permet donc lorsqu'on y écrit, d'envoyer des données de la carte à puce vers le monde extérieur, et lorsqu'on y lit, de recevoir des données (APDU) du monde extérieur.

Le registre TRISB permet lui de paramétrer en entrée ou en sortie chaque bit du port B. Si l'on met le bit 7 du registre TRISB à 1 alors le bit 7 du port B est en entrée. A 0 le bit 7 du port B sera en sortie.

Dans le cadre de l'utilisation du PIC dans la Silvercard, on veillera à ce que le bit 7 de TRISB soit à 1 en permanence, sauf les rares fois où l'on a quelque chose à émettre.

Tous les registres dont le noms commencent par EE sont impliqués dans la lecture ou l'écriture des données dans la zone d'EEPROM interne au PIC.

Un autre registre qui peut être intéressant est celui de l'adressage indirect (adresse 0, 0x80, 0x100 et 0x180). En fait, la lecture ou l'écriture dans cette case de RAM se fait en réalité dans la case de RAM dont l'adresse a été mise dans le registre FSR.

Voilà pratiquement tout ce qu'il y a à savoir sur la RAM pour utiliser le PIC dans le cadre d'une Silvercard.

La zone d'EEPROM interne de 256 octets

Le PIC comporte une zone de mémoire interne de 256 octets. C'est bien peu par rapport aux 8 Ko contenus dans l'EEPROM externe 24LC64. Il faut voir cependant qu'une donnée est beaucoup plus en sécurité dans l'EEPROM à l'intérieur du PIC (qui est protégeable en lecture) que dans l'EEPROM à l'extérieur du PIC (qui n'est pas protégeable en lecture). Une donnée sensible, comme une clé de cryptographie par exemple doit être mise en EEPROM interne.

Accéder en lecture ou en écriture dans la zone d'EEPROM interne est assez compliqué. En tout cas assez compliqué pour que la datasheet du PIC donne carrément les deux routines pour le faire proprement. Les voici :

Lecture :


On met dans ADDR (adresse qu'on choisit où l'on veut en RAM) l'adresse de la case d'EEPROM interne à lire (entre 0 et 255) et on appelle la routine ci-dessus. On récupère la donnée lue dans le registre W.

Tiens, c'est la première fois qu'on parle du registre W. Ne le cherchez pas en RAM, il n'y est pas. C'est d'ailleurs le seul registre qui n'est pas en RAM. Son petit nom dans tous les micro-processeurs du monde c'est « l'accumulateur ». L'accumulateur du PIC s'appelle W.

Bref, on voit qu'avec la routine ci-dessus, c'est facile d'aller lire une case d'EEPROM interne.

Ecriture :


On voit que l'écriture en EEPROM est plus compliquée que la lecture. On met dans ADDR et VALUE (2 adresses de RAM qu'on choisit arbitrairement) l'adresse de la case d'EEPROM dans laquelle on souhaite écrire, et la valeur (octet) à y écrire, puis on appelle la routine ci-dessus qui réalise l'écriture.

Même si la routine est compliquée, comme elle est donnée directement par le constructeur son utilisation est simple.

Au final, avec les deux routines données par le constructeur, lire ou écrire dans l'EEPROM interne est très facile.

Eh bien, mine de rien, on vient de voir comment ça se passe pour la zone de programme, la zone de RAM et la zone d'EEPROM.

Il ne reste plus qu'à voir le jeu d'instructions du PIC et on en aura déjà fait le tour, au moins en ce qui concerne son utilisation dans le cadre d'une Silvercard.

Jeu d'instruction du PIC est le suivant.


Le tableau ci-dessus montre les 35 instructions du PIC, avec la manière dont l'instruction sur 14 bits sera construite, et aussi les bits de statut qui sont impactés par l'instruction.

Il s'agit d'instructions très basiques, que nous verrons dans un prochain article.

Publié par Alan Cartman le 23 juillet 2016


















Aucun commentaire: