dimanche 18 juin 2023

projet pomme I

Après avoir adapter le moniteur Wozmon du Apple I sur le STM8 j'ai poursuivie sur ma lancée et créer le nouveau projet pomme I. Je veux créer un petit ordinateur 8 bits avec la carte NUCLEO-8S207K8. Cet ordinateur aura en mémoire flash le moniteur du Apple I ainsi que le BASIC du Apple I. En plus bien que ce n'était pas nécessaire j'ai ajouter un noyau système. D'ailleurs l'écriture de celui-ci m'a posé un problème auquel j'ai trouvé la solution suivante.

Pas d'interruption

Le noyau système utilise l'instruction machine TRAP du STM8 pour affectuer les appels syscall, hors cette interruption a la priorité la plus élevée. Donc quand l'ordinateur est en train d'exécuter un syscall les interruptions pour la minuterie des millisecondes et celle sur réception d'un charactère du UART de peuvent pas être déclenchées. Hors ces interruptions sont nécessaires à l'exécution de certaines fonctions du noyau. Comment résoudre ce problème?

La solution

Voici la solution que j'ai trouvé:


  TrapHandler::
    ldw x,(8,sp) ; get trap return address 
    _strxz trap_ret 
    ldw x,#syscall_handler 
    ldw (8,sp),x 
    iret 
 
     .macro _syscode n, t 
    cp a,#n 
    jrne t   
    .endm 

;---------------------------------
;  must be handled outside 
;  of TrapHandler to enable 
;  interrupts 
;---------------------------------
syscall_handler:      
    _syscode SYS_RST, 0$ 
    _swreset
0$:
    _syscode SYS_TICKS,1$
    _ldxz ticks 
    jp syscall_exit      
1$:
    _syscode PUTC, 2$  
    ld a,xl 
    call uart_putc
    jp syscall_exit 
2$:
    _syscode GETC,3$ 
    call uart_getc 
    jp syscall_exit
3$:
    _syscode QCHAR,4$ 
    call qgetc  
    jra syscall_exit
4$:
    _syscode CLS,5$ 
    call clr_screen
    jra syscall_exit 
5$: 
    _syscode DELBK,6$ 
    call bksp  
    jra syscall_exit 
6$: 
    _syscode GETLN , 7$
    call readln  
    jra syscall_exit 
7$: 
    _syscode PRT_STR , 8$
    call puts 
    jra syscall_exit
8$: 
    _syscode PRT_INT , 9$
    call print_int
    jra syscall_exit      
9$: 
    _syscode SET_TIMER , 10$
    bres sys_flags,#FSYS_TIMER 
    _strxz timer 
    jra syscall_exit 
10$:
    _syscode CHK_TIMOUT, 11$
    clr a 
    btjf sys_flags,#FSYS_TIMER,syscall_exit  
    cpl a 
    jra syscall_exit
11$: 
    _syscode START_TONE , 12$    
    call tone 
    jra syscall_exit 
12$: 
    _syscode GET_RND , 13$
    call prng 
    jra syscall_exit 
13$: 
    _syscode SEED_PRNG , 14$
    call set_seed 
    jra syscall_exit 
14$: 

; bad codes ignored 
syscall_exit:
    jp [trap_ret] 

 
Normalement à l'exécution de l'instruction IRET le programme devrait continuer à l'adresse qui suis l'instruction TRAP. Lorsqu'une interruption est déclenchée tous les registres du STM8 sont sauvegardés sur la pile, incluant l'adresse de retour qui est située à la position (8,sp) sur la pile. Donc le gestionnaire d'interruption logicielle va chercher cette addresse et la sauvegarde dans la variable système trap_ret. Ensuite il remplace sur la pile l'adresse original par l'adresse de la sous-routine qui gère les appels syscall et puis il quitte avec l'instruction IRET. Puisque l'adresse de retour a étée modifiée le programme continue non pas à l'endroit où il aurait du mais au début de la routine syscall_handler.

Notez que la sous-routine syscall_handler se termine par un jp [trap_ret]. trap_ret est une variable pointeur et cette instruction fait un saut à l'adresse contenue dans la variable pointeur qui se trouve être l'adresse où normalement le programme aurait du continuer à la sortie de TrapHandler. Et voilà le problème est résolu.

jeudi 8 juin 2023

Wozmon sur STM8

Après avoir regardé la vidéo de Ben Eater Running Apple 1 software on a breadboard computer (Wozmon) je me suis intéressé à l'histoire du Apple I et j'ai fait des recherches à ce sujet. J'ai trouvé le manuel d'opération du Apple I en format pdf. Dans ce manuel on retrouve le code du moniteur du Apple I

Un peu d'histoire

En 1975 Steve Jobs invite l'ingénieur Steve Wozniak à fonder une compagnie pour vendre l'ordinateur conçu par ce dernier. C'est Steve Jobs qui a eu l'idée d'appeller cette compagnie Apple . Ce nom réfère à la légendre (vrai ou fausse?) selon laquelle Isaac Newton aurait eu l'inspiration de la théorie de la gravitation lorsqu'assie au pied d'un pommier il aurait reçu une pomme sur la tête. C'est pour ça qu'on retrouve cette image sur la page couverture du manuel d'opération du Apple I.

