***** INTERRUPTIONS SUR LES MICROPROCESSEURS SATURN ***** et cas particuliers des calculateurs HP28 et HP48 (S et SX seulement, ***** mais les G et GX ne diffŠrent que par l'organisation du bus et par les ***** adresses en ROM : les principes sont les mˆmes). ***** par MJS 20/06/1994 I. Introduction. La documentation publi‚e par Regis DUCHESNE (HPReg) le 25/05/1994 me semblant quelque peu succinte, je me permets d'en publier une un peu plus complŠte. Notons que le seul tort de HPReg est de croire qu'il dispose de TOUTES les connaissances mondiales sur les HP48... Il a cependant le m‚rite d'avoir publi‚ quelque chose, ce que n'ont jamais fait auparavant les "initi‚s", qui disposaient des secrets des interruptions dŠs l'‚t‚ 1992. Je profite donc de cette introduction pour le remercier de son initiative. Ce texte donne une liste plus complŠte des interruptions existantes, et de leur exploitation. Passons aux choses s‚rieuses : que sont les interruptions. Pour ceux qui n'ont pas lu le rapport de HPReg, disons qu'il s'agit de programmes appel‚s par le processeur lorsque certains composants ‚lectroniques en font la demande : sur les HP28/48, ces composants sont les suivants : - le clavier - l'accumulateur de secours - le port infra-rouge - le port s‚rie (sauf HP28) - le "timer" - les modules de m‚moire vive (RAM) De plus, la touche RESET au dos des HP48 utilise un m‚canisme sp‚cial, qui sera d‚crit plus loin. Comme on le voit, il y a plus de deux types d'interruptions, contrairement … ce qu'affirmait HPReg, et ses deux types n'en font en fait qu'un. J'insiste cependant pour saluer son courage : qu'il ne prenne pas mes remarques aux s‚rieux ! (On ne doit jamais prendre les remarques de MJS au s‚rieux. Ni les programmes, d'ailleurs !) II. Structure normale d'une machine bas‚e sur le SATURN de MOTOROLA. Il est important de comprendre la structure de votre machine avant d'essayer de jouer au plus fin avec elle ! En gros, disons que, comme sur tout ordinateur (et pour ceux qui l'ignorent, le processeur SATURN est un processeur RISC de grande classe, ce qui lui permet d'ˆtre plus rapide qu'un IBM PC pour pas mal d'applications...), la piŠce centrale est le bus. Le bus (ou les bus) est en fait un groupe de fils. Pour le SATURN, il doit y avoir deux bus : un bus … 4 fils (on dit un bus 4 bits) pour les donn‚es, et un bus … 20 fils (20 bits) pour les adresses. A quoi ‡a sert ? Eh bien, tout composant branch‚ sur le bus s'en sert pour communiquer avec les autres. Les composants en question sont le processeur SATURN, les modules de m‚moires ROM et RAM, l'‚cran, et un composant sp‚cial pour g‚rer le reste du mat‚riel. Supposons que A (le processeur, par exemple) veuille envoyer une donn‚e … B (disons une RAM). Les op‚rations sont les suivantes : - A se rend maŒtre du bus en montant la tension d'un fil … +5 V. On dit que ce bit est … 1. D‚sormais, les autres circuits ne peuvent plus se servir du bus. - A "‚crit" l'adresse o— il veut ‚crire sur le bus d'adresse. Cela veut dire que pour chaque chiffre binaire de cette adresse, soit 20 bits, il place le fil correspondant … +5 V si ce bit est … 1, et … 0 V s'il est … 0. - A "‚crit" de mˆme la donn‚e - un quartet - sur le bus de donn‚e (… 4 bits). - A indique au reste de la machine qu'il va ‚crire, en changeant l'‚tat d'une ligne sp‚cial (il en existe une autre pour l'‚criture, mais rien n'indique si ces lignes sont actives lorsqu'elles portent un 1 ou un 0). - Tous les autres composants sur le bus savent alors que quelqu'un ‚crit. S'ils sont capables de lire quelque chose, ils d‚codent alors le bus d'adresse. B d‚tecte alors que c'est lui qui doit g‚rer cette adresse. Les autres savent aussi qu'ils ne doivent rien faire. - B lit donc le bus de donn‚e, et le copie … l'adresse vis‚e. - A libŠre le bus. Ceci vous explique beaucoup de choses : - quand on ‚crit plusieurs quartet en m‚moire, il faut ajouter un cycle d'horloge par quartet transmis : cela est d– au fait que le bus de donn‚e n'ait que 4 bits, et qu'il faille donc r‚p‚ter plusieurs fois le manŠge ci-dessus. - quand on ‚teint l'‚cran d'un HP48, il travaille plus vite, car l'afficheur des HP48 "vole" l'usage du bus au processeur pour rafraŒchir l'‚cran, environ 20 fois par seconde. - chaque circuit est responsable du d‚codage de ses adresses, et il faut donc qu'il sache o— il est plac‚ dans l'espace d'adressage, et combien d'adresses il y occupe. Pour les m‚moires, ces renseignements sont donn‚es par des registres sp‚ciaux. L'instruction UNCNFG donne l'ordre au module dont l'adresse de base courante est sur le bus d'adresse d'effacer ces registres, et d'attendre un ordre de configuration. Celui-ci est donn‚ par CONFIG. Le module en attente remplit alors son registre de configuration avec la valeur sur le bus d'adresse. S'il a plusieurs registres de configuration, et c'est le cas des RAM de 32 Ko et plus, il en remplit un (ici, la taille), et reste en attente. Un deuxiŠme CONFIG lui indique comment remplir le suivant. Vous savez maintenant comment on d‚place la RAM des HP48 ! Et si vous avez besoin de la d‚placer, c'est tout simplement parce que cette RAM d‚code son adresse AVANT la ROM dite cach‚e, qui ne re‡oit donc rien, tant qu'on n'a pas chang‚ l'adresse de base de la RAM... Notez d'autre part que UNCNFG ne d‚configure pas qu'un seul module, mais tous les modules … partir de l'adresse de base indiqu‚e. Il faut donc les reconfigurer tous un par un. Le HP48 le fait, mais pas les programmes des voyous comme vous et moi. Le r‚sultat est que, si vous utilisez une adresse sur un port pendant que la RAM est d‚plac‚e, c'est le drame. Mais avouons que ce cas est rare... - quand on tente un UNCNFG depuis le module … d‚configurer, la machine se plante lamentablement : le processeur ne peut plus y lire le programme … ex‚cuter. La solution classique est d'utiliser (sur HP48) la routine en 026BF, qui fait ‡a pour vous ! - le circuit qui calcule les CRC le fait en fait en consultant le bus de donn‚e … chaque fois que le bus est activ‚ en lecture. III. Cas du RESET. Quand on appuie sur la touche RESET au dos des HP48, on active la broche RESET du SATURN, ce qui provoque la r‚initialisation du processeur, puis l'appel de la routine en 00000. La routine effectivement appel‚e est donc celle qui se trouve au d‚but du module configur‚ en 00000 (et pas toujours la ROM qui devrait s'y trouver, si vous voyez ce que je veux dire...). C'est pourquoi chaque module (les ROM font en g‚n‚ral 64 Ko, soit 20000 quartets) contient au d‚but un GOSBVL sur l'adresse d'initialisation (la mˆme que celle atteinte aprŠs ON-UP sur HP28, ou ON-C sur HP48). Pourquoi un GOSBVL et non un GOVLNG ? Tout simplement parce que cela empile un 00000 dans la RSTK, et, en cas de RTN non identifi‚, la machine revient en 00000, fait un Machine Reset, et ‚vite au programmeur un Memory Clear (ou Lost, sur HP28), ce qui est bien agr‚able. Merci HP ! Ce paragraphe n'avait rien … voir avec les interruptions, mais certains sont persuad‚s que le RESET est reli‚ … une interruption... IV. Les interruptions. Lorsqu'un composant ‚lectronique est t‚moin d'un ‚v‚nement historique, au sens de la machine, elle signale au processeur qu'elle a un scoop par une ligne sp‚ciale. Le processeur sauve alors le bit qui distingue les modes INTOFF et INTON (interruptions interdites ou autoris‚es), interdit les interruptions, sauve l'adresse en cours (la valeur de PC) dans la RSTK, et saute en 0000F. Il faut donc qu'il y ait l… une routine se terminant par RTI, pour remettre en ‚tat le systŠme d'interruptions (selon le mode en vigueur avant cette interruption), et retourner dans le programme initial. HPReg a trŠs bien d‚crit la routine des HP48. Je vous y renvoie si cela vous int‚resse. Sur HP28, c'est pratiquement la mˆme chose, avec une astuce : la machine dispose d'une m‚moire sp‚ciale en FFE28 pour sauver les registres, comme en 7045D sur S(X) et 805DC sur G(X). L'int‚rˆt de cela est que, si la RAM a un problŠme, on peut encore s'y retrouver... A noter l'‚quivalent du ON-SPC des HP48 est ON-ENTER-BACKSPACE sur HP28. C'est un mode de sommeil, moins violent que Memory Clear, mais plus ‚nergique que ON-C ou ON-UP. En plus, il provoque moins de Memory Clear que ON-C. La derniŠre section de cette documentation est destin‚e … HPReg uniquement. Je lui demande de bien vouloir si reporter. IV.1) Interruption clavier. Son r“le est ‚vident : elle est d‚clench‚e par l'appui sur une touche. Le gestionnaire doit lire la touche, et g‚rer une ‚ventuelle r‚p‚tition automatique. La touche ON est g‚r‚e comme les autres, mais elle est aliment‚e par une ligne sp‚ciale de OUT, ce qui la rend plus difficile … masquer. IV.2) Interruption de l'accumulateur de secours. Elle signale que les piles sont faibles. IV.3) Interruption IR. Elle signale la r‚ception d'un caractŠre sur le port Infra-Rouge. Il faut le lire et le garder quelque part. IV.4) Interruption s‚rie. Elle signale l'arriv‚e d'un caractŠre sur le port s‚rie. Cette fois, c'est toute le "packet" qu'il faut lire... IV.5) Les "timers". Il n'y a qu'une seule horloge sur les HP28/48... Mais elle est reli‚e … deux compteurs, dont la mise … z‚ro provoque une interruption. Sur HP28, les compteurs sont en FFFF8 et FFBF8, et leur port de contr“le en FFx0F (si le bit 3 est … 1, la valeur est invalide, et on d‚marre le compteur en copiant le bit 1 dans le bit 2...). IV.6) Interruption RAM. Elle survient lors de la d‚faillance d'une RAM. C'est rare, mais fort gˆnant... V. D‚tournement des interruptions. Sur HP48, on ne peut que se prosterner devant le travail de HPReg et de ses collŠgues... Un extrait de la documentation de HPReg, ainsi que ses remerciements (politesse oblige), figure … la fin de cette documentation : je ne vais quand mˆme pas m'attribuer une m‚thode qui n'est pas de moi ! Je me suis cependant permis de corriger deux petites fautes de frappes : un "debut" ‚tait devenu "denut", et un "adresse" "addresse". Commentaire personnel sur la m‚thode avec une carte : cr‚ez un BACKUP a nom vide, comme indiqu‚, mais donnez lui une taille suffisante pour lui et votre nouveau gestionnaire d'interruptions, ET les parties de la ROM que vous conserverez. La routine-gestionnaire laissera des blancs aux adresses voulues, mais tout son code tiendra dans les 2 Ko d‚plac‚s. Bilan, ces 2 Ko ne sont pas perdus, et vous ‚vitez d'avoir … placer la "routine auxiliaire" … une adresse fixe : elle est dans le backup. (Tant pis pour ceux qui n'ont pas suivi...). Sur HP28, j'ai mention‚ l'existence d'une zone (FFE28 … FFE56) pour les sauvegardes du gestionnaire d'interruptions. Utilisez-l… pour votre propre gestionnaire, bien-s–r, mais aussi pour "l'‚changeur" : quelque chose comme UNCNFG / LC F / CONFIG / LC 0 / CONFIG / PC=A pourrait ˆtre utile. (Ex: A=adr de *SUITE, LC C0000, P=4, GOVLNG FFE28, *SUITE, P=0). On peut aussi utiliser l'‚cran, ou mˆme la zone des indicateurs LCD (je vois mˆme des yeux de possesseurs de HP48 qui p‚tillent...). VI. Conclusion. Cette documentation n'aura pas appris grand' chose aux ‚lectroniciens n‚s. Son but est surtout de dissiperr des id‚es fausses sur les interruptions, et de leur enlever une part de leur mystŠre. Mais la programmation par interruptions reste un art difficile … maŒtriser. Lancez-vous si vous le voulez, mais seulement si vous le voulez vraiment. C'est pour cette raison que je n'ai pas fourni de programme entier sur HP28, et que toute mes indications de programmation sont rest‚es vagues. Ceux qui ont tout compris en savent suffisamment pour programmer efficacement, pour les autres, m‚diter ou s'abstenir : vous ‚viterez des d‚gƒts mat‚riels. *************** SECTION EXTRAITE DE LA DOCUMENTATION DE HPREG ************** *************** sans l'aimable autorisation de l'auteur ******************** *************** mais on s'en fout ! **************************************** III - Detournement du gestionnaire de la HP48 III.I - Position du probleme Comme vous pourriez le constater en desassemblant completement le gestionnaire de la machine, il n'y a aucun moyen, une fois rentre dans la routine, de se brancher a une adresse fixee par vous. La seule possibilite pour substituer un gestionnaire a celui de la machine est donc de l'implanter a l'adresse 0000F. Mais comment faire puisqu'il y a de la ROM a cet endroit la? La reponse est simple, mais il fallait y penser: il suffit de deconfigurer un module RAM commencant a l'adresse AdrRam, dans lequel on aura ecrit notre gestionnaire a l'adresse AdrRam+0000F, puis de le reconfigurer a l'adresse 00000. Ainsi, la machine executera bien en 0000F notre propre gestionnaire. Nous disposons de deux sortes de module RAM: les cartes RAM (pour ceux qui ont la chance d'en avoir), et la RAM interne. Etudions chacun de ces cas... III.II - Detournement par carte RAM (HP48 eXpandable seulement) III.II.I - Explications Afin que la carte reste a peu pres utilisable, nous allons eviter d'ecrire "betement" notre nouveau gestionnaire a l'adresse AdrRam+0000F. Nous allons essayer de creer un veritable objet que nous mettrons au debut de la carte. Or il s'avere que le seul objet qui, mis a l'adresse AdrRam, puisse comporter des donnees a partir de l'adresse AdrRam+0000F est un objet backup ayant un nom vide. Evidemment, on veut que cet objet soit le plus petit possible, donc il faut le prendre de la plus petite taille de module configurable, soit 2 Ko. Le but du jeu, avec un nouveau gestionnaire, est que la machine ne plante pas! On va donc, en premier lieu, reprendre le gestionnaire de la machine, mais en lui apportant quelques petites modifications: Cf le commentaire du desassemblage du gestionnaire a l'adresse 000DF (voir plus haut), nous pouvons remarquer que si nous supprimons le GOTO 00140, nous avons une zone de 33 quartets, comprise entre les adresses 000DF et 000FF incluses, dont nous pouvons pleinement profiter, car HP nous a gentiment laisse de la place! Il n'est bien sur pas question de mettre toutes nos modifications du gestionnaire dans seulement 33 quartets, mais nous pouvons desormais nous brancher sur une routine que nous qualifierons d'"auxiliaire". Pour que l'on n'ait pas a reecrire notre objet backup a chaque fois que l'on deplace la routine auxiliaire, on a interet a stocker l'adresse de la routine auxiliaire en RAM interne, par exemple a l'adresse 7067E sur S, 807FC sur G (ce sont les adresses ou sont ecrites les adresses des noyaux des machines, elles ne servent plus a rien une fois que la machine a fini son arret systeme). III.II.II - Creation de l'objet backup Voici donc le programme RPL (qui suppose la possession de programmes classiques tels que PEEK, POKE, et H-> (librairie DEV par Etienne de Foras (ETI) de numero 1796 sur S, 1797 sur G) qui est aussi appele GASS ou RASS dans Voyage au centre de la HP48.) permettant de creer son propre objet backup: << "26B205001000000" @Prologue objet backup vide de taille 2 Ko (sans CRC) #F #D0 PEEK + @Recopie gestionnaire jusqu'a l'adresse 000DF exclue "34vwxyz808E" + @Rajoute les instructions LC zyxwv, PC=(C) qui @ tiennent sur 11 quartets, vwxyz vaut sur S:E7607, sur @ G:CF708 1 86 START "0" + NEXT @Rajoute 86=(#00140-#00100)+(33-11) quartets de vide #140 #EC0 PEEK + @Recopie le reste de la ROM pour remplir les 2 Ko "119200abcd" + @Rajoute le CRC de l'objet, abcd vaut sur S:C746, sur @ G:ADE1 H-> >> @Transformation de l'hexadecimal en un objet Nous avons desormais le nouveau gestionnaire, stockez-le au debut de votre carte (le plus simple est de MERGEr la carte, de faire 0 STO sur l'objet backup, puis de faire 0 PVARS x FREE, ou x est le numero du port contenant la carte). III.II.III - Creation de la routine auxiliaire A titre d'exemple, je vous propose comme routine auxiliaire une inversion video des 14 lignes du haut de l'ecran situees avant la barre horizontale (pourquoi pas...). Voici son source: "D0= 12D21 C=DAT0 A D0=C C=DAT0 A D0=C P= 2 *BOUCLE C=DAT0 16 C=-C-1 W DAT0=C 16 D0=D0+ 16 C=DAT0 16 C=-C-1 W DAT0=C 16 D0=D0+ 16 C=DAT0 B C=-C-1 B DAT0=C B D0=D0+ 2 P=P+1 GONC BOUCLE GOVLNG 00140 @" Remarques: - Ce source est compatible S et G, il suffit de faire une lecture en 12D21 pour obtenir l'adresse ou est sauvee l'adresse de la bitmap ecran, soit sur S:7050E et sur G:8068D. Cela constitue la Quatrieme Ruse. - Noter l'utilisation en incrementant P, plutot qu'en le decrementant, ce qui evite d'avoir a le remettre a zero a la fin. - Noter que DAT0=C 16 prends un cycle horloge de moins que DAT0=C W qui fait la meme chose... Assemblez le source et stockez l'objet Code qui contient la routine auxiliaire, a une adresse fixe: vous pouvez par exemple le mettre dans le var pour l'instant. Il ne nous reste plus qu'a ecrire le petit programme que nous appellerons "echangeur" qui va deconfigurer la carte et la reconfigurer en 00000 pour une taille de 2 Ko. III.II.IV - Creation de l'echangeur Voici le source d'un echangeur sous sa forme la plus simple: "AD0EX C=0 A P= 4 LC x %x vaut 8 pour une S, et C pour une G UNCNFG P= 3 LC FF CONFIG C=0 A CONFIG P= 0 D0=A GOVLNG 12002 %A=DATO A, D0=D0+ 5, PC=(A) @ Remarque: - Parfois, Il ne sert a rien d'utiliser les routines SAV.REG (0679B) et LOAD.REG (067D2). III.II.V - Action Vous voici fin pret. La premiere des choses a faire est de retirer une eventuelle deuxieme carte (celle qui ne comporte pas l'objet backup contenant le nouveau gestionnaire) de la machine et d'effectuer un arret systeme: ainsi, l'on est sur que la seule carte restante sera bien configure en 80000 sur les S, et en C0000 sur les G, ce qui va beaucoup aider l'echangeur... Maintenant, recuperez l' adresse de l'objet Code contenant la routine auxiliaire, ajoutez #A pour avoir l'adresse de la routine elle-meme, et POKEz cette adresse en 7067E sur S, 807FC sur G. Assemblez l'echangeur, ne le stockez surtout pas car vous modifieriez l'adresse de la routine auxiliaire, mais EVALuez-le: vous n'avez plus qu'a tapoter sur les touches de votre machine pour generer de belles interruptions. Vous venez d'assister a la naissance du multi-tache sur HP... C'est beau hein? Vous pouvez d'ailleurs constater au passage que c'est l'enfoncement d'une touche qui provoque une interruption, et non le fait de rester appuye dessus (a part pour la touche ON). Vous pouvez vous amuser a faire afficher l'heure a votre machine, il y aura inversion video du haut de l'ecran a chaque seconde! III.II.VI - Avantages, Inconvenients Les avantages sont interessants: - possibilite de faire plusieurs choses a la fois sous RPL, et en fabriquant un echangeur qui fait l'operation inverse, on peut revenir proprement (ici on est oblige de faire un arret systeme pour tout arreter) au gestionnaire de la machine, et avoir ainsi a nouveau acces a sa carte. - En ameliorant encore un peu plus l'echangeur, on peut meme utiliser une deuxieme carte pendant ce temps, ce qui permet par exemple d'observer cette animation sous tout programme autorisant les interruptions: Libex v2.2 de DEYLONE et HPReg par exemple... - on peut faire tout et n'importe quoi dans la routine auxiliaire: si l'on veut utiliser d'autres registres que ceux qui ont ete sauves par la machine, il suffit de reecrire un petit bout qui les sauve en debut de routine auxiliaire, et qui les restaure avant la fin de routine auxiliaire. De meme, personne ne vous oblige a vous rebrancher en 00140 sur le gestionnaire de la machine, on peut tout a fait sauter tous les tests de CMOS Word etc. dont on se fiche eperdument, et se rebrancher un peu plus loin, en 00218 par exemple, histoire de gagner un peu de temps machine. Remarque: J'avais essaye de faire une routine qui supprimait toutes les actions combinees avec la touche ON, afin que l'on ne puisse plus faire de ON A F sous RPL. Mais cela n'a pas bien marche, en appuyant beaucoup de fois sur ces trois touches, j'ai tout de meme obtenu un memory lost. Il doit donc y avoir d'autres tests a supprimer. Mais les inconvenients aussi sont de taille: - la zone des adresses 00000 a 0000E incluses est ecrasee par la partie declarative de l'objet backup. C'est dommage car lorsque la machine se plante, elle fait un redemarrage a chaud en 00000 la plupart du temps. Heuresement, les modules sont souvent tous redeconfigures dans ce cas-la. - detourner les interruptions de cette maniere necessite de gros moyens: une carte qui rend le systeme inutilisable sur les machines non eXpandables, un objet de 2 Ko... III.III - Detournement par la RAM interne III.III.I - Explications Evidemment, a premiere vue l'on se dit, il n'y a qu'a faire pareil, je deconfigure la RAM interne et je la reconfigure en 00000. Mais que va-t-il se passer lorsque le programme, qui est en RAM interne (on s'interdit desormais toute carte), va vouloir deconfigurer la RAM interne? C'est tout simple: l'instruction de deconfiguration va etre executee, et le registre PC, dont la valeur n'aura bien sur pas ete modifie, va gentiment faire pointer le microprocesseur vers du code qui n'est plus la, le programme va donc lamentablement se vautrer, en degoutant a jamais son auteur de s'etre attaque aux interruptions... Bien sur, l'ideal serait de trouver un bout de programme en ROM qui deconfigurerait la RAM interne et la reconfigurerait en 00000, en rendant la main a notre programme, mais il fallait se rendre a l'evidence, ce programme tant cherche n'existait pas en un seul morceau, il n'en existait que des petits bouts dissemines, l'un deconfigurant, l'autre reconfigurant... Comment recoller ces morceaux? Comment pouvait-on ecrire un programme en ROM? Heureusement, un jour, une bande de trois codeurs ETI, GHERKIN et Cyrille de Brebisson (HP Mad), des habitues du "Temple", a force de coucher avec leurs HP, enfanterent d'une idee geniale dont on ne sait en fait pas tres bien qui en est le pere: un petit exemple valant mieux qu'un long discours, supposons que l'on parvienne a trouver dans la ROM de la HP les petits bout de programme suivant: a l'adresse 014FC: C=C+C A a l'adresse 2ADC4: CSL A C=C+1 A RTNSC RTNSXM Considerons l'execution du source suivant, que va-t-il se passer? A=PC GOINC FIN C=C+A A RSTK=C LC 2ADC4 RSTK=C C=0 A C=C+7 A GOVLNG 014FC *FIN Commentaire: ------------ On charge l'adresse du label FIN dans RSTK, puis on charge l'adresse 2ADC4 dans RSTK, puis on charge C.A a la valeur 00007. Alors, on se branche en 014FC, donc C.A vaut 0000E puis 0000F puis il y a depilage (XM est arme au passage, cela nous laisse indifferent) donc retour a l'adresse 2ADC4, ou C.A prends la valeur 000F0 puis a nouveau depilage et retour au label FIN (CARRY armee au passage, ce dont nous nous moquons). Vous voyez, la Cinquieme Ruse est la plus grandiose. Il ne reste plus qu'a trouver les bouts de programmes qui font ce qu'on veut, en un minimum de saut. Heureusement pour vous, ca je m'en suis charge! III.III.II - Le driver d'interruption RAMINT Voici le source 'RAMINT.SRC' d'un echangeur s'appliquant a la RAM interne. Il est compose de 2 routines: l'une, INIT.INT qui permet de passer sur son propre gestionnaire d'interruption, qui doit necessairement etre en RAM interne et dont on passe l'adresse actuelle dans C.A, et l'autre STOP.INT qui sert a revenir au gestionnaire de la HP48. Les commentaires sont cette fois assez succints, il n'y a quand meme pas de raison que ce soit moi qui me tape tout le sale boulot hein? "*INIT.INT %Construit l'instruction permettant de sauter a l'adresse du gestionnaire D0= 61FD4 A=DAT0 A %Utilisation de la Quatrieme Ruse: A=AdrRam D0=A C=C-A A %Le nouveau gestionnaire va etre lui aussi translate CSL W CSL W LC D8 %L'instruction construite est un GOVLNG, qui se code 8Dvwxyz %Suvegarde des 7 quartets ecrases en ?000F sur le CMOS Word et le debut de %la taille de la RAM D0=D0+ 15 %D0= ?000F A=DAT0 7 ST=0 15 %On coupe les interruptions machines car on va ecraser le CMOS Word DAT0=C 7 D0=D0- 15 DAT0=A 7 %Construit le programme en ROM AD0EX C=RSTK %Il faut modifier l'adresse de retour de la routine INIT.INT C=C-A A % car le programme qui l'appelle va etre translate RSTK=C C=A A %A cet endroit, C.A=70000 pour une S, et 80000 pour une G C=C+C A % permet de determiner si on a affaire a une S ou une G GOC G % car je n'ai pas reussi a trouver d'adresses compatibles ici LC 3EFCB %On trouve en ROM a cette adresse: P= 0 GOC 3EF60 DAT1=A B CONFIG D1=C % RTN. Il est donc necessaire de faire pointer D1 sur la ROM GONC S *G LC 47228 %CONFIG $0E8F:C=C!D P P= 0 ASL A RTNSXM *S RSTK=C LC 567C4 %CONFIG SETHEX C=C+D A P= 6 D=D+C A RTN RSTK=C D0=A D0=D0+ 5 C=DAT0 A C=0 B %A cet endroit, C.A=taille de configuration du module RAM D=C A D=-D A ACEX A A=A+C A GOVLNG 34E09 %UNCNFG C=A-C A RTN *STOP.INT C=0 A D0=C A=DAT0 7 B=A W %B contient les 7 quartets ecrases par INIT.INT en ?000F %Reecriture du CMOS Word LC A5C3F DAT0=C A D0= 61FD4 A=DAT0 A %A.A=AdrRam C=RSTK C=C+A A %Translation dans le sens inverse... RSTK=C GOSUB SI2 D0= 61FD4 C=DAT0 A %C.A=AdrRam D0=C D0=D0+ 15 C=B W DAT0=C 7 %Restitue les 7 quartets ecrases GOVLNG 010E5 %Reautorise les interruptions du gestionnaire de la HP48 *SI2 C=RSTK C=C+A A %Translation dans le sens inverse... RSTK=C LC 0224F D0= 47333 %A cet endroit, A.B=07 sur S et 00 sur G A=DAT0 B %A cette addresse, une routine en ROM reconfigure la RAM, et C=C+A B % surtout reecrit la taille de la RAM et son adresse en ?0005 RSTK=C C=0 A ST=0 15 GOVLNG 4CFD0 %A cette adresse, on trouve en ROM: UNCNFG RTNCC @" III.III.III - Construction du nouveau gestionnaire C'est bien beau de pouvoir changer de gestionnaire d'interruption, mais encore faut-il avoir un autre gestionnaire sous la main! Voyons comment fabriquer un tel gestionnaire dans le cas le plus general. En fait, le source suivant est celui d'un gestionnaire qui ne fait rien, a part sauver puis restituer tous les registres, un peu a la maniere de celui de la machine: "*NEW.GEST %Sauvegarde de tous les registres RSTK=C C=PC GOC NI1 C=C+16 A %Ces instructions ne modifient pas la CARRY C=C+16 A % vous pouvez verifier... C=C+15 A GOTO NI2 *NI1 C=C+16 A C=C+16 A C=C+15 A GOTO NI3 %On reserve de la place pour stocker les registres $00000 %D0 $0000 %HEX/DEC,P,HST,NON CARRY $00000 %D1 $000 %ST On ne sauve que les flags 0 a 11 $0000000000000000 %A $0000000000000000 %B $0000000000000000 %C $0000000000000000 %D $0000000000000000 %R0 $0000000000000000 %R1 $0000000000000000 %R2 $0000000000000000 %R3 $0000000000000000 %R4 $00000 %RSTK1 Correspond au registre PC $00000 %RSTK2 $00000 %RSTK3 $00000 %RSTK4 $00000 %RSTK5 $00000 %RSTK6 On ne sauve pas RSTK8 car il est cense etre ecrase par le $00000 %RSTK7 RTSK=C au debut de cette routine. *NI2 CD0EX DAT0=C A C=0 A C=C+1 A GONC NI4 *NI3 CD0EX DAT0=C A C=0 A *NI4 D0=D0+ 5 CPEX 1 CSL A ?MP=0 GOYES NI5 CBIT=1 3 *NI5 ?SR=0 GOYES NI6 CBIT=1 2 *NI6 ?SB=0 GOYES NI7 CBIT=1 1 *NI7 ?XM=0 GOYES NI8 CBIT=1 0 *NI8 CSL A C=C-1 P SETHEX DAT0=C A D0=D0+ 4 CD1EX DAT0=C A D0=D0+ 5 C=ST DAT0=C A D0=D0+ 3 DAT0=A W D0=D0+ 16 BCEX W DAT0=C W D0=D0+ 16 C=B W C=RSTK DAT0=C W D0=D0+ 16 C=D W DAT0=C W D0=D0+ 16 C=R0 DAT0=C W D0=D0+ 16 C=R1 DAT0=C W D0=D0+ 16 C=R2 DAT0=C W D0=D0+ 16 C=R3 DAT0=C W D0=D0+ 16 C=R4 DAT0=C W D0=D0+ 16 P= 9 *NI9 C=RSTK DAT0=C A D0=D0+ 5 P=P+1 GONC NI9 %Ici, vous pouvez rajouter ce que vous voulez, c'est une sorte de routine %auxiliaire, vous pouvez mettre, ce qui nous servira d'exemple par la suite % D0= 00138 % C=DAT0 A % D0= 20 % DAT0=C A %Restaure tous les registres dans le sens inverse A=PC GOINC NI2 C=C+A A D0=C P= 9 *NI10 D0=D0- 5 C=DAT0 A RSTK=C P=P+1 GONC NI10 D0=D0- 16 C=DAT0 W R4=C D0=D0- 16 C=DAT0 W R3=C D0=D0- 16 C=DAT0 W R2=C D0=D0- 16 C=DAT0 W R1=C D0=D0- 16 C=DAT0 W R0=C D0=D0- 16 C=DAT0 W D=C W D0=D0- 16 C=DAT0 W RSTK=C B=C W D0=D0- 16 C=DAT0 W BCEX W D0=D0- 16 A=DAT0 W D0=D0- 3 C=DAT0 A ST=C D0=D0- 5 C=DAT0 A D1=C D0=D0- 4 C=0 A C=DAT0 4 D0=D0- 5 C=C+1 P GOC NI11 SETDEC *NI11 CSR A CBIT=0 0 CBIT=0 2 CBIT=0 3 SB=0 CSR A CPEX 1 C=C-1 A C=DAT0 A D0=C C=RSTK RTI @" Stockez ce gestionnaire sous le nom 'NG', il va nous servir. Remarque: - On constate que, comme le gestionnaire d'interruption de la HP, celui-ci necessite l'utilisation de 2 niveaux de la pile RSTK III.III.IV - Utilisation de RAMINT En plus de cette documentation, vous avez surement entre les mains le fichier RAMINT. C'est un fichier precompile, c'est-a-dire qu'il fait exactement la meme chose que RAMINT.SRC, mais il est beaucoup plus petit (116 Octets, c'est la taille de la routine, contre 900 Octets, taille du source) et surtout, il ne prends quasiment aucun temps de compilation, car l'assembleur a juste a prendre en compte deux labels (pour ceux qui connaissent, l'assembleur sert ici de linker), et se contente de recopier le reste, que j'ai moi-meme compile pour vous. Le source d'un programme qui utilise RAMINT doit se presenter ainsi: "..... GOSUBL SUITE *NEW.GEST ..... *SUITE C=RSTK %C.A contient bien l'adresse courante du nouveau gestionnaire GOSUBL INIT.INT ..... %ca y'est, on a change de gestionnaire GOSUBL STOP.INT ..... %On est revenu sur le vrai gestionnaire 'RAMINT %Si vous n'avez pas RAMINT, mettez RAMINT.SRC @" Ou encore, de cette maniere, qui sert d'exemple et qui utilise le gestionnaire construit au paragraphe precedent: "GOSBVL 0679B A=PC GOINC NEW.GEST C=C+A A %C.A contient bien l'adresse courante du nouveau gestionnaire GOSUB INIT.INT %ca y'est, on a change de gestionnaire, ici on boucle mais on pourrait tres bien %trier une liste de nombre, peinard... LC 80000 *LOOP C=C-1 A GONC LOOP GOSUB STOP.INT %On est revenu sur le vrai gestionnaire GOSBVL 01C7F %Remets a jour la bitmap ecran GOVLNG 138B9 %Recupere registres et retour au RPL 'NG %cf paragraphe precedent 'RAMINT %Si vous n'avez pas RAMINT, mettez RAMINT.SRC @" Assemblez, EVALuez, et tapotez... C'est encore plus beau! III.III.V - RAMINT vu a la loupe - INIT.INT: En entree, C.A doit contenir l'adresse courante du nouveau gestionnaire qui doit se trouver en RAM interne. On suppose aussi que P= 0. En sortie, C,D,D0,D1 sont modifies et le flag 15 est desarme. - STOP.INT: En entree, on suppose P= 0 En sortie, B,C,D0,D1 sont modifies et les interruptions HP autorisees. - Il est grandement conseille, sous peine de crash avec STOP.INT, de ne rien ecrire, une fois que INIT.INT a ete execute, dans la zone 00000 a 00006. - On constate que l'on a besoin de 3 niveaux de la pile RSTK pour faire l'une ou l'autre des manipulation. En realite, le fait d'echanger n'en utilise que 2, c'est la presentation simplifiee de l'echangeur sous forme de routines qui implique le troisieme. Il existe une methode pour n'en utiliser qu'un (ce qui ferait 2 avec cette presentation simplifiee). C'est ATLAS qui en a trouve le principe: il suffit d'arreter l'horloge 2 et d'ecrire sa routine dedans, en en sauvant sa valeur. En effet, l'horloge deux est quel que soit la configuration ed la RAM interne, situee entre les adresses 00138 et 0013F incluses. J'ai ecrit un echangeur fonde sur ce principe, mais il n'apporte en fait pas grand chose de plus, a part une augmentation de taille de 150 octets. Il n'avait donc aucune raison de figurer ici, mais c'est neammoins un tres bon exercice de style si vous voulez vous entrainer (la premiere difficulte consiste a bloquer l'horloge puis a la faire redemarrer sans que la machine fasse d'arret systeme...) - Prenez bien garde aux adresses que vous emploierez, car lors d'un echange, il est necessaire de recalculer les adresses des bitmaps ecran et menu, et beaucoup d'adresses vont se trouver decalees. Prenez garde aussi a ne pas utiliser, lorsque la RAM interne est reconfiguree en 00000, les routines en ROM situees aux adresses comprises entre 00000 et 10000 sur les machines sans cartes, et entre 00000 et 40000 sur celles eXpandable. - N'oubliez pas qu'il est tres facile de provoquer une interruption a intervalle regulier: on met une valeur initiale dans l'horloge 2, quand l'horloge 2 passe a la valeur zero, elle declenche une interruption si son quartet de controle (Cf voyage au centre de la HP48) l'y autorise, et dans la routine d'interruption, il suffit de reinitialiser l'horloge 2 a cette meme valeur initiale. - Le gros avantage de RAMINT est sa compatibilite S/G. Profitez-en! IV - Conclusions J'espere que cette documentation qui traite d'un sujet relativement epineux sur HP48 aura eu le merite d'etre claire. J'espere que tout ceux qui utiliseront ces sources les utiliseront a bon escient, et n'oublierons pas de me remercier dans leur production futures. Il faut bien se dire que rien ni personne a par ma bonne volonte ne m'obligeait a passer trois jours a taper cette documentation alors que j'aurais pu garder tout cela pour moi. Pour toutes les questions et suggestions, vous pouvez me joindre par minitel sur le 3615 RTEL, ainsi que sur le serveur minitel prive RTC ONE au 48 58 46 17 et au 48 70 10 29, ou par modem au 49 88 76 91, dans ma boite aux lettres HPReg. Vous pouvez egalement me joindre sous le nom de Regis DUCHESNE sur les BBS de la RP: THE 0NE, JOSHUA, ALF, OUT TIME BBS, ou je modere la conference HP48 redistribuee. Enfin, vous pouvez me contacter par EMAIL aux adresses electroniques suivantes: HPREG.ONE@ON101.COM et HPREG@EMAIL.TEASER.COM. Je remercie, car ils nous simplifient la vie sur HP: - Marc Vogel (DEYLONE) pour avoir ecrit PCT avec moi - Atlas pour True Color - Thomas Looten pour Starway (sur G) - Nathalie Brisset (CYMORIL) pour ses splendides GROBs - Phong N'Guyen pour AsmFlash - Frenhofer pour Unass - Jean-Yves Avenard (GHERKIN) pour String-Writer - Cyrille de Brebisson (HP Mad) pour ses splendides jeux _____________ *************** SECTION SPECIALE : CORRESPONDANCE PRIVEE POUR HPREG ******** Salut bonhomme ! Et encore bravo pour ta petite bafouille sur les interruptions. Pardonne moi si j'ai eu tendance … ˆtre un peu ironique dans les sections pr‚c‚dentes... Je vais ici tenter de me racheter, avec quelques informations qui t'ont manqu‚es. * Sur la routine d'interruption - le flag 13 est un flag anti-r‚cursif, qui ‚vite qu'un test rat‚ (exemple : le test m‚moire) ne provoque une interruption non masquable, qui tenterait un test, qui reprovoquerait la mˆme interruption non masquable, etc... - la "bizarre lecture avant ‚criture" en 0010E n'est pas du tout bizarre : ce quartet s'efface aprŠs sa lecture (l'‚tat READ du bus … cette adresse agit comme une commande pour le contr“leur de p‚riph‚riques). Ce genre de pratiques est trŠs courant en ‚lectronique : plut“t que d'analyser la valeur 0, 1, ou 2 d'un octet de commande, on pr‚fŠre mettre 3 adresses fictives, sans rien derriŠre, et c'est l'adresse (ou plut“t ses derniers bits) qui donnent la commande, la commande ‚tant d‚clench‚e soit par l'‚tat WRITE, soit par l'‚tat READ. Ici, le but de la manoeuvre est de s'assurer que le quartet de configuration indique bien l'‚tat le plus r‚cent, et ne contienne pas de traces du dernier RESET : il s'efface automatiquement. Mais le programmeur a pr‚f‚r‚ garder sa valeur, au cas o— il en aurait besoin plus loin. - astuce personnelle sur le flag CARRY (peut-ˆtre d‚j… trŠs r‚pandue, et donc plus du tout personnelle) : les programmeurs de la HP28 ont utilis‚ une astuce g‚niale : un test avec une valeur de saut 02. C'est que CARRY n'est pas utilis‚ ici comme indicateur de retenue (ce qui aurait permis de d‚tecter l'inf‚riorit‚ stricte), mais POUR TOUS LES TESTS, CARRY indique que le saut a lieu. On peut donc diff‚rer l'action, si on ne modifie pas CARRY entre temps. - la valeur du CMOS Word ne contient pas toutes les combinaisons possibles de bits sur un quartet : il y aurait 16 valeurs ! Ces valeurs sont tout … fait pifom‚triques, et on espŠre qu'elle donne la plus grande fiabilit‚. Les disquettes des PC sont souvent format‚es … coups de A5 pour la mˆme raison. En fait, il n'y a aucune raison scientifiquement valable de faire ‡a... - la table des cycles d'horloges du "Voyage" est fausse : elle ne tient pas compte des cycles de bus pour l'‚cran et autres vacheries. Le seul moyen est de chronom‚trer chaque instruction (un million de fois, dans une boucle), … l'aide du timer, de r‚p‚ter l'op‚ration en notant les temps, d'effectuer une moyenne, d'en soustraire le temps mis par la boucle … vide, et de diviser par un million. On obtient le temps r‚ellement mis par la machine pour effectuer cette instruction, et ce temps d‚pend de la configuration (HP28, HP48 S, SX avec carte, G...). Compter une aprŠs-midi pour tester une machine. A noter que si on fait un INTOFF/INTON pour ne pas tenir compte des interruptions clavier et autres, il ne faut pas compter tester SHUTDN... Par ailleurs, j'‚mets un doute sur le cycle suppl‚mentaire pour DAT0=C W par rapport … DAT0=C 16. Affaire … suivre. - la touche ON est interruptible : INTOFF C=0 A OUT=C SHUTDN et bon courage... - trŠs brillante compr‚hension des causes profondes qui ont interdit l'usage de OUT=C, sous pr‚texte que cela corrompait la m‚moire : bravo ! - la "ruse" sur SB ‚tait d‚j… connue, cf description des mn‚moniques du SATURN dans "Voyage au coeur du HP28". - la RSTK fonctionne comme la pile RPL : par index d‚croissant … l'empilage. Il est d'usage de donner la valeur la plus r‚cente en bas de la liste. Sinon, trŠs bonne compr‚hension de l'effet de bord, dont il faut tenir compte … chaque appel d'une routine en ROM (elles utilisent jusqu'… 4 niveaux de la RSTK, plus 1 pour l'appel...). - bravo ! (J'ai d‚j… lu ‡a quelque part...) La technique de l'incr‚mentation de P au lieu de la d‚cr‚mentation est g‚niale ! Personne n'y avait pens‚ chez HP, et c'est la premiŠre fois que je vois ‡a ! Moi qui me prenait pour un as de l'optimisation... - pour supprimer le ON-A-F, il suffit d'utiliser un flag anti-r‚cursion, qui permette de faire un RTI imm‚diatement, si c'est le gestionnaire qui est interrompu. On risque alors de perdre quelques caractŠres du clavier ou du port IR. Le multi-tƒche, c'est effetivement beau, mais ‡a demande beaucoup d'exp‚rience pour synchroniser correctement les processus... - va quand mˆme lire ma section V. sur le HP28... - continue comme ‡a, coco, c'est PARFAIT ! MJS, Paris, le 20/6/1994 enfin... 21/6/1994, maintenant !