Programowanie: Użycie OS-a przy wyłączonym ROM-ie

From Atariki

(Różnice między wersjami)
Jump to: navigation, search
Wersja z dnia 16:05, 4 gru 2019
Mono (Dyskusja | wkład)
(Przelotki)
← Previous diff
Aktualna wersja
Mono (Dyskusja | wkład)
(Przelotki - function not implemented)
Linia 6: Linia 6:
<pre> <pre>
nmiint sec nmiint sec
- scs+ .byte $24 ;BIT $18 ($18 to opcode CLC niżej)
irqint clc irqint clc
 +
 + ;wlaczenie OS ROM
 +
 + inc PORTB ;$D301
pha pha
Linia 14: Linia 18:
pha pha
tsx tsx
- 
- ;wlaczenie OS ROM 
- 
- inc PORTB ;$D301 
;odlozenie na stos danych dla powrotu z przerwania (RTI) ;odlozenie na stos danych dla powrotu z przerwania (RTI)
Linia 34: Linia 34:
jmp (IRQVEC) ;$FFFE jmp (IRQVEC) ;$FFFE
-iret ;wylaczenie OS ROM+iret pla
- +
- dec PORTB ;$D301+
- +
- pla+
tax tax
pla pla
 +
 + ;wylaczenie OS ROM
 +
 + dec PORTB ;$D301
rti rti
</pre> </pre>
Linia 76: Linia 76:
Kiedy OS ROM jest odłączony wektor wejścia w przerwanie pobierany jest z NMIVEC lub IRQVEC, które znajdują się w RAM i wykonywana jest procedura przerwania nmiint lub irqint zależnie od rodzaju zgłoszonego przerwania. Kiedy OS ROM jest odłączony wektor wejścia w przerwanie pobierany jest z NMIVEC lub IRQVEC, które znajdują się w RAM i wykonywana jest procedura przerwania nmiint lub irqint zależnie od rodzaju zgłoszonego przerwania.
W obydwu przypadkach ma ona za zadanie włączenie ROM-u, wykonanie procedury obsługi przerwania według wektora znajdującego się już w ROM, oraz przywrócenie konfiguracji pamięci po powrocie. W obydwu przypadkach ma ona za zadanie włączenie ROM-u, wykonanie procedury obsługi przerwania według wektora znajdującego się już w ROM, oraz przywrócenie konfiguracji pamięci po powrocie.
-Odbywa się to poprzez zapalenie najmłodszego bitu PORTB (włączenie OS ROM), odłożenie na stos adresu powrotu do procedury iret oraz wartości rejestru F procesora odłożonego na stos w sekwencji wywołania przerwania. Zduplikowanie tej wartości jest niezbędne dla poprawnego działania systemowych procedur obsługi przerwań, ponieważ testują one:+Odbywa się to poprzez zapalenie najmłodszego bitu PORTB (włączenie OS ROM), odłożenie na stos adresu powrotu do procedury iret oraz zawartości rejestru stanu F procesora odłożonego na stos w sekwencji wywołania przerwania. Zduplikowanie tej wartości jest niezbędne dla poprawnego działania systemowych procedur obsługi przerwań (tylko wartość rejestru F odłożona na stosie zawiera poprawne wartości znaczników I i B), ponieważ testują one:
* czy przerwane zostało wykonanie przerwania IRQ (w przypadku obsługi przerwania NMI), * czy przerwane zostało wykonanie przerwania IRQ (w przypadku obsługi przerwania NMI),
* czy przerwanie IRQ zostało zgłoszone przez układ I/O, czy może przerwanie zostało wywołane przez rozkaz BRK (w przypadku obsługi przerwania IRQ). * czy przerwanie IRQ zostało zgłoszone przez układ I/O, czy może przerwanie zostało wywołane przez rozkaz BRK (w przypadku obsługi przerwania IRQ).
Po wykonaniu procedury z ROM sterowanie przekazywane jest do procedury iret, której jedynym zadaniem jest ponowne odtworzenie konfiguracji pamięci (odłączenie ROM). Po wykonaniu procedury z ROM sterowanie przekazywane jest do procedury iret, której jedynym zadaniem jest ponowne odtworzenie konfiguracji pamięci (odłączenie ROM).
 +
 +Podczas obsługi przerwania IRQ może się zdarzyć, że nadejdzie nowe zgłoszenie IRQ. W tej sytuacji, po powrocie z procedury obsługi bieżącego przerwania a jeszcze przed wykonaniem procedury iret, obsłużone zostanie nowe przerwanie za pomocą systemowej procedury zawartej w ROM. Dzieje się tak z powodu duplikacji rejestru F odkładanego na stos w procedurze irqint, w którym znacznik I jest zgaszony. Dopiero po zakończeniu obsługi wszystkich zgłoszonych przerwań następuje wykonanie procedury iret przywracającej konfigurację PORTB.
