Asembler 8080 - przerwania i zrzucanie stanu rejestr

Chciałem trochę popchnąć do przodu prace nad swoim projektem komputera z polskim procesorem MCY7880 (klon intela 8080). Właśnie jestem w trakcie uruchamiania procedur do obsługi sterownika ekranu (TMS9918). Wszystko działa prawidłowo - jestem w stanie komunikować się układem poprzez jego dwa rejestry, wysyłać i odczytywać dane z VRAM-u oraz wypisywać znaki w odpowiednich miejscach na ekranie. Teraz postanowiłem napisać krótką funkcję do przewijania ekranu o jedną linię w momencie, gdy kursor dotrze do jego końca. Kod działa prawidłowo, ale tylko przez pewien czas - zwykle po kilku (czasem kilkunastu) minutach pojawia się błąd skutkujący zniknięciem wszystkich linii za wyjątkiem ostatniej. Raczej mogę wykluczyć problem sprzętowy. Wymieniłem zarówno pamięć jak i TMS9918, poza tym problem znika za każdym razem po ponownym uruchomieniu urządzenia i nie manifestuje się jeśli nie używam tej procedury do przewijania.

Ponieważ błąd manifestuje się nieregularnie, wygląda mi to na problem z przerwaniem nadpisującym któryś z rejestrów. Sama funkcja do przewijania ekranu wywołuje kilka innych procedur do odczytu, zapisu i zerowania VRAM-u, które przyjmują parametry w parach rejestrów BC, DE oraz HL.

VDPSCROLLUP: ;Mowe 12 lines ;Read them first LXI B, BLKDAT LXI D, 0828H LXI H, 01E0H CALL VDPRVRAM ;Move lines from buffer to the beginning of the screen LXI B, BLKDAT LXI D, 0800H LXI H, 01E0H CALL VDPWVRAM ;Move remaining 11 lines ;Read them first LXI B, BLKDAT LXI D, 0A08H LXI H, 01B8H CALL VDPRVRAM ;Write those lines to the middle of the screen LXI B, BLKDAT LXI D, 09E0H LXI H, 01B8H CALL VDPWVRAM ;Clear last line LXI D, 0B98H LXI H, 0028H CALL VDPZEROVRAM RET

W aktywnych przerwaniach faktycznie mam instrukcje modyfikujące HL, DE oraz oczywiście akumulator/rejestr flag, jednak przed wykonaniem procedury obsługi przerwania zrzucam ich stany na stos za pomocą PUSH, a potem przywracam instrukcją POP.

Aby oszczędzić jak najszybciej wyjść z procedury obsługi przerwania, zrzucam na stos tylko te rejestry, które są wykorzystywane w jego wnętrzu. Nie widzę więc gdzie przerwanie mogłoby mi mieszać w przewijaniu ekranu.

No chyba, że któraś z instrukcji może w sposób niejawny modyfikować rejestry inne niż A/flagi? Czy wskazane jest na wszelki wypadek w przerwaniu zapisywać na stos wszystkie rejestry, nawet jeśli się ich nie używa?

Ktoś ma pomysł co do innej możliwej przyczyny?

Reply to
Atlantis
Loading thread data ...

W dniu 2021-08-06 o 09:00, Atlantis pisze:

A 8080 nie ma czasami banków rejestrów jak 51?

No i dobrze.

Nie widzę więc gdzie przerwanie mogłoby mi mieszać w

Masz gdzieś błąd.

Wątpię. to są stare procki i o czymś takim bym słyszał.

Czy wskazane jest na wszelki wypadek w

Możesz spróbować dla testu, normalnie to bez sensu.

Reply to
Janusz

Nie, ten cud techniki pojawił się w Z80, nie w 8080

formatting link
porównania:
formatting link

Reply to
Zbych

W dniu 2021-08-06 o 09:39, Janusz pisze:

Dawno nie zajmowałem się 8080, ale jestem pewien, że nie. Ale MCY7880 znam tylko ze słyszenia, może ma jakieś własne wynalazki?

Inne sugestie do testów:

  1. wyłączyć wszystkie przerwania, jeśli można
  2. sprawdzić, czy stos nie przepełnia się / nie wychodzi poza obszar pamięci (masz pełne 64KB?)

Pozdrowienia, MKi

Reply to
MKi

Wrzuć kod tego przerwania, a przynajmniej początek i koniec.

Reply to
Zbych

Wydaje mi się, że nie. Pod tym względem 8080 to taki uproszczony Z80. Posiada tylko akumulator, rejestr flag oraz pary rejestrów, które można traktować jako rejestr szesnastobitowe rejestry do wykonywania niektórych instrukcji, albo dwa ośmiobitowe, niezależne rejestry: BC, DE oraz HL. Ten ostatni jest wykorzystywany przez niektóre instrukcje jaki wskaźnik na określoną lokalizację w pamięci. No i oczywiście jest jeszcze SP oraz wskaźnik stosu.

