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 :
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:
Enregistrer un commentaire