MétroPole > Exploitation > SACEM > 4. Processeur codé

RER
 

 
L'une des principales innovations du SACEM est l'utilisation de microprocesseurs pour l'ensemble des traitements. Il a donc fallu mettre au point un procédé qui assure une sécurité totale au système à chaque fois qu'il fait appel aux microprocesseurs (par exemple dans le module contrôle de vitesse). C'est le rôle du « processeur codé ».

Retour  |  Mono- ou bi- ?  |  Code  |  Signatures  |  Réalisation  |  Révolution ?  |  Suite

Comment concevoir un système sûr ?

Biprocesseur...

On dit qu'un système est « de sécurité » si toutes les pannes pouvant l'affecter (défaillance de composants, ou aléas extérieurs au système) conduisent à un état ne mettant pas en danger la vie humaine. Habituellement, on utilise une sécurité « intrinsèque », c'est-à-dire une connaissance totale et sûre des composants du système, qui génère en cas de problème un état restrictif des commandes de sortie (arrêt d'un train, par exemple). Mais compte-tenu de la complexité des systèmes à microprocesseurs, il est extrêmement difficile d'en modéliser toutes les possibilités de défaillances, donc de conserver la même approche de sécurité.

Une première possibilité consiste à utiliser une redondance matérielle, en l'occurrence plusieurs processeurs calculant indépendamment, et à y associer un jeu de tests. Cela assujettit la sécurité du système à la durée du jeu de tests (temps de fonctionnement maximal avant détection d'une panne), l'exhaustivité du jeu de tests (proportion de pannes détectables), et à l'impossibilité de pannes communes à toutes les unités redondantes (condition pour que le système détecte les pannes non couvertes par les tests).

Les systèmes à redondance matérielle sont le plus souvent de deux types :

Les premières études de SACEM ont été lancées sur la base d'une architecture à deux microprocesseurs, et comparateur de sécurité (« biprocesseur de sécurité »). Mais il est apparu que les tests mis en œuvre dans ces systèmes redondants, donc la garantie de leur sécurité, sont fortement liés aux composants utilisés (processeurs, mémoires...) ; il est donc nécessaire de les remettre en cause à chaque évolution technologique du matériel. Cela constituait évidemment un inconvénient important pour assurer la pérennité du système SACEM.

... ou monoprocesseur codé ?

On a donc préféré à la redondance matérielle une autre méthode, permettant d'assurer la sécurité uniquement par un codage approprié des informations, traitées alors dans un seul processeur (appelé « monoprocesseur codé »). Fondée sur une approche probabiliste, elle a été développée au début des années 1980 à partir d'une idée de Matra Transport. Cette méthode associe deux techniques de codage :

A partir du programme source, le processeur codé peut détecter toutes les défaillances de la chaîne de traitement, depuis la compilation jusqu'à l'exécution du programme, sans vérification préalable des outils intermédiaires (compilateur, assembleur, ...). La sécurité du système ne dépend plus de la technolgie utilisée, ni de sa fiabilité, mais seulement de la taille (le nombre de bits) du codage. Cette transparence vis-à-vis du matériel est l'avantage majeur du processeur codé : elle permet de suivre les progrès technologiques de la micro-informatique, donc de bénéficier des gains de performances des nouveaux composants, sans renouveler de démonstrations de sécurité. Certes la manipulation du code, en plus de l'information utile, augmente nettement les temps de traitement par rapport au « biprocesseur » à sécurité intrinsèque ; mais la puissance croissante des microprocesseurs devait permettre de gommer cet effet.

Après réalisation d'un prototype biprocesseur et d'un prototype « monoprocesseur codé » du SACEM, c'est en définitive cette seconde solution qui a été retenue, compte-tenu des avantages qu'elle laissait espérer.

L'utilisation du codage ne se limite d'ailleurs pas aux seuls processeurs : elle couvre la quasi-totalité du système, et en particulier les transmissions de sécurité (sol-train, train-sol, sol-sol). Pour être totalement cohérent, il a même été décidé de développer un capteur de déplacement numérique codé (la roue phonique).

Néanmoins, la sécurité intrinsèque n'a pas disparu pour autant : elle continue de protéger les interfaces de sortie et certaines interfaces d'entrée.

Retour  |  Mono- ou bi- ?  |  Code  |  Signatures  |  Réalisation  |  Révolution ?  |  Suite

Le code arithmétique

