Interesuje mnie jak wywoływać procedury z romu kiedy go nie ma :D
Konkretnie chodzi o zagwarantowanie poprawnej obsługi przerwań przez system kiedy podnoszę sobie rom i operuję na ramie pod nim.
Założenia:
1. Nie satysfakcjonuje mnie blokada przerwań na czas operacji na ramie pod romem.
2. Chciałbym wywoływać przerwanie z romu przez jmp ($fffe) zakończone oczywiście przez rti.
Czy poniższy kod zadziała poprawnie? Na początek irq:
;ustawiamy wektory obslugi przerwan w ramie pod romem
sei
lda #0
sta irqen
lda #%11111110
sta portb
ldx <irqproc
ldy >irqproc
stx irqvec ;$fffe
sty irqvec+1 ;$ffff
;opuszczamy rom
lda #%11111111
sta portb
lda #$c0
sta irqen
cli
...
;tu się dalej coś dzieje łącznie z podnoszeniem romu i opuszczaniem bez żadnej synchronizacji
...
irqproc equ *
sta irq_a
lda portb
sta irq_pb
lda #%11111111
sta portb
lda <irqret
pha
lda >irqret
pha
php
lda irq_a
jmp (irqvec) ;$fffe
irqret equ *
lda irq_pb
sta portb
lda irq_a
rti
irq_a org *+1
irq_pb org *+1
Żeby spełnić założenia mój kod obsługi irq:
1. Zachowuje konfigurację pamięci.
2. Wstawia flagi i adres procedury odtwarzającej portb na stos.
3. Opuszcza rom i skacze pod $fffe.
Ponieważ flagi odkładane na stos mają celowo ustawiony znacznik I (php w procedurze przerwania - dodatkowo przenosi ono jeszcze flagę B dla przerwań brk) więc po wykonaniu rti z procedury systemowej (do której skaczemy jmp ($fffe)) powinniśmy z blokadą przerwań irq wrócić pod irqret i odtworzyć konfigurację pamięci - prawda? irq, które zdarzy się podczas obsługi nie powinno zostać odebrane, bo ma czekać na skasowanie flagi I. Akumulator w zasadzie mógłby być odtwarzany tylko w irqret, ale zakładam, że może być potrzebny userowi i stąd lda irq_a przed jmp ($fffe).
A teraz ta sama sztuczka tylko dla nmi :)
Jak wiadomo nmi nie można opóźnić (niezależnie od stanu flagi I zawsze jest wykonywana procedura obsługi przerwania) - da się go tylko zablokować, co mi kompletnie nie odpowiada, bo nie wiem w którym momencie przyjdzie mi skorzystać z ramu pod romem.
Czy poniższy kod zadziała poprawnie?
nmiproc equ *
sta nmi_a
lda portb
sta nmi_pb
lda #%11111111
sta portb
lda <nmiret
pha
lda >nmiret
pha
php
lda nmi_a
jmp (nmivec) ;$fffa
nmiret equ *
lda nmi_pb
sta portb
lda nmi_a
rti
nmi_a org *+1
nmi_pb org *+1
Implementacja się nie różni od tej dla irq, ale:
1. Mimo, że nmi mogą się przerywać, to w chwili kiedy włączymy rom mamy już obsługę nmi systemową i nie musimy nic przełączać (!) a więc specjalna obsługa potrzebna jest tylko kiedy rom jest podniesiony.
2. Sztuczka z php dalej przydaje się do odwlekania irq.
Najbardziej wrażliwy punkt to moment od przyjęcia przerwania do włączenia romu - 17 cykli. Jeśli vblk i dli nie będą interferować to chyba nie powinno być problemu?
Może ktoś z tym ma jakieś doświadczenia? Będzie to działać poprawnie?
Edit: Oczywiście całe cyklowanie dli pójdzie w kosz, ale na to już nic nie poradzę :(
niewiedza buduje, wiedza rujnuje