by zrobić trochę badań i eksperymentów.
Jest wyświetlacz LCD, więc weryfikacja nieudokumentowanych
instrukcji daje się łatwo zrealizować. Na początek
badania związane z przerwaniami połówkowymi.
Generowało mi się trochę „dziwności”, ale później się okazało,
że był błąd w sofcie i po poprawce per saldo
zgadza się z literaturą. Jest jeszcze jedna „dziwność”,
bo nie zauważyłem wpływu operacji zerowania
przerwania 7.5 na działanie całości. Być może problem
jest szerszy i należy go rozpatrywać w szerszej perspektywie.
Badania przerwania 7.5 w 8085
Mając hardware z prockiem i8085 pomyślałem sobie, że fajnie jest zrobić trochę doświadczeń dotyczących przerwania 7.5 (inne są niestety sprzętowo zablokowane, jak pokazuje schemat), tylko przerwanie 7.5 ma doprowadzony sygnał, pozostałe są uglebione na stałe (przerwanie 5.5 i 6.5 reagują na poziom wysoki, przerwanie 7.5 reaguje na zbocze narastające).
Więc by uruchomić przerwanie należy wykonać następujący zapis instrukcją SIM (set interrupt mask).
Kod: Zaznacz cały
Init_hardware ;
mvi a , Enable75Inter ;
sim ;
ret
Wartość i znaczenie bitów w Enable75Inter jest następujące:
Jak tego się nie wykona, to procek nie reaguje na przerwania (sprawdziłem). Jak wygląda problematyka po sygnale reset? Przed ustawieniem maski wykonałem instrukcję RIM (read interrupt mask) i stan akumulatora zapisałem w zmiennej do późniejszego wyświetlenia.
Kod: Zaznacz cały
Init_hardware ;
rim ;
sta RIMByte ;
mvi a , Enable75Inter ;
sim ;
ret
By mieć pełna kontrolę nad przerwaniami (czyli generować je samemu), wyjąłem z układu 8253 i dałem taki oto układ (taki ogólnofilozoficzny zadawacz stanów bez dzwonienia styków bazujący na CD4044 – poczwórnym przerzutniku RS).
Czerwony kabelek to plus zasilania, niebieski to minus zasilania a pozostałe to wyjścia (jest używane jedno: też czerwony skrajnie prawy).
Po odpaleniu programu jest wyświetlony stan konfiguracyjny po resecie.
Gdzie znaczenie bitów jest następujące:
To by się zgadzało z tym, co jest napisane w dokumentacji Intela.
Naciśnięcie przycisku w zadawaczu stanów nie generuje jeszcze nic (jest stan zera: dioda nie świeci).
Zmiana stanu z zera na jedynkę (zbocze narastające) generuje przerwanie.
Jego obsługa to:
Kod: Zaznacz cały
.org RST75Entry ;
push psw ;
rim ;
sta RIMByte ;
lda IRQCnt ;
inr a ;
sta IRQCnt ;
mvi a , 1 ;
sta IRQFlag ;
mvi a , Cler75FlipFlop ;
sim ;
pop psw ;
ei ;
ret ;
czyli zapamiętanie stanu RIM wewnątrz obsługi przerwania (zmienna RIMByte), zliczenie przerwania (zmienna IRQCnt) i ustawienie flagi, że doszło do przerwania (zmienna IRQFlag). Wyniki są „spożytkowane” w programie „na zewnątrz” przerwania w funkcji main.
Kod: Zaznacz cały
Main ;
call InitialiseLCD ;
call ClrScrLCD ;
lxi h , HelloMessage ;
call WriteTextLCD ;
call NewLineLCD ;
mvi a , '#' ;
call WriteChLCD ;
lda IRQCnt ;
call DispHex ;
call DisplayRIM ;
Main_0 ;
lda IRQFlag ;
cpi 0 ;
jz Main_0 ;
mvi a , 0 ;
sta IRQFlag ;
call ClrScrLCD ;
mvi a , '*' ;
call WriteChLCD ;
lda IRQCnt ;
call DispHex ;
call DisplayRIM ;
call NewLineLCD ;
rim ;
sta RIMByte ;
mvi a , ' ' ;
call WriteChLCD ;
mvi a , ' ' ;
call WriteChLCD ;
mvi a , ' ' ;
call WriteChLCD ;
call DisplayRIM ;
jmp Main_0 ;
W pierwszym wierszu są zapamiętane dane z wnętrza przerwania, w drugim wierszu są spoza obsługi przerwania (z funkcji main).
Różnice są niewielkie: widać, że przyjęcie przerwania jest połączone z wykonaniem instrukcji blokującej przerwania (DI). W obsłudze przerwania jest jeszcze:
Kod: Zaznacz cały
.org RST75Entry ;
.
.
.
mvi a , Cler75FlipFlop ;
sim ;
.
.
.
ret ;
ale nie zauważyłem różnicy: czy flaga jest zerowana czy nie.