Si le Apple II est célèbre il n'en va pas de même pour le Apple I. Il ne s'en est vendu qu'environ 200. Mais cette rareté même fait que les collectionneurs se les arrachent à prix d'or. Selon mes recherches en 2018 quelqu'un offrait un Apple I aux enchères pour un prix de départ de 1.5 millions US$.

Les raisons pour lesquelles le Apple I ne s'est pas très bien vendu sont d'abord qu'il ne s'agissait pas d'un produit grand public. Seul la carte mère était vendue.

CopsonApple1 2k cropped.jpg
By Achim Baqué - <a rel="nofollow" class="external free" href="https://www.apple1registry.com/en/press.html">https://www.apple1registry.com/en/press.html</a>, CC BY-SA 4.0, Link

L'acheteur devait fabriquer le bloc d'alimentation lui-même ou bien trouver quelqu'un pour le faire. De même pour le boitier. Il devait aussi trouver un clavier, et un moniteur. À ses début Apple Computer n'avait pas de réseau de distribution. C'est Steve Jobs qui faisait le démarchage pour convraincre les boutiquiers d'informatique (secteur naissant) de vendre le Apple I. Certains de ces détaillants complétaient l'offre d'Apple en vendant le Apple I dans un boitier en bois avec l'alimentation et le clavier inclus. Il y avait donc de la variété dans l'apparence.

L'autre raison est qu'Apple a mis en marché le Apple II très tôt après le Apple I et s'est désintéressé du premier laissant les acheteurs se débrouiller avec le Apple I.

Qu'est-ce que Wozmon

L'ingénieur qui a conçu les Apple I et Apple II c'est Steve Wozniak. Steve Jobs s'était un homme d'affaires pas un ingénieur. Pour en revenir au Apple I, la mémoire était coûteuse à cette époque donc pour couper dans les coûts Wozniak a fait 2 choses Il a utilisé dans le Apple I de la RAM dynamique plutôt que statique comme on retrouvait à l'époque dans la plupart des petits ordinateurs 8 bits. Ce qui lui a permit de fournir la carte mère avec 4K octets de RAM et il y avait de la place sur la carte pour en ajouter 4K de plus. Pour la mémoire ROM le Apple I ne disposait que de 256 Octets. Quoi installer comme programme dans un espace aussi réduit? À cette époque on installait un petit programme appellé un moniteur. Ce programme faisait peu de choses.

  • Examiner le contenu de la mémoire
  • Modifier le contenu de la mémoire
  • Lancer un programme écris en langage machine
Le moniteur du Apple I, qui a finit par être affublé du nom de Wozmon contraction de Wozniak et monitor. ne faisait rien de plus que ça. Mais faire entrer ce programme dans moins de 256 octets est déjà difficile. D'abord le cpu 6502 du Apple I utililse 6 octets pour les vecteurs
  • NMI, adresse 0xFFFA..0xFFFB, c'est l'adresse de la routine d'interruption non masquable.
  • RESET, adresse 0xFFFC..0xFFFD, est chargée dans le compteur ordinal au démarrage.
  • IRQ, adresse 0xFFFE..0xFFFF, c'est l'adresse de la routine d'interruption.
Donc Wozniak ne disposait que de 250 octets pour installer le moniteur il a réssie à le faire entrer dans 248 octets. Ce n'était pas une mince affaire d'autant plus qu'il ne disposait d'aucun outil de programmation dont nous disposons aujourd'hui. Il a écris le code assembleur sur des feuilles de papiers et générer lui-même le code binaire à partir de ce listing. J'ai connu cette époque sauf que moi je travaillait avec un mcu RCA CDP1802. Il faillait être vraiment passionné pour travailler de cette façon.

STM8 Wozmon

Après avoir trouver le manuel d'opération du Apple I je me suis mis à étudier le code du Wozmon qui s'y trouve et me suis demandé combien d'octets ce programme occuperait sur STM8. La question est pertinante puisque l'architecture du STM8 est une extension de celle du cpu 6502, mais le jeu d'instructions est complètement différent. J'ai d'abord écris une première version en travaillant dans mon style de programmation habituel pour voir qu'elle taille ça aurait. J'ai bâptisé ce programme stm8_picmon.asm et le binaire a une taille de 357 octets.

Dans un deuxième essaie j'ai collé au modèle du moniteur de Wozniak autant que possible, compte de tenu des différences entre les architectures matérielle et du jeu d'instructions plus étendu qu'offre le STM8. J'ai bâptisé ce programme stm8_wozmon.asm. Le binaire de ce programme a une taille de 260 octets soit 12 octets de plus que celui de Wozniak. Il serait probablement possible de supprimer quelques octets supplémentaire en faisant quelques compromis mais je n'ai pas cherché à le faire.

Le code source du programme est sur https://github.com/Picatout/stm8_wozmon

Vidéo de démonstration