= Wywoływanie procedur OS = = Wywoływanie procedur OS =
Linia 138: Linia 140:
Ta metoda powinna być używana również do wywołania procedury PUTBT dostępnej w rejestrze ICPUTB bloku IOCB n.p. Ta metoda powinna być używana również do wywołania procedury PUTBT dostępnej w rejestrze ICPUTB bloku IOCB n.p.
<pre> <pre>
-;IN: X-IOCB#*16, A-ATASCII+;IN: X-IOCB#*16, A-data
;OUT: Y-status, N-error flag ;OUT: Y-status, N-error flag
CIO_PUTBT_jump: CIO_PUTBT_jump:
Linia 159: Linia 161:
pha pha
tya tya
 + ldy #$92 ;FUNCTION NOT IMPLEMENTED
rts rts
</pre> </pre>
Linia 175: Linia 178:
sec sec
- scs+ .byte $24 ;BIT $18
irqint clc irqint clc
Linia 210: Linia 213:
rti rti
</pre> </pre>
-<b>UWAGA!</b> Należy również mieć na uwadze, że wektor VDSLST powinien wskazywać na procedurę obsługi DLI zdefiniowaną przez użytkownika i znajdującą się poza obszarem w którym może pojawić się ROM (patrz "Restrykcje pamięciowe").+Trzeba to mieć też na uwadze kiedy w procedurze DLI wykorzystuje się dane lub procedury leżące pod ROM-em i w analogiczny sposób zagwarantować odpowiednią konfigurację PORTB.
 + 
 +<b>UWAGA!</b> Wektor VDSLST powinien wskazywać na procedurę obsługi DLI zdefiniowaną przez użytkownika i znajdującą się poza obszarem w którym może pojawić się ROM (patrz "Restrykcje pamięciowe").