Pour assurer la sécurité du système, il faut détecter tous les dysfonctionnements et les erreurs pouvant se produire entre l'écriture du code source logiciel et l'exécution de ce logiciel dans l'équipement. Qu'elles surviennent lors de la compilation ou l'exécution du programme, ces défaillances se ramènent toujours à une combinaison des trois cas suivants :

Puissance du codage

Une variable quelconque du programme est représentée, dans le cadre du traitement codé, par une valeur X codée comprenant une partie « information » et une partie « contrôle ».

La partie contrôle étant fixée par ailleurs, parmi les 2Ni+Nc mots possibles, seuls 2Ni (toutes les valeurs fonctionnelles possibles) sont correctes. Donc la probabilité pour qu'un mot codé erroné soit considéré comme valide est :

Cette grandeur, appelée puissance de codage, détermine le niveau de sécurité du système, car elle représente la probabilité de ne pas détecter une erreur.

Ainsi, le niveau de sécurité du système peut théoriquement être rendu aussi élevé que possible en utilisant une taille de code suffisamment grande (Nc suffisamment grand). Se fixer un objectif de sécurité pour le système revient à choisir la taille du code.

Protection contre les erreurs de calcul

Les erreurs d'opération sont traitées par un codage arithmétique.

Si x est la valeur fonctionnelle de la variable X traitée, on peut écrire : x = qx A + rx, où A est un entier premier (appelé clef du code) et rx le reste de la division euclidienne de x par A.

Quand A est grand, x = rx, et le codage se ramène à une simple redondance. On introduit donc un entier positif k tel que 2k > A, et on a : 2k = qk A + rk, où rk est le reste de la division euclidienne de 2k par A. Donc : 2k x = rk rx = rkx [A] (où [A] représente l'opération « modulo A »). On positionne alors -rkx sur les k bits de contrôle, et on obtient une représentation qui permet la vérification : 2k x - rkx = 0 [A].

Par exemple, si on doit effectuer l'addition de Y et Z et affecter le résultat à X, la partie fonctionnelle de X aura pour valeur x = y + z et la partie contrôle de X contiendra  -rk(y+z). Si cette addition est corrctement effectuée, le résultat X conservera sa propriété de divisiblité par A, puisque 2k (y + z) - rk(y+z) sera multiple de A.

De même, dans le cas de la multiplication des parties fonctionnelles y et z, l'opération associée portant sur les valeurs codées Y et Z est telle que le résultat reste divisible par A.

Protection contre les erreurs d'opérande et d'opérateur

Les erreurs d'opérande et d'opérateur sont traitées par le concept de « prédétermination de signature », permettant de vérifier le fonctionnement correct d'une séquence de programme.

A toute information du programme, on associe une valeur prédéterminée Bx, appelée signature statique de X, liée à l'identité de X mais indépendante de sa valeur. Cette signature est ajoutée à la partie contrôle de la valeur codée X : X devient ( 2k x , - rkx + Bx ).

Par exemple, si on doit effectuer l'addition de Y et Z et affecter le résultat à X (X = Y + Z), les cas suivants peuvent se présenter :

Une approche déterministe assurant que ces relations sont vérifiées en tout point du programme étant extrêmement délicate, voire impossible si l'on doit considérer des erreurs multiples, on utilise une méthode probabiliste : les signatures statiques Bx sont choisies au hasard (dans l'ensemble [1,2,3,...(A-1)]), et seules quelques vérifications complémentaires sont nécessaires pour éviter les éléments absorbants des fonctions Fop (tels 0 pour la multiplication).

Cependant, à ce stade de définition, tous les cycles de calcul manipulent les mêmes signatures. Il y aurait donc possibilité de leurrer le contrôle en lui fournissant toujours la même constante, et le programme pourrait utiliser des données non rafraîchies. Pour éviter cela, on introduit, dans la partie contrôle de la variable codée, une variable supplémentaire appelée date. Elle est différente à chaque cycle d'exécution du microprocesseur ; commune à toutes les informations codées traitées dans un même cycle, elle garantit leur validité temporelle. On utilise ainsi une signature dynamique.

Le « codage », c'est donc l'association à toute information x contenue dans le programme d'une variable codée X. Celle-ci intègre une redondance arithmérique (-rkx) de la valeur x, et témoigne de son identité (BX) et de sa validité temporelle. Elle est de la forme :

partie fonctionnelle

partie contrôle

2k x

- rkx + BX + D [A]
redondance arithmétique + signature statique + date

