Autore Topic: La Gestione Degli Interrupt.  (Letto 2305 volte)

geos_forever

  • Neo-iscritto
  • *
  • Post: 15
  • Gioco Preferito: Purple Heart
La Gestione Degli Interrupt.
« il: 03 Giugno 2005, 22:03:03 »
 Dedicando tempo al reversing del monitor di cui ho parlato nella presentazione mi sono trovato di fronte alle prime lacune della mia conoscenza riguardo il funzionamento del C64.

Mi spiego...

Nelle locazioni da FFFA a FFFF, nel C64, vi sono tre vettori che riguardano

1) il NMI not maskable interrupt

2) il Reset

3) il BRK/IRQ interrupt

A questo punto mi sono domandato:
quando entrano in gioco?

Per quanto riguarda quella di Reset, la risposta è semplice, penso: quando si resetta la macchina. Si può simulare il reset via software con un semplice e molto conosciuto SYS 64738; 64738=FCE2 hex è l'indirizzo di inizio della routine.

Ma in realtà cosa succede quando resetto? Come fa il C64 a capire che deve chiamare la routine di Reset?

Per quanto riguarda gli interrupt? Come vengono gestiti?

Ipotizzo una sequenza operativa: accendo il C64, qualcosa chiama la routine in FCE2 e poi?

Se non ricordo male, in ambiente Geos c'e una routine, Main Loop, che viene chiamata dopo l'inizializzazione del sistema, e che gira in un loop finchè qualche evento richiede la sua attenzione, dopodoche gestisce in modo appropriato l'evento.

Il discorso è simile anche con il C64?
Chi chiama il NMI? e chi il BRK/IRQ?

Spero che le domande non siano troppo...banali.

Se il discorso è troppo complesso qualcuno mi può indicare qualche fonte on line dove approfondire in modo appropriato questi concetti?

Ciao.

Sergio

iAN CooG

  • Utente
  • **
  • Post: 1774
    • http://iancoog.altervista.org
  • Gioco Preferito: Turbo Assembler, ActionReplay Monitor, DiskDemon
La Gestione Degli Interrupt.
« Risposta #1 il: 03 Giugno 2005, 22:49:05 »
 
Citazione
1) il NMI not maskable interrupt

2) il Reset

3) il BRK/IRQ interrupt

A questo punto mi sono domandato:
quando entrano in gioco?

I vettori sono direttamente collegati al 6502 e sono sotto il suo controllo. Ogni macchina 65xx-based ha quegli stessi vettori nelle stesse posizioni. Ovviamente contengono indirizzi diversi, a seconda della macchina, che puntano alle routine nel kernal preposte a quelle funzioni.
Ad esempio sul C64 $FFFC/D contengono E2 FC, ti dice niente? :)

Il vettore di IRQ ridirige ad una routine in kernal che fa un ulteriore ridirezione ai vettori in $0314/5, che sono in ram quindi ridefinibili
Idem dicasi per l'NMI. NMI ad esempio e' chiamato dal tasto Restore, direttamente collegato al 6510 del C64.

Citazione
Ma in realtà cosa succede quando resetto? Come fa il C64 a capire che deve chiamare la routine di Reset?
Il 6510 esegue una JMP indiretta a $FFFC, che guarda caso punta a $FCE2

Citazione
Per quanto riguarda gli interrupt? Come vengono gestiti?
Vengono chiamati "ogni tanto" a seconda degli eventi che li fanno scaturire, il C64 puo' generare IRQ dal processore, dal VIC e dai CIA.

Citazione
Ipotizzo una sequenza operativa: accendo il C64, qualcosa chiama la routine in FCE2 e poi?
Se segui il disassemblato del kernal ti accorgerai che la routine a $FCE2 controlla che sia inserita una cartuccia, se si la fa partire con una JMP ($8000) altrimenti fa tutti i preparativi per un warm start del basic.

Citazione
Se non ricordo male, in ambiente Geos c'e una routine, Main Loop, che viene chiamata dopo l'inizializzazione del sistema, e che gira in un loop finchè qualche evento richiede la sua attenzione, dopodoche gestisce in modo appropriato l'evento.
Scordati queste cose, roba troppo ad alto livello ;) Comunque si', c'e' un qualcosa del genere.

Citazione
Chi chiama il NMI? e chi il BRK/IRQ?

BRK e' il vettore che viene eseguito quando il processore incontra l'opcode 0 (BRK appunto) e puo' essere usato per debug, facendolo deviare al restar del monitor attualmente in uso ad esempio. Normalmente e' associato alla stessa funzione collegata da Runstop+Restore.