= Restrykcje pamięciowe = = Restrykcje pamięciowe =
-Procedury handlera, "przelotek" czy procedur obsługi przerwań zdefiniowanych przez użytkownika (a także procedura inicjalizacji całego mechanizmu) powinny znajdować się w RAM poza obszarami w których istnieje ryzyko pojawienia się pamięci ROM:+Procedury handlera, "przelotek" czy procedur obsługi przerwań zdefiniowanych przez użytkownika (a także procedura inicjalizacji całego mechanizmu) powinny znajdować się w RAM poza obszarami w których istnieje ryzyko pojawienia się pamięci ROM, a takim ryzykiem obarczone są:
-* $5000..$57FF - SELF-TEST+* $5000..$57FF - [[SELF TEST|SELF-TEST]], lub [[MapRAM]]
-* $8000..$9FFF - cartridge+* $8000..$9FFF - [[Cartridge|cartridge]]
-* $A000..$BFFF - cartridge, wbudowany BASIC (XL/XE), wbudowana gra (XEGS)+* $A000..$BFFF - [[Cartridge|cartridge]], wbudowany [[Atari BASIC]] (XL/XE), wbudowana gra ([[XEGS]])
-* $C000..$CFFF - OS ROM+* $C000..$CFFF - [[XL OS|OS]] ROM
* $D000..$D7FF - obszar rejestrów hardware * $D000..$D7FF - obszar rejestrów hardware
-* $D800..$DFFF - OS ROM (pakiet matematyczny) lub ROM nowego urządzenia+* $D800..$DFFF - [[XL OS|OS]] ROM ([[Pakiet matematyczny|pakiet matematyczny]]) lub ROM [[Nowe urządzenia|nowego urządzenia]]
-* $E000..$FFFF - OS ROM+* $E000..$FFFF - [[XL OS|OS]] ROM
-W przypadku gdy wykorzystywana jest pamięć dodatkowa (XE) również obszar $4000..$7FFF jest obszarem ryzykownym.+W przypadku gdy wykorzystywana jest pamięć dodatkowa ([[130XE|XE]]) również obszar $4000..$7FFF jest obszarem ryzykownym.
Jeśli programista może zagwarantować, że określony rodzaj pamięci nie będzie nigdy przełączany, wtedy oczywiście procedury obsługi przełączania pamięci mogą być umieszczone w odnośnym obszarze (z oczywistych przyczyn obszar rejestrów hardware ani OS ROM do takich nie należy). Jeśli programista może zagwarantować, że określony rodzaj pamięci nie będzie nigdy przełączany, wtedy oczywiście procedury obsługi przełączania pamięci mogą być umieszczone w odnośnym obszarze (z oczywistych przyczyn obszar rejestrów hardware ani OS ROM do takich nie należy).
Linia 235: Linia 240:
* http://www.atari.org.pl/forum/viewtopic.php?id=7336 - dyskusja na forum AtariArea * http://www.atari.org.pl/forum/viewtopic.php?id=7336 - dyskusja na forum AtariArea
 +* [[Mapa pamięci]]
[[Kategoria:Niezbędnik kodera]] [[Kategoria:Niezbędnik kodera]]

Aktualna wersja

Żeby swobodnie używać mechanizmów OS-a a przy tym mieć dostęp do całego RAM-u trzeba zadbać tylko o poprawne wykonanie procedur przerwań umieszczonych w ROM-ie w sytuacji kiedy ten jest wyłączony.

Spis treści

Handler

Kod handlera przerwań powinien być umieszczony poza obszarem, w którym może się pojawić ROM (patrz "Restrykcje pamięciowe"):

nmiint  sec
        .byte $24       ;BIT $18 ($18 to opcode CLC niżej)

irqint  clc

        ;wlaczenie OS ROM

        inc PORTB       ;$D301

        pha
        txa
        pha
        tsx

        ;odlozenie na stos danych dla powrotu z przerwania (RTI)

        lda #>iret      ;adres procedury iret
        pha
        lda #<iret
        pha
        lda $103,x      ;skopiowanie wartosci rejestru stanu procesora
        pha

        ;skok przez odpowiedni wektor przerwania

        scc
        jmp (NMIVEC)    ;$FFFA
        jmp (IRQVEC)    ;$FFFE

iret    pla
        tax
        pla

        ;wylaczenie OS ROM

        dec PORTB       ;$D301
        rti

Inicjalizacja

Wszystko co jest potrzebne do uruchomienia mechanizmu to inicjalizacja wektorów NMIVEC i IRQVEC pod ROM-em:

        sei
        lda #%00000000
        sta NMIEN       ;$D40E
        lda #%11111110
        sta PORTB       ;$D301

        ldx #<nmiint
        ldy #>nmiint
        stx NMIVEC      ;$FFFA
        sty NMIVEC+1

        ldx #<irqint
        ldy #>irqint
        stx IRQVEC      ;$FFFE
        sty IRQVEC+1

        lda #%01000000
        sta NMIEN       ;$D40E
        cli

Od tej pory można swobodnie wyłączać i włączać dowolny obszar ROM (przez zwykłą modyfikację rejestru PORTB) bez obawy o to, że komputer się zawiesi.

Działanie