Nous avons vu que 2k x - rkx = 0 [A]. Si le programme s'est bien déroulé, la variable résultante doit présenter une signature (BX + D) modulo A. En cas d'erreur de calcul, la partie contrôle ne représente pas la même valeur que la partie fonctionnelle, et on a 2k x - rkx = e [A]. La détection se fait en montrant que la variable résultante X n'est pas congrue à BX + D (mais à BX + D + e).

Vérification

Les applications de sécurité ferroviaire présentant un état stable (par exemple l'arrêt du train) sont souvent conçues en un programme unique appelé périodiquement. Il est donc naturel de prévoir une vérification des signatures synchronisée avec l'appel du programme. Au lieu de faire ce calcul en parallèle avec le programme (ce qui s'apparente à une redondance et présente les inconvénients de défaillances communes décrits précédemment), on procède par « prédétermination » des signatures attendues, c'est-à-dire qu'on les calcule avant toute exécution.

Pour une information codée X quelconque, le critère de validité est la vérification de la congruence modulo A à une valeur prédéterminée Bx. L'information est considérée valide si cette propriété caractéristique est vérifiée ; sinon, elle est dite « hors code ». Cette vérification se fait en dédatant la variable codée, en effectuant la division euclidienne par A et en comparant la valeur obtenue à la valeur prédéterminée.

Pour réaliser cette vérification à chaque étape élémentaire du programme, il aurait fallu un processeur dédié fonctionnant parallèlement à l'application. Cette solution, posant à nouveau le problème des systèmes redondants, a été écartée au profit d'une sécurité intrinsèque : la vérification n'est effectuée qu'au moment de la commande des actionnements de sortie. Il y a donc une seule vérification par cycle, mais ce n'est pas très pénalisant puisque la probabilité de compensation d'erreurs multiples est de l'ordre de grandeur de la puissance du code.

Cette très haute probabilité de détecter, quoi qu'il arrive, toutes les erreurs pouvant survenir au cours du traitement est la clé de la sécurité du système.

Retour  |  Mono- ou bi- ?  |  Code  |  Signatures  |  Réalisation  |  Révolution ?  |  Suite

Principe des signatures

Pour rendre le codage utilisable, il faut aussi s'assurer, lors d'un branchement (un test SI... ALORS... SINON...), que la branche suivie est bien celle qui doit l'être, et dans le cas contraire, provoquer un « hors code » des variables modifiées. Or le reste caractéristique d'une variable évolue différemment selon la branche empruntée, puisque les opérations sont différentes d'une branche à l'autre (c'est la raison du branchement). Pour que le contrôle final de bon séquencement soit possible, les restes caractéristiques issus des différentes branches sont donc compensés de façon à être identiques en fin de branchement :

Comme cette précaution, tout en assurant un bon suivi des signatures, est insuffisante pour garantir que la branche suivie est bien celle attendue, on effectue un marquage supplémentaire des signatures des variables à l'aide d'une variable codée appelée variable de test T. Dans le cas d'un test à deux branches, la partie redondance de T peut prendre les valeurs T alors = - rk alors + BT ou T sinon = - rk sinon + BT.

En fin de branchement, la signature de X est marquée par cette partie redondance de T. La compensation CompX est donc précalculée, de manière à obtenir, après marquage et compensation, l'égalité suivante :
BX alors - rk alors + BT = BX sinon - rk sinon + BT + CompX  (1).

Toute erreur de branchement se traduira alors par un brouillage des signaux en fin de branchement. Par exemple, si la branche « sinon » est exécutée à la place de la branche « alors », la signature de la variable X est marquée par BT - rk alors ,  puis compensée par CompX. D'après (1), on aura :
BX sinon + BT - rk alors + CompX = BX alors + BT - 2 rk alors + rk sinon, valeur comparée au BX alors + BT - rk alors  correspondant à la signature de X en l'absence d'erreur. En cas d'erreur, la valeur obtenue diffère de la valeur attendue de BX alors + BT - rk alors.

Pour les structures répétitives (boucles), le principe est analogue : marquage par la variable de test et compensation.

Retour  |  Mono- ou bi- ?  |  Code  |  Signatures  |  Réalisation  |  Révolution ?  |  Suite

Réalisation matérielle

L'organisation générale du matériel est basée, pour le système SACEM ligne A, autour d'un microprocesseur 68020. Cela justifie, a posteriori, certains choix stratégiques du codage, par exemple celui de ne travailler qu'avec des entiers (imposé par les médiocres performances du 68020 en virgule flottante), ou d'introduire un facteur 2n (les multiplications par 2n sont très rapides, puisqu'il suffit de décaler les variables à multiplier de n bits).

La conversion des entrées intrinsèques (issues de capteurs) en valeurs codées est assurée par une carte conçue en sécurité intrinsèque. La valeur codée n'est élaborée que si l'entrée correspondante est dans un état permissif, c'est-à-dire si elle est à l'état logique haut pendant toute la durée de l'échantillonnage (25 à 100 ms). Les valeurs codées des entrées sont également datées avant d'être traitées par le microprocesseur.

Une fois les valeurs codées des entrées reçues, le microprocesseur effectue le traitement simultané des parties fonctionnelles et codées des informations. Il élabore ensuite les sorties (non codées) commandant les actionneurs de sortie.

Les cartes d'interface entre les sorties du processeur et les actionneurs n'étant pas conçues en sécurité intrinsèque, il faut vérifier qu'une commande restrictive du processeur correspond bien à une action restrictive de l'actionneur, et n'a pas été transformée de façon erronée en sortie permissive. Pour cela, on effectue une relecture des sorties restrictives, qui sont inversées en sécurité, puis encodées de la même façon que les entrées de sécurité.

Le contrôle des sorties

Le microprocesseur élabore alors une signature résultant de l'exécution de tous les cycles de traitement depuis l'initialisation, et qui tient compte des parties contrôle des sorties permissives, et des parties contrôle des relectures des sorties restrictives. Cette séquence datée est envoyée à un dispositif de vérification, dit contrôleur dynamique. Conçu en sécurité intrinsèque, ce contrôleur décode la séquence reçue ; si la séquence datée issue du processeur coïncide exactement, après dédatation, avec celle contenue en mémoire morte (PROM), le contrôleur dynamique fournit l'énergie d'alimentation des sorties. Sinon, les sorties sont forcées à l'état restrictif.

Ce contrôleur dynamique assure donc le fonctionnement en sécurité de tout le processus : validité du traitement effectué par le microprocesseur, et fonctionnement correct des interfaces de sortie. Pour limiter les coûts, une seule carte contrôleur est utilisée, au lieu d'une par sortie.

Retour  |  Mono- ou bi- ?  |  Code  |  Signatures  |  Réalisation  |  Révolution ?  |  Suite

Une révolution dans les transports ?

Le développement du « processeur codé », qui aura demandé une dizaine d'années d'efforts, a constitué une nouveauté importante dans le domaine de la sécurité des systèmes de transport : il a facilité la transition vers des systèmes « de sécurité » plus performants ou assurant des fonctions nouvelles, à base de microprocesseurs.

Le processeur codé n'a pas exactement été mis au point pour SACEM. Néanmoins, le SACEM ligne A en constitue la première application opérationnelle, et le processeur codé est à ce titre considéré comme l'une des grandes avancées technologiques du projet.

La (relative) simplicité des concepts auxquels il fait appel ne doit pas masquer une certaine complexité dans sa mise en œuvre, en particulier pour le développement de l'outil de prédétermination de signatures. Néanmoins, la puissance du codage (possibilité de détecter toute défaillance du processus, de la compilation du logiciel à l'exécution sur le microprocesseur), et le niveau de sécurité qu'il garantit quel que soit le matériel utilisé, l'ont déjà fait choisir pour un nombre sans cesse croissant d'applications : outre le SACEM, citons le POMA 2000 à Laon, Maggaly à Lyon, le VAL de Chicago O'Hare, la TVM 430 du TGV Nord, le SAET de Météor...

En fait, dans la plupart des applications où la sécurité de fonctionnement est un point critique, c'est lui que l'on a tendance à employer. Il reste quelques cas où l'on préfère utiliser des systèmes à vote majoritaire, essentiellement parce qu'ils sont moins gourmands en puissance de calcul. Mais, au fur et à mesure que les performances des microprocesseurs utilisés en informatique industrielle augmentent (avec le 68030, puis le 68040), ce (gros) inconvénient de la technique « processeur codé » s'estompe.

Et, en attendant, le codage qui en est à la base fait des merveilles : on l'a dit, non content de sécuriser les traitements d'informations, il permet aussi de détecter les erreurs dans leur transmission !

Retour  |  Mono- ou bi- ?  |  Code  |  Signatures  |  Réalisation  |  Révolution ?  |  Suite

Sommaire Actu Guide Reseau Stations Horaires Exploitation Liens