|
La bibliothèque can.s comporte les fonctions de base nécessaires
à l'utilisation de la carte SJA1000-PPC:
- sja_init_pelican
- Initialise le SJA1000
- receive_trame
- Réception d'une trame sur le bus
- send_trame
- Envoi d'une trame sur le bus
- send_trame_sans_verif
- Envoi d'une trame prioritaire sur le bus
- print_trame
- Affiche une trame sur un terminal
Ces fonctions sont toutes programmées en assembleur.
4.1.1 Représentation machine des trames CAN
Pour rendre plus aisée la manipulation des trames CAN avec le PPC403, nous
avons défini un format de représentation, que nous avons utilisée dans
chacune des procédures de la bibliothèque can.s
Afin d'optimiser le traitement des trames, le format retenu est très proche de
celui des registres du SJA1000 :
| r3 |
| XX | FFI | ID1 | ID2 |
| r4 |
| Data1 | Data2 | Data3 | Data4 |
| r5 |
| Data4 | Data5 | Data6 | Data7 |
4.1.2 Le fichier pelican.h
Le fichier pelican.h comporte les définitions d'équivalence de tous
les registres du SJA1000 lorsque celui-ci est en mode PeliCAN.
4.1.2.1 Procédure sja_init_pelican
Le procédure sja_init_pelican permet d'initialiser le SJA1000
en mode PeliCAN. La structure de cette procédure est celle donnée par la
notice d'application de Philips.
- Demande de passage en mode RESET
- Attente que le passage soit fait
- Demande de passage en mode PeliCAN
- Attente que le passage soit fait
- Configuration des Acceptance Masks
- Configuration du bit timing
- Configuration les autorisations d'interruptions (INTERRUPT_ENABLE)
- Configuration les drivers de sortie (OUTPUT_CONTROL)
- Demande de passage en mode normal
- Attente que le passage soit fait
D'autre part, la procédure donnée ici est une configuration possible,
mais il est évident qu'elle peut être adaptée au cas-par-cas.
En particulier, la version donnée laisse passer tous les messages vers le
buffer de réception... ce qui n'est pas toujours souhaitable !
Il est à noter que l'initialisation du SJA1000 provoque la perte du
contenu des buffers de réception et de transmission.
/**************************************
* sja_init_pelican *
* Initialisation du SJA1000 *
* params:aucun *
* resultat:aucun *
* GPR modifies:aucun *
**************************************/
sja_init_pelican:
push r3
attente_mode_reset:
/* passage en reset */
wrsjai 0x01,MODE
rdsja MODE,r3
andi. r3,r3,0x01
beq attente_mode_reset
attente_pelican:
/* Passage en Mode PeliCAN (bit 7) */
wrsjai 0x80,CLOCK_DIVIDER;
rdsja CLOCK_DIVIDER,r2
andi. r2,r2,0x80
beq attente_pelican
/* on accepte tout */
wrsjai 0xFF,ACCEPTANCE_MASK_0
wrsjai 0xFF,ACCEPTANCE_MASK_1
wrsjai 0xFF,ACCEPTANCE_MASK_2
wrsjai 0xFF,ACCEPTANCE_MASK_3
/* doit etre regle en fct des autres noeuds */
/* Bit time=20us pour un Xtal de 16MHz*/
wrsjai 0x07,BUS_TIMING_0
wrsjai 0x4D,BUS_TIMING_1
/*Desactivation des interruptions */
wrsjai 0x00,INTERRUPT_ENABLE
wrsjai 0xDB,OUTPUT_CONTROL
/* Bit 0 = 0: Sortie du mode RESET
Bit 1 = 0: Pas le mode Listen Only (donne des ACK)
Bit 2 = 0: Pas le mode Self Test
Bit 3 = 1: Acceptance filter mode = single */
attente_fin_mode_reset:
wrsjai 0x08,MODE
rdsja MODE,r3
andi. r3,r3,0x01
bne attente_fin_mode_reset
mode_normal:
pop r3
blr
|
Procédure sja_init_pelican.
4.1.2.2 Procédure receive_trame
La procédure receive_trame permet de regarder dans le buffer de
réception du SJA1000 afin de voir si une trame y a été reçue.
Si tel est le cas, la trame présente sera mise dans les registres r3, r4, r5 du
PPC selon le format défini précédemment.
- Test du bit 0 du registre STATUS du SJA1000. Si 1: on a reçu une trame. Si 0: le buffer est vide on ressort de la procédure.
- Positionnement r6 à 1 pour signaler la présence d'une trame valide dans r3, r4, r5
- Lecture des registres du buffer de réception: RX_DATA, RX_DATA+1...
- Libération la place du dernier message dans le buffer (positionnement du bit 2 du registre COMMAND)
- Si une surchage a eu lieu, on réinitialise l'indicateur (positionnement du bit 3 du registre COMMAND)
/******************************************************************
* RECEIVE_TRAME *
* Reception d'une trame. *
* Registres de resultat: r3 = ID, r4 = Data 1-4, r5 = Data 5-8 *
* r6=0 si pas de trame, 1 sinon *
******************************************************************/
receive_trame:
pushlr
li r3,0x0
attente_trame:
rdsja STATUS,r6
andi r6,r6,0x01 /* Receive buffer plein ? */
beq fin_receive_trame /* si =0 on sort */
rdsja RX_FRAME_INFO,r3
slwi r3,r3,0x8
rdsja RX_ID_1_S,r6 /* ID */
or r3,r3,r6
slwi r3,r3,0x8
rdsja RX_ID_2_S,r6
or r3,r3,r6
rdsja RX_DATA_S,r4 /* Data 1*/
slwi r4,r4,8
rdsja RX_DATA_S+1,r6 /* Data 2 */
or r4,r4,r6
slwi r4,r4,8
rdsja RX_DATA_S+2,r6 /* Data 3 */
or r4,r4,r6
slwi r4,r4,8
rdsja RX_DATA_S+3,r6 /* Data 4 */
or r4,r4,r6
rdsja RX_DATA_S+4,r5 /* Data 5 */
slwi r5,r5,8
rdsja RX_DATA_S+5,r6 /* Data 6 */
or r5,r5,r6
slwi r5,r5,8
rdsja RX_DATA_S+6,r6 /* Data 7 */
or r5,r5,r6
slwi r5,r5,8
rdsja RX_DATA_S+7,r6 /* Data 8 */
or r5,r5,r6
wrsjai 0x04,COMMAND /* Release receive buffer */
li r6,0xFF
/* clear le data overrun status si il y a lieu*/
rdsja STATUS,r2
andi. r2,r2,0x02
beq fin_receive_trame
wrsjai 0x08,COMMAND
fin_receive_trame:
poplr
blr
|
Procédure receive_trame.
4.1.2.3 Procédure send_trame
La procédure send_trame permet d'envoyer sur le bus CAN une trame
présente dans les registres r3, r4, r5 dans le format défini auparavant.
La structure de la procédure est celle donnée par la notice d'application de Philips :
- Attente de la disponibilié du buffer de transmission (i.e. attente que son contenu ait été transmis)
- Ecriture des octets de contrôle dans le registre TX_FRAME_INFO du SJA1000
- Ecriture des données dans le buffer : TX_DATA, TX_DATA+1...
- Demande de transmission : positionnement du bit 0 du registre COMMAND).
4.1.2.4 Procédure send_trame_sans_verif
La procédure send_trame_sans_verif est quasiment identique à la
procédure send_trame. La différence réside dans le fait que la
procédure send_trame_sans_verif ne vérifie pas la disponibilité
du buffer de transmission avant d'écrire dedans. Elle est donc susceptible
d'en écraser le contenu.
La procédure send_trame_sans_verif est donc à utiliser avec
précautions. Elle est utile lorsque l'utilisateur à besoin de transmettre un
message en priorité absolue par rapport aux autres.
/*************************************************************
* SEND_TRAME_SANS_VERIF *
* Envoi d'une trame sans verification du "tx buffer ready". *
* Registres: r3 = FFI, r4 = Data 1-4, r5 = Data 5-8 *
* NB: Ces registres ne sont pas modifies. *
************************************************************/
send_trame_sans_verif:
pushlr
push r3
wrsja r3,TX_ID_2_S
srwi r3,r3,8
wrsja r3,TX_ID_1_S
srwi r3,r3,8
wrsja r3,TX_FRAME_INFO
mr r3,r4
wrsja r3,TX_DATA_S+3
srwi r3,r3,8
wrsja r3,TX_DATA_S+2
srwi r3,r3,8
wrsja r3,TX_DATA_S+1
srwi r3,r3,8
wrsja r3,TX_DATA_S
mr r3,r5
srwi r3,r3,8
wrsja r3,TX_DATA_S+7
srwi r3,r3,8
wrsja r3,TX_DATA_S+6
srwi r3,r3,8
wrsja r3,TX_DATA_S+5
srwi r3,r3,8
wrsja r3,TX_DATA_S+4
wrsjai 0x01,COMMAND /* envoi */
pop r3
poplr
blr
|
Procédure send_trame_sans_verif.
|
|
La bibliothèque slio.s comporte les fonctions de base pour la gestion
de noeuds de type SLIO-82C150.
- calibration_slio
- Calibre tous les SLIOs présents sur le bus
- send_calibration
- Envoie un message de calibration sur le bus
- make_slio_ffi
- Initialise r3 (FFI+ID1+ID2) en vue de l'envoi d'un message à un SLIO
- wr_reg_slio
- Ecrit une donnée dans un des registres d'un SLIO
- test_slio_id
- Teste si le message contenu dans r3, r4, r5 provient d'un SLIO
4.2.1 Le fichier slio.h
Le fichier slio.h contient les définitions d'équivalence des registres des SLIOs.
4.2.1.1 Procédure calibration_slio
Calibration des SLIOs.
Cette procédure permet à l'utilisateur d'effectuer la première calibration
des SLIOs du bus. Comme expliqué auparavant, la calibration des noeuds de type
SLIO est indispensable à toute communication avec des SLIOs.
/**********************
* CALIBRATION_SLIO *
* parametres: aucun *
* GPR modifies:aucun *
**********************/
calibration_slio:
pushlr
push r3
push r4
li r4,0x30
attente_buffer:
rdsja STATUS,r3
andi. r3,r3,0x04 /* TXbuffer pret ? */
beq attente_buffer /* si = 0 on attend */
/* on place le message de calibrationd dans le buffer*/
wrsjai 0x40,TX_ID_2_S
wrsjai 0x15,TX_ID_1_S
wrsjai 0x02,TX_FRAME_INFO
wrsjai 0xAA,TX_DATA_S
wrsjai 0x04,TX_DATA_S+1
/* on attend que la transmission precedente soit terminee*/
attente_fin_transmission_prec:
rdsja STATUS,r3
andi. r3,r3,0x20
bne attente_fin_transmission_prec
/* on fait une demande d'envoi*/
wrsjai 0x01,COMMAND
/* On attend que la transmission ait commence*/
attente_debut_transmission:
rdsja STATUS,r3
andi. r3,r3,0x20
beq attente_debut_transmission
/* on avorte la transmission*/
wrsjai 0x02,COMMAND
/* on boucle 48 fois*/
boucle_de_calibration:
subic. r4,r4,1
bne attente_fin_transmission_prec
fin_calibration:
pop r4
pop r3
poplr
blr
|
Procédure calibration_slio.
Remarque : au début de l'exécution de la procédure de calibration, les SLIOs
n'acquittent pas les messages présents sur le bus. Dans le cas où seuls le
PPC et les SLIOs sont pr\'sents sur le bus, le SJA1000 du PPC comprendra que son
message a été mal reçu et il renverra son message jusqu'à
acquittement. C'est pourquoi on annule la transmission.
4.2.1.2 Procédure send_calibration
La procédure send_calibration est utilisée pour envoyer sur le bus
un message de calibration destiné aux SLIOs présents sur le bus.
Typiquement, cette procédure est utilisée pour effectuer la nécessaire
calibration périodique des SLIOs.
/****************************
* SEND_CALIBRATION *
* envoie un message de *
* calibration sur le bus *
* parametres:aucun *
* registres modifies:r3,r4 *
*****************************/
send_calibration:
pushlr
/* 0x00,0000 0010 000 1010 1010 0 0000*/
ld32b r3,0x00021540
/* 1010 1010 0000 0100*/
ld32b r4,0xAA040000
bl send_trame_sans_verif
poplr
blr
|
Procédure send_calibration.
4.2.1.3 Procédure make_slio_ffi
La procédure make_slio_ffi est utilisée pour écrire dans r3 les informations
nécessaires à l'envoi d'un message à un certain SLIO, spécifié dans r6.
On utilisera pour cela la procédure send_trame.
/*******************************
* MAKE_SLIO_FFI *
* initialisation de r3 pour *
* le slio precise sur r6 *
* params:r6 *
* GPRs modifies:aucun *
*******************************/
make_slio_ffi:
pushlr
push r6
push r7
li r3,0x0
mr r8,r6
FFI:
/* FF=0,RTR=0,DLC=3*/
li r7,0b00000011
slwi r7,r7,16
or r3,r3,r7
id:
/* r7=debut de l'id du SLIO (fixe)*/
/* 0101 0000 1000 0000*/
li r7,0x5080
or r3,r3,r7
/* r6=id*/
andi. r6,r6,0xF
/* on recupere P0 ds r7*/
andi. r7,r6,0x1
/* que l'on decale de 8+0 pr le mettre ds r3*/
slwi r7,r7,0x8
or r3,r3,r7
/* on recupere P1 ds r7*/
srwi r6,r6,1
andi. r7,r6,0x1
/* que l'on decale de 8+1 pr le mettre ds r3*/
slwi r7,r7,0x9
or r3,r3,r7
/* on recupere P2 ds r7*/
srwi r6,r6,1
andi. r7,r6,0x1
/* que l'on decale de 8+2 pr le mettre ds r3*/
slwi r7,r7,0xA
or r3,r3,r7
/* on recupere P3 ds r7*/
srwi r6,r6,1
andi. r7,r6,0x1
/* que l'on decale de 8+5 pr le mettre ds r3*/
slwi r7,r7,13
or r3,r3,r7
/* r3=0000 0011 01P31 0P2P1P0 1000 000 */
pop r7
pop r6
poplr
blr
|
Procédure make_slio_ffi.
Exemple d'utilisation
li r6,0x0Abl
make_slio_ffi
r3 est alors initialisé pour un envoi au SLIO d'ID 0x0A.
4.2.1.4 Procédure wr_reg_slio
La procédure wr_reg_slio est utilisée pour initialiser les
registres r4 et r5 en vue de l'écriture d'une donnée dans un registre d'un
SLIO.
La donnée à écrire est placée dans r7, et le numéro de registre dans
r6. Pour l'envoi à un SLIO, il est évidemment nécessaire d'initialiser
correctement le registre r3. On peut utiliser pour cela la procédure
make_slio_ffi.
/****************************
* WR_REG_SLIO *
* adapte une trame CAN *
* pour ecrire r7 (sur 16b) *
* dans r6 (sur 4b) *
* ATTENTION: suppose r3 (FFI*
* et ID) deja mis a jour *
* parametres:r4,r5,r6 *
* resultat:aucun *
* GPR modifies:r4,r6 *
****************************/
wr_reg_slio:
push r7
li r4,0x0
andi. r7,r7,0xFFFF
/* on met r6 sur les pds faibles du byte1*/
slwi r6,r6,24
or r4,r4,r6
/* on met r7 sur les bytes2 et 3 */
slwi r7,r7,8
or r4,r4,r7
pop r7
blr
|
Procédure wr_reg_slio
Exemple d'utilisation
La séquence de code ci-dessous écrit 0x32E5 dans le registre 0x7 (DATA_OUTPUT) du SLIO 0x0A.
li r6,0x0A
bl make_slio_ffi
li r7,0x32E5
li r6,0x3
bl wr_reg_slio
bl send_trame
4.2.1.5 Procédure test_slio_id
La procédure permet de tester si le message contenu dans r3,r4,r5 a un
ID correspondant à un SLIO. Si oui, r6 est mis à 1,et le numéro de SLIO est mis dans r7.
/*********************************
* TEST_SLIO_ID *
* renvoie r6=1 si le message *
* contenu dans r3 vient *
* d'un slio, et si oui, renvoie *
* son N d'id dans r7 *
* GPR modifies:r6,r7 *
*********************************/
test_slio_id:
pushlr
/* on ne s'interesse qu'a l'id fixe d'un slio*/
/*1101 1000 1110 0000*/
andi. r6,r3,0xD8E0
/* 0101 0000 1010 0000*/
cmpi 0,0,r6,0x50A0
/* s'il ne correspond pas on sort tt de suite*/
bne prov_non_slio
prov_slio:
/* on recupere (P2 P1 P0) sur r6*/
andi. r6,r3,0x700
srwi r6,r6,8
/* on recupere P3 dans r7*/
andi. r7,r3,0x2000
srwi r7,r7,10
/* on y ajoute r6*/
or r7,r7,r6
/*r7=0x(P3 P2 P1 P0)*/
li r6,0x1
b fin_test_slio_id
prov_non_slio:
andi. r6,r6,0x0
fin_test_slio_id:
poplr
blr
|
Procédure test_slio_id
|
|
MoniCAN est un outil de développement et de démonstration pour bus CAN, fait
pour être associé à la carte SLIO décrite précédemment. De plus, le
programme MoniCAN est un exemple d'application CAN utilisant les bibliothèques
can.s, slio.s ainsi que le programme loader loadCAN.s
MoniCAN permet à un utilisateur de contrôler jusqu'à 16 cartes SLIO
simultanément à l'aide d'un terminal de type VT100.
4.3.1 Caractéristiques
- Calibration et recensement de tous les SLIOs sur le BUS (jusqu'à 16)
- Commande des 5*16 sorties digitales
- Lecture des 4*16 entrées digitales
- Commande des 2*16 sorties DPM
- Lecture des 2*16 entrées ADC
- Programme uploadable par un superviseur
- Messages uploadables par un superviseur (mail, messages divers...)
4.3.2 Fonctionnement
Ecran de contrôle de MoniCAN
4.3.2.1 Initialisation
- Initialisation de l'écran du terminal
- Initialisation du SJA1000
- Lancement de la procédure de calibration calibration_slio
- Attente de la réception de trames
- Pour chaque message de signature venant d'un SLIO :
- Initialisation des sorties digitales et DPM des SLIOs reconnus
- Signalisation de la présence des SLIOs sur l'écran du terminal
4.3.2.2 Fonctionnement normal
Fonctionnement de MoniCAN
Les commandes entrées par l'utilisateur sont gérées par interruptions,
alors que la réception et le traitement des trames est fait par
scrutation. Ce choix ce justifie car le traitement d'une trame reçue est
toujours le même quels que soient les évènements antérieurs, alors
que la saisie des commandes se fait séquentiellement.
Lors de la saisie complète d'une commande par l'utilisateur, une trame est
envoyée au SLIO demandé. Cette trame spécifie au SLIO le registre à
modifier et la valeur à lui affecter. Une fois cette affectation faite, le
SLIO renvoie une trame comportant la nouvelle valeur du registre. Cette
trame est alors capturée, et la valeur du registre affichée sur le
terminal.
Ainsi, les états des entrés/sorties des SLIOs ne sont affichés que
lorsque les SLIOs les ont confirmés, et non pas lorsque l'utilisateur en a
fait la demande.
4.3.2.3 Traitement d'une trame reçue
- Test de l'ID :
- Si l'ID est l'ID d'un SLIO, on met à jour l'affichage du registre
concerné sur l'écran du terminal.
- Si l'ID correspond à une demande d'affichage d'un message (mail,...). On
prévient l'utilisateur par un message sur l'écran du terminal
- Si l'ID correspond à une demande de chargement de fichier par un
superviseur, on exécute le programme loadCAN (qui se trouve en FLASH-EEPROM)
- Retour à la boucle de scrutation
4.3.3 Utilisation
4.3.3.1 Envoi d'une commande
- Taper le numéro de SLIO demandé (de 0 à F)
- Taper 'I' pour une demande d'entrée et 'O' pour une demande de sortie
- Taper le numéro de Pin demandée
- Taper s'il y a lieu la valeur de la sortie (00/01 pour une sortie digitale, 00-FF pour une sortie DPM)
Remarque :
- Pour un bon fonctionnement, le clavier du terminal doit être en mode CAPS-LOCK, et le baudrate à 19200 bauds.
- L'affichage en bas de l'écran permet de suivre la commande tapée
4.3.3.2 Lecture d'un message envoyé par un superviseur
Lorsqu'un superviseur désire afficher un message/mail sur l'écran de
l'utilisateur, il envoie un message avec un ID particulier. Le message
you've got mail !(press Ctrl R to read it) s'affiche en bas de
l'écran du terminal. Lorsque l'utilisateur tape effectivement Ctrl R,
l'écran de gestion des SLIOs s'efface, et on signale au superviseur que l'on
est prêt à afficher son message.
4.3.3.3 Chargement d'un nouveau programme
Pour charger un nouveau programme dans le PPC (par exemple une nouvelle version
de MoniCAN), le superviseur doit envoyer une Remote Frame d'ID 0. Une fois cette
trame reçue, Monican effectue un branchement vers le programme loader en
FLASH-EEPROM, lequel signale au superviseur qu'il est prêt à recevoir le
programme. Pour plus de détails, voir le chapitre sur le programme
loadcan.s.
Remarque importante : A chaque compilation du loader, il faut modifier la valeur de
"loader" dans le fichier config.h à l'adresse du label "loader" du fichier
.L généré lors de la compilation du programme loadcan.s
|
4.4.1 Fonctionnement
Le loader CAN (loadcan.s) permet à un superviseur de transmettre à
un noeud PPC, un fichier s29, qui sera éxecuté.
La seule exigence pour le superviseur est de pouvoir transmettre un fichier ASCII par bus CAN.
4.4.1.1 Transmission du programme.
A la mise sous tension, le loader CAN se met en attente d'une trame de commande
("Remote frame") d'identificateur 0 et de DLC 0. Le superviseur doit envoyer une
telle trame lorsqu'il est prêt à envoyer le fichier .s29. Le loader répond
à cette trame de commande par une trame de données ayant le même ID, et ne
comportant aucune données. Cette trame signale au superviseur qu'il peut
commencer la transmission.
Le superviseur doit ensuite transmettre le fichier s29 en ASCII avec 8 octets de
données par trame, sauf pour la dernière trame (le test du DCL est le moyen
utilisé par le loader pour détecter la fin de la transmission). Une fois la
transmission ASCII terminée, le loader convertit le fichier ASCII en fichier
binaire.
4.4.1.2 Implémentation en mémoire.
Le loader charge le fichier s29, en ASCII à l'adresse debut_fichier,
specifiée dans le fichier de configuration config_loader.h.
Puis, lors de la conversion, l'exécutable est implanté a l'adresse
specifiée dans le s29.
4.4.2 Utilisation
4.4.2.1 Compilation du loader
Bien évidemment, le loader doit être implementé en Flash-EEPROM afin
d'autoriser la chargement d'un programme dès la mise sous tension. Par
consèquent, le linkage du loader doit inclure le bootstrap (objet boot.o).
4.4.2.2 Compilation du programme à loader
Le programme à charger ne doit en revanche pas etre linké avec boot.o, et il
ne doit pas non-plus inclure de symbole global de branchement au boot. Pour
contrôler l'adresse d'implantation en mémoire du programme chargé, il
suffit de préciser l'adresse dans le fichier de link du programme à loader.
4.4.2.3 Exemple
Pour un développement facile, il est utile d'avoir deux scripts de compilation
et deux fichiers de link (un pour le loader, et un pour le programme à
charger)
Le programme ci-après est un exemple fichier de link pour le loader.
Le fichier de loader y est implémenté en debut de Flash-EEPROM (en
laissant 2000h de place pour le procédures d'interruption)
SECTIONS
{
output_boot 0xfffffffc :
{
boot.o(.text)
}
output 0xfffe2000 :
{
*(.text)
*(.data)
}
}
|
Exemple fichier de link pour le loader.
Le programme ci-après est un exemple de fichier de link pour le
programme à loader. On peut y remarquer l'absence de link avec l'objet
boot.o (le branchement étant effectué par le loader).
SECTIONS
{
output_it 0x30000 :
{
ith.o(.text)
}
output 0x32000 :
{
*(.text)
*(.data)
}
}
|
Exemple fichier de link pour le programme à loader.
Avec un tel fichier de link, le programme à charger sera implanté en
30000h (les procédures d'interruption se situant entre 30000h et 32000h).
A noter que l'adresse d'implémentation du programme loadé doit bien
évidemment se situer en RAM.
L'arrivée des microprocesseurs dans les équipements de
sécurité automobile permettra de faire des accidents high-tech.
Prédiction de Krashtest Dummy.
|