W przypadku kiedy OS ROM jest włączony przerwanie obsługiwane jest przez standardowe procedury umieszczone w systemie operacyjnym (ponieważ wektory NMIVEC oraz IRQVEC znajdują się wtedy w obszarze ROM).

Kiedy OS ROM jest odłączony wektor wejścia w przerwanie pobierany jest z NMIVEC lub IRQVEC, które znajdują się w RAM i wykonywana jest procedura przerwania nmiint lub irqint zależnie od rodzaju zgłoszonego przerwania. W obydwu przypadkach ma ona za zadanie włączenie ROM-u, wykonanie procedury obsługi przerwania według wektora znajdującego się już w ROM, oraz przywrócenie konfiguracji pamięci po powrocie. Odbywa się to poprzez zapalenie najmłodszego bitu PORTB (włączenie OS ROM), odłożenie na stos adresu powrotu do procedury iret oraz zawartości rejestru stanu F procesora odłożonego na stos w sekwencji wywołania przerwania. Zduplikowanie tej wartości jest niezbędne dla poprawnego działania systemowych procedur obsługi przerwań (tylko wartość rejestru F odłożona na stosie zawiera poprawne wartości znaczników I i B), ponieważ testują one:

  • czy przerwane zostało wykonanie przerwania IRQ (w przypadku obsługi przerwania NMI),
  • czy przerwanie IRQ zostało zgłoszone przez układ I/O, czy może przerwanie zostało wywołane przez rozkaz BRK (w przypadku obsługi przerwania IRQ).

Po wykonaniu procedury z ROM sterowanie przekazywane jest do procedury iret, której jedynym zadaniem jest ponowne odtworzenie konfiguracji pamięci (odłączenie ROM).

Podczas obsługi przerwania IRQ może się zdarzyć, że nadejdzie nowe zgłoszenie IRQ. W tej sytuacji, po powrocie z procedury obsługi bieżącego przerwania a jeszcze przed wykonaniem procedury iret, obsłużone zostanie nowe przerwanie za pomocą systemowej procedury zawartej w ROM. Dzieje się tak z powodu duplikacji rejestru F odkładanego na stos w procedurze irqint, w którym znacznik I jest zgaszony. Dopiero po zakończeniu obsługi wszystkich zgłoszonych przerwań następuje wykonanie procedury iret przywracającej konfigurację PORTB.

Wywoływanie procedur OS

Trzeba pamiętać (co właściwie powinno być oczywiste), że gdy w programie chcemy wywołać dowolną systemową procedurę z ROM, a jest on aktualnie odłączony, to trzeba go sobie włączyć:

        lda #%11111111
        sta PORTB       ;$D301

        jsr JSIOINT     ;$E459

Odwołania do procedur OS-a odbywają się przez tablice wektorów oraz tablicę skoków. Stanowią one oficjalne punkty wejścia do procedur systemu operacyjnego i gwarantują, że niezależnie od wersji oraz rodzaju systemu operacyjnego zainstalowanego w komputerze zawsze zostanie wywołana procedura żądana przez użytkownika.

Wyjątek stanowią procedury pakietu matematycznego który nie posiada tablicy skoków, przez co odpowiednie procedury niezależnie od wersji pakietu zainstalowanego w komputerze zawsze muszą znajdować się pod ustalonymi adresami.

Przelotki

Wygodnym sposobem realizowania skoków do procedur OS jest zdefiniowanie tzw. "przelotek", które zadbają o konfigurację pamięci i jej odtworzenie po powrocie z procedury.

UWAGA! Takie "przelotki" analogicznie, jak procedura handlera przerwań, powinny również znajdować się poza obszarem, w którym może pojawić się ROM (patrz "Restrykcje pamięciowe").

Wywołania przez systemową tablicę skoków:

JSIOINT_jump:
        lda PORTB       ;$D301
        pha
        ora #%00000001
        sta PORTB       ;$D301

        jsr JSIOINT     ;$E459

        pla
        sta PORTB       ;$D301
        rts