Citazione
Spero che le domande non siano troppo...banali.
Anzi, tuttaltro che facile sia da spiegare che da capire :)

Citazione
Se il discorso è troppo complesso qualcuno mi può indicare qualche fonte on line dove approfondire in modo appropriato questi concetti?
http://project64.c64.org/index.htm
Qui trovi la Programmers reference guide, la Mappa della memoria, il disassemblato del kernal.

Per un edizione italiana della Guida di Riferimento, c'e' quella realizzata da MarC=ello, che trovi nel sito principale di ready64.
-=[]=--- iAN CooG/HVSC^C64Intros ---=[]=-
- http://hvsc.c64.org - http://intros.c64.org -

geos_forever

  • Neo-iscritto
  • *
  • Post: 15
  • Gioco Preferito: Purple Heart
La Gestione Degli Interrupt.
« Risposta #2 il: 03 Giugno 2005, 23:29:18 »
 
Citazione da: "iAN CooG/HF"
I vettori sono direttamente collegati al 6502 e sono sotto il suo controllo. Ogni macchina 65xx-based ha quegli stessi vettori nelle stesse posizioni. Ovviamente contengono indirizzi diversi, a seconda della macchina, che puntano alle routine nel kernal preposte a quelle funzioni.
Ad esempio sul C64 $FFFC/D contengono E2 FC, ti dice niente? :)

Mi dice, mi dice :) ; in questi giorni, infatti, sto cercando di capire il lavoro svolto dalla routine FCE2; non ero ancora arrivato dove fa un JMP indiretto in A000 dove c'è, guarda caso, l'indirizzo (E394) di un altra RESET routine che si conclude con la stampa del messaggio READY.
Ho l'impressione che il lavoro svolto dalla macchina a partire da FCE2 sia molto importante (e interessante) dato che si conclude con la stampa del messaggio READY e da quel momento la macchina dovrebbe essere nel loop di attesa ipotizzato in precedenza (il cursore lampeggia in attesa che l'utente digiti qualcosa).
Ma allora quel loop ha un unico compito? Attendere la pressione di un tasto?

Citazione
Il vettore di IRQ ridirige ad una routine in kernal che fa un ulteriore ridirezione ai vettori in $0314/5, che sono in ram quindi ridefinibili
Idem dicasi per l'NMI. NMI ad esempio e' chiamato dal tasto Restore, direttamente collegato al 6510 del C64.

Infatti il monitor che sto "esaminando" inizia modificando i vettori sia in $0314/5 che in $316/7

