Ist jetzt kein Witz aber manchmal glaube ich, dass seit meiner
Kopfoperation Ende 2009, wo ein Tumor entfernt wurde
einiges "weg" ist. Hatte zwar ne Reha 1/2 Jahr aber auch 5 Jahre
später sind immer noch Lücken da...
Christian J. schrieb:> ein IDE Interface auf eine CF abzubilden
Wesentlich primitiver als CF -> IDE -> Z80 Bus geht es kaum noch. Wenn
du einen 8255 spendierst, hast du schon 90% der Miete. Das mit den
Glitches ist bekannt und es gibt eine Lösung dafür. Der Text kommt als
Anlage.
Die Software, einen Sektor zu lesen / zu schreiben ist trivial, Sektor,
Track, Head in das passende Register, Lesebefehl und dann Daten in aller
Ruhe holen (es geht gut ohne DMA und der Z80 kann wunderbar Blöcke per
IO transferieren).
Wenn dir FAT zu umständlich ist, bietet sich ein Disk-Allocation-Vector
Prinzip wie bei CP/M an. Auch dafür gibt es erprobte Software. Oder du
nimmst gleich CP/M (was auch keine Großtat ist).
Georg G. schrieb:> Wenn dir FAT zu umständlich ist, bietet sich ein Disk-Allocation-Vector> Prinzip wie bei CP/M an. Auch dafür gibt es erprobte Software. Oder du> nimmst gleich CP/M (was auch keine Großtat ist).
Doch, wenn man absolut keine Ahnung davon hat muss man sich in das ganze
Thema einarbeiten, nicht nur einen Teil und CP/M ist nicht mein Ziel. es
gibt ne Reihe Lösungen die an das BDOS des CPM angepasst sind, weiss
ich. Den Text oben kenne ich auch schon. Ich belasse es bei einer SPI,
da es eh nur individuell ist.
A. K. schrieb:> Holm Tiffe schrieb:>> PIC ollte ich mir nicht antun und andere µC mit>> BUS fähigen Latches sind dünn gesäht.>> Hab ein paar alte Z8594 (Z8-UPC) rumliegen, mitsame 2K RAMs huckepack.> Die haben mehr als bloss ein Latch, die haben ein mustergültiges> Slave-Interface mit Dualport-Registern, Blocktransfer usw.
Nice, kannste bei mir abkippen :-)
Ich habe nur irgend einen µPD75C-irgendwas 4 Bit Controlletti von NEC
mit solch einem Gehäuse, den gabs wohl vor Urzeiten mal bei Polin? Mir
ist es nie gelungen eine ordentliche Doku dafür zu finden, aber einen
Assembler hatte ich schon mal angepaßt vor langer Zeit.
Gruß,
Holm
Mannomann ;-(
Seit Stunden versuche ich den TX Buffer ans Laufen zu kriegen aber es
kommt nur Zeichenmüll dabei raus. Einzelzeichen mit Pause laufen aber
das schnelle Vollschreiben erzeugt nur Müll als Ausgabe.
Das sieht alles absolut richtig aus aber es klappt nicht.
Was funktioniert ist:
- ISR wird aufgerufen, Int klappt also
- Einzelzeichenausgabe
Testsequenz:
1. String als Ganzes
2. Einzelzeichen
Defintion
(1) Race condition bei
if (tx.f_idle) {
// TX ist leer und abgeschaltet
tx.f_idle = false;
Da muss eine Interrupt-Sperre rein.
(2) In putchar bei Pufferüberlauf Daten wegwerfen ist selten eine
sinnvolle Strategie. Da macht man üblicherweise nur im
Receiver-Interrupt, weil alternativlos.
(3) Ich denke nicht, dass das Register so richtig bedient wird:
// STI_PVR = STI_IERA;
// STI_PVR = MODE2_VECTOR;
Auf diese Art schaltest du zwischendurch den IM2 Vektorbereich ab. Das
wird meistens gut gehen - aber eben nur meistens.
A. K. schrieb:> Ich denke nicht, dass das Register so richtig bedient wird:> // STI_PVR = STI_IERA;> // STI_PVR = MODE2_VECTOR;> Auf diese Art schaltest du zwischendurch den IM2 Vektorbereich ab. Das> wird meistens gut gehen - aber eben nur meistens.
Geht nicht anders, da PVR benutzt wird für indirekte Adressierung und
zum Schluss wieder auf Tabelle gesetzt wird. Ist aber auskommentiert,
man muss keinen Int abschalten, Ergebnis mit und ohne gleich.
Christian J. schrieb:> Läuft trotzdem nicht.
Wundert mich nicht.
(4) Vorher warten ob voll, dann reinschreiben. Nicht nachher warten und
trotzdem wegwerfen,
(5) Race condition rund um tx.f_buf_full. Dieses Flag ist ohnehin
unnötig. Wenn man mit einem N+1 Puffer arbeitet, dann kann man diese
Bedingung ohne Abschaltung von Interrupts feststellen, indem man die
Indizes vergleicht, ohne ein Flag verwenden zu müssen.
A. K. schrieb:> (5) Race condition rund um tx.f_buf_full. Dieses Flag ist ohnehin> unnötig. Wenn man mit einem N+1 Puffer arbeitet, dann kann man diese> Bedingung ohne Abschaltung von Interrupts feststellen, indem man die> Indizes vergleicht, ohne ein Flag verwenden zu müssen.
Ok....
Christian J. schrieb:> Weisser Mann sprechen in Rätseln....
Da ist ein "s" zu viel. ;-)
Was du machst:
if (!full)
reinschreiben;
else
while (full)
und das führt nicht dazu, dass bei vollem Puffer das Byte irgendwo
landet.
Besser wäre das Prinzip
while (full)
;
reinschreiben;
Christian J. schrieb:> Ah, Winnetou verstehen langsam was sein weißer Bruder ihm sagen will....
Na endlich. Ich habe mich schon lange gefragt, was alles passieren muss,
bis du rot wirst. ;-)
Christian J. schrieb:> Komt trotzdem der gleiche Müll bei raus:> if (tx.f_idle) {> // TX ist leer und abgeschaltet> CLI;> tx.f_idle = false;> STI_UDR = c;> EI;
Immer noch (1).
#define CLI __asm di __endasm // Interrupts
sperren/frei
#define EI __asm ei __endasm
Wieso? Ints sind aus.... auß0erdem verliert der auch so Zeichen, wenn
Puffer voll mit der while Schleife.
Christian J. schrieb:> tx.wr_ptr = (tx.wr_ptr +1) & tx.mask;
Kann man so machen, wenn BUFSIZE+1 eine Zweierpotenz ist. Sicherer ist
aber
wr = (wr <= BUFSIZE-1) ? wr + 1 : 0;
weil davon unabhängig und kaum aufwändiger.
A. K. schrieb:>> if (tx.f_idle) {>> // TX ist leer und abgeschaltet>> CLI;>> tx.f_idle = false;>> STI_UDR = c;>> EI;>> Immer noch (1).
Wenn Interrupt zwischen if() und CLI und darin das Flag gesetzt wird.
Christian J. schrieb:> So besser?
Fast. Die race condition ist weg, ...
> while (tx.wr_ptr == tx.rd_ptr);
... aber die Abfrage ist falsch. Diese Bedingung kann nicht gleichzeitig
für voll und für leer stehen.
Leer braucht man nicht, alles was nicht voll ist ist garantiert "leer"
bzw noch 1 Zeichen Platz.
Er hängt sich aber auch genau da auf und bleibt ewig drin. Egal wie ich
es auch drehe und wende, es kommt nur Müll bei raus und ich werde mir
debug Funktionen schreiben müssen, damit ich weiss was Sache ist.
wr und rd können ihre Positionen tauschen, je nachdem wer schnell läuft.
rd kann aber wr nie "überholen", muss bei gleichheit stehen bleiben.
Daher kann es nur die Abfrage == geben.
Christian J. schrieb:> Leer braucht man nicht, alles was nicht voll ist ist garantiert "leer"
Meinst du nicht, dass sich da was beisst?
// Sind noch Zeichen im TX Buffer?
if (tx.rd_ptr != tx.wr_ptr) {
// TX sendet noch. Warte bis Buffer frei.....
while (tx.wr_ptr == tx.rd_ptr);
> bzw noch 1 Zeichen Platz.
Eben. Voll ist bei ((wr + 1) % N == rd).
Hmm......
ISR guckt, ob Zeiger unterschiedlich sind. Wenj ja, wird Zeichen
eingeschrieben und Zeiger +1. Beim nächsten Durchlauf sind Zeiger
entwederr gleich oder es wurde schon was Neues eingeschrieben.
Soo auf Anhieb sehe ich das jetzt nicht aber das ist meist so wenn man
schon einige Stunden damit verbracht hat.
Entweder steht rd==wr für Puffer voll, oder es steht für Puffer leer.
Aber es kann nicht sein, dass es für beides steht.
Theoretischer Hintergrund: Das Prinzip besteht darin, dass man in einen
Puffer von N Bytes nie mehr als N-1 Bytes reinschreibt. Andernfalls
hätte man N+1 Füllungsgrade (0..N). Die Differenz der Indizes kann aber
nur N Zustände darstellen. Also muss einer dran glauben, und das kann
nur der Füllungsgrad N sein.
Ist mir klar aber
#define BUF_SIZE 128
// RX Empfangspuffer
struct rx_type{
int8_t buf[BUF_SIZE+1];
uint8_t rd_ptr;
uint8_t wr_ptr;
uint8_t mask;
uint8_t f_buf_full;
uint8_t f_buf_overflow;
};
Puffer ist 1 groesser als der Index, ein Reservebyte.
Weiss jetzt aber auch nicht weiter .....
Ich kann das problem jetzt nur so einkreisen, dass ich definierte
Füllzustände erzeuge.
zb 10 Zeichen in Puffer schreiben
TX anstossen durch Direkteinschreiben des 1sten zeichens
Warten ob ISR dann alle 10 Zeichen richtig ausgibt.
ISR als Ok abhaken, weiter bei putchar() machen.-
Ich werde mir nochmwas was durhclesen wie man diese beiden Fälle
abfängt.
Christian J. schrieb:> Ist mir klar
Offensichtlich nicht.
> #define BUF_SIZE 128> int8_t buf[BUF_SIZE+1];
Es reicht nicht, den Puffer eins grösser zu definieren. Du musst die
"Puffer voll" Abfrage passend gestalten.
Ausserdem bringt es nichts, den Puffer 129 Bytes gross zu machen, wenn
du dank einer Maske von 0x7F grundsätzlich das letzte Bytes unbenutzt
lässt.
Entweder
Du suchst im Internet nach diesem Verfahren und schreibst es
passend ab, ohne unverstandendenen Code kreativ zu optimieren.
Oder
Du versuchst den Kram zu verstehen.
Ja, man muss bei diesem Verfahren etwas nachdenken. Die intellektuell
anspruchslosere Methode ist eine Variable, die angibt, wieviele Bytes im
Puffer gefüllt sind. Die taugt an beiden Enden, also n==0 für "leer" und
n==N für "voll". Ist aber nicht frei von race conditions, muss also mit
Sperre arbeiten. Ausserdem gibts eine kleine Falle bei N==256.
A. K. schrieb:> Die intellektuell> anspruchslosere Methode ist eine Variable, die angibt, wieviele Bytes im> Puffer gefüllt sind
Das werde ich mal einbauen, da recht einfach.
Der RX Buffer klappt übrigens einwandfrei, direkt von Anfang an. Aber
der wird auch immer schneller gelesen als er beschrieben werden kann.
1
char getchar()
2
{
3
register char ch;
4
5
// Bei Überlauf alles resetten, Buffer wertlos
6
if (rx.f_buf_overflow) {
7
init_buffer();
8
return (0);
9
}
10
11
// Warte solange bis ein Zeichen im Buffer ist, auch ewig.
Christian J. schrieb:> {> // Byte muss in den Puffer rein...> EI;
...
> CLI;> tx.buf[tx.wr_ptr] = c;> tx.wr_ptr = (tx.wr_ptr +1) & tx.mask; // wr+1 am Bufferende> auf 0 zurücksetzen> tx.bytes_to_send++;> }
Fehlt da nicht was?
Christian J. schrieb:> if (tx.bytes_to_send-- != 0) { // ja.....
...
> }> else> { // nein, letztes zeichen> ging grad raus> SetDigit(counter2++);> tx.f_idle = true; // TX aus> }
Welchen Wert hat nun tx.bytes_to_send, wenn er vorher 0 war?
Du, hier ist grad alles im Ar...... ich kümmere mich da später drum.
Bevor ich mir jetzt aber den Wolf suche werde ich die Version von
gestern wieder einspielen aus dem Backup und das Neue draufsetzen.
Hi,
nach so ca 2h lief es dann...... nachdem ich etwas gefunden hatte, was
das Indianerauge übersah.... mich erst eine Debugausgabe der Variablen
auf den Pfad brachte....wer findet den Unterschied?
1
// Löscht den TX Buffer und setzt Zeiger auf 0
2
void init_buffer()
3
{
4
// RX....
5
rx.wr_ptr = 0;
6
rx.rd_ptr = 0;
7
rx.bytes_to_read = 0;
8
rx.f_buf_overflow = false;
9
rx.mask = (BUF_SIZE-1) & 0xff;
10
11
// TX.....
12
tx.wr_ptr = 0;
13
tx.rd_ptr = 0;
14
tx.bytes_to_send = 0;
15
tx.f_idle = true;
16
tx.mask = (BUF_SIZE-1) & 0xff;
17
}
1
// Löscht den TX Buffer und setzt Zeiger auf 0
2
void init_buffer()
3
{
4
// RX....
5
rx.wr_ptr = 0;
6
rx.rd_ptr = 0;
7
rx.bytes_to_read = 0;
8
rx.f_buf_overflow = false;
9
rx.mask = (BUF_SIZE-1) & 0xff;
10
11
// TX.....
12
tx.wr_ptr = 0;
13
tx.rd_ptr = 0;
14
tx.bytes_to_send = 0;
15
tx.f_idle = true;
16
rx.mask = (BUF_SIZE-1) & 0xff;
17
}
Wenn man die bytes_to_send auf die LED Zeile abbildet kann man sehr
schön sehen wieder Buffer beim Schreiben voll wird und sich durch den
Interupt danach wieder leert.
@A.K.:
Alles fertig .....Monitor komplett, EPROM randvoll mit mcurses und
hexedit, weil der sdcc ja keinen dead code raus wirft. Andererseits muss
der Monitor wirklich nicht gross sein, glaube meiner ist schon etwas
überladen....
...na also geht doch.
Unterschied ist rx.mask..
Wenn man den Basic Interpreter weg läßt hast Du einen durchaus üblichen
Funktionsumfang.
Die Frage ist, was dieser Hex-Monitor umfaßt.
Gruß,
Holm
Der Hex Dump stammt ja von Frank Mk hier und ist ganz nützlich wenn man
mal schauen will wie das geladene Programm so liegt, wo der Stack und
die Variablen etc. Volle Funktion eines Hex Editors eben. Den Basic
Interpreter kriege ich natürlich nicht mehr rein, dann platzt das EPROM,
was bis auf 300 Bytes jetzt auch voll ist.
Der Monitor kann von einem Skript aus gesteuert werden wenn man echo -n-
-e "...\r" verwendet. Das nutze ich um die Load Sequenz zu vereinfachen,
die auch nicht unbedingt in Intel Hex vorliegen muss. Dateilaenge
übertragen, Datei, "start" Befehl dazu und schon rennt es los. Ein druck
auf die NMI Taste und er resettet sich wieder in den Monitor, sonst
bewirkt Reset Neustart des RAM Programmes .... ja, ein bisschen Z80
Assembler habe ich ja gelernt :-)
1
ld sp,#stack ;; Stack an Spitze des RAM legen
2
3
; Teste ob Userprogramm im RAM vorhanden (nur bei EPROM Version)
4
;ld a, (ram_prog) ; Lade Start des RAM 0x2000
5
;cp #0xC3 ; vergleiche mit "C3" = JP Befehl
6
;jp Z, ram_prog ; Ja, dann springe direkt ins Ram hinein
7
8
; Ram ausnullen (auskommentieren, wenn von PC Upload erfolgt)
9
;xor a ; clear a and carry
10
;ld bc,#0xdfff ; ram size left
11
;ld hl,#0x2000 ; starting from 2000
12
;ld de,#0x2001
13
;ld (hl),a ; 0 -> (2000)
14
;ldir ; (HL) -> (DE)
Nettes Spielzeug das Ding und mit dem sdcc Compiler und einer kleinen
HAL drüber lässt sich ne Menge machen.
Übrigens ist der KC85 angekommen, mit Robotron Datasette und RAM
Erweiterung..... gib mal Deine Adresse, dann geht er direkt durch....
Ein paar Worte zum Datenspeicher:
Nachdem ich mir im Netz einiges über das XT/AT Computer IDE Interface
durchgelesen habe stand für mich fest, dass das Thema sich erledigt hat.
"Alles ganz easy...."
>> Wesentlich primitiver als CF -> IDE -> Z80 Bus geht es kaum noch
Wer mal einen Z80 Minirechner nachbaut sollte sich davon nicht einlullen
lassen. Die IDE Register am Bus sind eine Sache und recht einfach zu
mappen aber das IDE Protokoll an sich ist genug Lesestoff für eine Woche
und dann ist noch immer keine Low Level Verwaltung für das Laufwerk
geschrieben und erst recht keine High Level. Dann ist man nämlich recht
schnell hier:
http://www.retroleum.co.uk/z80-filesystem.html
wo sich jemand aus lauter Not, weil FAT zum komplex ist ein eigenes
Filesystem gestrickt hat. Wozu wenn es das alles schon als fertige
Bausteine gibt?
Ein in knapp einer Woche an einigen Abenden machbares Dateninterface
um eine beliebige Reihe Binärdaten weg zu schreiben und wieder zurück zu
lesen sieht bei mir jetzt so aus:
- Atmega328 Controller
- Arduino SD Library von Ardafruit mit 10 Basis Funktionen,ca 12 KB
- SD Card Adapter mit CD4050 Level Shifter an SPI Bus des Atmega328
- Arduino IDE zur Codentwicklung auf einen nackten Atmega328 dessen ISP
heraus geführt wurde.
- RX/TX des 328er als Debug Interface
Wenn man noch mehr Luxus haben will nimmt man einen Arduino Nano und
steckt den wie ein IC in die Platine. Dann hat man gleich eine Debug
Schnittstelle mit dabei und ein ISP.
Anbindung an Z80 PIO über eine Software SPI (SDO, SDI, SCK, SS, WAIT).
Da die Hardware SPI des Atmega bereits für die SD karte benutzt ist wird
hier in Richtung Z80 PIO die Bitbang-Funktion "shiftin()" und shiftout()
benutzt, zusammen mit dem SS Signal und einer extra WAIT Leitung für den
Z80 SPI Master, da es aufwendiger ist eine Wait Funktion in Software zu
machen.
Die eigentliche Aufgabe besteht "nur" darin, die SD Library Funktionen
welche man benötigt und das sind nur open, close, write, read, delete
auf ein SPI Protokoll zu matchen. Dateinamen sind 1,2,3,4,5....viele.
Ein Masterkommando vom Z80 sähe dann so aus:
Master: <Write Command> <No of Data Bytes> <Data>.....<Data> <CRC>
Master: <Read Command> <Filename> ........
Slave: <WAIT> ... <Data> <Data> .....
Master <get File Info> <File Name>
Slave: <WAIT> ... <Data> <Data> .....
usw.
Der AVR hat genug RAM Speicher (2K), um einen ganzen Datensatz vom Z80
in einem Rutsch zu übernehmen, um ihn dann als Ganzes wegzuschreiben,
während er die Wait Leitung zieht. Eine Kenntnis des Atmega328 von innen
ist nicht nötig, da die Arduino Lib die Hardware völlig abstrahiert, das
Ganze ist nur durch Nutzug der High Level Funktionen machbar.
Fangen wir mal an :-)
Das Standard OS das gerne Massenspeicher wie IDE Disks am Z80 hatte war
CP/M und das realisierte das CP/M typische Dateisystem für logische
Disks bis 8Mbyte, davon waren dann mehrere auf einer Platte möglich.
Ich verstehe nicht, warum Du Dich ausgerechnet in der DOS Ecke
herumtreibst und dort nach einem passenden FS suchst. Für CP/M gibts das
Alles fertig und getestet (GIDE).
Gru0,
Holm
Christian J. schrieb:> (...) Die IDE Register am Bus sind eine Sache und recht einfach zu> mappen aber das IDE Protokoll an sich ist genug Lesestoff für eine Woche
Was für ein Protokoll? Du beschreibst vier Register mit der Nummer des
gewünschten Blocks, dann eins mit dem Kommando für lesen oder schreiben,
und dann holst Du Dir 512 bytes Daten ab bzw schickst sie hin.
Das ist wesentlich einfacher als das Gefummel mit einer SD-Karte oder
einem NAND-Flash.
Tja,
also manchmal ist der sdcc etwas "seltsam". Stellt man dann etwas um,
auch wenn es logisch das Gleiche wie vorher ist klappt es wieder. Schon
einige Male solche "unerklärlichen Phänonomene" erlebt. In diesem Fall
half es in die Warteschleife ein NOP in den Rumpf zu nehmen.
Sieht schon ganz nett aus mit CPOL=1, CPHA=1 und 22 khz maximaler Rate.
Solche Fehler kenne ich auch von anderen Compilern und die haben i.A.
nichts mit dem Compiler zu tun, sondern das der Stack nicht mehr stimmt
weil Du irgendwas nicht aufgeräumt hast. Unter Unix gibts dann eine
Speicherschutzverletzung..
Gruß,
Holm
Moin,
aktuell "Heavy Working on Project". Leider passt der Monitor nicht mehr
in 8kb EPROM rein, mcurses haut sich leider zu viel weg und auch der
Hexeditor frisst 1,8kb. Eine Kommunikation mit der SD karte haut nicht
mehr hin, um von dort Anwenderprogramme zu laden.
Abhilfe: 16KB EPROM und nur noch 48KB RAM. 48KB reicht auch finde ich.
Schaltplan: Leitung A13 abklemmen. Input Pin 9 auf GND legen.
27128 EPROM, Leitung A13 zusätzlich an CPU
Nur zur Sicherheit: Das wars doch?
Wegen der Fädetechnik kann nichts umverdrahtet werden, nur abschneiden
und neu legen. Sonst würde ich das ganze Gatter für A13, A14
herausnehmen und A14 und A15 auf das andere legen.
Ic würde mit an Deiner Stelle Gedanken um eine Urlademimik machen, die
den gesamten ROM nach dem Reset in den RAM umlädt und diesen dann
abschaltet.
Damit ermöglichst Du Anwenderprogrammen den RAM der mit Monitorcode
belegt ist nach Bedarf zu überschreiben, wenn das Programm beendet wird,
ist nichts weiter nötig als den Urlademechanismus erneut anzustoßen und
den Zustand vor
dem Überschreiben des RAMs wieder her zu stellen.
Auf diese Art und Weise funktionieren üblicherweise die meisten
CP/M-fähigen Z80 Rechner, da die Anwenderprogramme auf eine Startadresse
von 0x100 gebunden sind. der CCP und das BDOS sind nachladbare
Programmteile und ganz oben im RAM residiert da BIOS und Systemvariablen
wie Stack usw.
Im Prinzip läßt sich das verwirklichen in dem nach Reset beim Lesen das
ROM, beim Schreiben aber das RAM selektiert wird, nach erfolgtem Umladen
des ROM Inhaltes wird dann ein Flipflop gekippt, das den ROM vollständig
deselektiert
und den RAM fest einschaltet. Ein Reset kippt die Mimik zurück.
Ich weiß nicht ob Du das in Deinem Fitz noch unterbringen kannst, aber
das hatte ich wohl schon mal "zeitig genug" erzählt..
RAM ist durch Nichts zu ersetzten, außer durch noch mehr RAM.
Gruß,
Holm
Das TDL-Basic gibt es auch als TDLBAS.REL. D.h. man kann es auf eine
bestimmte Adresse relozieren. Ich habe mir einen "Reolzierer" in vb.net
geschrieben.
Das scheint (bin mal vorsichtig) zu funktionieren. Mein Basic liegt ab
4000h im ROM, RAM ist wie original (ab 100h).
[[http://www.mikrocontroller.net/articles/ZAtmel:_ein_minimalistisches_Z80-System]]
Hi,
da lässt sich nix mehr umverdrahten, das ist endgültig bei dem Brett.
Nächster Wuirf vielleicht. Habe jetzt 16kb und das klappt ganz gut, mehr
Platz für das OS.
Ein kompletter CPM rechner in dem fast 2 Jahre Arbeit stecken laut Autor
ist hier dokumentiert:
http://searle.hostei.com/grant/cpm/index.html
Eine Unmenge an Anpassungen mussten da gemacht werden an das original
BDOS.
Wäre mal eine Sache den eingfach nur stur nachzubauen, 1-2 Wochen
Einarbeitung müssten sicher reichen..
Da findest du in U7.C+D die mehrfach erwähnte ROM/RAM-Umschaltung.
Allerdings komplizierter als nötig, die Adressdekodierung über U6.C+D
wäre nicht nötig (ROM lesen / RAM schreiben reicht aus).
Edit: Die Dekodierung ist sogar ungünstig. Wenn man sie weglässt, im
ROM sofort unabhängig von der ROM-Grösse die gesamten(!) 64KB auf sich
selbst kopiert und dann auf RAM umschaltet, dann landet das BIOS direkt
aus dem ROM an passender Stelle im RAM und kann angesprungen werden.
Steffen S. schrieb:> Das TDL-Basic gibt es auch als TDLBAS.REL. D.h. man kann es auf eine> bestimmte Adresse relozieren. Ich habe mir einen "Reolzierer" in vb.net> geschrieben.
Den Begriff hab ich noch nie gehört. Beim aussprechen bricht man sich ja
die Zunge. Erklär mal näher.
Steffen S. schrieb:> Das scheint (bin mal vorsichtig) zu funktionieren. Mein Basic liegt ab> 4000h im ROM, RAM ist wie original (ab 100h).
Das ist gleich ob ROM oder RAM. Wichtig ist die CP/M Sprungtabelle ab
100H.
Moin,
nur kurz zum Verstehen:
1. Rechner startet aus dem Bios. Da Z80 immer bei 0x0000 anfängt muss
bei 0x0000 ROM zu finden sein
2. Urlader zieht sich das OS rein ins RAM und springt dorthin. Er sieht
entweder ROM oder RAM, d h. ein Kopiervorgang ins drunter liegende RAM
ist so nicht mögllich, es sei denn dass jeder Schreibzugriff umgeleitet
wird auf RAM indem die WR Leitung mit decodiert wird. Dann würde eine
Kopierroutine das ROM ins RAM kopieren können, danach umschalten und
fertig.
Ok?
Übrigens: Hat jemand eine Kauf Eagle Version? Ich würde den Z80 Rechner
für CPM gerne auf richtiger Platine machen.
Christian J. schrieb:> nur kurz zum Verstehen:
Das geht so:
Startphase, Flipflop ausgelöst durch Cold Reset:
Memory Read => ROM, adressunabhängig,
Memory Write => RAM, adressunabhängig.
Betriebsphase, Flipflop umgeschaltet per I/O Zugriff:
Memory Read => RAM, adressunabhängig,
Memory Write => RAM, adressunabhängig.
Reset:
Kopiere 64KB von Adresse 0 nach Adresse 0,
damit wird also beim Cold Reset das ROM exakt 1:1 ins RAM kopiert
und beim Warm Reset das RAM exakt 1:1 auf sich selbst.
Schalte danach per IO-Zugriff auf Betriebsphase.
Da im RAM die 1:1 Kopie vom ROM steht, ggf. mit ein paar gespiegelten
Kopien, geht es im Code nahtlos weiter, nur kommt der nächste Befehl
dann aus dem RAM statt aus dem ROM.
Für CP/M setzt das voraus, dass 64KB RAM vorhanden sind.
CP/M erwartet sein BIOS am oberen Ende des Adressraums. Dort liegt
unabhängig von der Grösse des ROMs garantiert immer das hintere Ende vom
ROM-Inhalt, sofern du nicht den Fehler machst, das ROM adressmässig
einzuschränken. Wenn das BIOS also fertig entwickelt ist und ins ROM
passt, dann ist nach diesem Blocktransfer nur noch ein Sprung an die
entsprechende BIOS-Adresse nötig.
Ok, verstanden.
Die Decodierung hälst du also für unnötig? Irgendwie muss man ja aber
umschalten. Ich habe mir diesen Rechner angeschaut, was mir etwas fehlt
ist die peripherie, also Ports, Timer und andere Spielsachen. So ist das
ja nur ein Rechner der Software verarbeiten kann aber nichts steuern.
CPM kann damit sicher nichts anfangen. Es stellt sich dann auch die
Frage wie man eigene programme entwickelt denn mit dem sdcc wird das
wohl kaum mehr gehen. Die müssen ja "für CPM sein".
Ist das also nur ein Spielzeug um mal wieder CPM Software zu fahren?
Diese RAM Umschaltung hätte ich bei meinem auch machen sollen vorher.
Wäre easy gewesen:
1: Monitor lädt Programm vom PC
2. Monitor kopiert Programm "unter sich" ab 0x0000
3. Monitor schaltet um um löst Soft reset für 0x0000 aus
4. User programm rennt los und hat 64k für sich.
Christian J. schrieb:> 1. Rechner startet aus dem Bios. Da Z80 immer bei 0x0000 anfängt muss> bei 0x0000 ROM zu finden sein
Nicht zwingend.
Beim KC85/3 und Konsorten, gibt es eine Bootstrap-Schaltung. Dort liegt
das BIOS bei 0xE000. Bei Reset wird für ein paar M1-Zyklen dieser
Bereich nach 0x0000 gemappt. Als erstes steht ein Jump in den
'richtigen' ROM. Das Mapping wird nach diesem Jump deaktiviert.
Also ja und nein. Es wird bei 0x0000 angefangen, aber es muß nicht
zwingend ein ROM dort sitzen. Es reicht, wenn die ersten Memread auf dem
Bus 0xC3 0xll 0xhh vorfinden, um von einer anderen Adresse zu starten.
> 2. Urlader zieht sich das OS rein ins RAM und springt dorthin.
[...]
Genau.
> Übrigens: Hat jemand eine Kauf Eagle Version?
Wenn es größer als 80 x 100 mm wird, verwende ich (privat) KiCad. Es ist
zwar noch etwas kryptischer als Eagle zu bedienen, aber alles in allem
recht brauchbar und nicht irgendwie limitiert.
Jens
Christian J. schrieb:> Die Decodierung hälst du also für unnötig? Irgendwie muss man ja aber> umschalten.
Durch einen passenden IO-Zugriff. Das kann auch ein Zugriff auf den ADC
sein, wenn dein IO-Dekoder nichts mehr frei haben sollte.
> 2. Monitor kopiert Programm "unter sich" ab 0x0000
Das setzt voraus, dass alle Schreibzugriffe im RAM landen. Auch die
auf dem Adressbereich des ROM. Technisch kein Problem, Umbau ist
einfach.
Christian J. schrieb:> So ist das> ja nur ein Rechner der Software verarbeiten kann aber nichts steuern.> CPM kann damit sicher nichts anfangen.
Das hängt von den CP/M-Programmen ab. Es gibt relativ viele, nur das
Minimalsystem (Console-IO und Disk-IO) brauchen: TurboPascal, WordStar,
Microsoft Basic, dBase, Zork etc. pp.
> Es stellt sich dann auch die> Frage wie man eigene programme entwickelt denn mit dem sdcc wird das> wohl kaum mehr gehen. Die müssen ja "für CPM sein".
Richtig. Reichen Dir die Entwicklungswerkzeuge, die hier unter
Programming aufgeführt sind?:
http://pcsauro.altervista.org/CPM.PHP
Jens
Christian J. schrieb:> Frage wie man eigene programme entwickelt denn mit dem sdcc wird das> wohl kaum mehr gehen.
Kannst es mit PL/I versuchen. ;-)
War ein recht bemerkenswertes Produkt.
> Die müssen ja "für CPM sein".
Nur wenn du auf dem Zielsystem entwickeln willst. Cross-Development auf
dem PC mit sdcc geht natürlich immer noch.
Jens schrieb:> Beim KC85/3 und Konsorten, gibt es eine Bootstrap-Schaltung. Dort liegt> das BIOS bei 0xE000. Bei Reset wird für ein paar M1-Zyklen dieser> Bereich nach 0x0000 gemappt. Als erstes steht ein Jump in den> 'richtigen' ROM. Das Mapping wird nach diesem Jump deaktiviert
Na, man will ja auch Software schreiben und wenn es kompliziert ist
diese auf den Rechner zu kriegen, dann macht es keinen Spass. Ich frage
mich auch grad wofür man CPM braucht wenn man keine Peripherie hat,
keine Tastatur, keinen Monitor.
Als ich so 16 war fing es mit dem Apple 2 an, da war das OS ein
blinkender Cursor, es gab ein besch.... Basic und ein paar Format
Befehle. Nichts was man wirklich damit machen konnte. Mehr als UCSD
Pascal hat der 2e, den wir hatten nie gemacht und auf dem "Basis 108"
lief ein Stundenplan Planungsprogram, was die Lehrer auf die Klassen
aufteilte. Dauerte Tage bis das fertig war.
Klar weiss ich, dass ich das alles besser und schöner mit einer IDE auf
meinem ARM7 Board haben kann, Luxus Debugger, GCC, Crossworks IDE dabei
und schneller, 80Mhz, mehr Ports, mehr Timer ..... aber das Z80
Minisystem macht mehr Spass und es ist überschaubarer, grünes Terminal,
9600 baud ..... eben Retro :-) fehlt nur noch das Fiepen für die 9600
baud.
Zerbreche mir noch den Kopf wie ich 2 Software SPI miteinander
verheiraten kann, die im Arduino und die auf dem Z80. Das könnte
verdammt eng werden vom Timing her, der Slave (Ardu) muss deutlich
schneller sein als der Z80 beim Datenempfang.
A. K. schrieb:> Technisch kein Problem, Umbau ist> einfach.
Bei Fädeltechnik ist nix mehr mit Umbau :-) Bin froh, dass ich den 16kb
ROM Umbau geschafft habe, 2 Drähte abknipsen, 3 neue verlegen. Ende.
Kein draht geht mehr raus und nur noch wenige rein.
Christian J. schrieb:> keine Tastatur, keinen Monitor.
CP/M funktioniert auch über die serielle Schnittstelle, und die ist in
seinem Teil drin (mit SIO ;-). Der PC stellt Tastatur und Bildschirm.
A. K. schrieb:> CP/M funktioniert auch über die serielle Schnittstelle, und die ist in> seinem Teil drin (mit SIO ;-). Der PC stellt Tastatur und Bildschirm.
habe mir grad die Softwaresammlung angechaut.....Wahnsinn. Turbo Pascal
würde mich mal wieder reizen.
Andererseits muss der Bau Zeitraum überschaubar bleiben. Wenn es erst
ein halbes Jahr dauert, bis das System überhaupt Piep sagt lohnt es
nicht. Dieser Searle hatr aber alles gut dokumentiert, d.h. Nachbau 1:1
dürfte möglich sein. Software läuft ja soweit wie ich das sehe. Er
selbst hat 2 Jahre gebraucht wie er schrieb.
Dummerweise finde ich die Eagle Files nirgendwo, müsste also abzeichnen.
@AK:
Überlege die ganze zeit noch für eine sinnvolle SPI Übertragung wegen
der SD Karte. Selten sowas benutzt bisher.
Wie sind den Protokolle allgemein aufgebaut? Arbeiten die auch mit Start
Token, warten auf Antwort usw? Es gibt unzählige Möglichkeiten.
Ich tendiere fast dazu einen Header für den Datensatz in einen Struct zu
packen, den Header dann stur zum Slave zu ballern und der sucht sich
dann die Eckedaten heraus, wieviele Bytes kommen, Filenamen, File
Descriptor (1,2,3....). Filenamen will ich schon haben, Catalog Funktion
auch, Sichern und Laden.
#define CMD_WR 'W' // Token für Daten schreiben
#define CMD_RD 'R' // Token für Daten lesen
#define CMD_HEAD 'H' // Token für Daten Header
#define DUMMY 0xff
#define RES_ACK 'A' // Response für "OK"
#define RES_WAIT 'T' // Response für "Warte!"
#define RES_ERR 'E' // Response für "Warte!"
////////////////////////////////////////////////////////////
// sd_write_data
//
// Schreibt einen Datensatz auf die SD Karte
// Eingabe: file = filenummer 1..255
// *filename = Zeiger auf Filename
// *data = Zeiger auf Daten
// len = Länge der Daten in Bytes
// Rückgabe: 1 = ok, 0 = fehler
char sd_write_data(char fileno, char* filename, char* data, uint16_t
len)
{
uint16_t i,cnt;
uint8_t resp; // Antwort des Slaves
// Slave aktivieren
sd_select(true);
delay8(100);
// Start Token senden
spi_transmit(CMD_WR);
delay8(100);
// Filenummer und Länge des Datensatzes senden
spi_transmit(CMD_HEAD);
spi_transmit(fileno);
spi_transmit(HIBYTE(len));
spi_transmit(LOBYTE(len));
delay8(100);
// Ganzen Datensatz senden
cnt = 0;
for (i=0;i<len;i++)
{
while(spi_get_wait()); // WAIT vom Slave?
SetLedByte(*data);
resp = spi_transmit(*(data++)); // WAIT vom Slave?
if (resp==RES_ERR) // Slave ok?
return (0);
}
delay8(50);
sd_select(false);
return (1);
}
A. K. schrieb:> Für CP/M setzt das voraus, dass 64KB RAM vorhanden sind.> CP/M erwartet sein BIOS am oberen Ende des Adressraums.
Normalerweise definiert man die Speichergröße (MSIZE). Daraus ergeben
sich dann das Ende des gültigen Adressraums und die Adressen von CCP,
BDOS und BIOS. Bei mir lebt alles in nur 32 KB, die Mindestanforderung
von CP/M 2.2 sind 20 KB.
Ein Adressraum voller RAM macht Dinge natürlich trotzdem einfacher.
Christian J. schrieb:> Die Decodierung hälst du also für unnötig? Irgendwie muss man ja aber> umschalten.
Das kann im Zweifelsfall der allererste I/O-Zugriff sein, egal zu
welcher Adresse, oder ein Gerät mit einem steuerbaren Pin (z.B. die
serielle Schnittstelle - ein 16550 hat zwei Ausgänge).
> Es stellt sich dann auch die Frage wie man eigene programme entwickelt> denn mit dem sdcc wird das wohl kaum mehr gehen. Die müssen ja "für CPM> sein".
Warum sollte das nicht gehen? Ein CP/M-Programm ist ein an 0x100
gelinkter Haufen Bytes, der über eine festgelegte Schnittstelle (JMP auf
fixe Adressen) mit dem Betriebssystem redet. Wenn du die entsprechenden
Syscalls dem SDCC beibringst, kannst du auch mit dem arbeiten. Ansonsten
gibt es die ganze Software von damals immernoch.
> Ist das also nur ein Spielzeug um mal wieder CPM Software zu fahren?
Davor schriebst du noch, das ginge ohne Ports oder Timer nicht ginge.
Geht also doch. ;-)
> Diese RAM Umschaltung hätte ich bei meinem auch machen sollen vorher.
Ist ja nicht so, dass das jetzt eine neue Information wäre. Aber du
hörst ja nie zu.
Christian J. schrieb:> Wie sind den Protokolle allgemein aufgebaut? Arbeiten die auch mit Start> Token, warten auf Antwort usw? Es gibt unzählige Möglichkeiten.
Das Protokoll zwischen Z80 und "SD-Karten-Controller"? Das kannst du dir
beliebig aussuchen. Mir fallen da drei Möglichkeiten ein, wenn es um die
SD-Karte geht:
(a) Der Arduino ist eine SPI-Bridge. Dein Protokoll muss dann "read",
"write" und Chipselect für jedes Gerät abbilden können. Auf dem Z80
kannst du dann jedes beliebige SPI-Gerät ansteuern, musst aber sowohl
das SD-Protokoll als auch das Dateisystem auf dem Z80 implementieren.
(b) Der Arduino spielt Block-Device. Dein Protokoll muss dann "read",
"write" und "seek" abbilden können. Der Z80 muss dann nur das
Dateisystem implementieren (CP/M bringt übrigens eins mit!) und kann
über diese Schnittstelle auch nur auf SD-Karten zugreifen. FAT gibt's
nur, wenn du auch FAT implementierst.
(c) Der Arduino spielt File-Server. Dein Protokoll muss dann alle
Dateisystemfunktionen abbilden können, die du möchtest (Datei oder
Verzeichnis öffnen, schließen, lesen, schreiben, löschen, erstellen,
...) und der Z80 braucht dann diese Funktionen nur aufzurufen und die
ganze Arbeit findet im Arduino statt.
Für irgendwas davon musst du dich schon entscheiden. Über die
Datenstrukturen nachzudenken bringt dich an der Stelle nicht wirklich
weiter, solange du nicht weißt, was du brauchst und was nicht.
Warum willst du dem Z80 überhaupt SPI in Software aufbürden? Der hat
einen wunderbar schnellen, parallelen Bus mit genialen Zugriffsbefehlen.
Übrigens wiederhole ich nochmal einen Vorschlag: Deine serielle
Schnittstelle kann all das, was du willst, auch machen. Du musst dafür
keine SD-Karte an dein System frickeln. Das Protokoll der Wahl dafür
nennt sich ZMODEM.
S. R. schrieb:> Du musst dafür> keine SD-Karte an dein System frickeln. Das Protokoll der Wahl dafür> nennt sich ZMODEM.
Hi,
weiss ich aber ich implementiere kein ZMODEM auf dem Z80 Board, bzw
schreibe ich sicherlich nicht selbst. Es wird ein Fileserver, der Ardu
übernimmt alles, der Z80 hat nur 4 Befehle: write, read, seek, delete.
Jede Datei hat vorne 64 Bytes "Header Infos" und danach die Daten.
Header:
- Dateityp (exe, dat)
- Länge
- Filenummer
- Filename
- File Description
SPI Datentransfer ist auch 64 Bytes Header, danach justiert sich der
Slave darauf, legt Datei an etc und nimmt Daten entgegen oder sendet
sie. Arduino hat eine SD FAT light die nur ein Verzeichnis kennt und nur
Basisfunktionen. Passt in 8k rein, der atmega328 hat 32k.
Fiel mir so ein aber vielleicht gibt es ja sowas auch im "üblichen
Rahmen".
>Warum willst du dem Z80 überhaupt SPI in Software aufbürden? Der hat>einen wunderbar schnellen, parallelen Bus mit genialen >Zugriffsbefehlen.
Hätte er...... wenn ich damals das wüsste was ich heute weiss.... der
hat nämlich eine IDE on board quasi. CF Card direkt dran gepaoppt.
Mein Bus ist s.o.
Christian J. schrieb:> Hoffe ich bereue es nicht:
Da fehlen noch mindestens 8, besser 16 digitale Kanäle.
Und selbst für analoges hab ich gern 4 statt 2....
ebay: 161313879775
oder: 181288566514
Beides zusammen gibt es sicher auch noch irgendwo.
Jens
michael_ schrieb:> Den Begriff hab ich noch nie gehört. Beim aussprechen bricht man sich ja> die Zunge. Erklär mal näher.
Sorry, habe mich vertippt. Meinte "relozieren"
Macht normalerweiser ein Loader im Monitor. Da ich nur das TDL-Basic
an eine andere Adresse haben wollte (nicht 300h sondern 4000h) habe ich
ein kleines vb.net-Programm dafür geschrieben.
Grundlage dafür:
http://www.seasip.demon.co.uk/Cpm/rel.html
Jens schrieb:> Christian J. schrieb:>> Hoffe ich bereue es nicht:> Da fehlen noch mindestens 8, besser 16 digitale Kanäle.> Und selbst für analoges hab ich gern 4 statt 2....>> ebay: 161313879775> oder: 181288566514>> Beides zusammen gibt es sicher auch noch irgendwo.>> Jens
Logic Analyser habe ich schon, einen für 25 Euro :-) Tuts aber. Nette
Dinger aber Kohle fehlt für sowas.
@Leo:
Sag mal, wie kommt es dass der sddc für eine einfache Zuweisung an eine
Struct Variable dermassen ein Fass aufmacht? Der Compiler kennt doch die
Adressen aller member? Structs sollen ja effizient sein aber hier eher
das Gegenteil. Auch mit -> sieht es schlimm aus.
Und noch eine Sache:
Es ist leider so, dass gleiche Routinen sich sowohl im ROM als auch im
Userprogramm finden, zb die Hardware Inits, Kommunikation usw. Gibt es
mit einem C Compiler irgendeine Möglichkeit aus einem RAM Programm
heraus Routinen im ROM anzuspringen? Der Variablenbereich des ROM ist
unangetastet, der liegt unter der Decke bei B0000, 2K sind reserviert.
Sowas wie
function lala (char.....) @ ROM-Adresse
Die Einsprünge kenne ich ja alle aus den .rst Files.
> Gibt es mit einem C Compiler irgendeine Möglichkeit aus einem RAM> Programm heraus Routinen im ROM anzuspringen?
Der Linker hat einen Schalter, mit dem das möglich sein sollte:
The linker commands are explained in some more detail:
5
...
6
5. -o/-v Specifies that subsequent linked
7
files/libraries will generate object output (default)
8
or suppress object output. (if option -i, -s, or -t
9
was specified)
Also erst das ROM-Programm normal compilieren und linken.
Dann die Funktionen für RAM-Progamm compilieren, und beim Linken nach
dem Schalter -v die Object-Dateien der referenzierten ROM-Teile listen.
Hi,
klingt schwierig. ROM und RAM Programm sind zwei unterschiedliche
Projekte, die nichts miteinander zu tun haben bisher. In Assembler wäre
das kein Thema, wäre nur Register laden und JP dahin.
Das RAM Programm müsste ja genau wissen wie es Parameter an eine ROM
Funktion übergeben müsste, die es ja nicht kennt.
zb:
Monitor Programm hat:
void delay(zeit)
{
.....
}
Adresse ist bekannt und fix im EPROM, bzw lässt sich herausfinden. zb
0x1234
Das RAM Programm will nun diese Funktion nutzen.... und da scheiden sich
die Geister.
@Leo:
Ich lege das problem oben erstmal beiseite. Fällt Dir eine Mögliochkeit
ein, wie man zur Laufzeit feststellen kann, wie gross ein Programm in
Bytes ist?
Oder wie man eine Kennung hinten am Code anbringt, so dass man aus dem
laufenden Programm feststellen kann, wieviele Bytes man auf die SD
sichern muss?
Leider hat der Z80 keinen internen E2PROM wie die AVR, PIC, ARM usw :-(
> Fällt Dir eine Mögliochkeit> ein, wie man zur Laufzeit feststellen kann, wie gross ein Programm in> Bytes ist?
Der Compiler generiert für jede Funktion Symbole in der Form
_functionname_start und _functionname_end
Also vielleicht sowas?
1
#include<stdio.h>
2
3
externmain_start(),main_end();
4
5
intmain(void)
6
{
7
printf("main start: %04x\n"
8
"main end: %04x\n"
9
"main size: %04x\n",
10
main,main_end,(void*)main_end-(void*)main);
11
12
return0;
13
}
main_start braucht man nicht, da es ja das gleiche wie main ist.
Ich kanns nicht laufen lassen, aber das Ergebnis sieht ganz gut aus:
Einfacher in der crt0.s :-) Muss man erstmal drauf kommen.
gsinit:
; Initialisiere globale Variablen im RAM
ld bc, #l__INITIALIZER
ld a, b
or a, c
jr Z, weiter
ld de, #s__INITIALIZED
ld hl, #s__INITIALIZER
ldir
weiter:
; // Hier muss ein ret rein
.area _GSFINAL
ret
;Markiert das Ende des Programmes
.ascii "FINAL"
Das Wort FINAL steht direkt nach dem CODE Segment. Beim Start des
Programmes suche ich danach.
Jetzt würde nur noch ein Assemblerbefehl fehlen, der ein Alignment auf
zb 16 Bytes vornimmt, damit ich den Suchlauf schneller machen kann,
nämlich nur auf das erste von jeweils 16 Bytes auf F testen und dann
gleich +16 Bytes weiter.
SPI etc läuift schon im Trockendock..... tolles Maschinchen :-) Mit dem
sdcc macht es erst richtig Spass.
> Einfacher :-)
Na, Du wirst doch nicht behaupten, daß eine Suchschleife einfacher als
die Subtraktion zweier Symbole ist.
Und wenn die Code-size einer einzelnen Funktion nicht das Gewünschte
ist, dann suchst Du dir halt die passenden Symbole aus der Mapfile raus.
> Das Wort FINAL steht direkt nach dem CODE Segment. Beim Start des> Programmes suche ich danach.
Aber nur, wenn Du es extra hinschreibst. Das braucht auch zusätzlichen
Platz. Stattdessen kanns Du auch das Symbol "s__GSFINAL" nehmen.
> Jetzt würde nur noch ein Assemblerbefehl fehlen, der ein Alignment auf> zb 16 Bytes vornimmt, damit ich den Suchlauf schneller machen kann,
Dann brauchst Du Dir über sowas auch nicht den Kopf zu zerbrechen. Du
hast sowieso andere Probleme, als die Geschwindigkeit so einer kleinen
Schleife. :-)
Leo C. schrieb:> Na, Du wirst doch nicht behaupten, daß eine Suchschleife einfacher als> die Subtraktion zweier Symbole ist
Ich weiss nicht was du da vorhast aber wo die Module stehen hängt nur
davon ab in welcher Reihenfolge man sie linkt. Und die genannten Symbole
erzeugen nur "kennt er nicht" Fehlermeldungen. ich brauche das in sd.c,
da ist _main nicht bekannt.
Hallo Leo,
deine Methoden da funktionieren alle nicht. Die Symbole sind nicht
bekannt in den einzelnen Modulen. Ob mit oder ohne Unterstrich.
Nur das hier funktioniert einwandfrei:
1
// Suche das Codeende
2
__at (RAM_START) uint8_t ram[RAM_SIZE]; // Bereich des RAM
Christian J. schrieb:> deine Methoden da funktionieren alle nicht. Die Symbole sind nicht> bekannt in den einzelnen Modulen. Ob mit oder ohne Unterstrich.
Ich hatte ein vollständiges, auf Minimum reduziertes Beispiel gepostet,
daß das Gegenteil beweist. Offensichtlich hast Du es nicht angesehen,
zumindest die Zeile 3 nicht.
Leo C. schrieb:> Stattdessen kanns Du auch das Symbol "s__GSFINAL" nehmen.
Ok, da habe ich leider übersehen, daß diesen Symbolen das fürhrende "_"
fehlt. In C kann man die nicht referenzieren.
Aber Statt einer Marke, die zusätzlich RAM belegt, und die Du suchen
mußt, kannst Du Dir auch selber Symbole in den passenden Segmenten
definieren (in crt0.s).
crt0.s:
Läuft nicht. Sobald ich das einbaue kriege ich jede Menge Fehler an
anderen Stellen die vorher liefen.
ASlink Warning_Undefined-Global "_main" refrence by module
usw.
ne ganze Latte.
Vergessen wir es. Das hatte ich schonmal.
PS: Nach realclean kompiliert es wieder. Mal sehen wie lange.
Geht nicht. Nach der nächsten Codeänderung völlig woanders
kommen wieder reihenweise die asmlink Fehler....
Jetzt doch wieder.... nach "realclean".... au weia..... bloss nicht mehr
anfassen den Konstrukt. Aber Ergebnis mit printf ist richtig.
Die Geheimnisse dieses Compilers ind unergründlich :-)
Zuweisung der absoluten Werte und Umwandlung in Integerer
code_start = (uint16_t)erste_code_adresse;
code_end = (uint16_t)letzte_code_adresse;
Das ham wa .... 4000 und 705D. Passt laut crts0.rst file
Und mit xprintf und printf gleichermassen gibt er aus
Erste Codeadresse = ffc3
Letzte Codeadresse = ffc3
Verschieben wir die Zuweisung oben einfach etwas weiter nach oben im
Main File, was eigentlich völlig egal ist erhalten wir:
Erste Codeadresse = ffc3
Letzte Codeadresse = 7e5D <<<=== Hurra richtig!
Fazit:
Ich bin froh den sdcc zu haben (weil es nichts anderes Gescheites gibt)
aber müsste ich damit beruflich arbeiten (solche Sachen habe ich mit dem
Keil nie ...) würde ich das Ding zurückschicken und mir das Geld
auszahlen lassen. Im industriellen Umfeld wäre der sdcc nicht
"qualifizierbar" und in meiner Branche wo Source SIL 3 erfüllen muss
auch "lebensgefährlich."
A. K. schrieb:> Christian J. schrieb:>> Warum so etwas? Arrays?
Wei Pointerarithmetik nur mit sinnvollen Datentypen richtig
funktionieren kann.
> Erspart den & Operator.
Mit & hatte ich seltsame Ergebnisse. Da dürfre aber noch was anderes
falsch deklariert gewesen sein.
Leo C. schrieb:> Mit & hatte ich seltsame Ergebnisse.
Mit & geht es auch aber umständlicher. Ich musste a auf void* casten
damit ich überhaupt kompilieren kann. Ich habe jetzt einfach mal wild
rumprobiert, bis ich den Wert der Symbole hatte und nicht deren Inhalt.
extern char erste_code_adresse[]; // Zeiger auf SDCC Globals
extern char letzte_code_adresse[];
// Adressen für Start und Ende des Programms
uint16_t code_start, code_end;
// Sichere die Start- und Endadresse des Codes
code_start = (uint16_t)erste_code_adresse;
code_end = (uint16_t)letzte_code_adresse;
4112 21 2E 65 [10] 103 ld hl,#_letzte_code_adresse+0
7
4115 22 30 65 [16] 104 ld (_code_end),hl
Möchte man unbedingt ein Kaufmanns UND verwenden geht es so:
extern char erste_code_adresse; // Zeiger auf SDCC Globals
extern char letzte_code_adresse;
// Adressen für Start und Ende des Programms
uint16_t *code_start, *code_end;
// Sichere die Start- und Endadresse des Codes
code_start = (void*)&erste_code_adresse;
code_end = (void*)&letzte_code_adresse;
ergibt:
99 ;main.c:52: code_start =
(void*)&erste_code_adresse;
410C 21 00 40 [10] 100 ld hl,#_erste_code_adresse+0
410F 22 36 65 [16] 101 ld (_code_start),hl
102 ;main.c:53: code_end =
(void*)&letzte_code_adresse;
4112 21 36 65 [10] 103 ld hl,#_letzte_code_adresse+0
4115 22 38 65 [16] 104 ld (_code_end),hl
Das passiert alles meist dann, wenn man das normale Fahrwasser eines
Compilers verlässt und seine Spezialfunktionen benutzt. Denn hier greift
man ja schon tief in die Kiste der Tricks.
Christian J. schrieb:> // Adressen für Start und Ende des Programms> uint16_t *code_start, *code_end;
Rechne hier mal die Differenz aus, und lass sie Dir ausgeben.
Nee, da kam das Gleiche bei raus. Siehste doch an dem Asm Code. Ausgabe
mit xprintf. Ich vermeide call by ref sowieso wo es nur geht und auch
nur selten Pointer, außer eben beim Heap.
Du kannst dich damit ja gern weiter befassen, ich bin froh dass es mit
[] läuft und fasse das Modul nicht mehr an. Allein schon die ganzen Asm
Warnungen des Linkers vorher.
ps: sehe grad dass ich im modul sd.c bei dem "extern uint16_t
code_start" die * vergessen habe. kann sein dass da ein ungewollter typ
cast über die Module hinweg stattgefunden hat.
Die nächste Zeit ist auch Arduino angesagt... da auf Z80 "blind"
programmiert, ohne Testmöglichkeit, nur nach Logic Analyzer.
Es wächst nämlich grad noch ein Platinchen heran.... mit 32 Bit Counter,
SD, programmierbarem Taktteiler (4020 und 74151), Display und noch ein
paar Ausgängen für die nächste Stufe...
Es werden immer mehr :-)
Hallo,
> Ich bin froh den sdcc zu haben (weil es nichts anderes Gescheites gibt)> aber müsste ich damit beruflich arbeiten (solche Sachen habe ich mit dem> Keil nie ...) würde ich das Ding zurückschicken und mir das Geld> auszahlen lassen.
Die null Dollar, die du dafür bezahlt hast, kann sogar ich dir
überweisen. Es gibt (gab) übrigens auch einen Keil-Compiler für den Z80,
den ich allerdings nie gefunden habe. Der liefert aber vergleichbare bis
bessere Ergebnisse als SDCC und dürfte auch zertifiziert sein.
Alternativ gibt es auch noch den z88dk als C-Compiler, aber ob der
bugfreier ist, weiß ich nicht.
> Im industriellen Umfeld wäre der sdcc nicht "qualifizierbar" und in> meiner Branche wo Source SIL 3 erfüllen muss auch "lebensgefährlich."
Dafür ist er auch nicht gebaut. Siehe Keil.
> Die nächste Zeit ist auch Arduino angesagt... da auf Z80 "blind"> programmiert, ohne Testmöglichkeit, nur nach Logic Analyzer.
Verstehe ich nicht. Ich hatte auf meinem System eine Turnaround-Zeit von
vielleicht 15 Sekunden: "make all", Reset-Knopf drücken, Sende-Befehl
des Terminals, Dateiname eingeben, paar Sekunden warten, Ergebnis
gucken.
Aber ich bin positiv überrascht, mit wieviel Wucht du immer wieder mit
dem Kopf gegen die Wände rennst (Türen ignorierend) - und trotzdem
durchkommst.
Gruß,
Svenska
S. R. schrieb:> Verstehe ich nicht. Ich hatte auf meinem System eine Turnaround-Zeit von> vielleicht 15 Sekunden: "make all", Reset-Knopf drücken, Sende-Befehl> des Terminals, Dateiname eingeben, paar Sekunden warten, Ergebnis> gucken.
Glaubst du bei mir läuft das anders? 10s wenn es hoch kommt. NMI Reset
für Laden, ./load Script aufrufen und das Ding rennt los. Aber das
Extension Board ist noch nicht verdrahtet.
https://www.youtube.com/watch?v=gSVBFNCqYeQ
und
https://www.youtube.com/watch?v=PpTISqDCT0c
Das nächste Projekt steht schon in den Löchern.... Z80 mit Bildschirm
und Tastatur, S100 Bus und CP/M :-) Aber keines dieser Kunstrgiff
Systeme wie Atmega Emulator mit Z80 als Slave. ne eine richtige schöne
Platine mit fetten Chips drauf und viel RAM :-)
Wäre aber auch mal was, ne CPU ohne CPU:
https://www.youtube.com/watch?v=GeSSkvwFDHs
Bin in dem Zaks Buch inzwischen schon weiter ..... frage mich dennoch
wie Menschen die Nerven hatten ganze OS damit zu schreiben. Allerdings
hat der Jäger damals auch Stunde damit verbracht seine Pfeilspitzen zu
schärfen, damit sie dann, wenn das Wild auftaucht scharf sind :-)
Mal ne allgemeine Frage: Ich habe mir den Asm des sdcc ja nun oft genug
angeschaut. Er ist clever genug aus einem strcpy oder memcpy eine LDIR
Schleife zu bauen. Also die mächtigen Befehle zu nutzen, die mit
Mikrocode abgearbeitet werden.
Wie ist denn überhaupt die Nutzung des gesamten Befehlsvorrates? Gefühlt
nutzt er nicht mehr als 20 Befehle. Ich vermute man könnte in Asm locker
30% Code einsparen.
Christian J. schrieb:
[..]
> Wie ist denn überhaupt die Nutzung des gesamten Befehlsvorrates? Gefühlt> nutzt er nicht mehr als 20 Befehle. Ich vermute man könnte in Asm locker> 30% Code einsparen.
Du bist auf dem besten Wege herauszufinden warum RISC CPUs erfunden
wurden.
Ich denke nicht das das auf den Z80 zutrifft aber bei der VAX gab es
komplexe Maschinenbefehle deren Ausführungszeiten länger waren als ihr
Ersatz durch Befehlsfolgen einfacherer Befehle.
Gruß,
Holm
Holm Tiffe schrieb:> Du bist auf dem besten Wege herauszufinden warum RISC CPUs erfunden> wurden.http://www.cis.upenn.edu/~milom/cis501-Fall08/papers/cocke-RISC.pdf
"There even were instances of code which, when compiled for the 801 and
simulated on a System/370 Model 168, ran faster in real time than the
same program run directly on a Model 168 when compiled by the PL/I
compiler."
Christian J. schrieb:> Im industriellen Umfeld wäre der sdcc nicht> "qualifizierbar" und in meiner Branche wo Source SIL 3 erfüllen muss> auch "lebensgefährlich."
Sorry daß ich mich hier mal einmische und eurer Trialog störe.
Aber obige Aussage von Christian, daß er beruflich was mit "SIL 3" zu
tun hätte, und das in Verbindung mit seiner Arbeitsweise was hier auf
inzwischen 1329 Beiträgen dokumentiert ist ...
Das macht mir richtig Angst.
Gruss
A. K. schrieb:> Holm Tiffe schrieb:>> Du bist auf dem besten Wege herauszufinden warum RISC CPUs erfunden>> wurden.>> http://www.cis.upenn.edu/~milom/cis501-Fall08/papers/cocke-RISC.pdf>> "There even were instances of code which, when compiled for the 801 and> simulated on a System/370 Model 168, ran faster in real time than the> same program run directly on a Model 168 when compiled by the PL/I> compiler."
...das ist ja schräg... allerdings lief emuliertes Linux bzw. Linux
Programme auf einem FreeBSD eine Zeit lang auch schneller als auf Linux.
Da war der Emulator aber mehr oder weniger ein system call wrapper und
dadurch war das Ganze auch erklärbar.
Bei dem VAX Beispiel, das ich von cctalk@classiccmp.org habe, frage ich
mich allerdings was die Designer des Microcodes geraucht haben wenn sie
es hinkriegen das eine Makrobefehlsfolge schneller ist als der
spezialisierte Mikrocode auf der selben Maschine..
Ich weiß nicht viel über PL/1 aber IMHO sagt da schon was über die
Qualität und Implementation des Compilers aus.
Die DDR hat mal eine wenig kompatible und als langsamste geltende PDP11
gebaut, den Robotron K1630 mit asynchroner CPU. Für das Ding gabs
Einschubplatinen um einen KRS4200 emulieren zu können um alte Programme
ablaufen zu lassen. Wenn dieser Emulator lief, war der Rest der Maschine
nicht für anderes verwendbar. Der Emulator aber seinerseits war deutlich
schneller als der eigentliche KRS4200 (Honeywell 9000).
Gruß,
Holm
Holm Tiffe schrieb:> Bei dem VAX Beispiel, das ich von cctalk@classiccmp.org habe, frage ich> mich allerdings was die Designer des Microcodes geraucht haben wenn sie> es hinkriegen das eine Makrobefehlsfolge schneller ist als der> spezialisierte Mikrocode auf der selben Maschine..
Bekannt war diese Verhalten von den CALLx/RET Befehlen. Die waren als
eierlegende Wollmilchsau so komplex geraten, dass viele auf die
einfacheren und schnelleren JSB/RSB auswichen.
Der Microcode eines komplexen Befehls muss alle möglichen Optionen des
Befehls zur Laufzeit einzeln durchprobieren. Nur um meist festzustellen,
dass es nichts zu tun gibt. Das kostet Zeit. Ein Compiler hingegen
erzeugt einfach nur die Befehle, die wirklich benötigt werden.
A. K. schrieb:
[..]
> Der Microcode eines komplexen Befehls muss alle möglichen Optionen des> Befehls zur Laufzeit einzeln durchprobieren. Nur um meist festzustellen,> dass es nichts zu tun gibt. Das kostet Zeit. Ein Compiler hingegen> erzeugt einfach nur die Befehle, die wirklich benötigt werden.
..nein, im konkreten Falle war das nicht der Call, ich glaube das war
irgend ein String Befehl, wobei ich aber auch weiß das der Call auf VAX
so ziemlich "Alles" macht..
Klar ist das die CPU immer ein "Interpreter" für die Maschinensprache
ist
der sich durchwursteln muß.Das ist aber beim Microcode zu einem
Maschinenbefehl auch nicht anders und auch da kann man gut oder
beschissen programmieren.
Gruß,
Holm
Erich schrieb:> Sorry daß ich mich hier mal einmische und eurer Trialog störe.> Aber obige Aussage von Christian, daß er beruflich was mit "SIL 3" zu> tun hätte, und das in Verbindung mit seiner Arbeitsweise was hier auf> inzwischen 1329 Beiträgen dokumentiert ist ...>> Das macht mir richtig Angst.>> Gruss
Wahrscheinlich schlackerst du jetzt auch nicht mit den Ohren, wenn ich
dir sage, dass einige Fachbeiträge über die 61508, 62061, 13849 und Co.
in Fachzeitungen auf mein Konto gehen und ich sogar Schulungen gehalten
habe, wie diese anzuwenden sind. Gefühlt so ca 500 Geräte mit SIL3
wurden von mir für den Markt zugelassen, mehrere davon in
Kernkraftwerken (Reaktorabschaltung, Sicherheitsbereich E1). Du lebst ja
noch, also scheinen sie zu funktionieren.
Du verwechselst ARBEIT mit HOBBY! Wie viele hier leider....
Schönen Tag noch!
Holm Tiffe schrieb:> Du bist auf dem besten Wege herauszufinden warum RISC CPUs erfunden> wurden.
Das frage ich mich auch, wenn ich mir den Befehlssatz einer Intel CPU
heute anschaue..... ein PIC kommt mit 35 Befehlen aus...... für alles.
Holm Tiffe schrieb:> Das ist aber beim Microcode zu einem> Maschinenbefehl auch nicht anders und auch da kann man gut oder> beschissen programmieren.
Auch Microcode kocht nur mit Wasser. Wenn für einen komplexen Befehl
beispielsweise 20 Microinstructions benötigt werden, von denen die
Hälfte nutzloser Code ist, der nicht zum Ergebnis beiträgt, dann kommt
eine Ersatzsequenz vielleicht nur mit 10 Microinstructions aus. Und das
liegt dann nicht daran, dass der Programmierer besoffen war, sondern
dass der komplexe Befehl Teile enthält, die in diesem Fall nicht
benötigt werden.
Wenn du einen Befehl alles reinsteckst, was irgendwie mal gebraucht
werden könnte, dann ist manches davon nur selten notwendig. Dieser Teil
des Microcodes kostet beim Komplexbefehl trotzdem Takte, nur um
festzustellen, dass ein Wert 0 ist. Der Compiler lässt das in der
Ersatzsequenz aber von vorneherein weg.
Als Beispiel Intels ENTER/LEAVE Befehle. Diese Befehle hatte Intel für
Sprachen vom PASCAL Typ vorgesehen, die lokale Funktionen mit Zugriff
auf die Variablen der umgebenden Funktion unterstützen. Dazu benötigt
man einen viel komplexeren Stackframe als für C, weil ein Pointer-Array
kopiert werden muss.
In C lässt sich der ENTER Befehl auch nutzen, es wird dann aber nur ein
Teil von dessen Funktion genutzt. Einer der Parameter des Befehls ist
dann stets 0 (nesting level). Der Microcode des Befehls muss zur
Laufzeit überprüfen, ob der Wert 0 ist, das kostet Zeit. Die
Ersatzsequenz enthält diesen Teil nicht, das kostet also dann keine
Laufzeit. Folglich waren bei Intel die 2-3 Ersatzbefehle schneller als
Intels ENTER Befehl. Der folglich von kaum einem C Compiler verwendet
wurde.
Zweites Beispiel, wenn der Prozessor bei einem Speicherzugriffsfehler
den Befehl abbricht, um ihn später erneut ausführen zu können. Meistens
ist das so realisiert (m.W. auch bei den VAXen), nur die 68000 Familie
arbeitete anders. Dann darf während der Laufzeit nichts geschehen, das
dies verhindern könnte. Das kann Microcode deutlich komplizierter machen
als eine exakt äquivalente Ersatzsequenz.
So kann es bei Befehlen mit mehreren möglicherweise gleichen oder gar
überlappenden Speicheradressen nötig werden, dass der Microcode zur
Laufzeit die Speicheradressen vergleicht, um abhängig davon verschiedene
Pfade einzuschlagen. In einer Ersatzsequenz aus einfachen Befehlen ist
das einerseits oft unnötig, da sie zwischendrin unterbrochen werden
kann. Andererseits kann der Compiler eigenes Wissen über die Beziehung
der Operanden einbringen.
Dieses Problem kann bereits bei einem scheinbar einfachen Befehl
auftreten, der nur von Speicher zu Speicher addiert.
Komplexe Befehle erzeugen also künstlich Probleme und Laufzeit, die man
in Ersatzsequenzen aus einfachen Befehlen überhaupt nicht hat.
Christian J. schrieb:> Gefühlt so ca 500 Geräte mit SIL3> wurden von mir für den Markt zugelassen, mehrere davon in> Kernkraftwerken (Reaktorabschaltung, Sicherheitsbereich E1). Du lebst ja> noch, also scheinen sie zu funktionieren.
Offensichtlich ist in diesen Geräten keine CPU drin. Oder sie wurde
nicht von Dir programmiert...
> Du verwechselst ARBEIT mit HOBBY!
Hmm. Warum machst Du Dir die Methoden, die Du professionell nutzt, nicht
auch privat zu eigen?
A. K. schrieb:> Komplexe Befehle erzeugen also künstlich Probleme und Laufzeit, die man> in Ersatzsequenzen aus einfachen Befehlen überhaupt nicht hat.
Beeindruckend deine Kenntnisse über die Architektur! Enter und Leave
habe ich damals auch nie gebraucht ca 1995 als ich viel Intel Asm
machte, und auch viele andere nicht. Gehört zwar nicht hierhin aber als
1996 die PIC auftauchten war das wie eine Erlösung. Gestehe, dass ich
niemals auch nur einen in Asm programmierte. Erst denr extrem buggy Byte
Craft Compiler benutzt, dann den CCS ab 2000.
Die Compiler waren allerdings limitiert und auch heute kennt der CCS als
bekanntester Vertreter wohl noch kein char** ptr. Indizierte
Adressierung kannten die PIC nicht, nur ein Destination Bit, was angab
wo etwas zu speichern ist, W oder Speicherzelle. Da ist sicherlich viel
Grips reingeflossen den absolut minimalen einen Befehlssatz zu
erarbeiten, der ohne Microcode auskommt und daher sehr schnell ist,
nämlich nur 1 Takt pro Befehl. Da die Programmierung eh "maschinennah"
auch in C erfolgt ist der Code sehr kompakt
Christian J. schrieb:> Beeindruckend deine Kenntnisse über die Architektur! Enter und Leave> habe ich damals auch nie gebraucht ca 1995 als ich viel Intel Asm> machte, und auch viele andere nicht. Gehört zwar nicht hierhin aber als> 1996 die PIC auftauchten war das wie eine Erlösung.
Intels x86 Architektur war zwar nie der Brüller, aber dass es wahrhaftig
jemanden gibt, der die 8-Bit PICs als Erlösung gegenüber 386 betrachtet,
das hätte ich nicht gedacht. ;-)
Das hasse ich an diesen Forum.... dieses "in den Mund legen" :-( PIC
waren fürs Hobby wie eine Erlösung, nach dem 8051 Krampf, 8048 usw.
Als der 16F84 rauskam habe ich Tage damit verbracht den auszureizen.
Christian J. schrieb:> Das hasse ich an diesen Forum.... dieses "in den Mund legen" :-(
Sachte. Ich dachte mir zwar, dass du 8051 meintest, aber ENTER/LEAVE
sind nun einmal x86 Befehle. So eine Vorlage darf man sich nicht
entgehen lassen. ;-)
Und es ist nach wie vor "faszinierend", dass der kleine 14-Pinner in der
Mitte zusammen mit einem Schieberegister in der Lage ist Sensoren
auszulesen, Temperatur, Feuchte anzuzeigen, nebenbei noch eine Anzeige
zu multiplexen ohne dass diese flackert (ok, ich lese im Umschaltmoment
aus, da fällt es nicht auf :-) und alles was er macht auch noch über
eine Uart auszugeben , Min Max im internen EEPROM speichert usw. usw.
Mag sein das verwöhnte Bengels das heute alles als "normal" bezeichnen.
Von sowas hätte ich als 18-20 Jähriger nur geträumt damals.
Ne ähnliche Schaltung, die ich 1996 mit dem 8051 machte (ext. EPROM, NTC
Widerstand) undderen Hartpapier Platte heute so schwarz braun statt
hellbraun aussieht läuft aber heute auch noch, EPROMs schaffen also
mindestens 20 Jahre :-)
greg schrieb:> So krampfig ist der 8051 doch auch nicht. Jedenfalls nicht schlimmer als> diese krude PIC12-Architektur. :o
Vielleicht meinte er auch 8048. Die war deutlich krampfiger als 8051.
PIC12 ist ok, wenn man in Assembler programmiert und das Programm
maximal 256 Worte umfasst. Für grössere Programme war diese Architektur
- die übrigens die älteste noch genutzte µC Architektur ist - nie
gedacht. Und als Ziel von Compilern schon garnicht.
greg schrieb:> So krampfig ist der 8051 doch auch nicht. Jedenfalls nicht schlimmer als> diese krude PIC12-Architektur. :o
Soso, 256 Byte Stack limiert.... ok, Keil Compiler damals gehabt. Immer
ein EPROM mit dran was Pins kostete. Und 100 DM für einen 87C51
ausgegeben, der nach 3 Mal Brennen kaputt war :-(
Ich warte noch auf die hier für Z80:
http://en.wikipedia.org/wiki/MCU_8051_IDE#mediaviewer/File:MCU_8051_IDE_-_I.png
A. K. schrieb:> PIC12 ist ok, wenn man in Assembler programmiert und das Programm> maximal 256 Worte umfasst
Das sind die im SOT-23 Gehäuse, 6 Pins, winzige Dinger, die aber reichen
um zb eine IR Diode zu modulieren, TSOP zu decodieren usw. Nie gehabt,
nur Asm, kein Debug Interface usw.
Christian J. schrieb:> Soso, 256 Byte Stack limiert.... ok,
Nix Stack. Der Code. Notfalls 512 Worte, wenn man die Unterprogramme in
die erste Hälfte davon legt. Bis dahin geht es ohne Banking ab. Mehr
hatte der PIC1650A auch nicht. Dass dessen Architektur auch 4 Jahrzehnte
später noch lebt hatte GI sicher nicht auf der Rechnung.
@Frank Meyer:
Wäre es ohne weiteres für Dich möglich eine nützliche Option in den
Minieditor getstrng einzubauen, nämlich dass er den Buffer in das
Eingabefeld ausdruckt? Dieser müsste also leer sein wenn man ein leeres
Feld haben will aber es wäre sehr nützlich um fehlerjafte Eingaben zu
korrigieren ohne alles neu tippen zu müssen. Habe den Parser
geschrieben, der die Kommandozeile zerlegt und da es jede Menge gibt,
was ein User (auch wenn nur ich es bin) da verbrechen kann wäre eine
"Back" Funktion sehr nützlich.
1
do {
2
getnstr(cl.inbuf,CMDBUFSIZE-1);
3
while (strlen(cl.inbuf)==0);
4
5
// String splitten
6
res = split_command(&cl)
7
} while (res != 1);
8
9
......
10
11
12
char split_command(struct cl_type* ptr)
13
{
14
char cbuf[CMDBUFSIZE]; // Kopie Eingabepuffer
15
char* cptr; // Zeiger auf Eingabepuffer
16
char j,i;
17
18
// Stringzerlegung (ok!)
19
strcpy(cbuf,ptr->inbuf); // String Kopie erzeugen
20
21
j = 0;
22
cptr = strtok(cbuf," "); // Zeichentrenner und erster Abschnitt
S. R. schrieb:> Übrigens wiederhole ich nochmal einen Vorschlag: Deine serielle> Schnittstelle kann all das, was du willst, auch machen. Du musst dafür> keine SD-Karte an dein System frickeln. Das Protokoll der Wahl dafür> nennt sich ZMODEM.
Ich habe Dich "erhört" :-) Nur ist es nicht ZMODEM geworden, sondern
wegen der kleineren Codegröße XMODEM. 10 Minuten einfügen, etwas
umstellen, CRC mit rein nehmen, getchar und putchar einbauen,
Kompilieren ohne Fehler und der Test war dann schnell gemacht, dass
minicom Dateien entgegen nimmt und abspeichert und auch der Z80 sie von
dort laden kann.
Wie war das noch mit Boris Becker? "Bin ich schon drin?" :-)
Schön, neben der SD Karte eine weitere Möglichkeit Programme
einzuspielen und zu sichern. Damit haben wir
a) Intel Hex Upload
b) SD karte
c) XMODEM
und die 16kb sind leider auch bald voll :-((
http://www.menie.org/georges/embedded/xmodem.c
Christian J. schrieb:>> Das Protokoll der Wahl dafür nennt sich ZMODEM.> Ich habe Dich "erhört" :-) Nur ist es nicht ZMODEM geworden, sondern> wegen der kleineren Codegröße XMODEM.
Naja, immerhin. Das ZMODEM hatte übrigens auch einen konkreten
Hintergrund, denn es bietet dir drei relevante Vorteile gegenüber
XMODEM:
- ZMODEM überträgt Dateinamen
- ZMODEM überträgt byte-exakte Dateigrößen (XMODEM paddet auf 128 Byte)
- ZMODEM kann automatische Übertragungen (in beide Richtungen, wenn ich
mich recht entsinne) anstoßen.
Damit kannst du dir schon fast einen richtigen Fileserver bauen. Wenn
dein Terminal gut genug ist, dann braucht der Z80 nur noch "gib mir
TEST.TXT" sagen und bekommt die Datei, ohne dass du in deinem Terminal
den Namen nochmal angeben müsstest.
Gruß,
Sebastian
Hi,
naja, es klappt ja. Aber es soll ja eigentlich von ner Karte kommen. Der
Z80 wird später mal nur an einen Raspi kommen, mit Monitor und Keyboard.
PC als Stromfresser soll nur zur Entwicklung sein.
Leider habe ich mir mit dem Intel Hex Decoder auch die doppelte Upload
Zeit eingefangen wie vorher auf Binärebene. Aber es klappt auch und ist
sehr einfach, wenn man vieles weglässt und auch keine Fehlerprüfungen
mehr als die Prüfsumme einbaut.
Interessieren würde mich mal woher die Z80er und Co. auf ebay etc
derzeit noch kommen. Ist das NOS Ware? Oder wird der immer noch
hergestellt? Habe einen von 1981 und andere von 1994 hier.
Für den ders nachbauen will hier der Source. Lässt man die Prüfsumme
auch noch weg wird es noch um 30% kürzer.
Der Programmcode 08.12.2014 12:02 erscheint mir wiederum sehr
hobbymäßig, eher sogar mäßig bis ...mäßig. Jedenfalls nicht SIL3.
Früher ---als es noch keine SIL Stufen gab--- da hat man schon erst das
Zeugs dekodiert und erst in den Speicher geschrieben wenn alles ok war.
Aber das war früher...
Gruss
Erich schrieb:> Der Programmcode 08.12.2014 12:02 erscheint mir wiederum sehr> hobbymäßig, eher sogar mäßig bis ...mäßig. Jedenfalls nicht SIL3.
Rede keinen Stuss und melde Dich erstmal an, bevor Du hier rumnörgelst.
Code muss funktionieren und das tut er. Schönheitspreise braucht er
nicht zu bekommen. SIL3 bei Z80? Gehts noch? Und bevor ich nicht von Dir
etwas hier gesehen habe halt dich bitte mit Kommentaren zurück.
Jedenfalls kam er heute an, gebraucht für 149 Ocken. Sehr nettes
Teilchen!
Das Zeug daneben finde ich interessanter: Den nicht sehr erdbebenfest
wirkenden und schon windschiefen Plattenstapel auf Platte. ;-)
Der Rest ist leider nicht zu erkennen. Freiluft-Server?
A. K. schrieb:> Freiluft-Server?
Yep, ein 24/7 Server mit 6 TB, kleine Cubietruck "Fabrik"..... da drauf
wird ja auch alles Z80 Zeug entwickelt, kompiliert, hochgeladen usw.
AK?
Kann es sein, dass die 8254 Timer schweineheiss werden? Den hier kann
man kaum länger anfassen. Pendelt sich bei 41 Grad ein. 1W Pv laut
Datenblatt aber ich frage mich wo der die lässt. Gibt es die auch als
CMOS? Oder den 8253? Der Stromverbrauch nähert sich den 500mA.....
Christian J. schrieb:> 1W Pv laut Datenblatt
170mA max, sagt mir das Datasheet. Yep, darf also warm werden.
> Der Stromverbrauch nähert sich den 500mA.....
Nur vom 8254? Das wären 2,5W und das wäre mehr als warm, mehr als
schlappe 41°C würde ich meinen.
CMOS wäre 82C54. Ganz dem Intel'schen Schema entsprechend.
A. K. schrieb:> CMOS wäre 82C54. Ganz dem Intel'schen Schema entsprechend.
500mA alles zusammen inzwischen, beide Platinen. Der 8254 zieht sich
135ma aktuell rein.
Und schon 82C54 "bestellt" in der Bucht..... geht nicht dass der hier
die Bude aufheizt. Die 7805 sind auch an ihrer Grenze.
Anbei die Peripherie, noch nicht ganz fertig aber frag bitte keiner nach
dem "Sinn", es ist einfach nur etwas Elektronik, die sich konfigurieren
lässt, mehr nicht. Das ist das Problem bei solchen Sachen.... eine echte
Anwendung haben sie nicht :-(
Es wächst und wächst und falls mir noch was einfällt ist die nächste
Leiste schon zur 3.ten Platine fertig :-)
Bisher:
3 x 16 Bit Timer verkettet zu 32 Bit + 1 Interrupt Ausgang für Z80
1: 4 bis 1:14 Teilbarer 1Mhz Takgeber per Multiplexer
SD Karten Interface mit Atmega 328
8 zusätzliche Inputs seriell
8 zusätzliches Output seriell
1 x Display mit Controller
1 x 8255 zur "Verwaltung" des Ganzen.
Blöd, dass der 8255 sich nicht on the fly umschalten lässt an seinen
Ports. Jede Änderung des Config Wortes resettet die anderen Register
auch.
Und wenn mal Langeweile ist, das ist der Original Schaltplan des Spiels
PONG von Atari mit TTL Gattern....
Christian J. schrieb:> Es wächst und wächst und falls mir noch was einfällt ist die nächste> Leiste schon zur 3.ten Platine fertig :-)>> Bisher:>> 3 x 16 Bit Timer verkettet zu 32 Bit + 1 Interrupt Ausgang für Z80> 1: 4 bis 1:14 Teilbarer 1Mhz Takgeber per Multiplexer> SD Karten Interface mit Atmega 328> 8 zusätzliche Inputs seriell> 8 zusätzliches Output seriell> 1 x Display mit Controller> 1 x 8255 zur "Verwaltung" des Ganzen.>> Blöd, dass der 8255 sich nicht on the fly umschalten lässt an seinen> Ports. Jede Änderung des Config Wortes resettet die anderen Register> auch.
Das wurde Dir doch aber vorher gesagt. Warum baust Du auch die
schrottigen Intel Teile ein die es schon gab bevor der Z80 mit seiner
Peripherie entwickelt wurde?
Stelle Dein Oszi woanders hin sonst hast Du bei Zeiten Zinn Spritzer auf
dem Display.
Das Paket ist angekommen..THX.
Gruß,
Holm
Leo?
Hast Du ne Erklärung dafür?
Definiere ich das hier global
struct ihx_data {
uint8_t len;
uint16_t datalength;
uint16_t recordsets;
uint16_t adress;
uint8_t record;
uint8_t csum;
} ihx;
kommt das bei raus:
195 ;tools.c:79: ihx.datalength = 0;
00A1 21 00 00 [10] 196 ld hl,#0x0000
00A4 22r01r00 [16] 197 ld ((_ihx + 0x0001)), hl
Definere ich es aber in der Funktion, also "dynamisch" explodiert das zu
1
192 ;tools.c:80: ihx.datalength = 0;
2
00A3 21 00 00 [10] 193 ld hl,#0x0000
3
00A6 39 [11] 194 add hl,sp
4
00A7 DD 75 EF [19] 195 ld -17 (ix),l
5
00AA DD 74 F0 [19] 196 ld -16 (ix),h
6
00AD DD 7E EF [19] 197 ld a,-17 (ix)
7
00B0 C6 01 [ 7] 198 add a, #0x01
8
00B2 DD 77 F9 [19] 199 ld -7 (ix),a
9
00B5 DD 7E F0 [19] 200 ld a,-16 (ix)
10
00B8 CE 00 [ 7] 201 adc a, #0x00
11
00BA DD 77 FA [19] 202 ld -6 (ix),a
12
00BD DD 6E F9 [19] 203 ld l,-7 (ix)
13
00C0 DD 66 FA [19] 204 ld h,-6 (ix)
14
00C3 AF [ 4] 205 xor a, a
15
00C4 77 [ 7] 206 ld (hl), a
16
00C5 23 [ 6] 207 inc hl
17
00C6 77 [ 7] 208 ld (hl), a
Die ganze Routine betreffend, wo der struct zigmal angefasst wird
sind das 500 (!!!) Bytes. Absolut ineffzienter Code.
Solte man da nicht lieber fast alle global machen, bzw. quasi
Universalvariablen einführen, statt dynamische zu verwenden?
Lege ich den struct in den Heap sieht es ähnlich aus wie unten. :-(
Irre!
Ah, der Dolmetscher...
naja, ich kann es umso besser reproduzieren, da ich das an mehren
Stellen ausprobiert habe. Globale Vars erzeugen erheblich weniger Code
als dynamische. Ob die Knapserei mit dem RAM also Sinn macht sei mal
dahingestellt. Der Heap ist sonst gern meine Rettung aber auch der wird
über Zeiger angesprochen.
Nochmal deutlich: Definiert man einen Struct IN einer Funktion, so dass
er dynamisch angelegt wird, so explodiert die Codemenge. Legt man ihn
nach außen, samt seiner Variablen, so ist es prima.
Christian J. schrieb:> Ja, bitte?
Du meinst, wir hätten bessere Glaskugeln als Du?
Mit den Codefetzen, die Du hier immer abwirfst, kann man jedenfalls auch
nicht mehr anfangen.
A. K. schrieb:> Übersetzung: Er kann es nicht reproduzieren. Bei ihm kommt optimaler> Code raus.
Genau. Dabei habe ich alle Informationen, die Christian geliefert hat,
für das Beispiel verwendet.
Christian J. schrieb:> Nochmal deutlich: Definiert man einen Struct IN einer Funktion, so dass> er dynamisch angelegt wird, so explodiert die Codemenge.
Das ist mal wieder so eine falsche Behauptung die Du nicht bewiesen
hast. Mein Beispiel zeigt, daß das Gegenteil richtig ist. Jedenfalls in
diesem Einzelfall.
Inzwischen habe ich mir mal Deinen Kot-Brocken (tools.c) angeschaut.
Zuerst habe ich alles auskommentiert, was ich nicht kompilieren kann.
Die Funktion, um die es Dir offensichtlich geht, ihx_decode(), ist aber
größtenteils noch drin. Kompiliert mit Standard-Optimierung (sdcc -mz80
--opt-code-size -c) zu 0x1fe Bytes.
Dann habe ich etwas umorganisiert und das umständliche hin- und
herkopieren zwischen Hilfsvariablen beseitigt. --> Größe ist auf 0x107
Bytes, also fast nur noch die Hälfte, implodiert. Man könnte auch sagen,
die Codemenge explodiert durch ineffiziente Programmierung.
Ich vermute, Sinn der "struct ihx_data" soll sein, daß die gesammelten
Hex-Record-Daten an andere Programmteile weitergereicht werden können.
Deshalb habe ich die struct nicht in der Funktion deklariert (wäre ja
sinnlos), sondern ihr einen Pointer übergeben. Codegröße jetzt 0x223
Bytes, also mehr als verdoppelt. Aber der Compiler kann ja noch
optimieren, in dem man dem Register Allocator mehr Zeit läßt. Und hier
bringt das besonders viel. Mit "--max-allocs-per-node 70000" kommt
0x1bf raus.
Leo C. schrieb:> Das ist mal wieder so eine falsche Behauptung die Du nicht bewiesen> hast. Mein Beispiel zeigt, daß das Gegenteil richtig ist. Jedenfalls in> diesem Einzelfall.
Ich lass es. Ich bin blind, ich habe keine Ahnung und ich schreibe
Blödsinn, den ich nicht beweisen kann. Der Codefetzen da oben ist auch
sicherlich nur ausgedacht.
Die Zusammenfassung der Mehrfachaufrufe und die Prüfsummenauslagerung
habe ich inzwischen auch gemacht, allerdings etwas anders. Die erste
Lösung muss funktionieren, optimieren kann man immer noch. Trotzdem gute
Ideen dabei, ich lerne was dazu.
Optimierung ist aus, die hat mir nur Murks mal erzeugt. Code der ohne
Opt läuft und mit nicht mehr kann ja nicht so richtig sein.
Danke für die Mühe!
Mit --max-allocs-per-node 70000 kompiliert er inzwischen seit 13
Minuten.....
Christian J. schrieb:> Optimierung ist aus, die hat mir nur Murks mal erzeugt.
Hältst du das nicht für ziemlich frech? Optimierung abschalten und dann
über unoptimierten Code meckern?
Großer Dank an Holm für seine "Wundertüte" !!!
Und man glaubt es nicht...... "Sowjetiski 8255 brrrauchen mehrrr Strom,
Towarisch aber wenn sie erstmal warm sind dann laufen sie auch". Gehäuse
scheint entweder aus gepresstem Schwarzbrot zu bestehen oder Bakellit.
Und auch DDR "Klon" im 2,5er Raster spielt (nachdem der
Kessel-Dampfdruck hoch genug war) hatte wie gewünscht trotz Probleme mit
der Beinfreiheit im Sockel .... allerdings liegt die Stromaufnahme
gesamt inzwischen bei dramatischen 550mA für die vielen NMOS Chips und
der 7805 gerät langsam ins Schwitzen ohne Kühlkörper.
Christian J. schrieb:> Und man glaubt es nicht...... "Sowjetiski 8255 brrrauchen mehrrr Strom,> Towarisch aber wenn sie erstmal warm sind dann laufen sie auch". Gehäuse> scheint entweder aus gepresstem Schwarzbrot zu bestehen oder Bakellit.
Diese ICs waren doch teilweise lichtdurchlässig, was zur folge hatte daß
sie im prallen Sonnenlicht nicht mehr zuverlässig funktionieren und
resetten auch mit dem Blitzlicht (richtiges, nicht LED...) möglich ist.
:-) Schon mal getestet???
Glaube der Effekt war seinerzeit beim ostzonalen Taschenrechner
"Konkret600" öfter zu beobachten. Reperatur nur an dunklen
Arbeitsplätzen möglich...
@Christian: ich habe dir extra die braunen 8255A geschickt weil die
"besser" aussahen. Mit der Stromaufnahme von NMOS ICs mußt Du freilich
klar kommen,
wobei diese Teile da noch relativ genügsam sind, weitaus mehr Strom
wurde damals (TM) in deren Umgebung durch TTL ICs verbraten. Z80 wuren
in der DDR auch später als CMOS Versionen gebaut, bin mir aber nicht
sicher ob ich da was da habe..
Über die seltsame Farbe der russischen Vergußmassen wird "ostzonal"
(danke IGOR für diesen Begriff, Du mußt wohl westzonal sein, Zone aber
auf jeden Fall) schon öfter gerätselt und ich habe den Verdacht das das
Zeug auch mehr Wasser aufnimmt als die gewöhnliche schwarze Vergußmasse
die auch in der DDR benutzt wurde. Die Farbe ging von kackbraun bis zu
spinatfahl.. Was fürs Auge sind russische Keramik-ICs in
Schweinchenrosa/Gold..
Hier mal ein Bild (1,1Mb!) einer russischen LSI11/03 CPU, die rosa Teile
sind 4kx1 DRAMs kompatibel zu I2107:
http://www.tiffe.de/Robotron/PDP-VAX/E60/E60-01.jpg
Einen lichtempfindlichen Taschenrechner hatte ich auch schon, allerdings
war der komplett russisch, ein Konkret 600 dürfte so selten gewesen sein
das kaum Jemand das Vergnügen gehabt haben dürfte das Teil reparieren zu
dürfen.
Gruß,
Holm
Hi,
hauptsache sie spielen und das tun sie. Bevor ich wieder teuer bestellen
muss aus China überlege ich mir, ob der MK3801-04 auch wohl 5Mhz an
seinem Timer und Clock aushält oder ob ich doch auf den -06 wechseln
muss, der sehr selten ist? Ich brauche höhere Baudraten und eine
schnellere CPU und da wären 19600 die nächste durch Taktverdoppelung.
-06 bisher nur in China gefundenm, das dauert wieder 6 Wochen bis der
hier ist.
Da ich an dem "Homebrew Z80" immer noch Spass habe, jedenfalls mehr als
an einem fertigen ARM, AVR usw, wo eh alles funktioniert wächst der
Monitor inzwischen beachtlich an. Kompletter Kommandoparser ist fertig
und wird grad " Size optimiert", wobei die 16Kb Grenze das Limit des
Machbaren darstellt.
Dass der sdcc bei --max-allocs-per-node 50000 auch locker mal 1kB bei
13kb Code einspart war mir auch neu, nur dauert das eben locker 10min zu
kompilieren, so dass es nur für den "relaese" in Frage kommt. Fuer Frank
haette ich noch nette Funktionen, die ich mir zu mcurses dazugeschrieben
habe aber er scheint ja weg zu sein.....
Holm Tiffe schrieb:> Hier mal ein Bild (1,1Mb!) einer russischen LSI11/03 CPU, die rosa Teile> sind 4kx1 DRAMs kompatibel zu I2107:
Ist das Ding mal mit der Axt repariert worden?
A. K. schrieb:> Holm Tiffe schrieb:>> Hier mal ein Bild (1,1Mb!) einer russischen LSI11/03 CPU, die rosa Teile>> sind 4kx1 DRAMs kompatibel zu I2107:>> Ist das Ding mal mit der Axt repariert worden?
Nee, aber wahrscheinlich mies transportiert (bei der Verschrottung).
Der RAM funzt aber noch (also kein Grund zum tauschen ,,hätte aber
Ersatz da), die ganze Platine bzw. der gesamte Rechner geht wieder und
man kann darauf das Tetris-Original oder auch SpaceInvaders spielen.
Der Rechner ist zwar groß, aber das dazugehörige Doppelfloppy ist
größer.
http://www.tiffe.de/Robotron/PDP-VAX/E60/CPU-oben.jpg
Gruß,
Holm
Holm Tiffe schrieb:> Nee, aber wahrscheinlich mies transportiert (bei der Verschrottung).
Die Block-C's sehen aber auch schon schön "knusprig" aus .... gut
gelagert sicher. Und die TTL sind wohl mit dem Hammer in Position
gebracht worden?
Ich frage mich grad so wie es in deinem Keller aussieht oder der Garage?
Ist da noch Platz fur ein Auto? Und hat deine Frau noch keinen Wutanfall
bekommen "SCHMEISS DEN MÜLL ENDLICH MAL WEG!"
Jedenfalls merke ich grad schmerzlich, dass es besser gewesen wäre den
ROM/RAM Switch einzubauen, damit alles RAm ist nach dem Booten :-( Fast
alle fertige Software ist so konstruiert, dass sie nur aus einem RAM
laufen kann.
IGOR schrieb:> Diese ICs waren doch teilweise lichtdurchlässig, was zur folge hatte daß> sie im prallen Sonnenlicht nicht mehr zuverlässig funktionieren
Leider nicht nur Sonnenlicht oder intensives Blitzlicht. Eine normale
Schreibtischlampe bei der Fehlersuche reichte aus um absolut irreguläres
Verhalten zu erzeugen :-(
Christian J. schrieb:> Holm Tiffe schrieb:>>> Nee, aber wahrscheinlich mies transportiert (bei der Verschrottung).>> Die Block-C's sehen aber auch schon schön "knusprig" aus .... gut> gelagert sicher.
Die sind nur oberflächlich angekratzt, kein Grund zur Aufregung.
>> Ich frage mich grad so wie es in deinem Keller aussieht oder der Garage?> Ist da noch Platz fur ein Auto? Und hat deine Frau noch keinen Wutanfall> bekommen "SCHMEISS DEN MÜLL ENDLICH MAL WEG!"
Die habe ich nach 14 Jahren wilder Ehe erst in diesem September
geheiratet und das hätte ich kaum getan wenn sie ein Problem mit dieser
Art Hobby gehabt hätte.
War halt sorgfältiger Testbetrieb... :-)
>> Jedenfalls merke ich grad schmerzlich, dass es besser gewesen wäre den> ROM/RAM Switch einzubauen, damit alles RAm ist nach dem Booten :-( Fast> alle fertige Software ist so konstruiert, dass sie nur aus einem RAM> laufen kann.
Loriot: Ach?
Lernen durch Schmerz ist ein bewährtes Verfahren Christian..
Schaue mal Deinen Thread hier durch wie viele Leute Dir das anempfohlen
haben.
Gruß,
Holm
Holm Tiffe schrieb:> Lernen durch Schmerz ist ein bewährtes Verfahren Christian..
Ja... ich müsste so ca 150 Drähte wieder lösen aus den Fädelkämmen, die
proppevoll sind, 2 ICs rausholen, eines noch dazu bauen .... und wenn
ich fertig wäre, würde nichts mehr funktionieren und das Ding in hohem
Bogen über Nachbars Zaun gefeuert werden.....
Aber nur mal theoretisch.....
... 0 0x4000 0xffff
ROM -----------
RAM ###########|##########################
Wenn man es so verschaltet, dass jeder Schreib Zugriff aufs RAM geht
würde der Monitor das Userprogramm direkt ab 0x0000 laden können. Seine
eigenen Variablen würden dann oberhalb liegen, zb ab 0xF000
Dann kommt der Moment des Umschaltens ...... dann müsste quasi
glöeichzeitig noch ein Sprung auf 0x0000 ausgeführt werden, was aber
nicht geht, da der erste Portzugriff sofort umschalten würde. Der JP
start würde nicht mehr erreicht werden.
Mit dem SDCC ist es nicht möglich Code zu erzeugen, der beliebig liegen
kann, daher kann sich der Monitor nicht selbst hochkopieren und von dort
weitermachen, das ginge nur mit Asm.
Alternativ wäre das ROM oben ab 0xC000 und den Umschaltbefehl im
Userprogramm liegen zu haben. Dann würde nur der obere Teil wegklappen
und RAM frei werden. geht aber nicht weil bei 0x0000 ein JP liegen muss
bei Coldstart.
Wie wird es nun wirklich gemacht?
Christian J. schrieb:> Wenn man es so verschaltet, dass jeder Schreib Zugriff aufs RAM geht
Yep. Wie ich oben schon schrieb.
> würde der Monitor das Userprogramm direkt ab 0x0000 laden können.
Wie ich oben auch schon schrieb: Kopier als erste Aktion den Monitor
über sich selber und schalte einfach um. Von dem Moment an läuft der
Monitor aus dem RAM, ohne dass die CPU einen Unterschied sieht, und du
kannst dann tun und lassen was du willst.
A. K. schrieb:> Wie ich oben auch schon schrieb: Kopier als erste Aktion den Monitor> über sich selber und schalte einfach um. Von dem Moment an läuft der> Monitor aus dem RAM, ohne dass die CPU einen Unterschied sieht, und du> kannst dann tun und lassen was du willst.
Ok, kein Problem.... die Umschalteschaltung habe ich schon. Einfach
einen freien I/O Decoderausgang mit einem Flip Flop aus freien NANDs (2
sind eh übrig) verheiraten und die WR Leitung mit in den CS für das RAM
mischen.
A. K. schrieb:> Von dem Moment an läuft der> Monitor aus dem RAM, ohne dass die CPU einen Unterschied sieht, und du> kannst dann tun und lassen was du willst.>Nicht ganz. Du musst das ROM abschalten, nicht das RAM.
Klar, über den OE des ROMs...
Naja.....
Es müsste erstmal das userprogramm geladen werden und das wurde auf
einen fixe Adresse 0x0000 kompiliert. Der IHx8 Loader könnte es beim
Laden auf einen 0x4000 Offset setzen, so dass es im RAM über dem Monitor
liegt.
Dann muss das Userprogramm aber dahin wo der Monitor liegt und das geht
nicht, weil der ja läuft....
Christian J. schrieb:> ROM/RAM Switch einzubauen
Wenn schon Retro, dann nimm ein GAL zwecks Umschaltung. das sortiert dir
die /CE für RAM oben und unten und das Eprom. Und das Flipflop ist auch
gleich drin. Wenn du möchtest, macht es dir (später) auch die
Bankumschaltung für mehr als 64k RAM.
Und noch ein Tipp: Nimm ein Flash Eprom als Boot Medium. Dann kannst du
dir sogar deinen Monitor noch bequem ändern.
Ich erinnere mich ganz schwach an meine 486er ASM Zeiten.... da war es
so dass ein EXE File eine Tabelle mitführte, wo im Code die absoluten
Sprünge sind. Der DOS Lader patschte dann einzelne jede Adresse nach dem
Laden des Code, damit dieser relokatibel wurde.
>> Wenn schon Retro, dann nimm ein GAL zwecks Umschaltung.
GAL programm habe ich, aber keine Ahnung von den Dingern und keine
Software die Gleichungen einzugeben. Wäre aber noch besorgbar, wenn es
nicht DOS ist, da ich kein Windows mehr habe.
Christian J. schrieb:> Dann muss das Userprogramm aber dahin wo der Monitor liegt und das geht> nicht, weil der ja läuft....
Dann kompilier den Monitor auf die Adresse 0xC000.
Nur die ersten Paar Bytes vom Resetcode werden ab Adresse 0 ausgeführt,
kopieren 0x0000:3FFF nach 0xC000, schalten auf RAM um und springen in
den entsprechenden Entrypoint in den Monitor an 0xCxxx. Dann ist 0 frei.
Der Gal Code oben ist kaputt, ich hätte ein paar Code Tags drum herum
bauen müssen..., naja denke sowieso nicht das Du mit einem GAL hantieren
willst.
Gruß,
Holm
A. K. schrieb:> FF = Flipflop:> Boot: Lesen:ROM, Schreiben:RAM> RAM: Lesen/Schreiben:RAM> In ROM/RAM Dekodierung ist kein Adressbezug drin.http://searle.hostei.com/grant/cpm/CPMSchematic1.2.gif
Das erklärt immer noch nicht wie das Userprogramm da hinkommen soll wo
noch der Monitor läuft.....
Christian J. schrieb:> http://searle.hostei.com/grant/cpm/CPMSchematic1.2.gif
Yep, das hatten wir auch schon mal, irgendwo in einer CP/M Diskussion.
UC6:C/D sind unnötig wenn die Kopier/Umschaltaktion sofort nach dem
Reset erfolgt. Solange gibts zwar kein lesbares RAM, aber dafür brauchst
du auch keines.
A. K. schrieb:> Nur die ersten Paar Bytes vom Resetcode werden ab Adresse 0 ausgeführt,> kopieren 0x0000:3FFF nach 0xC000, schalten auf RAM um und springen in> den entsprechenden Entrypoint in den Monitor an 0xCxxx. Dann ist 0 frei.
Das geht deshalb nicht weil der Monitor ein Startup Programm enthält und
bei der Erzeugung des IHX8 Files dann alles zwischen 0x0000 und 0xC0000
mit Nullen gefüllt würde und das geht dann nicht mehr in EPROM rein.
Denn der programmer erwartet, dass die Ladeadressen sich mit denen des
Chip Raumes decken.
Erstmal Kaffee machen....... kopf raucht.....
Wenn es dir nicht gelingt, aus dem Monitor einen Binärklumpen von der
Grösse des EPROMs zu bauen und den ins EPROM zu brennen, unabhängig
davon was in dem Binärklumpen steht, dann ist Hopfen und Malz verloren.
A. K. schrieb:> Wenn es dir nicht gelingt, aus dem Monitor einen Binärklumpen von der> Grösse des EPROMs zu bauen und den ins EPROM zu brennen, unabhängig> davon was in dem Binärklumpen steht, dann ist Hopfen und Malz verloren.
Das mag sein .... aber um das in ein Projekt einzubetten müsste ein
weiteres programm geschrieben werden was den Code patscht und das will
ich vermeiden, da das aufwendig ist. Der SDCC kann keinen relokatiblen
Code erzeugen der während der Laufzeit die Positon ändert und fertig.
Und ohne Startup geht es auch nicht. Und genau aus einem ähnlichen Grund
musste Microsoft damals den Umweg über die EXE Patch Tabelle gehen, was
die bestimmt nicht gemacht hätten wenn das alles so einfach wäre.
Christian J. schrieb:> Software die Gleichungen einzugeben.
PLANII gibt es (noch), ist Freeware und gut.
Kann dein SDCC keine Assembler Ausgabe? Wenn ja: Der M80 ist nach wie
vor frei zu haben und kennt ".PHASE". Ruckzuck ist ein REL-File gemacht,
das du deinem Linker dann vorwerfen kannst. Musst dich nur von dem
Gedanken an einen monolithischen Monitor frei machen.
Deine Probleme haben andere schon vor Jahrzehnten gelöst. Und hier im
Thread sind dir Lösungen x-mal angeboten worden.
Doch es geht!
Objectcopy erzeugt ein BIN File aus dem HEX waas keine Adressbezüge mehr
enthält. Der Brenner kann sich das BIN an beliebiger Stelle reinholen,
er lädt es per default an 0x0000 aber das kann ich ändern.....
Ok...
Christian J. schrieb:> Der SDCC kann keinen relokatiblen> Code erzeugen der während der Laufzeit die Positon ändert und fertig.
Muss er dafür auch nicht. Es reicht, wenn er in der Lage ist, Code für
den festen Adressbereich 0xE000 (ich war vorhin von 16K ausgegangen) zu
erzeugen und du in der Lage bist, diese 8KB ins EPROM zu programmieren.
> Und ohne Startup geht es auch nicht.
Muss es auch nicht. Nur dass der Startup dann ab 0xE0xx läuft.
Sinngemäss (8K ROM), übersetzt für Adressraum E000-FFFF, unter der
Annahme, dass die RST Befehle vom Monitor nicht verwendet werden:
reset: ld bc, 0x2000 ;8KB
ld hp, 0x0000 ;von Quelle
ld de, 0xE000 ;nach Ziel
ldir ;kopieren
out (flipflop),a ;FF umschalten
jp startup ;absoluter Sprung nach 0xExxx
startup: ..hier fängt dein bisheriger Startup Code an..
Der Reset führt das ROM zwar ab 0x0000 aus, aber die paar Bytes bis zum
JP sind adressunabhängig.
Georg G. schrieb:> Deine Probleme haben andere schon vor Jahrzehnten gelöst. Und hier im> Thread sind dir Lösungen x-mal angeboten worden.
Nur zum Verständis... niemand hier im Thread kennt das System was ich
aufgebaut habe, damit von einer Codeänderung zum Test alles schnell
geht.
Das geht vom Compiler über eine Umwandlung des Codes bis zum Laden in
den Programmer und auch noch ein Ladeskript.
Ebenso kennst du nicht die Werkzeuge die ich verwende. Einen M80
Assembler mit rein zu bringen wäre unsinn. Der SDCC hat einen drin, der
gibt auch Asm aus aber der ist nicht kompatibel mit anderen, hat seine
eigene Syntax.
Die von AK vorgeschlagene Lösung ist ok, das Monitorprojekt muss auf
0xc000 kompiliert werden, dann kann ich es in adressloses BIN umwandeln
und dieses kann gebrannt und direkt kopiert werden, die Kopierroutine
bringt es im Startup Code mit.
A. K. schrieb:> Muss es auch nicht. Nur dass der Startup dann ab 0xE0xx läuft.
Genau so !!!!!
Anbei mal das projekt...... das ist schon etwas gwachsen und kann daher
nicht ohne weiteres in was anderers portiert werden.
A. K. schrieb:> Muss er dafür auch nicht. Es reicht, wenn er in der Lage ist, Code für> den festen Adressbereich 0xE000 (ich war vorhin von 16K ausgegangen) zu> erzeugen und du in der Lage bist, diese 8KB ins EPROM zu programmieren
Das geht aufgrund des Aufbaus eines IHX8 Files eben nur über den Umweg
es zu einem BIN File (COM Datei aus DOS) zu machen, da dann jeder
Adressbezug weg ist für den Brenner. IHX8 will er da sehen wo es hin
soll, zumindest meine China Möhre hier.....
A. K. schrieb:
Korrektur:
reset: ld bc, 0xFFFF ;64KB
ld hp, 0x0001 ;von Quelle
ld de, 0x0001 ;nach Ziel
ldir ;kopieren
out (flipflop),a ;FF umschalten
jp startup ;absoluter Sprung nach 0xExxx
startup: ..hier fängt dein bisheriger Startup Code an..
Setzt voraus, dass im ROM keine Adressdekodierung drin ist. Der JP muss
aus dem RAM laufen können, also wird das ROM einfach 8x hintereinander
in den Adressraum kopiert.
Es würden nur kopiert: 0x0000-0x4fff nach 0xC000-0xcfff
Darüber muss Platz bleiben für Stack, Vars und Heap.
D.h. ein userprogramm ist auch begrenzt und kann nur 48k gross sein.
Christian J. schrieb:> Es würden nur kopiert: 0x0000-0x4fff nach 0xC000-0xcfff> Darüber muss Platz bleiben für Stack, Vars und Heap.> D.h. ein userprogramm ist auch begrenzt und kann nur 48k gross sein.
Oder du platzierst dieses RAM unterhalb des Monitors. Zumindest jenen
Kram davon, den du bei laufendem Programm nicht mehr benötigst.
Ich sags mal so....
Die Entwicklung des Monitors macht man eh im RAM, habe ich bisher auch
so gemacht. Danach kommt er ins ROM rein, man ändert einige Codebezüge
vorher im Quelltext und für den letzten Schritt kann man auch mal im Hex
Code des Brenners etwas rumpatchen, da es nur einmal ist und einen
Sprung anpassen ist echt nicht die Welt. Der SDCC ist ein starkes
Werkzeug aber er schafft auch Probleme, die man ohne ihn nicht hätte,
denn Sonderlösungen sind in Asm einfacher.
Hallo,
Willst du volle 64 k für deine Userprogramme zur Verfügung haben, so
benötigst du ein spezielles Bankswiching incl. HW, welches 64K Ram
dadurch ermöglicht das minimal 1 page für die Kopierroutine und die
notwendigen Mapgingroutienen zum laden des Programmes in andere als die
Ramadressen zur Laufzeit laden und später ummapen, verschieben
(selbstentpacken) kann.
Als letzen Akt muss dieses Programm einen Zyklus anstoßen welcher die
64 KB linear adressiert und einen NMI auslöst um dann das nun im RAM
befindliche Userprogramm zu starten, welches komplett ohne OS auskommen
muss. Über die Sinnhaftigkeit eine solchen Vorgehens darf nachgedacht
werden.
Ich hatte damals meinen Monitor von Hand readressiert(an diese Adresse
kopiert dissasmbliert und alle Adressen umgeschrieben AXXX-->> 4XXX und
Bxxx-->>5xxx), so dass der Monitor sowohl ab A000 als auch ab 4000 im
Ram laufen konnte.
So konnte ich den Monitor je nach Notwendigkeit von verschiedenen
Speicheradressen laufen lassen. Zusätzlich habe ich in Page4
(Kasettenpuffer des Atari) Eine Datenschaufel und Mappingroutine
untergebracht, mit welcher ich vor dem Start jeden Programmes beliebige
Rammanipulationen vornehmen konnte.
So konnte ich Bootdisketten nach dem Booten nur durch Manipulation des
Einsprungvectors (Biosdefiniert) auf der Diskette (Diskeditor) da zu
veranlssen nach dem Bootvorgang nicht zu starten sondern viel mehr
meinen Monitor nach zu laden.
Dabei wurde freilich ein Teil des Ram überschrieben aber ich habe
alternierend beide Monitorversionen aufgerufen und konnte so das
komplette binär Image des jeweiligen Programmes in ein Dosformat
umwandeln. Egal wo im RAM es residierte.
Namaste
hallo,
auch nicth schlecht. das der sdcc aber kein Mapping unterstützt müsste
das auch wieder Sache des Monitors sein, wo dann endgültig die Frage
nach Asm entstehen würde.
und dann kommen wir auch zu meinem anderen hobby.... wenn ich einen 1.8l
VW Motor auf 200PS bringen will, dann kann ich tausende dafür ausgegen
seine Teile zu verändern, scharfe Nockenwelle, Kopf planen, Verdichtung
erhöhen, Ladedruck ändern, Kanäle schleifen, Abgasdruck niedriger machen
usw.
Oder ich lass den Shice bau einfach einen G60 Motor ein mit 200PS...
Sprich: Dann nehme ich keinen Z80 mehr sondern ARM...
Christian J. schrieb:> Oder ich lass den Shice bau einfach einen G60 Motor ein mit 200PS...> Sprich: Dann nehme ich keinen Z80 mehr sondern ARM...
Dabei lernst du nur wie man den richtigen Chip / Motor auswählt. Aber
nicht wie ein Motor/ Prozessor funktioniert.
ASM ist Maschinenorientiertes Programmieren, nicht modern aber sehr
lehrreich und der imho wesentliche Aspekt sich mit derart alter Technik
zu befassen. egal ob Oltimerautomobil oder Oltimercomputer.
Und über Geld und Zeit sollte man dabei schon gar nicht nachdenken. Es
kann nur der persönlichen Kunst zugerechnet werden und die kommt von
Können sonst hieße sie "Wunst".
PS. Sehr langsam gewinnt auch mein Retroprojekt an Form UB8830D +128 KB
SRAM (4*32)+2 *8 KB ROM. Ich weiss SRAM ist nicht wirklich Retro und
auch das geplante GLCD/PS2 ist es nicht. Aber eine gepollte Tastatur,
das habe ich schon mal gebastelt und ein (F)BAS Grafikausgang ... grr
will ich nicht. Also lass ich dass.
Namaste
Ok, fnde ich gut. Und da Du ja sicher ein guter lehrer bist
kanst du mir ja zum Üben mal diese Routine für die ich so
ca 25 Minuten gebraucht habe in Asm codieren :-)
Tick....tack.......Stoppuhr läuft...... ! Los !!!
@ Holm,
perfect
@Christian,
von der und Grundstruktur wäre mein Ansatz der selbe gewesen, lediglich
die Anwendung der Dezimalkorrektur kannte ich von der 6502 so nicht, was
bei mir einen bedingten Sprung erfordert hätte falls nibble >09
ausfällt. eine step by step übersetzung von C ist hier freilich mit
Spatzen auf Kanonen gesch.... ach nein andersrum. Fehlt noch eine
Zählschleife und ein Ein- und ein Ausgabepuffer um auch größere
(mehrstellige) Hexen zu konvertieren. Aber das kannst du ja schon
selbst? ;)
:-)
Habe ganz andere Sorgen derzeit nach .....moment.....10h Programmieren
heute ohne Pausen.
Der Monitor "DeLuxe" ist im ROM, gefühlt 50 EPROMs gelöscht und neu
gebrannt heute, bzw war der Löscher nie aus und wurde immer wieder neu
bestückt, da das im RAM nicht zu testen ging.
Damit das geladene File nicht verloren geht, habe ich 2 Resets
eingebaut, einen über NMI, der zurück in den Monitor führt aber das
Programm jederzeit neu startbar ist und einen Normalreset der es sofort
wieder startet.
Allerdings bemerkt, dass ein Nicht-Nullen des RAMs vor dem Laden zu
einem Programmabsturz des geladenen Programms führt. Intel Hex füllt ja
nur dort auf, wo was ist. Ich vermute mal, dass es mit nicht
initialisierten Vars zu tun hat.
Je größer das Ganze wird umso heikler bei Änderungen, dass plötzlich
auch was anderes nicht mehr funktioniert......
Theoretisch kann ich jetzt mehrere Programme laden und sie einzeln
starten und wieder beenden. Leider gibt es keine virtuellen Memory
Manager und eine MMU auf dem System, das würde einiges vereinfachen.
...Weshalb ich in meiner HW 2*8 KB EEPROM (statt EPRROM) beschreibbar
sowie mit Dipschaltersreibschutz vorgesehen habe. Dazu (beliebig)
mapbare 2* 2*32 KB RAM. So kann ich sowohl vom ROM als auch vom RAM je
ein Backup halten.
o.T.
@ Holm
Das "BM 200" befindet sich bereits in einem dieser EEPROMs.
Nur bin ich noch an der MMU. Der TFT Maximite hat mir das BinFile in
Pages geteilt an einen ATMEGA32 auf dem Brotbrett geschickt und dieser
hat es Byteweise ins 28C256 kaligrafiert, inclusive Verifycation.
Der TFT-Maximite wird mir auch als Serialterminal dienen.
Du hast mich da auf eine Idee gebracht..... lese mir grad den Abschnitt
über den "Z80 DMA Controller" durch..... damit wäre es ohne weiteres
möglich eine MMU aufzubauen, mehrere Pages zu haben usw.
Allerdings würde das Ganze dann auch größenordnungen annehmen, die mit
"Hobby" nicht mehr viel zu tun haben sondern mehr Richtung
"Vollzeitbeschäftigung" gehen. Und Z80 mit S100 Bus gibt es ja schon in
Form des N8VEM.
Holm Tiffe schrieb:> Einen lichtempfindlichen Taschenrechner hatte ich auch schon, allerdings> war der komplett russisch, ein Konkret 600 dürfte so selten gewesen sein> das kaum Jemand das Vergnügen gehabt haben dürfte das Teil reparieren zu> dürfen.
Wir haben damals russische Taschenrechner in der Fa. gestellt bekommen.
Solche mit Solarzelle.
Ja, die Dinger waren lichtempfindlich.
Kam jemand ins Zimmer, sagte "Warum habt ihr das Licht an, spart Strom!"
und schaltete das Licht aus.
In der Folge war das Ergebnis seitenlang eingetippter Listen weg.
Wir haben da oft geflucht.
@Leo:
Du hast auch keine Erklärung dafür, dass sich Bytes bei einem Programm
während der Laufzeit überschreiben, je dichter das Datensegment am Code
Segment liegt? Näher als 2kb, dann geht es los, dass sich "wahlos" Bytes
überschreiben und den Absturz verursachten bzw chaotische Ausgaben auf
dem Schirm?. Habe das sohar mit Checksummen überprüft nach dem Laden des
programms und nach dem Starten. Keine Erklärung, Code siege gut aus aber
je kleiner ich ihn mache (unbenutzte Teile mit einkompilieren), desto
besser wird es. Unter 12kb ist es ganz weg und wenn man die Daten ab
0xc000 legt, wenn der code bei 0x8600 endet.
Das sind s9 Dinge die dann Stunden dauern....... weil sie nicht
erklärbar sind ohne genauen Debugger. Aber aufgetren ist es schon öfter
mal, nur habe habe ich es am "Haken"
Christian so lange Du nicht sicher bist das Dein Code hinsichtlich
memory allocation und deallocation alles richtig macht, würde ich sehr
leise nachfragen..
Gruß,
Holm
Holm Tiffe schrieb:> Christian so lange Du nicht sicher bist das Dein Code hinsichtlich> memory allocation und deallocation alles richtig macht, würde ich sehr> leise nachfragen.
Ich habe derzeit keine dynamische Speicherallokation drin... aber die
Interruptts mit ihren Ringpuffern.......
PS: Es IST der TX Ringpuffer oder der TX Interrupt.... aber nur
sporadisch. Da scheinen "kritische Zustände" zu entstehen.