Nieco odmienna jest metoda wywoływania procedur dostępnych przez tablicę wektorów, ponieważ wektory wskazują adres procedury zmniejszony o jeden i jako takie służą do wykonania skoku przez RTS:

CIO_S_SPECIAL_jump:
        lda PORTB
        pha
        ora #%00000001
        sta PORTB

        jsr ?call

        pla
        sta PORTB
        rts

?call   lda $E410+$0A+1  ;tablica handlera S: wektor SPECIAL
        pha
        lda $E410+$0A
        pha
        rts

Ta metoda powinna być używana również do wywołania procedury PUTBT dostępnej w rejestrze ICPUTB bloku IOCB n.p.

;IN: X-IOCB#*16, A-data
;OUT: Y-status, N-error flag
CIO_PUTBT_jump:
        tay
        lda PORTB
        pha
        ora #%00000001
        sta PORTB

        jsr ?call

        pla
        sta PORTB
        cpy #0
        rts

?call   lda ICPUTB+1,x
        pha
        lda ICPUTB,x     ;$0346
        pha
        tya
        ldy #$92         ;FUNCTION NOT IMPLEMENTED
        rts

Rejestry OS w RAM

Rejestry $00..$7F oraz $2xx i $3xx są zarezerwowane dla potrzeb systemu operacyjnego.

DLI

W przypadku gdy w programie używane jest przerwanie Display List, które zazwyczaj jest krytyczne czasowo, można zmodyfikować punkt wejścia do przerwania NMI tak, aby zagwarantować identyczne zależności czasowe jak w przypadku gdy przerwanie obsługiwane jest bezpośrednio przez procedurę systemu operacyjnego:

nmiint  bit NMIST        ;$D40F
        spl
        jmp (VDSLST)     ;$0200

        sec
        .byte $24        ;BIT $18

irqint  clc

        ...

Należy jednak pamiętać, że wtedy po wejściu do procedury obsługi przez wektor VDSLST ($200) nie ma gwarancji że ROM jest włączony. Jeśli więc w procedurze obsługi przerwania DLI chcemy użyć jakiejś procedury z ROM należy osobiście zadbać o poprawne skonfigurowanie pamięci, oraz odtworzenie jej przed wyjściem z przerwania n.p. tak:

custom_dli:
        pha

        lda PORTB
        pha
        ora #%00000001
        sta PORTB

        ...
        jsr OS_ROUTINE
        ...

        pla
        sta PORTB
        pla
        rti

lub też wykorzystać opisane wyżej "przelotki":

custom_dli:
        pha
        ...
        jsr OS_ROUTINE_jump
        ...
        pla
        rti

Trzeba to mieć też na uwadze kiedy w procedurze DLI wykorzystuje się dane lub procedury leżące pod ROM-em i w analogiczny sposób zagwarantować odpowiednią konfigurację PORTB.

UWAGA! Wektor VDSLST powinien wskazywać na procedurę obsługi DLI zdefiniowaną przez użytkownika i znajdującą się poza obszarem w którym może pojawić się ROM (patrz "Restrykcje pamięciowe").

Restrykcje pamięciowe

Procedury handlera, "przelotek" czy procedur obsługi przerwań zdefiniowanych przez użytkownika (a także procedura inicjalizacji całego mechanizmu) powinny znajdować się w RAM poza obszarami w których istnieje ryzyko pojawienia się pamięci ROM, a takim ryzykiem obarczone są:

W przypadku gdy wykorzystywana jest pamięć dodatkowa (XE) również obszar $4000..$7FFF jest obszarem ryzykownym.

Jeśli programista może zagwarantować, że określony rodzaj pamięci nie będzie nigdy przełączany, wtedy oczywiście procedury obsługi przełączania pamięci mogą być umieszczone w odnośnym obszarze (z oczywistych przyczyn obszar rejestrów hardware ani OS ROM do takich nie należy).

Trivia

Opisana tutaj sztuczka jest stosowana między innymi przez Turbo BASIC XL, U-BASIC oraz SpartaDOS X.

Linki

Personal tools