Pytanie tylko gdzie... Poza hipotezą z przerwaniami nie przychodzi mi nic innego do głowy.

Funkcje do operacji na VRAM-ie wyglądają następująco:

;RAM ADDRES IN BC, VRAM ADDRES IN DE, DATA LENGTH IN HL VDPRVRAM: MOV A, E OUT VDP_MODE NOP NOP MOV A, D OUT VDP_MODE NOP NOP VDPRVRAML: IN VDP_DATA NOP NOP STAX B INX B DCX H MOV A, H ORA L JNZ VDPRVRAML RET

;RAM ADDRESS IN BC, VRAM ADDRES IN DE, DATA LENGTH IN HL VDPWVRAM: MOV A, E OUT VDP_MODE NOP NOP MOV A, D ORI 40H OUT VDP_MODE NOP NOP VDPWVRAML: LDAX B OUT VDP_DATA NOP NOP INX B DCX H MOV A, H ORA L JNZ VDPWVRAML RET

;VRAM ADDRES IN DE, DATA LENGTH IN HL VDPZEROVRAM: MOV A, E OUT VDP_MODE NOP NOP MOV A, D ORI 40H OUT VDP_MODE NOP NOP VDPZEROVRAML: MVI A, 00H OUT VDP_DATA NOP NOP DCX H MOV A, H ORA L JNZ VDPZEROVRAML RET

Instrukcje NOP umieszczone testowo, docelowo raczej nie będą potrzebne. Kod instrukcji do przewijania ekranu zamieściłem w poprzedniej wiadomości. Zawarte w niej adresy lokalizacji w VRAM-ie oraz długości odczytywanych/zapisywanych ciągów danych raczej są prawidłowe - przewijanie potrafi zachowywać się prawidłowo przez całe minuty, pomimo dużej ilości tekstu przelatującego przez ekran. Gdyby tam była pomyłka, to błędy bardzo szybko by się nawarstwiły i obraz zacząłby się rozjeżdżać już po pierwszym przewinięciu o linię do góry.

Reply to
Atlantis

Raczej z80 to rozbudowany 8080 :)

albo gdzieś się wskaźnik źle aktualizuje.

Reply to
Janusz

Nie sądzę. Z tego co czytałem to dość dokładny klon 8080. Podejrzewam, że gdyby były tam jakieś znaczące różnice, to już dałyby o sobie znać podczas uruchamiania innych peryferiów oraz TinyBasica pisanego z myślą o oryginalnym procesorze Intela.

W sumie racja. W tej chwili chyba nie obsługują jeszcze niczego krytycznego.

Tak i nie. Mam pełne 64kB RAM-u, ale tylko jeden 32kB układ jest zmapowany bezpośrednio na pierwszą połówkę przestrzeni adresowej. Druga połówka mieści stronnicowany RAM (2x16 kB) oraz 16kB EPROM. Stos rozpoczyna się na 0x7FFF, podczas gdy ostatnia zmienna w pamięci znajduje się pod adresem 0x2188. To bardzo dużo miejsca dla stosu, jak na prosty interpreter TinyBasica. Oczywiście biorę pod uwagę możliwość, że coś może sukcesywnie zapisywać dane do stosu bez ich zdejmowania, jest jednak jedno "ale" - wszystko działa całkowicie stabilnie, o ile nie używam procedury scrollującej. A procedura scrollująca (ani żadna z wywoływanych przez nią procedur) nie używa instrukcji PUSH.

Reply to
Atlantis

Poniżej. Z tego co widzę w chwili obecnej i tak zachowuję na stosie więcej niż potrzeba - trafiają tam nawet te rejestry, których w danej procedurze nie używam - pewnie pozostałość po jakichś eksperymentach. Nie widzę tam jednak niczego, co mogłoby powodować takie kłopoty. Wszystkie pary rejestrów są odkładane na stos i zdejmowane z niego we właściwej kolejności.

W chwili obecnej jedyne aktywne przerwanie to te od timera, RTC oraz klawiatury. Wszystkie pozostałe są wyłączone na poziomie kontrolera (8259).

;Interrupt routines UART_RX_ISR: PUSH PSW PUSH H PUSH D POP D POP H POP PSW EI RET

UART_TX_ISR: PUSH PSW PUSH H PUSH D POP D POP H POP PSW EI RET

KBD_ISR: PUSH PSW PUSH H PUSH D IN KBD_DATA STA KBDDATA POP D POP H POP PSW EI RET

TIMER_ISR: PUSH PSW PUSH H PUSH D LHLD SYSTICK INX H SHLD SYSTICK MVI A, 00H OUT COUNT_REG_1_8253 MVI A, 0A0H OUT COUNT_REG_1_8253 POP D POP H POP PSW EI RET RTC_ISR: PUSH PSW PUSH H PUSH D MVI A, 00H OUT RTC_CTRLD_REG LHLD RTCTICK INX H SHLD RTCTICK POP D POP H POP PSW EI RET VDP_ISR: PUSH PSW PUSH H PUSH D POP D POP H POP PSW EI RET

