3 Juillet 2019
Juillet 2019. Dans quelques jours nous célèbrerons l'événement majeur de la conquête spatiale, le premier pas de l'homme sur la Lune. Un événement qui est venu concrétiser une des plus vastes entreprises humaines de l'Histoire. Et comme toute histoire, elle a ses drames, ses succès et ses héros. Il ne fait nul doute que Neil Armstrong et Buzz Aldrin seront mis à l'honneur. Certains mettront en avant Michael Collins qui a fait le voyage sans poser son pied sur notre satellite. Les passionnés de politique parleront de l'élan donné par Kennedy avec son discours du 12 septembre 1962.
We choose to go to the Moon. We choose to go to the Moon in this decade and do the other things, not because they are easy, but because they are hard; because that goal will serve to organize and measure the best of our energies and skills; because that challenge is one that we are willing to accept, one we are unwilling to postpone, and one we intend to win.
D'autres chercheront à mettre les "figures de l'ombre" sous le feu des projecteurs; ceux qui ont oeuvré en amont pour préparer la mission, ceux qui ont exploré les solutions techniques, les quelques-uns qui ont laissé leur vie pour ouvrir la voie. En tant qu'informaticien, je serais tenté de mettre en avant celle qui a piloté le programme de développement logiciel de l'informatique embarquée sur la mission: Margaret Hamilton.
Il n'est plus si commun de nos jours de voir des femmes mener des projets d'une telle ampleur. Ce projet de développement logiciel de 1400 homme-ans, mobilisant jusqu'à 350 personnes au plus fort de son activité, aiguiserait l'appétit de pas mal de commerciaux de SSII aujourd'hui.
Ce n'est pourtant pas avec cette icône du mouvement "Women in tech" que je souhaiterais lancer cet article, mais avec Steve Bales, responsable du guidage lors de la phase d'alunissage. Et c'est la citation d'un autre président américain qui met en lumière son rôle crucial.
This is the young man, when the computers seemed to be confused and when he could have said Stop, or when he could have said Wait, said, Go.
L'AGC (Apollo Guidance Computer) est un ordinateur numérique (à cette époque certains s'efforçaient encore se produire des ordinateurs analogiques) responsable des calculs permettant à l'équipage d'assurer le guidage des véhicules. Un exemplaire de l'AGC était ainsi installé sur le module de commande et un autre sur le module lunaire. Le code source des logiciels tournant sur ces deux ordinateurs est disponible dans le dépôt suivant: https://github.com/chrislgarry/Apollo-11. A la racine du dépôt on trouve justement les deux composants logiciels fonctionnant respectivement sur le module de commande et sur le module lunaire. Pour comprendre le rôle joué par Steve Bales, nous nous intéresserons à celui du module lunaire: Luminary.
Au moment où le module lunaire se sépare du module de commande pour entamer sa descente vers la Lune, Aldrin active le radar de rendez-vous avec le module de commande. Cette manoeuvre vise à préparer le rendez-vous de retour qui pourrait avoir lieu dans l'urgence si un événement devait contraindre à l'abandon de la mission. Au cours de la descente, Aldrin doit vérifier que la trajectoire réelle correspond à celle calculée par l'AGC et active ainsi la commande 1668 qui doit lui permettre d'afficher sur le DSKY la valeur du paramètre DELTAH, différence entre l'altitude mesurée et l'altitude théorique. Au moment d'activer cette commande pour la première fois, l'AGC affiche le code d'erreur 1201 suivi du code d'erreur 1202. Sollicité par Aldrin, l'équipe sol lui demande réitérer la commande 1668 mais le résultat est le même.
It appears to come up when we have a 1668 up
Pour comprendre l'origine de cette erreur, il faut se reporter au fichier source EXECUTIVE qui regroupe les routines prenant en charge la gestion de l'exécution des commandes par l'AGC. Nous sommes aujourd'hui familiers de machines qui disposent de plusieurs coeurs et qui proposent donc un parallélisme d'exécution réel. Il ne faut néanmoins pas remonter très loin dans le temps pour n'avoir que des machines mono-coeur, incapables d'exécuter plusieurs opérations simultanément. Et c'est bien évidemment le cas de l'AGC. Il est pourtant nécessaire que l'AGC puisse fournir des informations calculées de manière continue à partir de mesures acquises en temps quasi-réel. Cette nécessité impose donc à l'AGC d'émuler un parallélisme en assurant une rotation des procédures sur l'unité de traitement (un mode de fonctionnement qui a perduré puisqu'il était encore enseigné sous le nom de "tourniquet" lors de mes cours d'UNIX il y a une vingtaine d'années). L'AGC est ainsi doté d'un ensemble de registres lui permettant de stocker la valeur du pointeur d'instruction de chacune des procédures actives. Lorsqu'une nouvelle commande est activée, son instruction de démarrage est ainsi insérée dans le premier registre (appelé "core") disponible. C'est lors de cette opération que se produisent les erreurs 1201 et 1202.
FINDVAC2 TS EXECTEM1 # (SAVE CALLER'S BANK FIRST.) | |
CCS VAC1USE | |
TCF VACFOUND | |
CCS VAC2USE | |
TCF VACFOUND | |
CCS VAC3USE | |
TCF VACFOUND | |
CCS VAC4USE | |
TCF VACFOUND | |
CCS VAC5USE | |
TCF VACFOUND | |
LXCH EXECTEM1 | |
CA Q | |
TC BAILOUT1 | |
OCT 1201 # NO VAC AREAS. |
La routine FINDVAC2 est destinée à chercher un registre vacant pour y insérer le pointeur d'instructions de la commande activée. L'issue de cette procédure laisse comprendre que la commande poussée par Aldrin est arrivée au moment où il n'y avait aucun registre vacant: "OCT 1201 # NO VAC AREAS." L'instruction OCT ne me semble pas documentée, mais ça pourrait bien correspondre à l'affichage octal de la valeur 1201. La découverte de ce programme de l'AGC est l'occasion de s'intéresser à son jeu d'instruction et de la façon dont on "codait" il y a cinquante ans.
La première instruction TS EXECTEM1 correspond à un "Transfer to Storage" qui transfère le contenu du registre A à l'adresse indiquée en paramètre. Le registre A correspond au registre dit d'accumulation (ou d'usage général) qu'on retrouve sous le nom AX dans nos processeurs x86 actuels.
La second instruction CCS VAC1USE correspond à une instruction "Count, Compare and Skip" et est certainement l'une des plus complexes du jeu d'instructions que j'ai pu découvrir. Pour en rester à la logique de la procédure qu nous intéresse, on peut la résumer à une instruction de branchement fonction de la valeur de l'adresse passée en paramètre. Si la valeur est positive, le branchement se fait sur l'instruction suivante, alors qu'une valeur nulle conduit à saut vers l'instruction d'après. Dans notre cas, cela revient à tester la valeur de VAC1USE: si elle est positive, on passe à l'instruction TCF VACFOUND alors que si elle est nulle, on passe à l'instruction CCS VAC2USE. On peut en déduire que l'adresse VAC1USE indique si le VAC1 (Vector Accumulator 1) est disponible pour être utilisé.
Si le VAC1 est disponible, on sort de la séquence. TCF VACFOUND correspond en effet à un "transfer control" consistant à changer le pointeur d'instruction de la procédure pour atteindre une autre procédure du logiciel de vol.
Si le VAC1 est occupé, on poursuit avec un test sur VAC2. En cas d'indisponibilité de l'ensemble des 5 "Vector Accumulators" on parvient à l'instruction LXCH EXECTEM1 qui consiste à échanger le contenu du registre A avec l'adresse mémoire indiquée en paramètre.
L'exécution se poursuit donc avec l'instruction CA Q qui correspond à un "Clear and Add" consistant ici à charger le registre A avec le contenu du registre Q qui contient l'adresse de retour de la procédure courante.
L'instruction TC BAILOUT1 qui suit consiste à effectuer un transfert de contrôle à l'adresse indiquée; à cette occasion, le registre Q qu'on a précédemment sauvegardée dans le registre A est remplacée par l'adresse de l'instruction suivante pour permettre un retour après l'exécution du bloc en BAILOUT1.
L'analyse de BAILOUT1 conduit dans les méandres du traitement des alarmes de l'AGC; son code source peut-être trouvé dans le module ALARM_AND_ABORT. On notera juste qu'il démarre avec l'instruction INHINT qui consiste à inhiber les interruptions. L'objectif ici est d'entrer dans une section critique qui ne doit pas être préemptée par le traitement d'un signal.
Pour conclure ce survol du logiciel de bord d'Apollo 11, nous pouvons jeter un rapide coup d'oeil au bloc NEXTCORE qui cherche le prochain Core disponible.
NEXTCORE CAF COREINC | |
ADS LOCCTR | |
CCS EXECTEM2 | |
TCF NOVAC3 | |
LXCH EXECTEM1 | |
CA Q | |
TC BAILOUT1 # NO CORE SETS AVAILABLE. | |
OCT 1202 |
On voit ici une certaine similitude avec le bloc étudié précédemment. L'issue est notamment la même avec un appel BAILOUT1 et un affichage du code 1202. Les deux codes d'erreur témoignent donc bien d'un problème de disponibilité des registres gérant le pointeur d'instruction des procédures en cours.
La dernière particularité qu'on pourra souligner sur le logiciel de vol de l'AGC, c'est le câblage direct de l'instruction ABORT derrière un bouton du panneau de commande du module lunaire. C'est ce bouton qu'Aldrin n'a pas pressé le 20 juillet 1969. Face à ces deux alarmes, la question s'est pourtant posée et la décision a été prise par Steve Bales de poursuivre la mission. Bales avait connaissance de ces deux warnings qui s'étaient produits lors des essais d'Apollo 5 et qui n'avaient pu être reproduits, sans donner lieu à des difficultés majeures pour la suite des essais. Le problème ne relevait pas d'une anomalie logicielle (pour une fois) ni d'une erreur de pilotage, mais plutôt d'une erreur de conception du module AGC qui n'a pas été conçu pour supporter la charge de calcul qui lui a été imposée pendant la phase d'alunissage, en particulier à cause d'une utilisation excessive de ressources processeur consommée par le radar de rendez-vous avec le module de commande., conduisant les autres procédures à durer plus longtemps et à saturer les registres de stockage des pointeurs d'instruction.