Hallo, in Anlehnung an den Beitrag Beitrag "Retro Fieber: Z80 oder 68000 ?" den ich mir neulich nochmal in Teilen durchgelesen habe und teilweise auch die Geduld der Leute bewunderte, die mir damals von Null an geholfen haben ein lauffähiges Z80 System aufzusetzen. Ganz besonders Frank M (UKW), der große Teile des Codes beisteuerte, die ganze Ausgabe basiert auf seinen Libs und auch Leo C für sein aufwendiges Makefile (was aber bis heute nicht eine Änderungen der .h erkennt.) für den sdcc Compiler. Es ist kein CP/M System, war nie geplant, wenn gleich der Bank Switch sinnvoll gewesen wäre um mehr RAM zu haben. Geht aber nicht mehr, Kamm-Fädeltechnik ist nicht mehr veränderbar. Aktuell gibt es einen Monitor, der im ROM werkelt und kleine Funktionen bereit stellt. Programm laden, Ram testen, LEDs einschalten, eine Life Demo, ein altes DDR/NVA Textverschluesselungssystem. Aktuell sieht ein Userprogramm immer noch so aus, dass es alles mitschleppt, was schon im ROM ist: ncurses Lib für VT100 Terminal, putchar, getchar zur Ausgabe und auch xprintf. Eigene INT Mode 2 Vektoren. Und das kostet Speicher! Wozu braucht ein Userpogramm Int Routinen? Vielleicht einen Timer Int. Das EPROM wird komplett nicht mehr benutzt, selbst die INT Tabelle klaue ich ihm, die wird dann bei 0x4040 neu erzeugt für das Userprogramm das bei 0x4100 beginnt hinter der sog. Zeropage. Was ist geplant? Aufräumen! Programmiert wird nur in C mit dem sdcc, Assembler nur im Startup Code und sonst nirgends. Die Basisfunktionen getchar und putchar, auf denen sowohl ncurses basiert als auch xprintf arbeiten vollautomatisch als ISR des MK3801 Multi-Funktionsbausteins von MOSTEK (da ist eine USART drin und 4 Timer und dazu noch einige GPIO, die interruptfähig sind). Zieht sich 150mA der Stein und ist lecker warm aber er spielt. Zeichen die ich im PC tippe im VT100 Terminal werden per ISR abgeholt und ge-ringpuffert, Zeichen zur Ausgabe des Z80 marschieren auch in einen Puffer und werden zum PC mit 38400 baud gelenkt. Das alles liegt bei Systemstart im EPROM drin. Und da soll es auch bleiben! Ein Userprogramm welches über IntelHex vom PC aus geladen wird soll sich aus den vielen Routinen des EPROMS bedienen, wo ich noch weiter alles mögliche Nützliche ablegen möchte, zb Funktionen der String Lib, die neu gekapselt werden. Bis es voll ist mit 16kb. Habe noch 8 kb übrig. Im Header des Userprogramm werden diese EPROM Funktionen dann referenziert. Das ist mühsam, ich muss mir aus dem Kompiler Listing alle Einsprungadressen raussuchen und per Hand eintragen. Das EPROM wird quasi als Library eingebunden. Wie ich sowas bei void xprintf (const char* fmt, ...); void xsprintf (char* buff, const char* fmt, ...); void xfprintf (void (*func)(unsigned char), const char* fmt, ...); mit variablen Parameterlisten mache genau mache weiss ich auch noch nicht, soweit reichen meine C Kenntnisse nicht. Was ich noch nicht weiss ist: Beim C64 gab es die Möglichkeit über sog. POKES viele Dinge des OS zu steuern. Mein EPROM hat ja auch einen eigenen Variablenbereich "oben" von 256 Bytes und der soll auch erhalten bleiben, braucht es ja auch für zb die ISR. Welche technische Lösung gäbe es, dass ein Userprogramm sich in ISR einhackt, die aktuell im EPROM liegen, die Int Mode 2 Vektor Tabelle auch dort bei 0x0040.? Liesse sich da bereits beim Booten etwas vorbereiten? Ich mlchte ungern im Userprogramm die INT Tabelle verschieben müssen,was allerdings ginge. Ich glaube der sdcc hat auch die Möglichkeit Variablen oder Vektoren auf festen Adressen anzusprechen, hat eigentlic jeder Kompiler. Ideen willkommen... Gruss, Christian
Christian J. schrieb: > Welche technische Lösung gäbe es, dass ein Userprogramm sich in ISR > einhackt, die aktuell im EPROM liegen, die Int Mode 2 Vektor Tabelle > auch dort bei 0x0040.? Liesse sich da bereits beim Booten etwas > vorbereiten? Ich mlchte ungern im Userprogramm die INT Tabelle > verschieben müssen,was allerdings ginge. Damals waren zwei Methoden üblich: 1. Im ROM zu jedem Interrupt-Vektor ein LD HL, (<ramvektor>); JMP (HL) hineinsetzen und beim Start die RAM-Vektoren ins ROM zeigen lassen. 2. Beim Reset das ROM ab Adresse 0 UND noch irgendwo anders (ab E000 oder F000) mappen und dann beim Booten in den oberen Adressbereich (immer noch ROM) springen und dann ab Adresse 0 RAM hinmappen. Das war bei CP/M-Maschinen Pflicht. Brauchte nur etwas Grips beim Designer und ein 74LS74. Aber ich glaube, das hast Du verpennt und dir buchstäblich verbaut. Ja, wer die Geschichte nicht kennt, ist dazu verdammt, sie zu wiederholen. fchk
Frank K. schrieb: > 2. Beim Reset das ROM ab Adresse 0 UND noch irgendwo anders (ab E000 > oder F000) mappen und dann beim Booten in den oberen Adressbereich > (immer noch ROM) springen und dann ab Adresse 0 RAM hinmappen. Sowas in der Art hatte ich damals schon erwähnt, als er das baute. Ein Modus, der ab Reset read=ROM,write=RAM schaltet und mit einem bestimmten I/O-Zugriff dann auf r/w=RAM wechselt. Die erste Aktion ab Reset ist dann eine Art memcpy(0, 0, N) um das ROM ins RAM zu kopieren. Danach wechselt man in den reinen RAM-Modus.
A. K. schrieb: > Frank K. schrieb: >> 2. Beim Reset das ROM ab Adresse 0 UND noch irgendwo anders (ab E000 >> oder F000) mappen und dann beim Booten in den oberen Adressbereich >> (immer noch ROM) springen und dann ab Adresse 0 RAM hinmappen. > > Sowas in der Art hatte ich damals schon erwähnt, als er das baute. Ein > Modus, der ab Reset read=ROM,write=RAM schaltet und mit einem bestimmten > I/O-Zugriff dann auf r/w=RAM wechselt. Die erste Aktion ab Reset ist > dann eine Art memcpy(0, 0, N) um das ROM ins RAM zu kopieren. Danach > wechselt man in den reinen RAM-Modus. Das geht aber jetzt nicht mehr und gut. Darüber zu philosophieren, was vor 3 Jahren war macht keinen Sinn. es gibt etliche systeme, die so ausgebaut waren wie meines, unten ROM, oben RAM. Der C64 lief auch damit. Mit CPM hatte ich nie was am Hut und es war nie Zweck das x.te CP/M Ding nachzubauen. Und damit kann man auch zurecht kommen. Die Idee die RAM Vektoren in die ROM Tabelle zeigen zu lassen werde ich mal aufgreifen...
A. K. schrieb: > Christian J. schrieb: >> Das geht aber jetzt nicht mehr und gut. > > Könnte man m.E. nachrüsten. Bitte...... Fädelkämme sind nicht mehr rückgängig zu machen! Teilweise mit Lack fixiert. Das 0,1mm dünne Kabel ist da zigfach umwickelt drin. Zudem keine freie Ecke mehr auf der Platine. Und nach 3 Jahren fange ich nicht an etwas Funktionierendes umzubauen, was nachher nicht mehr läuft. Der Datenbus + 8 Adressleitungen + Demuxer Leitungen sind rausgeführt und da kann man alles dran bauen. Ist auch alles schön bunt auf dem Bildschirm. Heute bin ich ja 3 Jahre älter, etwas grauer und etwas klüger als damals. So sieht das im Startup Code derzeit aus, da liegen nur Vektoren. Die Bodys der Routinen sind meist leer, nur ein RETFIE drin.
1 | .module crt0 ; Modul Name für den Linker |
2 | |
3 | ; Memory Map Adressen der Zeropage (vom Benutzer definierbar) |
4 | ; Definitions |
5 | |
6 | offset .equ 0x4000 ; Basisadresse des Codes |
7 | reset_vector .equ offset |
8 | stack .equ 0x000 ; Stack |
9 | adr_vec_table .equ offset + 0x40 ; Mode 2 Vektor Tabelle für STI Mostek Multi I/O |
10 | adr_copyright .equ offset + 0x80 |
11 | heap_size .equ 512 ; Benutzer definierte Heap Groesse |
12 | |
13 | ; Globale Funktionen und Variablen für das C-Programm |
14 | |
15 | .globl _main |
16 | |
17 | ; Interruptroutinen für den Mostek MK3801 Multi I/O Baustein |
18 | ; Manual STI Baustein MK3801 Figure 7 |
19 | .globl _int_sti_gpi_0 ; General Purpose Interrupt 0 |
20 | .globl _int_sti_gpi_1 ; General Purpose Interrupt 1 |
21 | .globl _int_sti_gpi_2 ; General Purpose Interrupt 2 |
22 | .globl _int_sti_gpi_3 ; General Purpose Interrupt 3 |
23 | .globl _int_sti_timer_d |
24 | .globl _int_sti_timer_c |
25 | .globl _int_sti_gpi_4 ; General Purpose Interrupt 4 |
26 | .globl _int_sti_gpi_5 ; General Purpose Interrupt 5 |
27 | .globl _int_sti_timer_b |
28 | .globl _int_sti_transmit_buffer_empty |
29 | .globl _int_sti_transmit_error |
30 | .globl _int_sti_receive_error |
31 | .globl _int_sti_receive_buffer_full |
32 | .globl _int_sti_timer_a |
33 | .globl _int_sti_gpi_6 ; General Purpose Interrupt 6 |
34 | .globl _int_sti_gpi_7 ; General Purpose Interrupt 7 |
35 | |
36 | .globl l__INITIALIZER |
37 | .globl s__INITIALIZER |
38 | .globl s__INITIALIZED |
39 | |
40 | .globl __sdcc_heap_init |
41 | .globl _letzte_code_adresse |
42 | .globl _erste_code_adresse |
43 | |
44 | ; ------------------------------------------------------------- |
45 | |
46 | .area _HEADER (ABS) |
47 | ; Reset vector bei Kaltstart und Sprung ins User Programm |
48 | .org reset_vector |
49 | _erste_code_adresse: |
50 | jp init |
51 | |
52 | ;/////////////////////////////////////////////////////////// |
53 | ; Tabelle der Mode 2 Int Vektoren auf die Handler Funktionen im C Modul |
54 | ; Reihenfolge beachten !!! Siehe Manual Mostek 3801, Interrupt Tabelle |
55 | .org adr_vec_table |
56 | .dw (_int_sti_gpi_0) |
57 | .dw (_int_sti_gpi_1) |
58 | .dw (_int_sti_gpi_2) |
59 | .dw (_int_sti_gpi_3) |
60 | .dw (_int_sti_timer_d) |
61 | .dw (_int_sti_timer_c) |
62 | .dw (_int_sti_gpi_4) |
63 | .dw (_int_sti_gpi_5) |
64 | .dw (_int_sti_timer_b) |
65 | .dw (_int_sti_transmit_error) |
66 | .dw (_int_sti_transmit_buffer_empty) |
67 | .dw (_int_sti_receive_error) |
68 | .dw (_int_sti_receive_buffer_full) |
69 | .dw (_int_sti_timer_a) |
70 | .dw (_int_sti_gpi_6) |
71 | .dw (_int_sti_gpi_7) |
Christian J. schrieb: > Der C64 lief auch damit. Auha. Gefährliches Viertelwissen. Der C64 hatte einen 6502, der seine drei Vektoren für Reset, NMI und IRQ bei FFFC, FFFA und FFFE hatte. Alle ROMs waren ausblendbar, und die Vektoren für die aktuellen NMI und IRQ-Routinen lagen in der Zeropage. Ein ZX Spectrum wäre ein geeigneteres Beispiel für Dich gewesen. Du hattest wohl weder das eine noch das andere gehabt. fchk
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.