Hallo Besucher, der Thread wurde 10k mal aufgerufen und enthält 98 Antworten

letzter Beitrag von Snoopy am

Verwendung von SYS in Bank 0 führt zu Absturz

  • crsc

    Ich hatte das jetzt so verstanden, das der VIC-IV sein Video RAM in den ersten 16MB RAM des Mega65 frei platzieren kann.

    Also aktuell in den 384kB fast RAM.

    Denn die 8MB ATTIC RAM liegen ab 128MB ($800.0000 - $87F.FFFF)

    und somit oberhalb der ersten 16MB.


    Aber vielleicht schaltet Paul ja noch ein paar hundert kB RAM frei, die aktuell ungenutzt im FPGA des Mega65 rumliegen.

    Aktuell macht er das wohl nicht, um die Kompatibilität des Cores zum NEXYS Board zu verlieren.


    Anbei ein Screenshot mit den derzeit existierenden Speicherbereichen.

    Das Character und das Color RAM des VIC-IV existiert aktuell auch schon, wenn ich mich recht entsinne.

  • Ich habe jetzt mal im Emulator (xmega65) mit dem neusten ROM 920285 ausprobiert.


    Das klappt hier auch bei $4000 in Bank 0 ohne Absturz.


  • Ich weiss jetzt was der Unterschied zwischen echter Hardware und XEMU ist. Ich habe das obige Programm auf beiden laufen lassen, aber zusätzlich eine eigene Interrupt-Routine geschrieben, die nichts weiter macht als die Interrupts zu zählen die auftreten, während die Warteschleife läuft.


    Auf dem XEMU hatte ich nach der Warteschleife, also nach etwas über einer Sekunde, 10790 Interrupts.

    Auf dem NEXYS Board wird die Warteschleife nie beendet. Also habe ich nach ca. 1 Sekunde die Reset-Taste gedrückt und in den Speicher geschaut, wo der Interrupt-Zähler steht. Ergebnis: Mehr als 4 Millionen Interrupts in derselben Zeit!


    Hier passiert folgendes: Die CIA, die den Interrupt auslöst, setzt die IRQ-Leitung auf aktiv. Wenn man den Interrupt in der CIA nicht bestätigt (Interrupt Acknowledge), bleibt die IRQ-Leitung dauerhaft aktiv. Wenn die Interrupt-Routine die Kontrolle mit RTI an das Hauptprogramm zurückgibt, wird deshalb sofort ein neuer Interrupt ausgelöst, noch bevor die nächste Anweisung der Warteschleife ausgeführt werden kann. Die Schleife läuft also so lange, bis der erste Interrupt auftritt, und bleibt dann effektiv stehen, weil der Prozessor ab diesem Zeitpunkt 100% mit Interrupts beschäftigt ist. Das ist auch das korrekte Verhalten, wie man es von einem 6502 Prozessor mit 6526 CIA erwarten würde.


    Warum das im Emulator anders ist? Keine Ahnung. Der emuliert die Abläufe, wie sie in der Realität auftreten, eben nicht zu 100%.

  • Das klingt als wenn das ein Fehler im XEMU und und auch im IRQ Handler wäre, oder sehe ich das falsch?

    Eine Ungenauigkeit im Interrupt Handling im XEMU ist das auf jeden Fall, da es nicht der realen Hardware entspricht. Von einem Fehler im IRQ Handler kann man meiner Meinung nach nicht sprechen, da der IRQ Handler des Mega65 ja gar nicht zum Einsatz kommen kann. Sobald man auf Bank 0 geht, kommen die oberen 8KB des 64K-Speichers ja nicht mehr aus Bank 3, wo der Kernel mit dem Interrupt Handler sitzt, sondern sind jetzt komplett RAM. Insbesondere der IRQ-Vektor bei $FFFE/$FFFF ist dann natürlich weg. Ich habe mal nachgeschaut, was da nach dem Switch auf Bank 0 steht: $00/$00! Sobald ein Interrupt auftritt, versucht er also einen IRQ-Handler bei Adresse $0000 aufzurufen, wo aber gar keiner steht -> Absturz.


    Für meinen obigen Test (IRQ-Aufrufe zählen) habe ich den Vektor bei $FFFE/$FFFF auf $5000 gesetzt, und bei $5000 einen eigenen Interrupt-handler geschrieben.

  • Eine Ungenauigkeit im Interrupt Handling im XEMU ist das auf jeden Fall, da es nicht der realen Hardware entspricht.

    Das auf jeden Fall.

    Zitat

    Von einem Fehler im IRQ Handler kann man meiner Meinung nach nicht sprechen, da der IRQ Handler des Mega65 ja gar nicht zum Einsatz kommen kann.

    Ich dachte der IRQ Handler würde den IRQ nicht bestätigen. Aber wenn er gar nicht da ist, dann ist das natürlich was Anderes. :D

  • Wenn das alles so zutrifft, dann kann man den SYS Befehl garnicht gebrauchen.

    Ausser man integriert immer auch einen Interrupt-handler in sein Maschinenprogramm.


    Oder sehe ich das falsch.


    Sollte der SYS Befehl nicht einfach alle IRQs abschalten?

    Oder oben in der Bank mit dem Maschinenprogramm ein Miniprogramm ablegen, das für die saubere Abarbeitung des IRQs sorgt?


    Nur so ein Gedanke.

  • IMO ist es nicht Aufgabe des SYS Befehls Anwendungslogik zu enthalten. Es wäre Aufgabe des ROMs dafür zu sorgen dass der IRQ Handler funktioniert, egal in welcher Bank man sich gerade befindet. Zumindest am C128 ist es so, dass man sich nicht darum kümmern muss, wenn man es nicht braucht. Das ist eindeutig Aufgabe des OS/Kernels.

  • Ich habe jetzt meinen eigenen Interrupthandler geschrieben, um die Interrupts zu bestätigen. Jetzt funktioniert alles wie es soll. Allerdings habe ich dabei einen Irrtum bemerkt: Ich bin bislang davon ausgegangen, dass die Interrupts von der 6526 CIA kommen (Timer-Interrupt). Also habe ich die Timer-Interrupts bestätigt; zu meiner Überraschung hat das gar nichts gebracht.


    Ich habe jetzt gelernt, dass der Mega65 den Timer gar nicht verwendet. Beim C64 gab es ja 60 mal pro Sekunden einen Timer Interrupt, der dann TI hochgezählt hat, den Cursor blinken liess, und die Tastaturabfrage gemacht hat.


    Beim Mega65 wird dafür jetzt der Rasterinterrupt des VIC benutzt. In meinem Fall triggert der auch 60 mal pro Sekunde, weil mein Bildschirm mit 60 Hz läuft.


    Ein simpler Interrupthandler, der den Raster Interrupt bestätigt, hat das Problem gelöst:


    IRQHANDLER PHA

    LDA $D019

    STA $D019

    PLA

    RTI


    Alternativ ist mein Programm auch einwandfrei gelaufen, wenn ich die Raster-Interrupts deaktiviert habe. Dann brauche ich nicht mal einen Interrupt Handler:


    LDA #$00

    STA $D01A


    Um einen eigenen Interrupt Handler einbinden zu können, musste ich natürlich das richtige Mapping einstellen, den I/O-Bereich bei D000-DFFF einblenden und den Interrupt-Vektor setzen:


    START SEI

    LDA #<IRQHANDLER ;LOW BYTE IRQ HANDLER

    STA $FFFE

    LDA #>IRQHANDLER ;HIGH BYTE

    STA $FFFF

    ;RAM MAPPEN, AUSSER BEI C000-DFFF (wegen I/O)

    LDA #$00

    LDX #$F0

    LDY #$00

    LDZ #$B0

    MAP

    NOP

    ;I/O EINBLENDEN, FARBRAM AUF 1K VERKÜRZEN DAMIT CIA SICHTBAR IST

    LDA $D030

    STA OLDMAPPING ;SICHERN ZUM SPAETEREN WIEDERHERSTELLEN

    AND #$06

    STA $D030

    CLI

    ; ----- Hauptprogramm ----

    ... z.B. die tolle Warteschleife ;-)

    ; ---- Aufräumen ----

    SEI

    LDA OLDMAPPING

    STA $D030

    RTS


    So hat alles einwandfrei funktioniert. Um auf Nummer Sicher zu gehen, sollte der Interrupt Handler natürlich trotzdem auch die CIA-Interrupts bestätigen, falls doch mal einer kommen sollte - sonst hängt ja wieder alles. Aber das kann ganz einfach gemacht werden, indem der Interrupt handler zusätzlich noch folgendes macht:


    LDA $DC0D ;LESEN DES INTERRUPT CONTROL REGISTER VON CIA#1 BESTAETIGT INTERRUPTS

    LDA $DD0D ;DAS GLEICHE FUER CIA#2


    Damit nicht zufällig vor dem SEI schon ein Interrupt das Programm aufhängt, sollte man schon beim SYS-Befehl die Interrupts abschalten:

    SYS START,0,0,0,0,4


    Na bitte, ist doch alles ganz einfach ;(

  • Ist auf jeden Fall gut zu wissen, aber ich denke trotzdem dass das der falsche Weg ist. Das bedeutet, dass man in JEDEM Maschinenprogramm immer einen IRQ Handler benötigt, obvwohl man den gar nicht braucht. Also wenn man sich eine BASIC Erweiterung schreibt, oder eine Sortierroutine oder sonstwas, das gar keine IRQs braucht, muss man das immer mitschleppen.


    Und den SYS Befehl macht das auch komplizierter. Man muss diese endlose Schlange an Parametern angeben obwohl man die ebenfalls nicht braucht. Dann sollte wenigstens der SYS Befehl das von selbst machen.

  • Ist auf jeden Fall gut zu wissen, aber ich denke trotzdem dass das der falsche Weg ist. Das bedeutet, dass man in JEDEM Maschinenprogramm immer einen IRQ Handler benötigt, obvwohl man den gar nicht braucht.

    Du hast natürlich Recht. Wenn man keine IRQs braucht, kann man einfach mit SYS....,0,0,0,0,4 aufrufen und gut ist.


    Was mich erschreckt hat, war halt dass mein supersimples Programm einfach so abgestürzt ist, und ich wusste nicht warum. Jetzt verstehe ich es. Obwohl die Interrupts das Problem waren, hat ja ein SEI zu Programmbeginn und ein CLI am Ende nichts gebracht, da sofort nach dem CLI wieder ein Absturz kommt - weil noch unbestätigte Interrupts pending sind. Also entweder auf Interrupts komplett verzichten, oder einen Interrupthandler einbinden.


    Was mich jetzt noch interessieren würde: Wie kann ich in Bank 0 oder 1 mein eigenes Programm ausführen, aber trotzdem das normale Kernel IRQ-Handling laufen lassen, z.B. weil ich die Tastaturabfrage des Systems nutzen will?

  • Wie kann ich in Bank 0 oder 1 mein eigenes Programm ausführen, aber trotzdem das normale Kernel IRQ-Handling laufen lassen, z.B. weil ich die Tastaturabfrage des Systems nutzen will?

    Indem du nur den Bereich von $0000 bis $1FFF verwendest.



    Alles andere benötigt einfach noch zusätzliche "Tricks", da ja bei BANK 0 Kernal und I/O "nicht sichtbar" sind.

  • Bit Shifter ist hier im Forum64 eher nicht unterwegs.


    Hier meine Zusammenfassung zum SYS-Befehl:

    Der SYS Befehl arbeitet wie gewollt.

    Er übergibt die volle Kontrolle an das aufgerufene Maschinenprogramm in der gewünschten Bank.

    Ein ab $2000 abgelegtes Maschinenprogramm wird ausgeführt.

    Die CPU sieht ab $2000 nur den Speicher der vorher im BASIC ausgewählten Bank.

    Lediglich $0000-$1FFF, also Zeropage, Bildschirmspeicher und der Begin des BASIC RAMs ab $1000, aus Bank 0 bleiben sichtbar.

    Das Maschinenprogramm benötigt einen eigenen IRQ handler, oder alle IRQs müssen für die Dauer des Aufrufs blockiert werden.

    Sollen ROM Routinen aufgerufen werden, so müssen diese bei Bedarf eingeblendet werden.


    Lt. Bit Shifter braucht es wohl ein eigenes Kapitel im Handbuch um der ganzen Komplexität des Themas Speicherverwaltung, IRQ-handling, IO-Bereiche, Kernel und BASIC ROM gerecht zu werden.


    Also heisst es, für kurze einfache Maschinenprogramme reicht es die IRQs zu blockieren.

    Für komplexere Programme mit ROM- und Kernel-Aufrufen, so wie IO-Abfragen mit IRQs bedarf es eines relativ umfangreichen Grundprogramms, das dann immer die Basis eines Maschinenprogramms darstellt.


    Ich hoffe ich hab das so richtig verstanden und hier wiedergegeben.

    :|

  • Ich habe Bit Shifter in Discord mal auf diesen Thread hingewiesen.

    Es wird ihn interessieren, denke ich.

    Am besten sollte er was dazu sagen, bzw. ggfs. den SYS Befehl so implementieren das man ihn ohne grössere IRQ Klimmzüge verwenden kann.

    Die "einfachste" Lösung wäre natürlich dass der SYS Befehl beim Aufruf das gleich automatisch macht. Allerdings ist das IMO keine gute Lösung, weil dann andere Sachen auch nicht richtig funktionieren z.B. TIMER, Tastaturabfrage, etc.. Bei C238 ist es eben so dass die IRQ Routine den aktuellen Stand sichert (welche BANK ist aktiv), dann auf die Bank schaltet die für die Serviceroutine benötigt wird und am Ende wird das wieder zurückgesetzt. So sollte eben eine OS IRQ Routine funktionieren.

  • sparhawk

    Vielleicht richtest du die Frage auf Discord in ‚closed-rom’ direkt an Bit Shifter.

    Es wäre schon interessant zu wissen wie der SYS Befehl sauber anzuwenden ist.


    Wie grubi schrieb lässt sich der IRQ durchaus vom BASIC aus abschalten.

    ***grubi:

    Damit nicht zufällig vor dem SEI schon ein Interrupt das Programm aufhängt, sollte man schon beim SYS-Befehl die Interrupts abschalten:

    SYS START,0,0,0,0,4

    ***
    Muss man beim Verlassen der Maschinenroutine noch was beachten?


    Ich stecke auch zu wenig im Thema, um mehr dazu sagen zu können.

    Aber interessant ist das Thema schon.