;Interrupt vectors IR0_VECT: ORG 0FFE0H EI RET NOP NOP IR1_VECT: EI RET NOP NOP IR2_VECT: JMP TIMER_ISR NOP IR3_VECT: JMP UART_TX_ISR NOP IR4_VECT: JMP UART_RX_ISR NOP IR5_VECT: JMP KBD_ISR NOP IR6_VECT: JMP RTC_ISR NOP IR7_VECT JMP VDP_ISR NOP

Reply to
Atlantis

Przychodzi mi do głowy jeszcze jedna hipoteza, że może coś jest nie tak z pamięcią systemową i w pewnym momencie przewijanie ekranu wysypuje się na odczycie z/zapisie do bufora BLKDAT. Byłoby to jednak wyjątkowo dziwną i niesamowicie selektywną awarią - w tym samym układzie pamięci SRAM mieści się przecież stos, kod wykonywanego programu w BASIC-u oraz kluczowe zmienne systemowe. Gdyby układ był wadliwy, to niestabilność systemu byłaby widoczna znacznie częściej, a nie tylko podczas wykonywania jednej procedury do scrollowania ekranu...

Reply to
Atlantis

Jeszcze jedna rzecz do mnie dotarła. Procedura scrollująca ekran jest jedyną częścią kodu, która korzysta z odczytu pamięci VRAM. Wszytsko inne (w tym alternatywa polegająca na skasowaniu ekranu i przesunięciu kursora na jego początek) zadowala się jedynie zapisem. Czy potencjalnie może istnieć jakaś sprzętowa przyczyna, która mogłaby się objawiać w ten sposób? Nie jest to raczej kwestia luźnej podstawki lub niełączącego kynaru, ponieważ przewijanie działa prawidłowo za każdym razem po włączeniu zasilania - nie wiem, np, uszkodzony inwerter na linii RD, "zatrzaskujący" się w jednej pozycji?

Reply to
Atlantis

The only way for the programmer to tell which set(s) are in context is to trace where each register swap is made at each point in the program.

Reply to
Zbych

W dniu 2021-08-06 o 15:00, Atlantis pisze:

Albo hazard czasowy na danych lub adresach. Trzeba oscylem sprawdzić czasy dostępu do pamięci.

Reply to
Janusz

Podmieniłem wszystkie układy scalone w sterowniku ekranu - nic się nie zmieniło. Gdy już kończyły mi się pomysły, a po kolejnym przeglądzie kody nie widziałem żadnego błędu, w akcie desperacji zacząłem sprawdzać mniej prawdopodobne hipotezy. Zacząłem od podmienienia pamięci SRAM. Nie tej w "karcie graficznej", ale głównej pamięci komputera. Wygląda na to, że trafiłem - komputer działa prawidłowo od kilku godzin, podczas gdy poprzednio problem z przewijaniem ekranu występował po kilku-kilkunastu-minutach.

Wygląda na to, że problem z danymi miał miejsce w buforze BLKDAT, pośredniczącym w przesuwanie tekstu na ekranie. Jak dotąd nie trafiłem na tak dziwny problem z pamięcią - przechodziła test na TL866, działała prawidłowo przez jakiś czas, ale potem zaczynała gubić dane w jednym konkretnym fragmencie - tym, który użyłem na bufor. Nie było problemów z kodem BASIC-a znajdującym się trochę wcześniej, ani zmiennymi systemowymi, które umieściłem za buforem. Co więcej - power cycle przywracał na chwilę prawidłowe działanie. Nie mogę też powiedzieć, żeby pamięć przekłamywała dane, bo wtedy widziałbym na ekranie losowe znaki - one je po prostu gubiła, najpewniej zastępując zerami (albo inną jednolitą wartością, która wskazywała sterownikowi ekranu pusty znak).

Reply to
Atlantis

Bo to malo prawdopodobne - wszystko dziala, tylko kopiowanie do sterownika ekranu nie. I to kopiowanie czysto programowe. Podmien jeszcze raz - zobaczysz czy problem wroci :-)

Jesli jednak wroci ... sterownik ekranu jakis wolny, i odczytany smieci na magistrali jeszcze dlugo? Szczegolnie, ze masz tam jeszcze kilka NOP .. no wlasnie - program z RAM czy EPROM czytany?

No wlasnie - nie tyle "gubi" co zastepuje zerami.

Ale to hipoteza, czy jakos sprawdziles, ze tak sie dzieje?

Bo znow - malo prawdopodobne. Chyba, ze pamiec na granicy parametrow. Ale bardziej bym podejrzewal jakis problem z dekoderem adresow - moze ci sie cos wcina w te przestrzen.

J.

Reply to
J.F

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.