Bene...allora il NMI è chiamato dalla pressione sul tasto RESTORE (è l'unico evento che lo richiama?)

Per ora mi fermo...c'è già troppa carne al fuoco per le mie capacità...

Grazie degli input.

Sergio

geos_forever

  • Neo-iscritto
  • *
  • Post: 15
  • Gioco Preferito: Purple Heart
La Gestione Degli Interrupt.
« Risposta #3 il: 03 Giugno 2005, 23:56:32 »
 Un grazie a iAN CooG/HF
ed anche a Mar :c64: ello...
leggendo il forum di Ready64 ho trovato un suo riferimento a Knowledge Base Article #121
che affronta l'argomento tema di questo thread... :hail:

Luca/FIRE

  • Utente
  • **
  • Post: 136
    • http://fire.plus4.net
  • Gioco Preferito: Wizball
La Gestione Degli Interrupt.
« Risposta #4 il: 04 Giugno 2005, 14:47:41 »
 Aò, ma sapete icche c'è? :huh:
Lamer per lamer, mi inerisco sinuoso nella discussione pur io! :mattsid:

É da poco che ho fatto la mia prima intro che possa chiamarsi tale...
Vabbè, non è la prima, però è quella che sento essere la prima, con lo splitting dello schermo, gli scrolltext, i bitmap bob in sin(x) eccetera (per le altre mi aiutavo con tool legali, ad esempio per editare moving rasterbar, ma farle da zero è un'altra cosa...)

Io, da bravo bambino, mi divido lo schermo per rastertime e faccio ciò che devo, zompando da irq a irq cambiando i vari $FFFE/$FFFF (NMI).
E se usassi anche l'interrupt a $0314/$0315?
E $0316/$0317 invece cosa fanno?
E se uso tutto insieme?
E se scoprissi di essere il figlio segreto di Schifani?  :sgrat:  

MarC=ello

  • Utente
  • **
  • Post: 337
  • Gioco Preferito: CBM BASIC 2.0
La Gestione Degli Interrupt.
« Risposta #5 il: 04 Giugno 2005, 16:08:56 »
 Ciao a tutti. Ho preparato questo post (un po' lungotto) per proseguire il discorso delle interruzioni e analizzare un po' alcuni aspetti del sistema operativo del c64.

Una fonte che è molto utile per studiare l'architettura del c64, e quindi anche le
interruzioni, è anche il testo "Mapping the Commodore 64", anche questo reperibile fra gli e-text di project 64. Questo libro è molto utile ed interessante in quanto fornisce delle preziose informazioni, tra le altre cose, riguardo agli adattatori di interfaccia. Nel nostro caso ci interessano il VIC-II e i CIA, visto che sono loro le fonti delle interruzioni su c64.

Citazione
Idem dicasi per l'NMI. NMI ad esempio e' chiamato dal tasto Restore, direttamente collegato al 6510 del C64.

Riguardo alle NMI, oltre che dalla pressione del tasto restore, queste possono essere causate anche dal CIA, come spiega Mapping the C64:

Citazione
792-793       $318-$319      NMINV
Vector: Non-Maskable Interrupt

This vector points to the address of the routine that will be executed
when a Non-Maskable Interrupt (NMI) occurs (currently at 65095
($FE47)).

There are two possible sources for an NMI interrupt.  The first is the
RESTORE key, which is connected directly to the 6510 NMI line.  The
second is CIA #2, the interrupt line of which is connected to the 6510
NMI line.

Impostando opportunamente un timer del CIA #2, è possibile generare ad ogni intervallo di tempo un segnale NMI, che va ad interessare ovviamente il pin NMI del 6510.

Il sistema operativo usa le NMI solo per il tasto RESTORE e per l'RS-232, ma ciò non toglie che l'utente possa scrivere un programma che utilizzi le NMI al posto delle IRQ, per dire.

Mi preme ora soffermarmi sulle IRQ.
Un timer del CIA #1 genera, per default ogni 1/60 di secondo circa, un segnale che va ad interessare il pin di IRQ del 6510. Quando il 6510 riceve questo segnale,
cosa succede? E' importante sapere il comportamento hardware del 6510, questo anche per poter comprendere le routine del sistema operativo che gestiscono le interruzioni.
Dal libro di Butterfield (Machine Language for the C64 and other C= Computers, sempre project 64 - il capitolo 7 fornisce una facile introduzione alle interruzioni):

Citazione
When an interrupt signal occurs, the processor completes the instruction it
is currently working on.  Then it takes the PC (the program counter, which
contains the address of the next instruction) and pushes it onto the stack,
high byte first.  Finally, it pushes the status register to the stack.
That's a total of three bytes that go to the stack.

The processor then takes its execution address from one of the following
locations:

  IRQ or BRK - from $FFFE and $FFFF
  NMI        - from $FFFA and $FFFB

(citazione da pag. 115)

Alla luce di questo, proviamo ad esempio ad esaminare cosa succede quando avviene una IRQ.

Quando si verifica un segnale di irq, il 6510 completa l'istruzione corrente, quindi colloca (push) nello stack il byte alto e basso del contatore di programma (PC) e il registro di stato. Quindi, salta all'indirizzo contenuto in $FFFE e $FFFF (vettore hardware delle IRQ).

In $FFFE e $FFFF è contenuto l'indirizzo: $FF48. Vediamo cosa fa la routine che inizia da questa locazione.
Codice: [Seleziona]

 $FF48/65352:   IRQ Entry

FF48: 48        PHA
FF49: 8A        TXA
FF4A: 48        PHA
FF4B: 98        TYA
FF4C: 48        PHA
FF4D: BA        TSX
FF4E: BD 04 01  LDA $0104,X  ; 6510 Hardware Stack Area
FF51: 29 10     AND #$10
FF53: F0 03     BEQ $FF58
FF55: 6C 16 03  JMP ($0316)  ; Vector: BRK Instruction Interrupt Address

Jump from $FF53:

FF58: 6C 14 03  JMP ($0314)  ; Vector: Hardware IRQ Interrupt Address

Si tratta della routine di interruzione di sistema, quella che per default viene eseguita circa 60 volte al secondo. Siccome l'interruzione consiste nell'interrompere il programma correntemente in esecuzione e nell'eseguire una particolare routine (interrupt job), la prima cosa che bisogna fare è salvare i contenuti dei registri nello stack. Il 6510 salva il PC di modo da sapere poi da dove riprendere il programma interrotto... ma dei registri deve occuparsene il software.

Le istruzioni PHA:TXA:PHA:TYA:PHA servono proprio a collocare i contenuti di A, X e Y nello stack.

Il passo successivo consiste nell'analizzare il contenuto del registro di stato del processore, collocato nello stack dal processore stesso all'atto dell'interruzione, per capire se si tratta di una IRQ hardware oppure della BRK. La BRK, per farsi riconoscere, setta il flag BREAK del registro di stato (bit 4 del registro di stato).

L'istruzione TSX trasferisce il puntatore allo stack (SP) nel registro indice X. La successiva LDA $0104,X preleva il contenuto del registro di stato precedentemente salvato nello stack dal processore. Perché $104? Beh, supponiamo che il SP sia $00. In tal caso, la locazione puntata è $100, ed è libera. Consideriamo la struttura dello stack (figura dal libro di Butterfield):

(guardare la figura a pag. 113)

Come si può vedere, lo stack parte da $01FF e va verso il basso. Il puntatore allo stack rappresentale due cifre più a destra della locazione di memoria corrente dello stack (vedi figura).

Se SP per ipotesi è $00, la locazione puntata è $100. Ora, la routine a $FF48 ha collocato nello stack A, X e Y. Quindi, spostiamoci verso l'alto. In $101 è presente Y, in $102 è presente X, in $103 è presente A... e in $104 è presente il registro di stato, che è stato collocato nello stack dal processore, proprio immediatamente prima dell'inizio della routine a $FF48.

Così, nel caso generale in cui SP è qualsiasi, TSX:LDA $104,X consentono di recuperare il contenuto del registro di stato salvato dal processore nello stack. La routine poi controlla se il flag BRK è 0 (IRQ hardware) o 1 (IRQ software dovuta all'istruzione BRK).

Se l'interruzione è una BRK, avviene il salto indiretto JMP ($0316), altrimenti se si tratta di una IRQ vera e propria, avviene il salto indiretto JMP ($0314). $0314-$0315 costituisce il vettore IRQ del sistema operativo. E' interessante osservare anche la routine puntata da tale vettore, residente a $ea31. Più che altro, mi limito a dire che questa routine gestisce la tastiera e vari altri aspetti del sistema operativo che devono essere "aggiornati" costantemente. E' interessante invece analizzare nello specifico come si conclude questa routine:
Codice: [Seleziona]
EA7E: AD 0D DC  LDA $DC0D    ; CIA1: Interrupt (IRQ) Control Register
EA81: 68        PLA
EA82: A8        TAY
EA83: 68        PLA
EA84: AA        TAX
EA85: 68        PLA
EA86: 40        RTI
LDA $DC0D è molto importante. Serve per ordinare al CIA di far cessare il segnale di IRQ. Infatti, nonostante sia avvenuta l'interruzione, il segnale permane fino a che non si ordina via software, al CIA, di smettere. Diversamente, l'interrupt job verrebbe eseguito in continuazione senza dare modo di riprendere al programma interrotto. L'interruzione di tale segnale viene fatta semplicemente leggendo $DC0D... è una caratteristica del CIA (vedi l'entry di $DC0D in Mapping the 64).

Ora, siccome nella routine puntata da $FFFE e $FFFF avevamo collocato i contenuti dei registri A,X e Y, ora dobbiamo recuperare questi valori e collocarli nei registri (che sono stati modificati dalla routine di interruzione) di modo che il programma interrotto possa riprendere correttamente. PLA:TAY:PLA:TAX:PLA fanno proprio questo. Notare che nello stack vige la regola LAST IN FIRST OUT, quindi se i registri sono stati salvati nell'ordine A, X, Y, questi vengono recuperati nell'ordine Y, X e A.

L'istruzione RTI ordina al microprocessore di ripristinare il registro di stato e il contatore di programma utilizzando i valori salvati nello stack dal processore all'atto dell'interruzione. A questo punto, il programma interrotto riprende tranquillamente.

Citazione
Un grazie a iAN CooG/HF
ed anche a MarC=ello...
leggendo il forum di Ready64 ho trovato un suo riferimento a Knowledge Base Article #121
che affronta l'argomento tema di questo thread... 

Sì, è un'articolo ben fatto. L'ho trovato particolarmente interessante per come spiega le interruzioni generate dal VIC-II. Naturalmente il VIC-II è trattato magistralmente in Mapping the C64, anche per quanto riguarda le interruzioni.




 
-=MarC=ellO=-