Die Schweizer wieder!
Axel Schwenke schrieb: > Christian J. schrieb: >> Erklär mir mal einer das: >> >> Mit so 16-19 schrieb ich hunderte Zeilen Asm locker auf dem Papier >> runter. Ummrechnungstabelle brauchte ich nicht, kannte die Hex Codes >> der Mnemonics auswendig. > ... >> Aber mit 45 breche ich mir einen ab mit DIESEM SCHEISS ASSEMBLER !!!! > > Du bist einfach zu alt. Also nicht physiologisch, sondern geistig. > Such dir ein anderes Hobby. Blumen züchten. Schnecken dressieren. > Briefmarken sammeln. Was einfaches halt :P Glaubst du wirklich, deine Alternativen sind nicht einfach :-) Und lass ihn doch. Er hat es doch fein hingekriegt mit seiner Fädeltechnik. Nie im Leben würde ich mir das antun. Alle Achtung! Natürlich muß man fragen, wie sein Zustand mit 60 Jahren ist. Aber im Grunde hat er Recht. Das genannte TDL-Basic hab ich damals auch mit Hand eingetippt. Heute würde ich sowas nicht mehr machen. Die Luft ist raus!
Georg G. schrieb: > Ich wiederhole diverse frühere Statements von vielen Leuten aus diesem > Thread: Nimm einen der vielen Debug Monitore. Dann lädst du dein > Programm ins RAM und kannst mit Brechpunkten das Ding Stück für Stück > durchgehen. Den Monitor an deine Hardware anzupassen ist eine Sache von > 15 Minuten (maximal). Hallo, danke für die Antworten. Das hier scheint mir das Sinvollste zu sein, da ich an der Hardware nichts mehr ändern kann und auch nicht an das Ram unter dem ROM dran komme. Was ist "einer der vielen Debug Monitore", ich würde nicht einen einzigen finden. Und 15 Minuten sicher nicht weil ja eine Kommunikation mit dem PC hergestellt werden muss. Es gibt es sicherlich keine Out of the Box Komplettlösungen, also den Server im Z80 und den Cliebt im PC, oder? Und dann bitte auch die USB Kommunikation dazu. Den STI wird wohl keiner kennen, den muss ich zuerst schreiben, bzw die putchar und getchar Routinen. Sobald das steht geht alles viel fixer. Nochmal PC: Kann es wirklich sein, dass ein cat main.hex >> /dev/ttyUSB0 ausreicht um den Code in den Z80 zu schiessen? Ich meine so einfach? Zumindest wenn der mit dem Lesen mitkommt, denn beim Handshake wird es schwieriger, das habe ich nämlich nicht. Maximal Software HS aber kein RTS/CTS.
Nochmal zum Debugger Ich habe da einen "NoIce" Debugger gefunden,der nur leider 30 Tage Version ist und sich auch ständig unter XP mit einer Schutzverletzung verabschiedet. In dem Paket ist eine IDE mit etwas Komfort, die ein hex einlesen kann oder ein Projekt File mit Debug Infos. Auf dem Zielsystem wird ein Monitor installiert, der "blind" angepasst werden muss an die Serielle. Die IDE kommuniziert mit dem Monitor so als würde man den Code Single Steppen. Eben das was auch JTAG kann, oder Linux oder, oder oder. Das wäre schon sehr nett, wenn es das als Freeware gäbe und es nicht ständig abstürzen würde. Wenn ich mich zurück erinnere an meine Jugend, so war der C64 damals Eprommer und der Code für das 8085 musste einfach fehlerfrei geschrieben werden. Eine andere Möglichkeit hatte ich nicht mit Hausmitteln.
Christian J. schrieb: > Kann es wirklich sein, dass ein > cat main.hex >> /dev/ttyUSB0 > ausreicht um den Code in den Z80 zu schiessen? Ich meine so einfach? Nein, einfacher, wenn du dich endlich vom Hexfile lösen würdest. Da deine Probleme primär auf der Z80-Seite liegen, solltest du zumindest in der ersten Stufe deren EPROM-Bootloader so einfachst wie möglich halten, und da ist eine umständliche Hexfile-Dekodierung in der Z80 unnötig. Was du brauchst ist ein Binärimage des Codes, von beispielsweise exakt 8kB Länge. Dann die Z80 resetten, damit der Bootloader aktiv wird, und: cat main.bin > /dev/ttyUSB0 Nur solltest du die TTY so einstellen, dass darin kein Software-Handshake und keine CRLF-Translation stattfinden kann (=> stty), denn die muss dafür 8-Bit transparent sein. > Zumindest wenn der mit dem Lesen mitkommt, denn beim Handshake wird es > schwieriger, das habe ich nämlich nicht. Vergiss Handshake. Bei 57600 kriechen 5760 Bytes pro Sekunde über die Leitung. Das sind grob 500 Takte pro Byte. Da muss niemand warten.
:
Bearbeitet durch User
wenn ich das recht sehe ist dein ROM gesockelt? Huckepack ein SRAM drauf und RD/WR-Bein hoch und einen Fädeldraht rausgezogen. Das ist kein Hexenwerk, so habe ich in fertigen Gräte neben den Bios ROM ganze dynmische RAM-Bänke ergänzt sowie IO Ports um 36Bit parallel erweitert. Das war damals Homebrewstandard mehr Retrofealing geht gar nicht. Namaste
:
Bearbeitet durch User
Christian J. schrieb: > Was ist "einer der vielen Debug Monitore" Kannst gern ein Muster von mir bekommen. Allerdings für einen "normalen" Assembler (M80 kompatibel, den kannst du mit Doku auch bekommen), eventuell will der mit dem SDCC gelieferte nicht. Du musst nur die Initialisierung deines UART anpassen (Tabelle, Port, Wert, der da rein soll) und die getchr und putchr Routinen (da muss man vermutlich nur die Position des Statusbit anpassen). Auf der PC Seite nimmst du Teraterm oder was ähnliches. Und das Laden des zu prüfenden Programms geht mit "R", gefolgt von "File senden" in Teraterm. Handshake und ähnliches wird nicht gebraucht. Das Ding ist keine eierlegende Wollmilchsau, reicht für 99.9% aller Fälle aber aus. [code] Befehlsliste: defb 'd<start>,<ende> = Speicherdump',0dh,0ah defb 'f<start>,<ende>,<wert> = Speicher fuellen', 0dh,0ah defb 'g<start>[,<break1>[,break2]] = Programm ausfuehren', 0dh, 0ah defb 'h<a>,<b> = a + b, a - b', 0dh, 0ah defb 'i<port> = Port lesen', 0dh, 0ah defb 'm<von>,<bis>,<nach> = Speicher verschieben', 0dh, 0ah defb 'o<port>,<wert> = Port schreiben', 0dh, 0ah defb 'r<offset> = Hex-File lesen',0dh,0ah defb 's<adresse>,<wert> = Speicher aendern', 0dh,0ah defb 'w<von>,bis> = Hex-File schreiben', 0dh,0ah defb 'x[<register>[,<wert>]] = Register anzeigen/aendern', 0dh, 0ah [\code]
Habt Ihrs noch nicht verstanden? Christian möchte eine grafische Entwicklungsumgebung unter Windows, also mit Debugger, die Ihm Programme auf seine Hardware lädt und dort test- und ausführbar macht. Was er nicht möchte ist: 1. Selber machen 2. Doku lesen 3. sich anstrengen. Also bitte Jungs, das Ding sollte bitteschön schon fertig sein... Interfaceroutinen sollten ebenfalls vorhanden und getestet sein so das er sie nur noch einbinden muß. Es geh ja nicht das er sich auch noch mit Registerpointern herumärgern muß. SCNR, Holm
Ich möchte im Zusammenhang mit Retro mal auf einen Thread im Robotron Forum aufmerksam machen: http://www.robotrontechnik.de/html/forum/thwb/showtopic.php?threadid=11373 Da möchte Jemand den DDR LC80 als Platine neu auflegen und hat das zur Diskussion gestellt. der LC80 ist ein Einplatinenrechner aka Mikroprofessor o.Ä. mit 7-Seg Anzeige und Hexa Tastatur. Um meinem Sohn evtl. was Sinnvolles beibringen zu können würde ich so ein Teil evtl. bauen wollen, vielleicht gibts hier noch mehr Interessenten die die Platinenkosten drücken helfen oder Vorschläge haben. Ich bin nicht der Threadersteller da, nur interessiert.. Gruß, Holm
Axel Schwenke schrieb: >> Und wozu brauche ich diese verdammten ' Register im Z80? > > Wenn du den zweiten Registersatz nicht brauchst, dann benutze ihn halt > nicht. Andere freuen sich, daß sie ein paar extra-Register haben aber du > maulst nur rum. Damit kann man prima Kleinstprogramme bauen, ohne auch nur ein Byte RAM extern zu brauchen. Ich hab mal ein Miniboard mit Z80 gemacht, indem dann die beiden obersten Adressleitungen Output Ports waren, Input lief über einen simplen 74244. Mit Oszillator und EPROM waren das dann 4 integrierte Schaltkreise.
Matthias schrieb: > @Winfried was für ein Atari ist das ? 800XL ? 130XE mit 800XE Platine aber ein erweiterter 800XL ist auch noch hier ;) Die 130er Platine mit 1 MB RAM hat meine EX auf dem Gewissen. Silberleitlack hineingegossen als Frustkompensation. Sehr effizient gewesen die Platine war nicht zu retten.:( Also nie die OW unterschätzen ;)
:
Bearbeitet durch User
Holm Tiffe schrieb: > Ich möchte im Zusammenhang mit Retro mal auf einen Thread An die Freunde des 8bit-Retrocomputing: Schaut auch mal hier ins Nachbar-Forum: Beitrag "8bit-Computing mit FPGA"
Ja, KC87 auf FPGA. Das ist allerdings genau das, was ich nicht will. Man kann sich den FPGA nämlich dann auch ganz kneifen und das Problem mit JKCEMU abwickeln. Gruß, Holm
Holm Tiffe schrieb: > Ich möchte im Zusammenhang mit Retro mal auf einen Thread im Robotron > Forum aufmerksam machen: > http://www.robotrontechnik.de/html/forum/thwb/showtopic.php?threadid=11373 Danke für den Hinweis! Der derzeitige Preis geht doch. Vor einem Jahr hab ich eine leere Z-1013 Platine in der Bucht angeboten und die haben mir freiwillig 40 EUR dafür überlassen.
Holm Tiffe schrieb: > Ja, KC87 auf FPGA. > Das ist allerdings genau das, was ich nicht will. Man kann sich den FPGA > nämlich dann auch ganz kneifen und das Problem mit JKCEMU abwickeln. Falls sich das auf den vorherigen Beitrag von mir bezieht: Eine FPGA-Realisierung hat mit Software-Emulation rein gar nichts zu tun. Im FPGA werden alle Gatter und Flipflops des Zielsystems eins zu eins realisiert.
Wegen 680x0 und Propeller... man kann es auch in einem FPGA realisieren... Aber mindestens 30k LE verdenken gebraucht. Schaltungen sind verfügbar wenn jemand es möchte. Viel Code habe ich leider nicht geschrieben, auch verfügbar. Die Platinen waren nicht genau was ich wollte. Jetzt versuche ich mit RISCV und FPGAs.
O.T. >Axel Schwenke schrieb: >> Schnecken dressieren. >Davon kann ich nur abraten! Wenn du da nicht die ganze Zeit aufpasst wie >ein Schießhund, dann brechen die aus. Ein winziger Moment nachlassender >Aufmerksamkeit und die sind über alle Berge auf und davon, die erwischt >du nie wieder. ;-) Als mir neulich eine Weinbergschneck abgehauen war, hatte ich sie ruck-zuck eingefangen: Ein Steinpilz war vor ihr aus dem Boden geschossen und hatte den Fluchtweg verstellt.
Schneckenzüchter schrieb: > Als mir neulich eine Weinbergschneck abgehauen war, hatte ich sie > ruck-zuck eingefangen: Ein Steinpilz war vor ihr aus dem Boden > geschossen und hatte den Fluchtweg verstellt. Glück gehabt! ;-)
heute unangemeldet schrieb: > Holm Tiffe schrieb: >> Ja, KC87 auf FPGA. >> Das ist allerdings genau das, was ich nicht will. Man kann sich den FPGA >> nämlich dann auch ganz kneifen und das Problem mit JKCEMU abwickeln. > > Falls sich das auf den vorherigen Beitrag von mir bezieht: > Eine FPGA-Realisierung hat mit Software-Emulation rein gar > nichts zu tun. Im FPGA werden alle Gatter und Flipflops > des Zielsystems eins zu eins realisiert. ...das halte ich zwar im konkreten Falle so wie Du es schreibst für ein Gerücht, aber ja, ich weiß was ein FPGA ist und was es tut und nein, ich schrieb schon, so Etwas will ich gerade nicht. Eine FPGA Platine sieht genauso aus wie ein Handy von innen und tut irgend Etwas, das kann ich einem 9 Jährigen weiß Gott nicht zum lernen vorsetzen. Es ist dann für mich einfacher auch das FPGA zu emluieren, jetzt verstanden? BTW: mir ist klar das man hier als Gast schreiben kann und sich nennen kann wie man will, aber muß das so bescheuert sein? Kannst Du Dir nicht wenigstens einen Tarn-Vornamen einfallen lassen? Gruß, Holm
Georg G. schrieb: > Kannst gern ein Muster von mir bekommen. Allerdings für einen "normalen" > Assembler (M80 kompatibel, den kannst du mit Doku auch bekommen), > eventuell will der mit dem SDCC gelieferte nicht. Hi, kannst Du mir das hier mal posten? Danke! Gruss, Christian
Hi, nur mal so als Info für jene, die vielleicht auch an sowas Spass haben. Der SDCC Compiler ist in seiner Version 3.3.0 relativ fehlerfrei, erzeugt aber doch umständlicheren Code als man in Asm schreibt. Klar, ist eben ein Baukasten. Mit Z80 Interrups kann er nichts anfangen. Die crt0.s muss unbedingt angepasst werden, die mitgelieferte erzeugt nicht lauffähigen Code und enthält Zeugs, was niemand braucht, löscht man es läuft es nämlich alles. Ich habe Stunden gebraucht das heraus zu finden. Aufpassen muss man allerdings, dass die Debian Repos nur bis zur Version 3.0.0 reichen von 2012 und da sind noch eine Menge Bugs drin bzw passt die Aneitungen einfach nicht zu dem Compiler da zb auch im ASZ80 Assembler einiges geändert wurde. Am besten zieht man sich den Source Code hier runter da immer die aktuellen Snap Shots vorhanden sind http://sdcc.sourceforge.net/snap.php und kompiliert sich das Ding selbst, auf meinem Cubie Board, wo ich die Z80 Geschichte mache sind das gefühlte 20 Pakete Nachinstallation (gputils, libboost-system-tools usw) da ./configure ständig meckert. Nach ca 2 Stunden ist das Cubie Board mit dem Kompilieren auch durch. Von den Libs ist der SDCC soweit brauchbar,l auch ein malloc ist vorhanden, allerdings ist die Heap Grosse auf 1kb gefixt und muss in einem Script erst angepasst werden, was tief versteckt im /usr/sdcc Verzeichnis liegt. Vermeiden sollte man tunlichst printf, vprintf und rand Funktionen zu verwenden, auch keine math.h, da allein rand 2kb Speicher frisst und niemand weiss warum. printf sind fast 3kb.
Christian J. schrieb: > nur mal so als Info für jene, die vielleicht auch an sowas Spass haben. > Der SDCC Compiler ist in seiner Version 3.3.0 relativ fehlerfrei, > erzeugt aber doch umständlicheren Code als man in Asm schreibt Man kann noch etwas an den Dingen schrauben, so winzig ist das Manual mit der Beschreibung aller Optionen nun auch wieder nicht, mit der Zeit bekommt man so langsam ein Gefühl dafür. Zwar verwende ich den SDCC für 8051, nicht Z80. Letztens erzeugte ich damit auch Debug-Code für ein SiLabs-Board, geht auch einwandfrei. So habe ich auch für ein modernes neueres Board einen unlimitierten Compiler fürs Hobby. Die Profi-Tools sind ja preislich für mich unerschwinglich, kleines Hobby eben. Jedenfalls ist er unlimitiert, kann die ganzen für den 8051 möglichen 64k Codegröße nutzen, womöglich sogar noch Vielfache davon in Banking, und hat diesbezüglich keine Fallstricke. Allerdings benutzt der SDCC einen 80C517 wie einen simplen 8051. Mit den schönen Peripherals wie Multiple Datapointer oder MDU kann er nichts anfangen, das muß man sich selbst in die Libraries und Funktionen hinein stricken, z.B. in memcpy(). Es ist halt kein teueres Profi-Tool, dafür kost er aber nix. Das Registerfile 80C517.h aus dem SDCC war auch eine mittlere Baustelle. Dort standen Register drin, die der 80C517 gar nicht hat. Andererseits fehlten wiederum andere. Das war auch einen Tag Anpassung, nur das H-File alleine. Ein Softie von Sourceforge hat bei sowas bestimmt einen mittleren Anfall bekommen und für eine simple Liste zu erstellen keinen Bock gehabt. Kann ich irgendwie sogar ein wenig verstehen, das ist wie Doku schreiben, Strafarbeit. > Vermeiden sollte man tunlichst printf Willst du denn Zahlenumrechnungen wirklich von Hand machen, also z.B. Mehrbyte ADD, SUB, MUL, DIV, BIN-BCD, in Assembler? Aber es geht auch. In Zeiten, als noch keine C-Compiler und kein Internet verfügbar waren, gewöhnte ich mich auch an sowas. Ein 80535-Board mit nur 2k ROM mußte ich gezwungenermaßen in ASM programmieren. Es kam sogar dort noch auf jedes freie Byte am Ende an. Das Board konstruierte eine Semestergruppe mit seinem Prof. mal gemeinsam, wobei der Prof. aus der 8048-Ära stammte. Daher wohl das 2k-EPROM, denn es gab zur Bauzeit ca. 1990 auch schon 32k-EPROM, wenn nicht sogar 1 MByte. Ich lese gerade, daß es den SDCC jetzt in 3.3.0 gibt, habe noch 3.2.0. So, ab heute gehts aber an mein neues PICkit 3 Debug Express. Es liegt noch verpackt vor mir. Dabei ist ein einfachstes Board mit weitgehend nur einem PIC18F45K20 drauf, einer frei bestückbaren Experimentierfläche, und raus geführten Pins, dazu bestellte ich noch ein paar PIC18F26K20 DIL28 fürs Steckbrett mit. Das ist fast der gleiche wie auf dem Board, nur eben weniger Pins, kein Flat Pack, aber mit doppelt großem RAM und Flash. Mal sehen, ob ich daran Spaß bekomme. Sie stellen mein Intel-Gedönse mit 80xx performancemäßig auch etwas in den Schatten. Die ERRATA-Liste beeindruckte mich etwas, aber mal sehen, vielleicht ist das halb so wild wie es aus sieht.
Elektrobrazzzler schrieb: > Ich lese gerade, daß es den SDCC jetzt in 3.3.0 gibt, habe noch 3.2.0. Die neueste Version ist 3.4.1. vom 18.10.2014. Habe die gestern als Source durchkompiliert. 80535 war bei mir Studium, hatte etliche davon. Alles schon damals mit Keil in C.
Mit dem PIC18F45K20 habe ich ein Industriedesign gemacht, 2 Stück, 2 Kanalig. Mit CCS als Compiler. Er funktioniert wie jeder andere Controller auch, da es bei C sowieso egal ist welchen man nimmt. Ich arbeite mit PIC seit gut 18 Jahren, seit der erste herauskam. Damals nch mit dem völlig fehlerhaften Bytecraft Compiler, seit 1997 mit CCS. Nur musste ich es vermeiden Libs zu nehmen, die die Peripherie einbetten, da der TÜV den Code zeritifzieren musste. Den CCS kann man sich "besorgen" wenn man weiss wo man suchen muss. Es ist ein hochwertiger Compiler, hat aber leider keinen Linker. Es darf nur ein File geben, man muss alles andere mit Include einbinden und darauf achten, dass man für jede Funktion Prototypen in main.h definiert. Der schönste Controller, den ich bisher hatte mit den meisten Features und Ressourcen war der ARM7, LPC2368 mit GCC Compiler. Allein 40kb Ram onchip, 512kb Flash, Batterieram auch noch, USB Ram 16kb usw. Man kann das Programm im RAM entwickeln wenn es nicht größer als 32kb wird und erst dann flashen, da er Code aus dem Ram aus führen kann. Bootloader, Startup Code usw., macht alles die Rowley IDE, da muss man sich nicht drum kümmern. Heute erzeugt die auch den Code für den Clock, man stellt nur ein was man haben will und die bindet das mit ein. Allerdings eben 32 Bit und nicht mehr so einfach zu verstehen. SD anbinden bin ich gescheitert und musste fertigen Code nehmen, da ich die Einarbeitung in das SD Protokoll vermeiden wollte, sondern nur Funktionen nutzen. Allein die Clock und PLL einzustellen, sowie den APB Bustakt sind viele Zeilen Code. Aber mit 80Mhz rennt der auch.
Christian J. schrieb: > annst Du mir das hier mal posten? Dann mal eine Jugendsünde. Das Ding läuft in einem Flash und kann sich selbst aktualisieren. Es gibt auch noch Versionen mit Unterstützung für 1791 Floppy Controller oder WD1002 Harddisk Board. Als Assembler-Linker-Locater-Librarian verwende ich eine M80-L80-Lib80 kompatible Version von M. Röhner. Wenn es C sein soll, ist es eine Variante von QC. Diese Werkzeuge sind nur für nicht kommerzielle Anwendungen frei.
Danke, sieht doch schön aus und ist gut dokumentiert. Werde sicher einiges da rauskopieren. Wie man bei Assembler von "struktrierter Programmierung" sprechen kann wird mir allerdings ewig ein Rätsel bleiben, für mich bleibt das ein Aneinander klatschen von Routinen ohne gescheite Parameter Übergabe und Techniken wie Variablen Overlaying sind da ganz abhanden gekommen.
Eine Sünde finde ich nicht auf anhieb, wirkt recht aufgerämt auf mich. Namaste
Christian J. schrieb: > ewig ein Rätsel bleiben Du bist eindeutig etwa 30 Jahre zu spät geboren. :-) (Wobei früher nicht alles schlechter war. Nur so ein Beispiel: Wordmaster konnte man 10-Finger-blind schreiben. Und Rechtschreib Korrektur und Drucken im Hintergrund konnte der auch schon.)
Georg G. schrieb: > Du bist eindeutig etwa 30 Jahre zu spät geboren. :-) Mag sein, gewissen Dingen kann ich ja noch einen gewissen Charme abgewinnen, wie in dem Beispiel das Laden von Ports mit Konfigurationdaten. Zumindest wenn man schn mitzählt wo der Pointer hochgezählt wird bzw runtergezählt. Trotzdem keine Ahnung wie man einen Befehl OUTI ausdenken kann, oder OTIR der wahrscheinlich genau dafür gemacht wurde. Typisch CISC Maschine. Nen freien, grafisch zu bedienenden (ja, ich will das!) Simulator habe ich immmer noch nicht gefunden, werde wohl die 25 Euro für einen ausgeben, der recht nett gemacht ist. Spasseshalber habe ich mir mal den Quellcode eines 4 Gewinnt Spieles gegen den Computer besorgt. Das kann man dann auch so umprogrammieren, dass er ständig gegen sich selbst spielt. Kompiliert bisher einwandfrei durch, auch wenn rand etc viel Speicher braucht. Bin mal gespannt wie das Gewinnverhältnis nach ein paar Stunden sein wird, ob Computergegner 1 oder 2 mehr Spiele gewinnt. Heute abend mal an die STI rangehen und die verdrahten, damit endlich auf dem PC was zu sehen ist. Erinnert mich so ein wenig an "Wargames" :-) Na hauptsache der Z80 ist beschäftigt und sei es nur mit sich selbst :-)
Nochmal ein Special für A.K.: Ich programmiere grad Code für den MK3801 und bin da noch etws unsicher. Weiter oben siehst du einen Auszug aus einer Appnote, die ich übersetzt habe. Müssen die Uart Eingänge RC (Receiver Clock Input) und TC (Transmitter Clock Input) alle beide an den Ausgang des Timers D angebunden werden, der dann die Baudrate erzeugt? Async übertragung wird durch Sampling bewerkstelligt, d.h. wird hier mit 1:16 abgetastet? Ich verstehe auch nicht ganz wieso die die PIO Ports im DDR Register auf 0x64 geetzt haben? Die haben doch mit der UART nix zu tun, oder? Was hat dieser Codefetzen da verloren? PS:L Der MK3801 schraubt sich unglaubliche 180ma rein! Mit der NMOS CPU frisst die Karre jetzt schon 380mA auf 100km !!!
1 | // STI konfigurieren für Uart Ausgabe |
2 | STI_UCR = 0x88; // = 10001000 UART Control Register 8N1, DIV16 |
3 | STI_RSR = 0x01; // RX Status - Enable RX |
4 | STI_RSR = 0x01; // TX Status - TX High, TX enabled |
5 | STI_PVR = STI_DDR; // Zeiger PVR auf indirect 6 (DDR) |
6 | STI_IDR = 0x64; // ???? Was soll das? |
7 | STI_PVR = STI_TDDR; // Zeiger PVR auf Timer D Data |
8 | STI_IDR = 0x03; // Timer D Zeitkonstante |
9 | STI_PVR = STI_TCDCR; // Zeiger auf Timer C,D Control Register |
10 | STI_IDR = 0x89; // Timer D DIV 4, C = Stop |
Defintionen:
1 | 0x00 IDR Indirect Data Register |
2 | 0x01 GPIP Purpose I/O Data Register |
3 | 0x02 IPRB lnterrupt Pending Register B |
4 | 0x03 IPRA Interrupt Pending Register A . |
5 | 0x04 ISRB Interrupt -Service Register B |
6 | 0x05 ISRA Interrupt in-Service Register A |
7 | 0x06 IMRB lnterrupt Mask Register B |
8 | 0x07 IMRA Interrupt Mask Register A |
9 | 0x08 PVR Pointer,/Vector Register |
10 | 0x09 TABCR Timers A and B Control Register |
11 | 0x0A TBDR Timer B Data Register |
12 | 0x0B TADR Timer A Data Register |
13 | 0x0C UCR USART Control Register |
14 | 0x0D RSR Receiver Status Register |
15 | 0x0E TSR Transmitter Status Register |
16 | 0x0F UDR USART Data Register |
17 | |
18 | // Indirekt adressbierbare Register des STI |
19 | |
20 | #define STI_SCR 0 // Sync Character Register |
21 | #define STI_TDDR 1 // Timer D Data Register |
22 | #define STI_TCDR 2 // Timer C Data Register |
23 | #define STI_AER 3 // Active Edge Register |
24 | #define STI_IERB 4 // Interrupt Enable Register B |
25 | #define STI_IERA 5 // Interrupt Enable Register A |
26 | #define STI_DDR 6 // Data Direction Register |
27 | #define STI_TCDCR 7 // Timer C und D Control Register |
Christian J. schrieb: > Müssen die Uart Eingänge RC (Receiver Clock Input) und TC (Transmitter > Clock Input) alle beide an den Ausgang des Timers D angebunden werden, > der dann die Baudrate erzeugt? Kannst auch einen anderen Timer verwenden, aber ohne RC/TC UART Takt wird es nichts mit der UART. > Async übertragung wird durch Sampling > bewerkstelligt, d.h. wird hier mit 1:16 abgetastet? Korrekt. Das ist bei fast allen UARTs so. > PS:L Der MK3801 schraubt sich unglaubliche 180ma rein! Mit der NMOS CPU > frisst die Karre jetzt schon 380mA auf 100km !!! Tja nun, NMOS frisst Dauerstrom. Da spürt man, wo der Strom landet. > STI_PVR = STI_DDR; // Zeiger PVR auf indirect 6 (DDR) > STI_IDR = 0x64; // ???? Was soll das? Bei mit steht da 0xA7, wegen /BOOT,5",FDC-TC,/STROBE,RTC-DATA. Soll heissen: Das hängt davon ab, was an den Pins dran hängt. Da der gezeigte Code wohl nicht von dir ist, hängt das von dem System ab, wovon du den Code kopiert hast. Der Anhang sieht eher nach deiner Platine als nach einer Appnote aus. Und deine UART Taktverdrahtung solltest du mal überprüfen, denn so wie gezeigt wird das nix.
:
Bearbeitet durch User
A. K. schrieb: > Der Anhang sieht eher nach deiner Platine als nach einer Appnote aus. > Und deine UART Taktverdrahtung solltest du mal überprüfen, denn so wie > gezeigt wird das nix. Yep ... Pindreher. Im Schaltplan falsch, am Board aber richtig. Die Appnote sollte eigentlich nur die UART behandeln, da denkt man sich ja nicht, dass die die PIO noch für was anderes brauchen. Hätte ja sein können, da manche Pins noch extra auf Output geschaltet werden müssen. Ist ja oft dass keinen Override gibt, wenn Pins mehrere Funktionen haben.
Wozu dient eigentlich R26? Falls der für NMI ist: Der INT Ausgang vom STI ist Open Drain, der INT Pin braucht also auch einen.
A. K. schrieb: > Wozu dient eigentlich R26? Falls der für NMI ist: Der INT Ausgang vom > STI ist Open Drain, der INT Pin braucht also auch einen. In dem Board ist da auch einer (smd), nur im Schaltplan leider vergessen :-( Habe alle Ints an 10K gehängt. Ab 3 Drähte an einem Lötpin wird es eng.... Datenbus ist ja überall dran. Den MK3801 gibt es nicht zufällig als CMOS..... 37 Grad hat der laut Messung.
Christian J. schrieb: > 37 Grad hat der laut Messung. Na und? Bei 900mW hätte ich etwas mehr erwartet. Gemessen oder aus dem Datasheet abgeschrieben?
:
Bearbeitet durch User
Mit der Infrarot Pistole gemessen. Inzwischen sind es 43 Grad. Es gab noch einen 68...irgendwas 901 von Thompson als CMOS, der ein aufgebohrter STI ist mit 48 Pins aber dann eben kein 2,54er Raster mehr. Der Stromverbrauch nervt doch etwas. Die ersten 7400 die ich noch hier habe fressen auch 50mA pro Stück. Die Suche bringt auch nicht mehr hervor, außer diesen Thread der inzwischen indiziert wurde. So, mir tun die Augen weh trotz Lupenlampe unter der ich das verdrahte. Zeit aufzuhören....
A. K. schrieb: > Christian J. schrieb: >> Mit der Infrarot Pistole gemessen. > > Ich dachte eher an den Strom. Also, A.K. .... so schwer ist es ja nicht an der Anzeige eines PS den Strom abzulesen vor und nachdem man den Chip reingesteckt hat. Und der ist 180ma höher als vorher.
so als inspiration :-) Nen OS für den Z80 mit Multitasking, Windows, Task Manager etc :-)
sorry ich das hier mit meiner Begeisterung zumülle, aber das ist einfach zu geil! Mit Videoplayer und einem VDP9990 graphic chip für z80 https://www.youtube.com/watch?v=a6v2EFAhiQA
@A.K. Der MK3801 spielt einwandfrei. Und nochwas ..pssst.... : Die Timer laufen rückwärts..igitt! Und bei 0 heben die den Pin hoch und einen Takt später wieder runter, laden sich wieder mit ihrem Reload Wert. PWM geht auch. Aber nicht weitersagen! :-)
Wieso igitt? So kann man den Teiler direkt eintragen, wie schon aus den gezeigten Initialisierungswerten hervorging.
A. K. schrieb: > Wieso igitt? So kann man den Teiler direkt eintragen, wie schon aus den > gezeigten Initialisierungswerten hervorging. Das war ein kleiner ironischer Witz...... Muss nur noch rausfinden, was der sdcc anstellt, wenn man read/modify/write Operationen auf den Ports auführt. Ob da der richtige Code bei rauskommt. Nein, erzeugt einen "fatal internal compiler error" if (stat==TRUE) // Bit ein STI_GPIP |= (1<<bitnr); I/O können nur geladen, verändert und zurück geschrieben werden.
Kurz, da ich derzeit immer noch "blind" programmiere, bis die Leitung zum PC endlich steht: Interrupt im MK3081 aber auch generell: Es gibt für die UART Interrupt ENABLE Register Interrupt MASK Register Interrupt PENDING Register Ist das richtig: enable = 0, mask = 0; => es wird weder ein Hardwarevorgang ausgelöst, noch wird das pending bit gesetzt, wenn ein Zeichen kommt. enable = 1, mask = 0; => es wird pending gesetzt und kann gepollt werden, aber es wird kein Hardware Int ausgelöst, weil der Int "ausmaskiert" ist. pending muss manuell gelöscht werden, ggf. durch auslesen des registers? enable = 1, mask = 1; => pending wird gesetzt, hardware int wird ausgelöst, vektor geht auf den bus, pending wird automatisch gelöscht, sobald die Z80 den Vektor entgegen nahm und IOREQ und M1 gezogen hat.
Und bevor es ins Bett geht (und der Thread versickert) noch eine Sache: Interrupts und Timer A testen. Hardware und Software. Zunächst Mode 1, da einfacher. Test 1: INT Pin und Software 1. 0x38 zeigt auf Routine, die LEDs durchzählt 2. im 1 ei im Hauptprogramm 3. Stück Draht an Pin 16 (INT) und Masse anticken => LEDs zählen hoch. INT ist pegelgetriggert wie ich sehe Test 2: Timer A testen 1. Timer A konfigurieren 2. Hauptprogramm schleife zeigt Timer A Data auf LEDs an (mit delay) => Timer A laeuft und reloaded richtig, Bits schnubbeln auf die LEDs Test 3: Timer A Interrupts bei Nulldurchgang sollen Int Mode 1 (0x38) triggern 1. Timer A enable Bit = 1 2. Timer A Mask Bit = 1 3. Timer A Reload Wert 0xff und DIV 200, damit man was sieht Läuft nicht! Pin INT wird nicht von Timer A Int über INT Pin getoggelt. Test mit Drahtstück klappt aber.
Christian J. schrieb: > Interrupt ENABLE Register > Interrupt MASK Register > Interrupt PENDING Register Und optional das "Interrupt in-Service Register". Relevant wenn man verschachtelte Interrupts zulassen will. > Ist das richtig: Ja. > manuell gelöscht werden, ggf. durch auslesen des registers? Steht doch in der Doku. 0 schreiben löscht, 1 unverändert.
Ich kriege leider trotzem keine kontinuierliche INT Auslösung. Nur mit dem Draht, also kommt vom MK3801 nichts. Was fehlt denn jetzt noch, damit der Timer Überlauf eben dauerhaft Ints auslöst? Zumindest Mode 1 schonmal, Mode 2 wird dann sicher auch funktionieren. PS: Erledigt. Man sollte nicht eine Hardware in Main und im Int ansprechen, das gibt Murks.
Und auch das Thema ist damit erledigt ..... puhhh. Blöd ist der Compiler ja nicht: aus while ((STI_TSR & 0x80) == 0); // Warte bis Buffer frei... wird: 00101$: in a,(_STI_TSR) rlca jr NC,00101$
Christian J. schrieb: > Blöd ist der Compiler ja nicht: Nimm dir mal einen alten 4MHz Z80 CP/M Kasten (fairerweise mit Harddisk) und einen modernen PC. Und dann nimm dir Wordstar und Word und lass eine Sekretärin, die richtig Schreibmaschine kann nacheinander auf beide Kisten los. Das Ergebnis wird dich verblüffen. Damals (tm) wurde noch mit Hirn und Nachdenken programmiert. Es gab kein Klicki Bunti Mausgeschiebe. Aber die Ergebnisse konnten sich sehen lassen.
Hallo, der Thread ist inzwischen abgesoffen und hat sich auf einen Nebenschauplatz verlegt, wo internste Details des sdcc Compiler geklärt werden mussten, weil der damit nicht so recht klarkommt globale Variablen zu intitialisieren. Dazu musste dieses Loch erst bis zur Sohle beschritten werden und ein Programmierer des sdcc leistete dazu wertvolle Hilfe,den ich angeschrieben hatte. Beitrag "Re: Mehrdimensionale char-arrays" Es funktioniert bisher alles, auch die Mode 2 Ints aber dieser Mechanismus ist ja fix installiert, was soll da also schief gehen. Am Monitor bin ich dran, weiss noch nicth genau wieviel ich im Int erledigen soll, schöne Konstrukte mit FIFO Buffer usw oder ob alles in einer Polling Schleife? Vielleicht noch Basic Interpreter dabei, Hex Dump usw. Wird sich zeigen. Der Z80 sendet und empfängt Zeichen. Damit wäre dieser Thread also am Ende und wenn jemand auf die gleiche Idee kommt und den sdcc verwendet, so sind da alle Probleme bisher gelöst worden. Die Hardware ist abgetrennt vom User Code, ein HAL liegt bei mir jetzt dazwischen. Zumindest bis auf den Umstand, dass man keine static Variablen in Ints verwenden kann, die nicht 0 sind. Das kann er (noch) nicht. Jo, danke an alle hier und die Geduld.....Einarbeitung war erfolgreich. Und Asm echt nur da wo unbedingt nötig. Ich mag kein Asm und auf Zeit kommt es eh nicht an. Gruss Christian
retrogerecht 1.FIFO gab es zu Z80 nicht manlegte ringbuffer mit overflowflag an. 2.Static erledigt man in einem eigen Variablenbereich welcher der Funktion zugeordnet ist. Also nicht im variablenbereich von main liegt und welcher so für den rest des Programms invisible bleibt. wärend Global entweder von main angelegte werden oder durch die installierende Funktion an den Compiler angemeldet werden damit er sie visible generiert. lokal erledigt mann gern auf dem Stack, mus ihn aber schön aufräumen. Also nach dem poppen alles sauber aufwischen. ;) Namaste
Sehr cool! Vielleicht kannst du ja für die Nachwelt dein Endergebnis in Hardware und Software hier posten..
Hallo, stellt sich dennoch die ein oder andere Frage, da ich mich mit Protokollen von Schnittstellen nicht so genau aus kenne. Wenn vom PC ein Binärdatenstrom über das USB Interface in die Uart reinkommt, wie zeigt dann der PC das Datenende an? Ich habe nur zwei Leitungen, RX und TX, kein Hardware Flow Control, kein Handshake. Daten die kommen müssen entgegen genommen werden da sie unentwegt weiterlaufen. Kann ich das Datenende nur über Timeout erkennen? Denn die Vereinbarung eines speziellen Zeichens geht ja im Binärcode nicht. Aktuell laufen die Zeichen über den SIO Interrupt rein und füllen einen Ringpuffer, der 3/4 "voll" meldet hofft hofft dass das Hauptprogramm sich um ihn kümmert bevor Daten verworfen werden.
Wenn du kein spezielles Übertragungsprotokoll gewählt hast, hilft nur Timeout, mit allen Risiken und Nebenwirkungen. Eben deshalb wurde so Dinge wie Z-Modem oder Kermit entwickelt. Flowcontrol hilft dir da auch nicht weiter.
Hallo, grundsätzlich kann der Empfänger antworten aber ich will PC seitig keinen Aufwand treiben und die Binärdaten nur mit cat daten.bin > /ttyUSB0 absenden nachdem die Schnittstelle vorher eingestellt wurde. Dazu muss ein Shell Script reichen. Ein Protokoll als Frame fällt daher auch flach und ist nicht nötig, ZModem ist ja für Überseeübertragungen konzipiert und mir noch aus FidoNet Zeiten bekannt damals. 9600 sind auch "zum mitschreiben". Ok, also Timeout Verfahren, zwei rotiernde Zeiger in einem Array, einer der schreibt, der andere der die Leseposition nachzieht und aufpassen dass der Z80 keine Zeichen verliert da es keine Pausen gibt... schauen wir mal...
Du denkst viel zu kompliziert. Feste Länge definieren, oder vorneweg senden. Das Board erwartet 4K, der Sender sendet 4KB (als Beispiel). Auch dein FIFO ist erst einmal unnötig. Einfacher gehts nicht. Auf die Art kannst du dann beispielsweise einen Hex-oder X/Y/Z-Modem/Kermit Loader entwickeln und wenn er läuft diesen einbrennen. Oder was auch immer. Weshalb sollte da was verloren gehen? Hast du hungrige Bitmäuse im Lab?
:
Bearbeitet durch User
Christian J. schrieb: > Wenn vom PC ein Binärdatenstrom über das USB Interface in die Uart > reinkommt, wie zeigt dann der PC das Datenende an? A. K. schrieb: > Was du brauchst ist ein Binärimage des Codes, von beispielsweise exakt > 8kB Länge. Dann die Z80 resetten, damit der Bootloader aktiv wird, und: beispielsweise exakt 8kB Länge beispielsweise exakt 8kB Länge beispielsweise exakt 8kB Länge beispielsweise exakt 8kB Länge Es können aber beispielsweise auch exakt 4KB Länge sein. Edit zu spät
:
Bearbeitet durch User
Hi, der Compiler spuckt leider nur variable Länge aus und der Binärconverter auch. Muss mal schauen ob sich das ändern lässt. Timeout ist mir sympathischer, schon damit er sich nicht aufhängt. Stelle grad fest, dass der PC 7-bit Daten sendet. Habe mal einiges an den Z80 geschickt mit cat testdatei.bin > /dev/ttyUSB0 und stelle es auf der LED Zeile dar, LED Nr 7 bleibt dunkel, die anderen flackern im Bytetakt. 9600... es dauert eben :-) Muss mal schauen wie ich stty irgendwie umstelle, dass es Binärdaten sendet, nicht ganz eays, die Hilfe ist schon erschlagend.
Und jetzt habe ich mir auc noch /dev/ttyUSB0 "gelockt" mit screen und außer einem Reboot des PC weiss ich auch nicht wie ich das unlocken kann.
Christian J. schrieb: > der Compiler spuckt leider nur variable Länge aus und der Binärconverter > auch. man objcopy man dd
Christian J. schrieb: > der Compiler spuckt leider nur variable Länge aus und der Binärconverter > auch. Muss mal schauen ob sich das ändern lässt. Und dein PC hat irgendwie jede Fähigkeit verloren, ein Binärfile auf feste Länge zu erweitern? Sowas ist doch schneller programmiert als hier ins Forum getippt. Aber geht auch ohne: dd if=main.bin of=main.4kb ibs=4k conv=sync
Christian J. schrieb: > Und jetzt habe ich mir auc noch /dev/ttyUSB0 "gelockt" mit screen und > außer einem Reboot des PC weiss ich auch nicht wie ich das unlocken > kann. Hast du Angst, dass er beim Reboot nicht mehr hochkommt? Wobei man ein TTY mitunter mit "stty sane < /dev/ttyXXX" wieder sauber kriegt. Wäre aber sinnvoll, im stty mit deinem USB zu reden, nicht mit der X-Konsole, in der du das eintippst.
Der Compiler erzeugt keine object files :-( dd ist sehr praktisch da mit bs = 8192 ja die Blockgröße gesetzt werden kann. Aber egal, 8 Bit sind auch, weil... nun Ascii Textdateien sind nunmal 7 Bit codiert. So ein 200kb Bild braucht seine Zeit aber der Z80 kommt gut mit, bisher keine Zeichen verloren. Etwas anders wird schon schwieriger.... denn ein Programm im RAM ab 0x2000, dem fehlen die ganze Zeropage und da liegen bekanntlich einige Vektoren. Und ich kann ROM nicht nach RAM überblenden, da das darunter liegt. D.h. dass zb Int Mode 2 gar nicht möglich ist, denn der würde auf das ROM zugreifen und die Vektoren zeigen irgendwo hin aber nicht auf die Routinen im RAm da die jedesmal woanders liegen. Daran habe ich leider nicht gedacht, dass alles aus der Zeropage jetzt unerreichbar ist. Auch die Software Interrupts RST n, NMI sowieso, alle Timer Interrupts usw. Der Compiler lässt es leider nicht zu, dass man Routinen fixe Adressen verpasst, der will da sehr frei wählen wo jedes Segment liegt.
RAMDISK Bankswitching Mapping konnte der Z80 nicht auch Blöcke im RAM per ASM Befehl verschieben? .... ;)
:
Bearbeitet durch User
Christian J. schrieb: > Der Compiler erzeugt keine object files :-( Natürlich erzeugt der Compiler object files. Auch wenn sie .rel statt .o heißen mögen. Aber das spielt ja hier überhaupt keine Rolle. Falls Du den Linker Hex-Files erzeugen läßt (statt bin), könntest Du die mit objcopy in Binärfiles konvertieren. > dd ist sehr praktisch da > mit bs = 8192 ja die Blockgröße gesetzt werden kann. Die Blockgröße spielt hier überhaupt keine Rolle.
Leo C. schrieb: > Die Blockgröße spielt hier überhaupt keine Rolle. ibs !!!!!! Ok, Problem gelöst, braucht nicht mehr diskutiert zu werden. Alles schon fix und foxi in einem Script verarbeitet. Compilieren, Hexen, Binären, umwandeln nach 8192 Bytes usw :-) Das Thema mit den fehlenden Int Möglichkeiten eines Upload Programms wird wohl nicht zu lösen sein.
Christian J. schrieb: > Etwas anders wird schon schwieriger.... denn ein Programm im RAM ab > 0x2000, dem fehlen die ganze Zeropage und da liegen bekanntlich einige > Vektoren. Im IM2 liegen die dort, wo du sie per I Register hinlegst. Dieses Register brennt nicht ab, wenn man es im RAM-Code passend verändert.
Winfried J. schrieb: > RAMDISK > Bankswitching > Mapping > konnte der Z80 nicht auch Blöcke im RAM per ASM Befehl verschieben? > .... > ;) Ja, sogar mit ldir in einem Rutsch, so Power Befehle hat der. Nutze ich zum Initialisieren der Variablenfelder im Startupcode. ; Initialisiere globale Variablen ld bc, #l__INITIALIZER ld a, b or a, c jr Z, weiter ld de, #s__INITIALIZED ld hl, #s__INITIALIZER ldir Geswitched werden kann da nix, das ist fest verdrahtet und inzwischen "unlösbar" in Fädelkämmen. Das RAM liegt unter dem ROM drunter und ist unerreichbar. Da sich bei jedem Kompiliervorgang die Adressen ändern können die Vektoren nicht mehr benutzt werden. Hätte ich das vorher gewusst hätte ich ein Bankswitching eingebaut. Mir fällt nichts ein um das zu umgehen, Programme werden also int-los sein müssen was sehr schade ist, da aktuell der Timer die Hardware bedient und im User Code keine direkten HW Zugriffe mehr nötig sind. >>Dieses Register brennt nicht ab, wenn man es im RAM-Code passend verändert. Auch das nützt nichts! Denn die Adressen sind vielfache von 0x100 im I Register. Denke dass ich einen Compiler nutze wo der Linker diese Arbeit abnimmt diese Tabelle an ihre Zielorte zu leiten und dass er das kann, weil ihm die Zieladressen bekannt sind, da er crt0.rel und mail.rel zu einem verklumpatscht.
1 | ; Tabelle der Mode 2 Int Vektoren auf die Handler Funktionen im C Modul |
2 | ; Reihenfolge beachten !!! Siehe Manual Mostek 3801, Interrupt Tabelle |
3 | .org 0x40 |
4 | .dw (_int_sti_gpi_0) |
5 | .dw (_int_sti_gpi_1) |
6 | .dw (_int_sti_gpi_2) |
7 | .dw (_int_sti_gpi_3) |
8 | .dw (_int_sti_timer_d) |
9 | .dw (_int_sti_timer_c) |
10 | .dw (_int_sti_gpi_4) |
11 | .dw (_int_sti_gpi_5) |
12 | .dw (_int_sti_timer_b) |
13 | .dw (_int_sti_transmit_error) |
14 | .dw (_int_sti_transmit_buffer_empty) |
15 | .dw (_int_sti_receive_error) |
16 | .dw (_int_sti_receive_buffer_full) |
17 | .dw (_int_sti_timer_a) |
18 | .dw (_int_sti_gpi_6) |
19 | .dw (_int_sti_gpi_7) |
A. K. schrieb: > Im IM2 liegen die dort, wo du sie per I Register hinlegst. Dieses > Register brennt nicht ab, wenn man es im RAM-Code passend verändert. Das ist ja gerade die aus allem in der 8-Bit Welt vorher dawesenem herrausstechende Eigenschaft des Interrupt Mode 2. Christian J. schrieb: > D.h. dass zb Int Mode 2 gar nicht möglich ist, denn der würde auf > das ROM zugreifen und die Vektoren zeigen irgendwo hin aber nicht auf > die Routinen im RAm da die jedesmal woanders liegen. Wo die Vektoren hinzeigen bestimmt einzig und allein der Programmierer, und nicht etwa der Compiler oder sonst was.
Leo C. schrieb: > Wo die Vektoren hinzeigen bestimmt einzig und allein der Programmierer, > und nicht etwa der Compiler oder sonst was. Die CPU erwartet sie da, wo das I-Register hinzeigt! Die einzige Möglichkeit die bestünde wäre, das I Register so weit umzubiegen, dass es zb auf 0x2000 zeigt, dort liegt eine künstlich erzeugte Tabelle und der eigentliche Code beginnt erst bei 0x2100. Trotzdem habe ich (noch) keine Ahnung wie ich aus einem laufenden Programm heraus diese Tabelle erzeugen kann, da ich dazu die Position von Routinen ermitteln muss. Ob ein const int (*myvektor) ptr_int_1; myvektor = int_routine_1 funktioniert weiss ich noch nicht. C kann bekanntlich Zeiger auf Funktionen verarbeiten, die zur Kompilationszeit bekannt sind. Habe ich noch nie benutzen müssen sowas. Da ich die ganze Sache aber noch nicht zu Ende gedacht habe mache ich hier keine Schnellschüsse.
Christian J. schrieb: > Trotzdem habe ich (noch) > keine Ahnung wie ich aus einem laufenden Programm heraus diese Tabelle > erzeugen kann, da ich dazu die Position von Routinen ermitteln muss. Dass du einen Zweifrontenkrieg gegen Hardware und Compiler kämpfst, das hast du dir selbst zuzuschreiben. Aber was fürs ROM mit 0x0040 funktioniert, das funktioniert fürs RAM an 0x2040 genauso. Du kannst den RAM Code exakt so bauen wie den ROM Code. Nur eben ab 0x2000 statt 0x0000. Einzig NMIs und die RST-Befehle fallen flach.
:
Bearbeitet durch User
A. K. schrieb: > Dass du einen Zweifrontenkrieg gegen Hardware und Compiler kämpfst, > das hast du dir selbst zuzuschreiben. Da der ganze Apparillo nichts weiter ist als anderen in Kreuzworträsel und keinen praktischen Nutzen hat außer Denksport und Spass am Problemlösen und Gestalten denke ich, dass man das vernachlässigen kann. Du wirst sicher zugeben müssen, dass da Auge der Ästhetik unten stehendes Codebeispiel ohne Augenkrebs zu bekommen anschauen kann. Auf jedenFall sicher besser als eine Tabelle voller Nummern, die per djnz Schleife in die Ports geschrieben werden. Und wenn ich Lust habe kriegt jedes Bit auch noch eine define Zeile.... Welcher Depp ist eigenlich dafür verantwortlich, dass unter Unix und Windows cr/lf und lf als Zeilenende unterschiedlich sind?
1 | void InitHardware() |
2 | { |
3 | // 8255: Mode 0: Port A,B,C Output |
4 | PIO8255_CNTRL = 0x80; //Mode 0: Port A,B,C Output |
5 | PIO8255_PORT_A = 0xff; |
6 | PIO8255_PORT_B = 0; |
7 | PIO8255_PORT_C = 0; |
8 | |
9 | // 7-Segment .... |
10 | SEG7 = 0xff; |
11 | |
12 | // STI konfigurieren für Uart Ausgabe |
13 | STI_UCR = 0x88; // = 10001000 UART Control Register 8N1, DIV16 |
14 | STI_RSR = 0x01; // RX Status - Enable RX |
15 | STI_TSR = 0x05; // TX Status - TX High, TX enabled |
16 | // Timer D... |
17 | STI_PVR = STI_TDDR; // Zeiger PVR auf Timer D Data |
18 | STI_IDR = 0x03; // Timer D Zeitkonstante |
19 | STI_PVR = STI_TCDCR; // Zeiger auf Timer C,D Control Register |
20 | STI_IDR = 0x89; // Timer D DIV 4, C = Stop |
21 | // GPIO..... |
22 | STI_PVR = STI_DDR; // Zeiger PVR auf indirect 6 (DDR) |
23 | STI_IDR = 0xff; // GPIO als Output |
24 | STI_GPIP = 0x00; // GPIO auf Null setzen |
25 | // Timer A = endlos Run |
26 | STI_TADR = 0xff; // Reload Wert Timer A |
27 | STI_TABCR = 0x70; // Timer A DIV 200, 255x200 = maximale Verzögerung |
28 | STI_PVR = STI_IERA; // Timer A /RX Buffer Interrupt einschalten |
29 | STI_IDR = 0x30; |
30 | STI_IMRA = 0x30; // Timer A Interrupt / RX Buffer full unmask |
31 | STI_IPRA = 0x00; //Pending Ints löschen |
32 | |
33 | // Zuletzt Interrupt Vektor für Mode 2 laden |
34 | STI_PVR = 0x40; // Basisadresse der Ints für crt0.s Tabelle setzen |
35 | |
36 | __asm // Mode 2 Interrupt auswählen und Ints einschalten |
37 | im 2 |
38 | ei |
39 | __endasm ; |
40 | |
41 | } |
Christian J. schrieb: > A. K. schrieb: >> Dass du einen Zweifrontenkrieg gegen Hardware und Compiler kämpfst, >> das hast du dir selbst zuzuschreiben. > > Da der ganze Apparillo nichts weiter ist als anderen in Kreuzworträsel > und keinen praktischen Nutzen hat außer Denksport und Spass am > Problemlösen und Gestalten denke ich, dass man das vernachlässigen kann. Du mußt Dir unbedingt mal angewöhnen zuzuhören wenn Dir Jemand was erklärt und nicht einfach immer vernachlässigen. Das rächt sich: Das Problem beim Troubleshooting ist, der Trouble shootes back! > > Du wirst sicher zugeben müssen, dass da Auge der Ästhetik unten > stehendes Codebeispiel ohne Augenkrebs zu bekommen anschauen kann. Auf > jedenFall sicher besser als eine Tabelle voller Nummern, die per djnz > Schleife in die Ports geschrieben werden. Und wenn ich Lust habe kriegt > jedes Bit auch noch eine define Zeile.... > > Welcher Depp ist eigenlich dafür verantwortlich, dass unter Unix und > Windows cr/lf und lf als Zeilenende unterschiedlich sind? > Guckste eventuell mal was eher da war? Ich schätze mal das war die selbe stinkreiche Person die meinte das der "wrong slash" (Tm) irnkwie besser aussieht... Gruß, Holm BTW: Schnittstelle Locked es gibt da ein einfaches Verfahren mit angelegten Lockfiles in einem Directory, die bleiben nach einem Abschuß vielfach stehen. Unter FreeBSD liegen die Standardmäßig unter /var/spool/lock und heißen beispielsweise LCK..cuau3. So ein File enthält die Process ID des lockenden Prozesses. $ cat /var/spool/lock/LCK* 8760 $ $ ps -ax|grep 8760 21337 0 S+ 0:00,00 grep 8760 8760 4 Ss+ 0:28,19 seyon -noemulator -modems /dev/cuau3 -emulator xterm -nodefargs $ Der LOCKPATH ist unter Looser Unix leicht anders, aber ähnlich.
Holm Tiffe schrieb: > Guckste eventuell mal was eher da war? Ich schätze mal das war die selbe > stinkreiche Person die meinte das der "wrong slash" (Tm) irnkwie besser > aussieht... Das kommt aus CP/M, da kann Gates nix für. Der hat bloss ein abgekupfertes CP/M für 8088 aufgekauft. Die Programme in CP/M verwendeten auch schon "/xxx" für Kommandozeilenoptionen, damit war "/" für Pfade weg. Auch die Laufwerksbuchstaben sind aus CP/M.
Holm Tiffe schrieb: > Du mußt Dir unbedingt mal angewöhnen zuzuhören wenn Dir Jemand was > erklärt und nicht einfach immer vernachlässigen. Das rächt sich: > Das Problem beim Troubleshooting ist, der Trouble shootes back! Und Du musst mal vopn dieser Jogi/Schenk-Denke runterkommen, dass andere ihre eigenen Vorstellungen haben und nicht blind das übernehmen, was "alte Hasen" meinen richtig sei sonder evtkl lediglich Nuancen oder Tendenzen übernehmen. Assembler ist für mich Rummgestammel auf Bitniveau mit dem keine komplexen Dinge gescheit zu lösen sind und man verschwendet seine Zeit damit. Das wird sich auch nicht mehr ändern. Dein Wissen ist aber willkommen, vor allem das aus DDR tagen was ich sehr interessant fand. Das mit der /var/loch habe ich mir auch gegoogelt, inzwischen läuft das aber problemlos und ich denke, dass ich in ein paar Tagen soweit bin Uploads zu machen, wenn noch einiges mehr verkabelt ist und vor allem die Dokumentation des Ganzen mal wächst, denn ohne die blicke ich in in einigen Monaten nicht mehr durch. Die Sache mit den Ints ist soweit klar, nur muss ich das noch in die Compiler Directiven einarbeiten und rausfinden, wie ich diese Tabelle erzeuge. Denn inzwischen ist der Huckepack Sockel vom EEPROM doch schon ausgeleiert und es nervt dauernd jede Programmänderung neu zu brennen.
Christian J. schrieb: > Assembler ist für mich Rummgestammel auf Bitniveau > mit dem keine komplexen Dinge gescheit zu lösen sind und man > verschwendet seine Zeit damit. Das wird sich auch nicht mehr ändern. Das ulkige an dieser bereits hinreichend bekannten Grundeinstellung ist freilich, dass du dich trotzdem ausgerechnet in jener Retro-Sphäre bewegst, in der man als Assembler-Analphabet ziemlich hilflos ist.
A. K. schrieb: > Das ulkige an dieser bereits hinreichend bekannten Grundeinstellung ist > freilich, dass du dich trotzdem ausgerechnet in jener Retro-Sphäre > bewegst, in der man als Assembler-Analphabet ziemlich hilflos ist Amen :-) Ich gehöre auch zu den "Schändern" in deren Röhrenverstärker ein Mikroprozessor und ein fertiger Klangnetzwerk-Chip für Höhe/Bässe/Balance verbaut sind....Jehova!
Christian J. schrieb: >> Du mußt Dir unbedingt mal angewöhnen zuzuhören wenn Dir Jemand was >> erklärt und nicht einfach immer vernachlässigen. Das rächt sich: >> Das Problem beim Troubleshooting ist, der Trouble shootes back! > > Und Du musst mal vopn dieser Jogi/Schenk-Denke runterkommen, dass andere > ihre eigenen Vorstellungen haben und nicht blind das übernehmen, was > "alte Hasen" meinen richtig sei Seine Anmerkung bezog sich sicherlich nicht nur auf die Weigerung, Assembler kennenzulernen. Sondern auch darauf, wie du stur wie ein Panzer auf dem komplizierten Weg beharrst und völlig unnötige Komplexität ins EPROM einzubaust und dich dabei auch noch mit Compiler-Irrwegen abkämpfst, statt ins ROM nur das absolute Minimum einzubauen und danach ohne Sockelei im RAM weiterzuarbeiten.
A. K. schrieb: > Komplexität ins EPROM einzubaust und dich dabei auch noch mit > Compiler-Irrwegen abkämpfst, statt ins ROM nur das absolute Minimum > einzubauen und danach ohne Sockelei im RAM weiterzuarbeiten. Ist in Arbeit...keep it simple, as simple as possible. Trotzdem dran denken, dass es Hobby ist und ein wenig Spielerei dazu gehört. Schonmal bei Fingers elektrischer Welt vorbei geschaut.... geniale Seite, da sind auch Projekte von mir drauf :-)
Christian J. schrieb: > Hätte ich das vorher gewusst hätte ich ein Bankswitching eingebaut. ;)))) Tja ist das nun ein Hexenwerk, das zu in HW zu debuggen ? CS Draht ab SRAM Huckepack CS über MUX Und ein Pioportbit (alternativ kannst du ein HW Handshakepin der SIO... liegt eh rum missbrauchen) für den MUX Glaub mir je, länger du rumpopelst desto länger wird dir das Kopfweh machen und du wirst deine Zeit damit vertrödeln neue Krücken zu basten. Je eher du das nachrüstest, desto schneller wirst du glücklich mit dem was du vorhast. ... Namaste
:
Bearbeitet durch User
Christian J. schrieb: > Holm Tiffe schrieb: >> Du mußt Dir unbedingt mal angewöhnen zuzuhören wenn Dir Jemand was >> erklärt und nicht einfach immer vernachlässigen. Das rächt sich: >> Das Problem beim Troubleshooting ist, der Trouble shootes back! > > Und Du musst mal vopn dieser Jogi/Schenk-Denke runterkommen, dass andere > ihre eigenen Vorstellungen haben und nicht blind das übernehmen, was > "alte Hasen" meinen richtig sei sonder evtkl lediglich Nuancen oder > Tendenzen übernehmen. Assembler ist für mich Rummgestammel auf Bitniveau > mit dem keine komplexen Dinge gescheit zu lösen sind und man > verschwendet seine Zeit damit. Jawoll, da isser wieder uns Krischan... > Das wird sich auch nicht mehr ändern. Das Gefühl habe ich auch. IM2 ist sowieso Quatsch und die 8255 ist ein Top Teil .. > Dein Wissen ist aber willkommen, vor allem das aus DDR tagen was ich > sehr interessant fand. Ich denke mal Du interessierst Dich für Geschichte die Dir in der Schule nicht beigebracht wurde. Mein Wissen interessiert Dich nicht wirklich, das hast Du gerade eben wieder bewiesen. > > Das mit der /var/loch What? > habe ich mir auch gegoogelt, inzwischen läuft das > aber problemlos und ich denke, dass ich in ein paar Tagen soweit bin > Uploads zu machen, wenn noch einiges mehr verkabelt ist und vor allem > die Dokumentation des Ganzen mal wächst, denn ohne die blicke ich in in > einigen Monaten nicht mehr durch. > > Die Sache mit den Ints ist soweit klar, nur muss ich das noch in die > Compiler Directiven einarbeiten und rausfinden, wie ich diese Tabelle > erzeuge. Denn inzwischen ist der Huckepack Sockel vom EEPROM doch schon > ausgeleiert und es nervt dauernd jede Programmänderung neu zu brennen. Ich habe mir mein Wissen mit Lesen angeeignet, damit hast Du es wohl nicht so. Warum rennst Du immer mit dem Kopf gegen die Wand wenn es dunkel ist, anstatt Dich vorsichtig und mit Bedacht an die Wand heran zu arbeiten? Gruß, Holm
A. K. schrieb: > Holm Tiffe schrieb: >> Guckste eventuell mal was eher da war? Ich schätze mal das war die selbe >> stinkreiche Person die meinte das der "wrong slash" (Tm) irnkwie besser >> aussieht... > > Das kommt aus CP/M, da kann Gates nix für. Der hat bloss ein > abgekupfertes CP/M für 8088 aufgekauft. Die Programme in CP/M > verwendeten auch schon "/xxx" für Kommandozeilenoptionen, damit war "/" > für Pfade weg. Auch die Laufwerksbuchstaben sind aus CP/M. Der stinkreiche Arsch hat auch ein Rudel Systemrufe und die Pfade aus Unix übernommen die in QDOS nicht drin waren, er hat also entschieden. Garry kann man keinen Vorwurf machen ,der war ja fliegen.. Gruß, Holm
Christian J. schrieb: > A. K. schrieb: >> Das ulkige an dieser bereits hinreichend bekannten Grundeinstellung ist >> freilich, dass du dich trotzdem ausgerechnet in jener Retro-Sphäre >> bewegst, in der man als Assembler-Analphabet ziemlich hilflos ist > > Amen :-) Ich gehöre auch zu den "Schändern" in deren Röhrenverstärker > ein Mikroprozessor und ein fertiger Klangnetzwerk-Chip für > Höhe/Bässe/Balance verbaut sind....Jehova! Jaaa, das Wichtigste aber sind die blauen LEDs. Christian ein guter Rat: Lege Dich nicht mit mir an in dem Du versuchst mich zu provozieren. Wie das ausgeht weißt Du. Du bist mir rhetorisch nicht gewachsen. Ich will das aber nicht wirklich und amüsiere mich derzeit. Laß es also dabei, dann behältst Du die Unterhosen an. Im Ernst, hättest Du nicht alle Ratschläge hier immer wieder in den Wind geschlagen, hätte ich mich auch etwas besser um Dich gekümmert. Dein Ansatz möglichst in C programmieren zu wollen ist mir auch nicht neu, ich habe das selbe Problem mit dem 68k nebenan. Z80 Assembler ist aber einer der einfacheren, die Menmonics sind eingängig und gut zu merken, die CPU überschaubar. Lies doch den Thread einfach nochmal von vorne und analysiere was Du alles an Ratschlägen missachtet und dann korreliere mit welchen Problemen Du jetzt zu kämpfen hast. Die Sache mit dem Controller im Röhrenverstärker beeindruckt mich wirklich, aber nur dahingehend das Du das als Besonderheit erwähnst. Was glaubst Du wohl wie andere Leute Infrarotfernbedienungen realisieren? Mit nem Wasserrad und Preßluft? Boah ehy. Die Tatsache das Du erfolgreich einen EL84 Verstärker zusammengelötet hast beeindruckt mich eher gar nicht. Das habe ich schon vor 40 Jahren gemacht und in der Röhrenbude wird das immer für Anfänger empfohlen. Gruß, Holm
Hallo, > stellt sich dennoch die ein oder andere Frage, da ich mich mit > Protokollen von Schnittstellen nicht so genau aus kenne. Das liegt daran, dass du nicht liest, was andere dir schreiben. Oder du ignorierst alles bewusst und absichtlich, was gerade außerhalb deiner Scheuklappen sitzt und bist gleichzeitig nicht willens, später nochmal zurückzublättern. > Wenn vom PC ein Binärdatenstrom über das USB Interface in die Uart > reinkommt, wie zeigt dann der PC das Datenende an? Garnicht, weil Binärdaten das nicht können. Du sagtest, du arbeitest in einem technischen Bereich? Irgendwie kann ich mir das nicht vorstellen, weil du die selben Anfängerfragen immer und immer wieder stellst. > Ich habe nur zwei Leitungen, RX und TX, kein Hardware Flow Control, > kein Handshake. Daten die kommen müssen entgegen genommen werden > da sie unentwegt weiterlaufen. Tja, selbst schuld. Hättest du auch nur ein kleines bisschen vorher nachgedacht und ein Protokoll entworfen, wäre das alles kein Problem gewesen. Natürlich hättest du eins der vorhandenen Protokolle benutzen können, oder sogar die hier genannten Vorschläge benutzen können (Tipp: Die sind in diesem Thread immernoch drin!), aber du willst ja offensichtlich nicht. > Kann ich das Datenende nur über Timeout erkennen? Denn die Vereinbarung > eines speziellen Zeichens geht ja im Binärcode nicht. Klar kannst du das machen, und unter den angegebenen Bedingungen bleibt dir auch keine Alternative. Gibt zwar kaum dümmere Methoden, aber wem der Schuh passt... > Aktuell laufen die Zeichen über den SIO Interrupt rein und füllen einen > Ringpuffer, der 3/4 "voll" meldet hofft hofft dass das Hauptprogramm > sich um ihn kümmert bevor Daten verworfen werden. Wenn ein Ringpuffer ab 75% Füllstand anfängt, Daten wegzuschmeißen, dann ist er entweder exakt vier Byte groß oder hochgradig hirnrissig implementiert. Es schadet übrigens nicht, in einer Bootstrap-Schleife mit Polling zu arbeiten - schließlich hat die CPU ja noch nichts besseres zu tun. > der Compiler spuckt leider nur variable Länge aus und der Binärconverter > auch. Sehr überraschend. Ich bin zufrieden, wenn für ein 400 Byte großes Programm keine 8 KB übertragen werden müssen. Je nach Geschwindigkeit der Schnittstelle dauert das nämlich eine Weile... > Der Compiler erzeugt keine object files :-( dd ist sehr praktisch > da mit bs = 8192 ja die Blockgröße gesetzt werden kann. Klar erzeugt er Object Files, aber eben keine ELF-Dateien auf *.o, sondern Textdateien auf *.rel. Ist halt kein GNU-Compiler. > Etwas anders wird schon schwieriger.... denn ein Programm im RAM ab > 0x2000, dem fehlen die ganze Zeropage und da liegen bekanntlich einige > Vektoren. Erstens liegen in der Zeropage keine Vektoren, wenn du sie da nicht willst (der Z80 ist intelligent genug). Zweitens fehlt die Zeropage nicht, sondern enthält das, was du ihr da hingelegt hast. Wenn du das ROM nicht wegschaltest, liegt da das ROM. > Und ich kann ROM nicht nach RAM überblenden, da das darunter > liegt. D.h. dass zb Int Mode 2 gar nicht möglich ist, denn der würde auf > das ROM zugreifen und die Vektoren zeigen irgendwo hin aber nicht auf > die Routinen im RAm da die jedesmal woanders liegen. Ein Binärformat würde das ohne Probleme lösen. Alternativ eine neue Vektortabelle im RAM, die vom Startup-Code durch Änderung des I-Registers aktiviert wird. Das ist alles keine Raketentechnologie. Du willst Retro, aber irgendwie bist du unwillig, dir auch nur die Lösungen anzuschauen, die dir auf dem Silbertablett serviert werden. > Daran habe ich leider nicht gedacht, dass alles aus der Zeropage jetzt > unerreichbar ist. Wieso unerreichbar? Da ist immernoch das, was da vorher auch war. Ob du es benutzen willst oder nicht, spielt doch keine Rolle. Es gibt durchaus Monitorprogramme mit Funktionen, die ein nachgeschaltetes Anwendungsprogramm weiternutzen will - nennt man oft BIOS oder so. > Auch die Software Interrupts RST n, NMI sowieso, > alle Timer Interrupts usw. Die Interrupts kannst du per I-Register im IM2 verlegen. RST n und NMI kannst du indirekt nutzen, indem du an die passende Stelle im Monitor einfach einen Sprung an eine RAM-Adresse legst... das darf im Zweifelsfall auch eine dynamische Adresse sein, die sich aus einem Header des Anwendungsprogramms ergibt... ach ne, du willst ja nur rohe Binärdaten. Dann geht das natürlich alles nicht. > Der Compiler lässt es leider nicht zu, dass man Routinen fixe Adressen > verpasst, der will da sehr frei wählen wo jedes Segment liegt. Der Compiler ist nicht intelligent genug, um dir das zu verbieten. Wenn du ein Symbol passend deklarierst, dann nutzt der das auch. Muss man halt nur (in (Inline-)Assembler) machen. Aber auch das willst du ja nicht. Dann geht das natürlich auch nicht, da hast du schon recht... Gruß
Holm Tiffe schrieb: > Lege Dich nicht mit mir an in dem Du versuchst mich zu provozieren. > Wie das ausgeht weißt Du. Du bist mir rhetorisch nicht gewachsen. Ich > will das aber nicht wirklich und amüsiere mich derzeit. Laß es also > dabei, dann behältst Du die Unterhosen an. @S.R.: Danke für Deine Ausführungen, das Allermeiste hat sich aber inzwischen auch so gelöst und hätte nicht diskutiert werden müssen, wenn man mal drüber geschlafen hat. @Holm: Es mag rund 10 Jahre her sein aber ich sitze da mit einem breiten Grinsen, weil ich genau weiss welche Hebel und Knöpfe ich drücken muss, damit Du "aufsteigst". Also seien wir lieb, Du bist nämlich ein feiner Kerl glaube ich :-) Ich habe mich erstmal entschieden, dass der reine Upload zu öde ist, da der in ein paar Zeilen kodiert ist und mich für eine "Terminal" Umgebung entschieden. Reiner Upload ist mit echo "U" > /dev/tty stat -c %s binaer.bin > /dev/tty cat binaer.bin > /dev/tty gemacht, wenn man U als Startzeichen sieht, danach Dateigröße (als ascii), dann die Daten und fertig. Timeout ist ebenso legal und einfach, wenn man die n-fache Bytezeit bei 9600 als TO deklariert. Das Kopieren ins Ram geht nur über inline asm, war auch nicht schwer. Ich habe bis spät abends gestern Routinen kodiert die es ermöglichen dem Z80 System Kommandozeilen zu übergeben. Leider sendet minicom bei Tasteneingaben jedes Zeichen einzeln so dass ich im Z80 zb Cursor, ESC, BS und DEL abfangen und korrigieren müsste durch Versetzung des Pointers im RX Buffer, hterm unter Windows sendet erst bei CR Strings ab. Dafür entfällt die Timeout Funktion, da CR das Datenende signalisiert. Das Parsen der Strings ist recht einfach. Ob ein ausführbares Programm im Speicher liegt wird im Startup des Monitors erfragt da der erste Befehl ein immer JP xxxx" ist. Dann wird das Ausnullen übersprungen und direkt losgelegt, damit ein Reset nicht alles löscht. Von daher werde ich beides in einem Schreiben: Ein Art Bediener-Menüführung, zb auch um ein 4 Gewinnt Spiel etc zu spielen (printf und scanf arbeiten) aber auch die Möglichkeit per Steuerzeichen Uploads und andere Funktionen zu erreichen. Entgegen meinen Befürchtungen stellt sich die INT Problematik gar nicht, auch nicht bei NMI. RST lassen sich umlenken, Mode 2 Ints ja über I Register und das Compiler Image arbeitet bei 0x2000 genau wie bei 0x0000, es ist eben alles nur verschoben und der Offset bekannt. Aktuell sehe ich nur minicom, screen oder picocom als passendes "Terminal", da sind Upload Funktionen bereit halten und andere Dinge. Es wird schon....
Hallo, da ich dem Rechner(chen) noch etwas mehr einbauen möchte suche ich C-Quellcodes von Spielen etc. die sich ausschliesslich printf und scanf, bzw puts und gets als Ausgabe bedienen, rein textbasiert sind. Ich habe aktuell ein recht starkes 4 gewinnt gegen den Computer aber wenn es ein Text Schachprogramm oder Schiffe versenken etc geben würde wäre das auch nett. Kennt da jemand noch etwas? Gruss, Christian
Noch ein Wort zum sdcc Compiler für den, den es interessiert: Erfreulichwerweise erlaubt er es Variablen an fixe Plätze im Speicher zu legen und vermeidet auch die Prüfung ob diese Variablen mit anderen Inhalten des RAM kollidieren. Auf diese Weise lässt sich zb mit __at 0x2000 char ram[56x1024]; das ganze RAM direkt adressieren (natürlich auch der SP zerschiessen). Oder Inhalte des ROM mit __at 0x0 char rom[8192]; rüber kopieren. Was NICHT geht und das schränkt doch erheblich ein ist es mit inline asm lokale Variablen oder Funktionsparameter zu erreichen. Niente, geht nicht! Aus dem Grund, weil diese im Stack übergeben werden und die Übergabe jedesmal anders ist, man nicht weiss wo sie liegen. Manchmal auf im DE oder BC Register. Ein (_variable) gilt nur für globale Werte und die sollte man eh vermeiden wo es geht. Weiterhin klappt es nicht statische Variablen in Funktionen zu initialisieren, diese Funktion gibt es (noch) nicht.
Das kann so nicht sein wie Du es beschreibst. Ein Compiler hat immer calling conventions für Subroutinen und die sind auch nicht jedesmal anders, sie richten sich maximal nach der Art der übergebenen Variable. Ich gehe davon aus das Du die entsprechende Doku einfach nicht gelesen hast, Du bist genu so stinkend faul wie ich, abe rwenn man was Konkretes wissen will muß man halt dediziert nach den Definitionen suchen, manchmal auch im Sourcecode. Gruß, Holm
Christian J. schrieb: > Was NICHT geht und das schränkt doch erheblich ein ist es mit inline asm > lokale Variablen oder Funktionsparameter zu erreichen. Niente, geht > nicht! Die falschen Behauptungen werden auch durch ständige Wiederholung nicht wahr. > Aus dem Grund, weil diese im Stack übergeben werden und die > Übergabe jedesmal anders ist, man nicht weiss wo sie liegen. Parameter werden immer auf dem Stack übergeben, und die Reihenfolge ist definiert. > Manchmal auf im DE oder BC Register. Von diesen beiden wird eines für lokale Variable verwendet, und das findet man in der Doku. Holm Tiffe schrieb: > Das kann so nicht sein wie Du es beschreibst. Ein Compiler hat immer > calling conventions für Subroutinen und die sind auch nicht jedesmal > anders, sie richten sich maximal nach der Art der übergebenen Variable. > Ich gehe davon aus das Du die entsprechende Doku einfach nicht gelesen Die Doku dazu ist zugegebenermaßen sehr dünn. Ausprobieren würde helfen. Wie das geht ist allerdings für den 8051 sehr ausfürlich mit einer "Schritt für Schritt" Anleitung in der Doku beschrieben, ab Kapitel "3.14 Inline Assembler Code". Christian J. schrieb: > Weiterhin klappt es nicht statische Variablen in Funktionen zu > initialisieren, diese Funktion gibt es (noch) nicht. Auch diese Falschbehauptung wurde schon irgendwo widerlegt. Ich finde nur die Stelle nicht. Wie man in meinem angehängten Versuch sehen kann, erzeugt der Compiler dafür (derzeit) Code in der GSINIT-Area. Ziemlich ineffizient, aber geht. Die lokale Variable 'local' liegt hier auch auf dem Stack. Den Platz dafür schafft der 'push af' am Anfang der Funktion. Test:
1 | extern int f(int *x); |
2 | |
3 | int test( int a, int b) |
4 | {
|
5 | static int drei = 3; |
6 | |
7 | int local; |
8 | |
9 | local = a + b; |
10 | |
11 | return drei + f(&local); |
12 | }
|
Compiler Output:
1 | ;-------------------------------------------------------- |
2 | ; File Created by SDCC : free open source ANSI-C Compiler |
3 | ; Version 3.4.0 #8981 (Jul 5 2014) (Linux) |
4 | ; This file was generated Thu Oct 30 11:39:18 2014 |
5 | ;-------------------------------------------------------- |
6 | .module testpar |
7 | .optsdcc -mz80 |
8 | |
9 | ;-------------------------------------------------------- |
10 | ; Public variables in this module |
11 | ;-------------------------------------------------------- |
12 | .globl _test |
13 | .globl _f |
14 | ;-------------------------------------------------------- |
15 | ; special function registers |
16 | ;-------------------------------------------------------- |
17 | ;-------------------------------------------------------- |
18 | ; ram data |
19 | ;-------------------------------------------------------- |
20 | .area _DATA |
21 | _test_drei_1_3: |
22 | .ds 2 |
23 | ;-------------------------------------------------------- |
24 | ; ram data |
25 | ;-------------------------------------------------------- |
26 | .area _INITIALIZED |
27 | ;-------------------------------------------------------- |
28 | ; absolute external ram data |
29 | ;-------------------------------------------------------- |
30 | .area _DABS (ABS) |
31 | ;-------------------------------------------------------- |
32 | ; global & static initialisations |
33 | ;-------------------------------------------------------- |
34 | .area _HOME |
35 | .area _GSINIT |
36 | .area _GSFINAL |
37 | .area _GSINIT |
38 | ;testpar.c:5: static int drei = 3; |
39 | ld iy,#_test_drei_1_3 |
40 | ld 0 (iy),#0x03 |
41 | ld iy,#_test_drei_1_3 |
42 | ld 1 (iy),#0x00 |
43 | ;-------------------------------------------------------- |
44 | ; Home |
45 | ;-------------------------------------------------------- |
46 | .area _HOME |
47 | .area _HOME |
48 | ;-------------------------------------------------------- |
49 | ; code |
50 | ;-------------------------------------------------------- |
51 | .area _CODE |
52 | ;testpar.c:3: int test( int a, int b) |
53 | ; --------------------------------- |
54 | ; Function test |
55 | ; --------------------------------- |
56 | _test_start:: |
57 | _test: |
58 | push af |
59 | ;testpar.c:9: local = a + b; |
60 | ld hl,#6 |
61 | add hl,sp |
62 | ld iy,#4 |
63 | add iy,sp |
64 | ld a,0 (iy) |
65 | add a, (hl) |
66 | ld d,a |
67 | ld a,1 (iy) |
68 | inc hl |
69 | adc a, (hl) |
70 | ld e,a |
71 | ld iy,#0 |
72 | add iy,sp |
73 | ld 0 (iy),d |
74 | ld 1 (iy),e |
75 | ;testpar.c:11: return drei + f(&local); |
76 | ld hl,#0x0000 |
77 | add hl,sp |
78 | push hl |
79 | call _f |
80 | pop af |
81 | ld de,(_test_drei_1_3) |
82 | add hl,de |
83 | pop af |
84 | ret |
85 | _test_end:: |
86 | .area _CODE |
87 | .area _INITIALIZER |
88 | .area _CABS (ABS) |
Christian J. schrieb: [sdcc] > Aufpassen muss man allerdings, dass die Debian Repos nur bis zur Version > 3.0.0 reichen von 2012 und da sind noch eine Menge Bugs drin Debian testing enthält v3.4.0 (https://packages.debian.org/testing/electronics/sdcc). Kann man nicht meckern.
Christian J. schrieb: > Aus dem Grund, weil diese im Stack übergeben werden und die > Übergabe jedesmal anders ist, man nicht weiss wo sie liegen. Wie schon gesagt werden die Parameter immer gleich übergeben. Der Zugriff darauf kann aber je nach Optimierungsmöglichkeiten variieren. Einfacher wirds, wenn man den Compiler davon abhält, den Framepointer wegzuoptimieren. Option: --fno-omit-frame-pointer In dem Zusammenhang meine ich, einen Compiler-Bug gefunden zu haben. Das muß ich mir aber erst noch genauer anschauen.
Leo C. schrieb: > Parameter werden immer auf dem Stack übergeben, und die Reihenfolge ist > definiert. Hm, dann sind die Compiler, welche die ersten N Parameter einer Funktion auch per Register übergeben können, Teufelswerk?
Frank M. schrieb: > Hm, dann sind die Compiler, welche die ersten N Parameter einer Funktion > auch per Register übergeben können, Teufelswerk? Wie kommst Du denn hier auf "Compiler, welche die ersten N Parameter einer Funktion auch per Register übergeben können"?
Ich denke, es geht hier im einen ganz bestimmten Compiler. Da kann es schon sein, dass der alle Parameter per Stack übergibt. Das bedeutet nicht, dass alle Compiler es so machen.
Nabend, ich schreibe das mir nicht aus den Fingern heraus, daher bitte ich darum auf die Frozzeleien zu verzichten. Ich habe mir den erzeugetn Code (mit Optimierung!) genau angeschaut und es ist so, dass er mal auf dem Stack übergibt und mal einfach nur per Register! Und darauf verlasse ich mich garantiert nicht, sondern mache das mit einem Workaround, idem ich lokale Variablen, die nicht mit Symbol erreichbar sind zuerst in eine globale Variable kopiere und mir von dort aus hole. Die Doku ist völig unzureichend. da steht nicht mal was über die .areas drin. Bitschiebrei und testen ist in Schleifen per Asm deutlich effizienter, sonst ist es egal wenn es nur einmal durchlaufen wird, platz genug ist da. Debian main liefert 3.3.0 derzeit. aktuell ist 3.4.5 und das hat 700 Bytes Code um ganze 150 Bytes reduziert. Die letzte Code Änderung fand heute statt: http://sdcc.sourceforge.net/snap.php Und was static angeht so habe ich die Aussage eines der Programmierer dieses Compilers, das das noch nicht ausgereift ist. Ineffizient sowieso aber es wäre noch eine Baustelle, die ich nicht benutzen sollte. @Leo Welchen ASM Code hast Du denn im Startup unter der area GSINIT stehen? Bei mir ist da nur ein ret drin.
1 | ;/////////////////////////////////////////////////////////// |
2 | ; Anordung der Segmente fuer den Linker, ab hier nur relative |
3 | ; Adressen |
4 | |
5 | .area _CODE |
6 | .area _INITIALIZER |
7 | .area _HOME |
8 | .area _GSINIT |
9 | .area _GSFINAL |
10 | .area _DATA |
11 | .area _INITIALIZED |
12 | .area _BSEG |
13 | .area _BSS |
14 | .area _HEAP |
15 | |
16 | ;/////////////////////////////////////////////////////////// |
17 | ;; ------- Start des Hauptprogramms nach der Zeropage ----------- |
18 | |
19 | .area _CODE |
20 | init: |
21 | |
22 | ld sp,#stack ;; Stack an Spitze des RAM legen |
23 | |
24 | ; Teste ob Userprogramm im RAM vorhanden |
25 | ; .... |
26 | |
27 | ; Ram ausnullen (auskommentieren, wenn von PC Upload erfolgt) |
28 | xor a ; clear a and carry |
29 | ld bc,#0xdfff ; ram size left |
30 | ld hl,#0x2000 ; starting from 2000 |
31 | ld de,#0x2001 |
32 | ld (hl),a ; 0 -> (2000) |
33 | ldir ; (HL) -> (DE) |
34 | |
35 | ; Initialisiere globale Variablen im RAM |
36 | ld bc, #l__INITIALIZER |
37 | ld a, b |
38 | or a, c |
39 | jr Z, weiter |
40 | ld de, #s__INITIALIZED |
41 | ld hl, #s__INITIALIZER |
42 | ldir |
43 | |
44 | weiter: |
45 | |
46 | ; ###### Hauptprogramm aufrufen ####### |
47 | jp _main |
48 | |
49 | ; Endlos Schleife |
50 | halt |
51 | endlos: |
52 | jr endlos ; Sicher ist sicher |
53 | |
54 | ret |
55 | |
56 | |
57 | ; // reserved |
58 | .area _GSFINAL |
59 | ret |
Wenn Du nur mit "geheimen" Informationen operierst, kannst Du den Rest auch noch für Dich behalten, und mußt nicht das Forum hier belästigen. Du stellst hier ständig falsche Behauptungen über sdcc auf, ohne irgendwas mit nachvollziehbaren Beispielen zu belegen, so daß sich ein sdcc-Entwickler schon genötigt sieht, hier eine ganze Artikelserie mit Klarstellungen zu posten. Und wenn man versucht Dir auf die Sprünge zu helfen, wirst Du auch noch pampig.
Seitenweise Bit für Bit: Beitrag "Mehrdimensionale char-arrays" "Du brauchst dann, später noch den Sprung nach gsinit, da leider die Initalisierung mit _INITIALIZER / _INITALIZED zur Zeit nur für globale Variablen funktioniert. Der _GSINIT-Mechanismus wird noch für lokale Variablen mit storage class static gebraucht."
Christian J. schrieb: > Ich habe mir den erzeugetn Code (mit Optimierung!) genau angeschaut und > es ist so, dass er mal auf dem Stack übergibt und mal einfach nur per > Register! Hast du da ein konkretes Beispiel?
:
Bearbeitet durch User
Christian J. schrieb: > Ich habe mir den erzeugetn Code (mit Optimierung!) genau angeschaut und > es ist so, dass er mal auf dem Stack übergibt und mal einfach nur per > Register! Wo sind Deine Beispiele (C-Source und Compiler Output (.asm))? Christian J. schrieb: > Welchen ASM Code hast Du denn im Startup unter der area GSINIT stehen? > Bei mir ist da nur ein ret drin. hier: Leo C. schrieb: > ;-------------------------------------------------------- > ; global & static initialisations > ;-------------------------------------------------------- > .area _HOME > .area _GSINIT > .area _GSFINAL > .area _GSINIT > ;testpar.c:5: static int drei = 3; > ld iy,#_test_drei_1_3 > ld 0 (iy),#0x03 > ld iy,#_test_drei_1_3 > ld 1 (iy),#0x00 Wenn ich das richtig sehe, hast Du oben Deine crt0.s gepostet. Da kann der Initialsierungscode einer Funktion, die in einer anderen Datei steht natürlich nicht drin sein. In der crt0.s muß allerdings Code sein, der den Code in GSINIT aufruft. Christian J. schrieb: > Und was static angeht so habe ich die Aussage eines der Programmierer > dieses Compilers, Zeigen! (link) > das das noch nicht ausgereift ist. Ich habe ja auch nichts anderes behauptet. Du behauptest aber, lokale statische Variablen würden überhaupt nicht initialisiert. > Ineffizient sowieso aber es wäre noch eine Baustelle, die ich nicht > benutzen sollte. Wenn man nichts effizientes hat, muß man eben mit dem ineffizienten Vorlieb nehmen. Funktionieren tut es ja.
Christian J. schrieb: > Leo C. schrieb: >> Zeigen! (link) > > s.o. So wird das nichts. Bitte konkret, nicht als summarischen Link auf einen sich über 8 Jahre erstreckenden Thread. Und bitte auch nicht als summarischen Verweis auf diesen sich über 4 Seiten erstreckenden Thread.
:
Bearbeitet durch User
Version 1:
1 | ;driver.c:49: void printstrng(char *k) |
2 | 340 ; --------------------------------- |
3 | 341 ; Function printstrng |
4 | 342 ; --------------------------------- |
5 | 01BD 343 _printstrng_start:: |
6 | 01BD 344 _printstrng: |
7 | 345 ;driver.c:51: while ((*k) != '\0') |
8 | 01BD C1 [10] 346 pop bc |
9 | 01BE E1 [10] 347 pop hl |
10 | 01BF E5 [11] 348 push hl |
11 | 01C0 C5 [11] 349 push bc |
12 | 01C1 350 00101$: |
13 | 01C1 7E [ 7] 351 ld a,(hl) |
14 | 01C2 B7 [ 4] 352 or a, a |
15 | 01C3 C8 [11] 353 ret Z |
Version 2:
1 | ; --------------------------------- |
2 | 367 ; Function SetDigit |
3 | 368 ; --------------------------------- |
4 | 01D0 369 _SetDigit_start:: |
5 | 01D0 370 _SetDigit: |
6 | 371 ;driver.c:61: SEG7 = digits[i & 0x0f]; |
7 | 01D0 21 02 00 [10] 372 ld hl, #2+0 |
8 | 01D3 39 [11] 373 add hl, sp |
9 | 01D4 7E [ 7] 374 ld a, (hl) |
10 | 01D5 E6 0F [ 7] 375 and a, #0x0F |
11 | 01D7 5F [ 4] 376 ld e,a |
12 | 01D8 21r5Cr00 [10] 377 ld hl,#_digits |
Die Registervariante hatte ich auch mal in den Fingern aber ichfinde sie nicht mehr, da ich seitdem was verändert habe. Ist mir trotzdem zu undurchschaubar, daher "Workaround". Nur zum Verständnis: static heisst "Nur bei Programmstart", nicht bei jedem Aufruf der Routine.
Version 1 hatten wir doch schon mal. Da wird keineswegs per Register übergeben, wie ich an dieser Stelle auch deutlich beschrieb.
A. K. schrieb: > So wird das nichts. Bitte konkret, nicht als summarischen Link auf > einen sich über 8 Jahre erstreckenden Thread Die letzten 30 oder 40 Beiträge handeln nur von diesem Thema "Variablen" in diesem Thread, weil das bis aufs letzte Bit auseinander genommen wurde, wie da was organsiert ist. Gute Nacht! Beispiel "Segment Problem", ob behoben weiss ich nicht. http://comments.gmane.org/gmane.comp.compilers.sdcc.user/2405 Hi, When I use my custom crt0, in the final binary, gsinit: is pointing to GSFINAL instead of GSINIT. Therefore, global variables do not get initialised. Also, GSINIT is placed into DATA which seems to be wrong. Finally, since my device only has RAM and not ROM, I don't think I need separate CODE and DATA areas - all variables can be stored in CODE like consts are. Is there some way to tell the compiler to do that?
A. K. schrieb: > wie ich an dieser Stelle auch deutlich beschrieb. ... und wieder gelöscht hatte, nachdem ich sah, dass KHB sich bereits korrigiert hatte. Jedenfalls kriegt _printstrng seinen Parameter völlig korrekt auf dem Stack und ins richtige Register.
:
Bearbeitet durch User
Ok... es gibt wie man sieht aber verschiedene Wege, über push/pop und über Indexierung einer Stack Adresse mit IY, bzw. die gehört auch noch dazu. Oben ist es ja über HL + Offset + SP. und wie ermittelt man dann die korr. Position auf dem Stack? Bzw finde ich derzeit noch meine Lösung mit dem zeitweisen Umkopieren auf global praktiklabler, da ich nicht im Stack fummeln muss und zudem symbolische Namen habe, auf die einfach zuzugreifen ist.
Christian J. schrieb: > und wie ermittelt man dann die korr. Position auf dem Stack? Am Anfang der Funktion gilt: SP+0: Return-Adresse. SP+2: Erster Parameter. Wie es danach weiter geht hängt von den Parametern und dem ABI ab. Vermutlich werden pro Parameter mindestens 2 Bytes fällig. Etwaige Veränderungen an SP innerhalb der Funktion müssen natürlich eingerechnet werden, wenn man SP als Basis der Adressierung verwendet. Je nach Compiler, Optionen und Laune kann es auch einen Frame-Pointer geben, hier wohl IY, der im Unterschied zum SP innerhalb einer Funktion unverändert bleibt und als Basis der Adressierung lokaler Daten und Parameter dient. Deine beiden vorhin gezeigten Beispiele greifen beide auf SP+2 zu, nur auf höchst unterschiedliche Weise. Variante 1 poppt beide Worte vom Stack und schiebt sie sofort wieder zurück, Variante 2 rechnet SP+2 aus und fischt sich das indirekt von dort.
:
Bearbeitet durch User
A. K. schrieb: > Je nach Compiler, Optionen und Laune kann es auch einen Frame-Pointer > geben, hier wohl IY, Witziger Weise nimmt er IX als Framepointer, wenn man ihm per Option sagt, daß er den Framepointer nicht weglassen darf. > der im Unterschied zum SP innerhalb einer Funktion > unverändert bleibt und als Basis der Adressierung lokaler Daten und > Parameter dient. Der Preis für die größere Übersichtlichkeit ist, daß für jeden Funktionsaufruf 2 Byte zusätzlich auf dem Stack gebraucht werden, da der aktuelle Framepointer gerettet werden muß. Hier mal ein Beispiel
1 | extern int f(int *x); |
2 | |
3 | int test(int pa, int pb) |
4 | {
|
5 | int local; |
6 | |
7 | local = pa*2 + pb; |
8 | |
9 | return f(&local); |
10 | }
|
Compiliert mit: $ sdcc -mz80 -S testpar.c --fno-omit-frame-pointer
1 | .area _CODE |
2 | ;testpar.c:3: int test(int pa, int pb) |
3 | ; --------------------------------- |
4 | ; Function test |
5 | ; --------------------------------- |
6 | _test_start:: |
7 | _test: |
8 | push ix ;framepointer (fp) der aufrufenden Funktion retten |
9 | ld ix,#0 ; |
10 | add ix,sp ;ix mit stackpointer laden (neuer fp) |
11 | push af ;Platz auf Stack für lokale Variable 'local' |
12 | |
13 | ;Der Stack sieht jetzt so aus: |
14 | ; |
15 | ; | | höhere Adressen |
16 | ; +----------+ |
17 | ; | pb | sp+8 ix+6 |
18 | ; +----------+ |
19 | ; | pa | sp+6 ix+4 |
20 | ; +----------+ |
21 | ; | ret-addr | sp+4 ix+2 |
22 | ; +----------+ |
23 | ; | ix | sp+2 ix+0 |
24 | ; +----------+ |
25 | ; | local | sp+0 ix-2 |
26 | ; +----------+ |
27 | ; | | Niedrigere Adressen |
28 | ; |
29 | |
30 | ;testpar.c:7: local = pa*2 + pb; |
31 | ld l,4 (ix) ;pa nach hl |
32 | ld h,5 (ix) |
33 | add hl, hl ;pa*2 |
34 | ld e,6 (ix) ;pb nach de |
35 | ld d,7 (ix) |
36 | add hl,de ;pa*2 + pb |
37 | inc sp ;sp auf 'local' zeigen lassen |
38 | inc sp ;trotz fp, so gehts schneller |
39 | push hl ;hl in 'local' speichern |
40 | ;testpar.c:9: return f(&local); |
41 | ld hl,#0x0000 |
42 | add hl,sp ;addresse von local |
43 | push hl ;auf Stack als Parameter für f |
44 | call _f |
45 | ld sp,ix ;locale Variablen vom Stack entfernen |
46 | pop ix ;fp der aufrufenden Funktion wiederherstellen |
47 | ret |
48 | _test_end:: |
Wenn man dieses Beispiel ohne Framepointer compiliert, wird beim Laden des 2. Parameters das Zwischenergebnis in hl teilweise zerstört. (sdcc 3.4.0) :(
Christian J. schrieb: > und wie ermittelt man dann die korr. Position auf dem Stack? Zitat sdcc-Manual:
1 | 3.14.2 A Step by Step Introduction |
2 | |
3 | Starting from a small snippet of c-code this example shows for the MCS51 how to use inline assembly, access |
4 | variables, a function parameter and an array in xdata memory. The example uses an MCS51 here but is easily |
5 | adapted for other architectures. This is a buffer routine which should be optimized: |
Wenn Du Inline-Assembler verwenden willst, wirst Du ums Lernen von Assembler nicht herum kommen.
Leo C. schrieb: >> geben, hier wohl IY, > > Witziger Weise nimmt er IX als Framepointer, wenn man ihm per Option > sagt, daß er den Framepointer nicht weglassen darf. Ich hatte IY von Christians Aussage übernommen. Dass es eines dieser beiden Register sein würde lag nahe, nur offen welches. Framepointer waren in früheren C Compilern ziemlich üblich. Da waren Compiler noch recht schematisch, ohne statementübergreifende Optimierung und mit Registerverwaltung durch den Anwender (Keyword "register").
:
Bearbeitet durch User
A. K. schrieb: > Ich hatte IY von Christians Aussage übernommen. Dass es eines dieser > beiden Register sein würde lag nahe, nur offen welches. Deswegen witzigerweise. Ohne Framepointer nimmt er IY, wenn er mit HL nicht auskommt. Wenn man dann das hier im Handbuch sieht:
1 | --reserve-regs-iy |
2 | This option tells the compiler that it is not allowed to use register pair |
3 | iy. The option can be useful for systems where iy is reserved for the OS. |
4 | This option is incompatible with --fomit-frame-pointer. |
glaubt man erst recht, daß IY der Framepointer sei. Mit der Option "--fno-omit-frame-pointer" nimmt er aber konsequent IX.
Nimmt er IY dann als einmalig in der Funktion definierten echten Framepointer? Oder als normales transientes Adressregister, als Ersatz für das grad nicht verfügbare HL?
Dachte ich es mir doch. HL ist sowas wie ein 16-Bit Akkumulator. Der kann nicht immer auch als Adressregister operieren und ein ADD BC/DE,SP gibt es nicht. Also muss IY dran glauben. Völlig normales Registermanagement.
:
Bearbeitet durch User
Danke, damit kann ich schon was anfangen und mit Asm bin ich ja sowieso dabei, allerdings macht hier Übung der Meister, bis man nicht mehr alles nachschauen muss, zb was indirekte Adressierung angeht usw. Ich habe es bei PC und auch 8085 damals wo ich nur Asm programmierte immer vermieden den Stack zu manipulieren, da ich den als vom System verwaltet ansah und auch Ints, die mir "dazwischen" funken als riskant ansah. Nur zwischendurch wenn registerknappheit herrscht mal eben was weg gepoppt und danach wieder geholt. Dieses Prinzip Framepointer unterstützt Rekursion und verschachtelte Aufrufe wurde auch wohl deshalb eingeführt. Dann werkeln wir mal weiter......
Nachtrag zu: Leo C. schrieb: > Letzteres Sieht man auch in diesem Beitrag: Beitrag "Re: Retro Fieber: Z80 oder 68000 ?" IY wird hier im Gegensatz zum "echten" Frampointer auch nicht auf den Stack gesichert. Christian J. schrieb: > Beitrag "Mehrdimensionale char-arrays" Das war die Stelle, die ich hier meinte: Leo C. schrieb: > Christian J. schrieb: >> Weiterhin klappt es nicht statische Variablen in Funktionen zu >> initialisieren, diese Funktion gibt es (noch) nicht. > > Auch diese Falschbehauptung wurde schon irgendwo widerlegt. Ich finde > nur die Stelle nicht. Wie man in meinem angehängten Versuch sehen kann, Auf die Idee, in uralten gekaperten Threads zu suchen, kommt man halt nicht. Aber es funktioniert. Zugegebenermaßen etwas tricky. Wichtig ist, das man die C-Dateien getrennt kompiliert, und beim Linken die crt0.rel zuerst kommt, da darin die Reihenfolge der Segmente definiert ist. Außerdem darf man beim Linken die Optionen --code-loc und evtl. --data-loc nicht weglassen, sonst werden Segmente übereinander statt hintereinander gelegt. Es kommt dann nicht mal eine Fehlermeldung. Gestern Abend habe ich das mal ausprobiert. D.h. ich habe ein komplett lauffähiges Demo erstellt. Zum Testen bin ich aber gestern nicht mehr gekommen, weil "mein" Debugger leider auch noch ein paar Ecken hat. Jetzt gehts aber. Im Anhang ist das komplette Beispiel incl. Makefile, daß Du auch für Dein Projekt verwenden kannst. Die crt0 habe ich auf das für mich absolut notwendige reduziert. Die (ABS) Area braucht man im Grunde nicht, auch nicht, wenn das Programm ab 0 im EPROM laufen soll. Man linkt dann einfach mit '--code-loc 0', bzw 'CODE_LOC := 0' im Makefile. Die Restart-Vektoren und den NMI-Vektor könnte man dann nach dem 'JP init' auch noch platzieren. Schau Dir das mal an, und vor allem: probier's aus. Schreib Dir dazu eine eigene, einfache putchar(). Dazu brauchst Du nicht mal Inline-Assembler und erst recht keine Interrupts. ungefähr so: void putchar(char c) { while ((sti_statusregister & TX_ready_maske) == 0) ; /* warten */ sti_senderegister = c; }
Noch ein paar Ergänzungen. Das Beispiel sollte zeigen, daß die Initialisierung von lokalen static Variablen funktioniert. Deshalb ist count in main() static deklariert. putchar() ist __naked deklariert, damit der Assemblercode den Parameter c auf dem Stack findet, unabhängig davon, ob mit oder ohne Framepointer compiliert wird. Ohne __naked und mit Framepointer würde der Compiler diesen Prolog generieren:
1 | push ix |
2 | ld ix,#0 |
3 | add ix,sp |
Und dann wäre der Offset zu c nicht mehr 2 sondern 4. Schön wäre ein Compiler-Macro, daß den Zustand dieses Compilerschalters liefern würde, habe ich aber nicht gefunden. Headerdatei zu myputchar.c habe ich weggelassen, und statt dessen stdio.h included. Damit ist sichergestellt, daß der Prototyp von putchar() zur libc paßt.
Leo C. schrieb: > Aber es funktioniert. Zugegebenermaßen etwas tricky. Wichtig ist, das > man die C-Dateien getrennt kompiliert, und beim Linken die crt0.rel > zuerst kommt, da darin die Reihenfolge der Segmente definiert ist. > Außerdem darf man beim Linken die Optionen --code-loc und evtl. > --data-loc nicht weglassen, sonst werden Segmente übereinander statt > hintereinander gelegt. Es kommt dann nicht mal eine Fehlermeldung. Hi, da bin ich schon länger, dass man es so machen muss:
1 | # Assembliere das crt0 startup file |
2 | echo "Assembliere....." |
3 | sdasz80 -plosgff -o -l crt0.rel crt0.s |
4 | echo "Kompiliere main.c...." |
5 | sdcc -mz80 main.c -c |
6 | echo "Linke beide Dateien...." |
7 | sdcc -mz80 --verbose --no-std-crt0 --vc --code-loc 0x0100 --data-loc 0x2000 crt0.rel main.rel |
8 | # In Binaerformazt wandeln |
9 | ./hex2bin -p 0 crt0.ihx |
10 | #echo "Datei zum Target uebertragen..." |
11 | #cat crt0.bin > /dev/ttyUSB0 |
1 | ///////////////////////////////////////////////////////// |
2 | // Zeichenausgabe für printf auf der STI mit 9600 Baud |
3 | void putchar(char c) |
4 | { |
5 | while ((STI_TSR & 0x80) == 0); // Warte bis Buffer frei... |
6 | STI_UDR = c; // Byte einschreiben |
7 | |
8 | } |
putchar funktioniert schon, getchar auch. Die Files schaue ich mir mal heute abend in Ruhe an. gruss, Christian
Christian J. schrieb: > und mit Asm bin ich ja sowieso > dabei, allerdings macht hier Übung der Meister, bis man nicht mehr alles > nachschauen muss, zb was indirekte Adressierung angeht usw. Hier ist eine Gedächtnisstütze. Das Ding stammt aus einer mc von 1982 und war damals sehr hilfreich. Ausgegraben habe ich es wieder, als wir für den AVR-CP/M-Computer den Z80-Interpreter gebaut haben. Danach habe ich zwischendurch immer mal wieder einen Block davon eingetippt. Nur die Farbe hat immer noch gefehlt. Bis heute. Auch wenn man heutzutage wohl selten die Opcodes eintippt, als Übersicht, welcher Befehl mit welchen Operanden funktioniert, und ob und wie die Flags beeinflusst werden, ist das "Poster" immer noch gut zu gebrauchen.
Danke aber auch das habe ich schon... in bunt ist aber cool, gleich mal ausgedruckt.
Das geht bei mir nicht! Wenn gsinit in der Area _GSINIT liegt wird ein Sprung ins Ram erzeugt wo nichts ist. Ich habe ewig dazu gebraucht das rauszu finden. gsinti daherin die Code Area übernommen und den Call weg gemacht Daanke für das makefile... ist nicht so meine Welt sowas. Baue ich noch ein. geht nicht:
1 | ;; Initialise global variables |
2 | call gsinit |
3 | call _main |
4 | jp _exit |
5 | |
6 | .area _CODE |
7 | _exit:: |
8 | ;; Exit - ddtz breakpoint entry |
9 | rst 0x30 |
10 | 1$: |
11 | halt |
12 | jr 1$ |
13 | |
14 | .area _GSINIT |
15 | gsinit:: |
16 | ld bc, #l__INITIALIZER |
17 | ld a, b |
18 | or a, c |
19 | jr Z, gsinit_next |
20 | ld de, #s__INITIALIZED |
21 | ld hl, #s__INITIALIZER |
22 | ldir |
23 | gsinit_next: |
geht:
1 | ;/////////////////////////////////////////////////////////// |
2 | ;; ------- Start des Hauptprogramms nach der Zeropage ----------- |
3 | |
4 | .area _CODE |
5 | init: |
6 | |
7 | ld sp,#stack ;; Stack an Spitze des RAM legen |
8 | |
9 | ; Teste ob Userprogramm im RAM vorhanden |
10 | ; .... |
11 | |
12 | ; Ram ausnullen (auskommentieren, wenn von PC Upload erfolgt) |
13 | xor a ; clear a and carry |
14 | ld bc,#0xdfff ; ram size left |
15 | ld hl,#0x2000 ; starting from 2000 |
16 | ld de,#0x2001 |
17 | ld (hl),a ; 0 -> (2000) |
18 | ldir ; (HL) -> (DE) |
19 | |
20 | ; Initialisiere globale Variablen im RAM |
21 | ld bc, #l__INITIALIZER |
22 | ld a, b |
23 | or a, c |
24 | jr Z, weiter |
25 | ld de, #s__INITIALIZED |
26 | ld hl, #s__INITIALIZER |
27 | ldir |
28 | |
29 | weiter: |
30 | |
31 | ; ###### Hauptprogramm aufrufen ####### |
32 | jp _main |
33 | |
34 | ; Endlos Schleife |
35 | halt |
36 | endlos: |
37 | jr endlos ; Sicher ist sicher |
38 | halt |
39 | |
40 | ; // Hier muss ein ret rein |
41 | .area _GSFINAL |
42 | ret |
> Das geht bei mir nicht!
Dann poste mal die komplette crt0.s (als Anhang)
Christian J. schrieb: > Danke aber auch das habe ich schon... Dann weißt Du ja jetzt, wo Matthias Buchhorn die Seiten 7 bis 9 abgekupfert hat. ;) Allerdings hat er für die Schiebebefehle noch Graphiken zugefügt. Mal sehen, ob ich die auch noch rein bekomme. > in bunt ist aber cool, gleich mal ausgedruckt. Und dann die beiden Seiten in eine Klarsichthülle, zum leichten Greifen und Wenden. Besser als 11 Seiten, die man blättern muß.
Leo C. schrieb: > Dann poste mal die komplette crt0.s (als Anhang) s. Anhang. es funktioniert nur so, da sonst der CD (gsinit) eine RAM Adresse zugeordnet bekommrt, weil die ganze Area _GSINIT dem RAM Bereich zugeordnet wird aus dem --data-loc Wort des Aufrufes. Die Area kann über den Linker sdld - .... auf einen Wert gefixt werden aber es gibt kein Beispiel und die Man Page ist kryptisch. Ich habe den Linker nicht benutzt sondern lasse das über sdcc erledigen. btw Manual: Ich habe noch nie ein Variable "c;" allein gesehen. Keine Ahnung was das soll.
1 | void to_buffer( unsigned char c ) |
2 | { |
3 | c; // to avoid warning: unreferenced function argument |
4 | __asm |
5 | ; save used registers here. |
6 | ; If we were still using r2,r3 we would have to push them here. |
Da Du dich ja so gut auskennst, wie würde ein Preprozessor Makro in C aussehen was mir alle register Pop't und eines was alle Push'ed. Mehrzilige makros habe ich noch nicht benutzt und kenne die Syntax auch nicht.
> btw Manual: Ich habe noch nie ein Variable "c;" allein gesehen. Keine > Ahnung was das soll. Ich kenne das nur in der Variante "(void)variable;". Das sagt dem Compiler, dass diese Variable benutzt wird und nicht wegoptimiert werden darf. Damit fällt eine Warnung weg, wenn man eine Variable z.B. nur in Inline-Asm benutzt.
Hallo, Bleibt eigentlich noch zu klären warum RST7 die gleiche Adresse 0x38 hat wie der Mode 1 Interrupt, den ich mal ausprobiert habe und der auch gut funktioniert. Die crt0.s fasse ich soweit nicht mehr an, da jetzt einschliesslich aller Fehlerabfangmechanismen das Ding läuft und genau das tut, was es soll. Da habe ich mir mich philipp Krause, der an dem sdcc mitwirkt einen Worlf diskutiert wo nun welches Segment steht und in welcher Reihenfolge das alles sein muss. Da kommt man nämlich nie drauf, wenn man nicht in jede Falle reinlief. Grundsätzlich ist alles nach dem ersten .area "relativ" zu sehen und kein .org darf da mehr stehen, es sei denn man definiert die .area (ABS) als absolut und teilt dem Linker mit wohin er sie zu legen hat, was wiederum nicht dokumentiert ist und die Syntax dazu Raterei ist. Mit --data-loc und --code-loc ist soweit alles gesagt, dass er weiss wohin es kommt, klar zwischen ROM Code und RAM unterscheidet. ------ ROM Start --code-loc= 0x100 ------ .area _CODE .area _INITIALIZER .area _HOME .area _GSINIT .area _GSFINAL ------------ROM Ende = RAM Start 0x2000 --------- .area _DATA .area _INITIALIZED .area _BSEG .area _BSS .area _HEAP Demzufolge müsste GSINIT eigentlich ins ROM zeigen aber alles was ich da reinschreibe landet mit Bezug zum RAM .... rätsel. Das "Kerlchen" spielt schon ganz prima, säuft Sprit, ähm Strom wie ein LKW und es macht Spass mal was anderes als nur einen Controller zu haben, der plug & play funktioniert und dank Arduino von jedem Schulkind zu bedienen ist.
S. R. schrieb: > Ich kenne das nur in der Variante "(void)variable;". Das sagt dem > Compiler, dass diese Variable benutzt wird und nicht wegoptimiert werden > darf. Damit fällt eine Warnung weg, wenn man eine Variable z.B. nur in > Inline-Asm benutzt. Eigentlich ist das eher ein Hinweis an Compiler und sich selbst, dass es Absicht ist, und kein Versehen. Inhaltlich ergibt das m.E. keinen Unterschied.
Christian J. schrieb: > Bleibt eigentlich noch zu klären warum RST7 die gleiche Adresse 0x38 > hat wie der Mode 1 Interrupt Weil Zilog zu faul war, es anders zu machen. ;-) IM0 liest im IACK einen Befehl vom Bus. Wie 8080. Exakt deshalb gibt es überhaupt die RST Befehle, damit das ohne grossem Aufwand in einem Byte geht. IM1 tut genau das gleiche wie IM0, kriegt aber statt dessen 0xFF = RST7. IM1 springt also nicht wirklich nach 0x38, sondern führt RST7 aus.
:
Bearbeitet durch User
Christian J. schrieb: > Das geht bei mir nicht! > Wenn gsinit in der Area _GSINIT liegt wird ein Sprung ins Ram erzeugt wo > nichts ist. (Kein Sprung, sondern ein Call, der auch wieder zurückkommen soll.) In dem Fall wurde die GSINIT-Area ins RAM gelegt was natürlich nicht sein sollte. Das Problem hatte ich auch mal. Ca. 2 Wochen her, und dann hatte ich das nicht mehr weiter verfolgt. Die alte crt0.s habe ich nicht mehr. Könnte sein, daß ich beim Linken crt0 am Schluß statt am Anfang hatte. Christian J. schrieb: > Die crt0.s fasse ich soweit nicht mehr an, da jetzt einschliesslich > aller Fehlerabfangmechanismen das Ding läuft und genau das tut, was es > soll. Es tut bei Dir eben nicht was es soll. Die statischen lokalen Variablen werden nicht initialisiert, und irgendwann behauptest Du wieder, das wäre ein Fehler von sdcc. Außerdem hast Du mir vorhin per Mail geschrieben, daß Du Fehler eben nicht abfangen willst. Deine "Mechanismen" sind wirkungslos oder verschleiern sorgar Fehler. Hoffnungslos. Für anderen, die hier noch mitlesen.. Christians crt0.s habe ich so (zurück) geändert, das die Initialisierung der globalen Variablen wieder im Unterprogramm gsinit in der Area _GSINIT liegt. Seine Interruptvektoren habe ich durch Platzhalter ersetzt, sonst habe ich nichts verändert. Ich kann diese Datei mit meinem Testprogramm von weiter oben linken, und alles liegt am richtigen Platz. crt0.rst
1 | 138 .area _CODE |
2 | 0100 139 init: |
3 | 140 |
4 | 0100 31 FF FF [10] 141 ld sp,#stack ;; Stack an Spitze des RAM legen |
...
1 | 154 ;; Initialise global variables |
2 | 0110 CD 72 0C [17] 155 call gsinit |
3 | 156 |
4 | 157 ; ###### Hauptprogramm aufrufen ####### |
5 | 0113 C3 1A 01 [10] 158 jp _main |
6 | 159 |
7 | 160 ; Endlos Schleife |
8 | 0116 76 [ 4] 161 halt |
9 | 0117 162 endlos: |
10 | 0117 18 FE [12] 163 jr endlos ; Sicher ist sicher |
11 | 164 |
12 | 0119 C9 [10] 165 ret |
13 | 166 |
14 | 167 ; Initialisiere globale Variablen im RAM |
15 | 168 .area _GSINIT |
16 | 0C72 169 gsinit:: |
17 | 0C72 01 02 00 [10] 170 ld bc, #l__INITIALIZER |
18 | 0C75 78 [ 4] 171 ld a, b |
19 | 0C76 B1 [ 4] 172 or a, c |
20 | 0C77 28 08 [12] 173 jr Z, weiter |
21 | 0C79 11 02 20 [10] 174 ld de, #s__INITIALIZED |
22 | 0C7C 21 70 0C [10] 175 ld hl, #s__INITIALIZER |
23 | 0C7F ED B0 [21] 176 ldir |
24 | 0C81 177 weiter: |
25 | 178 |
26 | 179 ;**************************************** |
27 | 180 ; hier wird der Initialisierungscode für |
28 | 181 ; statische funktionslokole eingefügt |
29 | 182 ;**************************************** |
30 | 183 |
31 | 184 ; // Hier muss ein ret rein |
32 | 185 .area _GSFINAL |
33 | 0C91 C9 [10] 186 ret |
Liegt alles im ROM. hallo_static.rst:
1 | ;-------------------------------------------------------- |
2 | 36 ; global & static initialisations |
3 | 37 ;-------------------------------------------------------- |
4 | 38 .area _HOME |
5 | 39 .area _GSINIT |
6 | 40 .area _GSFINAL |
7 | 41 .area _GSINIT |
8 | 42 ;hallo-static.c:8: static int count = 5; |
9 | 43 ; genAssign |
10 | 44 ;fetchLitPair |
11 | 0C81 FD 21 00 20 [14] 45 ld iy,#_main_count_1_13 |
12 | 0C85 FD 36 00 05 [19] 46 ld 0 (iy),#0x05 |
13 | 47 ;fetchLitPair |
14 | 0C89 FD 21 00 20 [14] 48 ld iy,#_main_count_1_13 |
15 | 0C8D FD 36 01 00 [19] 49 ld 1 (iy),#0x00 |
Wie man sieht, wird der Initialisierungscode aus hallo_static in _GSINIT am Ende angehängt. Nach allen Initialisierungsabschnitten der C-Dateien (hier gibts nur den einen), kommt die GSFINAL-Area mit dem ret-Befehl. Die rst-Dateien erzeugt übrigens der Linker bei gesetztem Schalter '-u'. Er setzt dann in die lst-Dateien des Compilers die aufgelösten Adressen ein. Im Anhang ist das ganze "Projekt", mit den vollständigen Dateien.
A. K. schrieb: > IM1 tut genau das gleiche wie IM0, kriegt aber statt dessen 0xFF = RST7. > IM1 springt also nicht wirklich nach 0x38, sondern führt RST7 aus. Eben, die waren nicht zu faul, sondern haben es faulen Entwicklern noch einfacher gemacht.
Christian J. schrieb: > wie würde ein Preprozessor Makro in C > aussehen was mir alle register Pop't und eines was alle Push'ed. Wozu soll das gut sein? Im Inline-Assembler braucht braucht man die Register des Aufrufers nicht zu retten. Wenn Du da soviel Code reinschreibst, daß Du Deine eigenen Zwischenstände retten mußt, machst Du irgendwas falsch. Blieben noch Interrupt-Service-Routinen, die __naked deklariert sind. So viele können das nicht sein. Etwas copy-and-paste ist da sicher keine Zumutung. > Mehrzeilige makros habe ich noch nicht benutzt und kenne die Syntax auch > nicht. Es gibt keine mehrzeiligen Makros. Aber man kann eine (logische) Makrozeile mit '\' am Zeilenende über mehrere physikalische Zeilen verteilen.
Leo C. schrieb: > Wie man sieht, wird der Initialisierungscode aus hallo_static in _GSINIT > am Ende angehängt. Nach allen Initialisierungsabschnitten der C-Dateien > (hier gibts nur den einen), kommt die GSFINAL-Area mit dem ret-Befehl. Ich kann Dir grad genau sagen was dabei herauskommt wenn ich deine crt0.s verwende: CD 00 00 oder anders call 0x0000 im Hex File, also Brennfile. beim Aufruf call gsinit. Immerhin was Neues, gabs noch nicht. Init lokaler Vars zu Fuss: 123 ;interrupts.c:21: static int variable = 5; 0000 FD 21r51r00 [14] 124 ld iy,#_nmi_vint_variable_1_77 0004 FD 36 00 05 [19] 125 ld 0 (iy),#0x05
Christian J. schrieb:
Mit einer Antwort warte ich wohl noch eine Weile. Man weiß ja nie, wie
oft Du den Text noch änderst, oder wieviele Abschnitte, die alles wieder
anders aussehen lassen, anhängst.
ES GEHT NICHT ! Ok? Ich habe das schon hundertmal durchprobiert.... diese sch..... GSINIT liegt immer falsch ! Lassen wir es hier auch bitte gut sein. Es hat so funktioniert und ich habe auch keine Lust mehr da ewig dran zu sitzen, warum das mit den .areas so ist und nicht anders. Ich kann noch mal deine Sache gleich durchkompilieren aber dazu brauche ich zeit,.
Lieber Christian, mit den zwei Schnipseln oben kann man ohne weiteren Kontext absolut nichts anfangen. Ganz ehrlich.
Hier die crt0.s und den Memory Dump musst du mir glauben, den ich im Brenner Tool sehe und wo der Call auf 0x0000 zeigt. vorher nach 0x2000.
1 | ;-------------------------------------------------------------------------- |
2 | ; crt0.s - Generic crt0.s for a Z80 |
3 | ; |
4 | ; Minimum Z80 System mit Mostek 3801 Multi I/O Chip |
5 | ; |
6 | ;-------------------------------------------------------------------------- |
7 | |
8 | .module crt0 ; Modul Name für den Linker |
9 | |
10 | ; Memory Map Adressen der Zeropage (vom Benutzer definierbar) |
11 | ; 0x00 Reset Vector und Aufruf Hauptprogramm |
12 | ; 0x38 Mode 1 Int Vektor |
13 | ; 0x40 Mode 2 Vektor Tabelle für STI Mostek Multi I/O |
14 | ; 0x66 NMI Reset Vektor |
15 | ; 0x80 Copyright String |
16 | ; 0x100 User Programm |
17 | |
18 | ; Definitions |
19 | stack .equ 0xffff |
20 | adr_vec_table .equ 0x40 |
21 | adr_nmi .equ 0x66 |
22 | adr_copyright .equ 0x80 |
23 | adr_userprog .equ 0x100 |
24 | |
25 | ; Globale Funktionen und Variablen für das C-Programm |
26 | |
27 | .globl _main |
28 | .globl _nmi_vint ; Funktion des NMI Handlers |
29 | |
30 | ; Interruptroutinen für den Mostek MK3801 Multi I/O Baustein |
31 | ; Manual STI Baustein MK3801 Figure 7 |
32 | .globl _int_sti_gpi_0 ; General Purpose Interrupt 0 |
33 | .globl _int_sti_gpi_1 ; General Purpose Interrupt 1 |
34 | .globl _int_sti_gpi_2 ; General Purpose Interrupt 2 |
35 | .globl _int_sti_gpi_3 ; General Purpose Interrupt 3 |
36 | .globl _int_sti_timer_d |
37 | .globl _int_sti_timer_c |
38 | .globl _int_sti_gpi_4 ; General Purpose Interrupt 4 |
39 | .globl _int_sti_gpi_5 ; General Purpose Interrupt 5 |
40 | .globl _int_sti_timer_b |
41 | .globl _int_sti_transmit_error |
42 | .globl _int_sti_transmit_buffer_empty |
43 | .globl _int_sti_receive_error |
44 | .globl _int_sti_receive_buffer_full |
45 | .globl _int_sti_timer_a |
46 | .globl _int_sti_gpi_6 ; General Purpose Interrupt 6 |
47 | .globl _int_sti_gpi_7 ; General Purpose Interrupt 7 |
48 | ; Mode 1, alles auf eine Routine umleiten |
49 | .globl _int_sti_all |
50 | |
51 | .globl l__INITIALIZER |
52 | .globl s__INITIALIZER |
53 | .globl s__INITIALIZED |
54 | |
55 | ; ------------------------------------------------------------- |
56 | |
57 | .area _HEADER (ABS) |
58 | ; Reset vector bei Kaltstart und Sprung ins User Programm |
59 | .org 0 |
60 | jp init |
61 | |
62 | ;; Tabelle der RST Vektoren für Software Interrupts |
63 | .org 0x08 |
64 | ret |
65 | .org 0x10 |
66 | ret |
67 | .org 0x18 |
68 | ret |
69 | .org 0x20 |
70 | ret |
71 | .org 0x28 |
72 | ret |
73 | .org 0x30 |
74 | ret |
75 | ;.org 0x38 |
76 | ;reti |
77 | |
78 | |
79 | ;/////////////////////////////////////////////////////////// |
80 | ;// Mode 1 Interrupt |
81 | .org 0x38 |
82 | jp _int_sti_all |
83 | |
84 | |
85 | ;/////////////////////////////////////////////////////////// |
86 | ; Tabelle der Mode 2 Int Vektoren auf die Handler Funktionen im C Modul |
87 | ; Reihenfolge beachten !!! Siehe Manual Mostek 3801, Interrupt Tabelle |
88 | .org 0x40 |
89 | .dw (_int_sti_gpi_0) |
90 | .dw (_int_sti_gpi_1) |
91 | .dw (_int_sti_gpi_2) |
92 | .dw (_int_sti_gpi_3) |
93 | .dw (_int_sti_timer_d) |
94 | .dw (_int_sti_timer_c) |
95 | .dw (_int_sti_gpi_4) |
96 | .dw (_int_sti_gpi_5) |
97 | .dw (_int_sti_timer_b) |
98 | .dw (_int_sti_transmit_error) |
99 | .dw (_int_sti_transmit_buffer_empty) |
100 | .dw (_int_sti_receive_error) |
101 | .dw (_int_sti_receive_buffer_full) |
102 | .dw (_int_sti_timer_a) |
103 | .dw (_int_sti_gpi_6) |
104 | .dw (_int_sti_gpi_7) |
105 | |
106 | ;/////////////////////////////////////////////////////////// |
107 | ; NMI Interrupt 0x66, muss mit retn abgeschlossen werden |
108 | .org 0x66 |
109 | jp _nmi_vint ; Aufruf Handler im C Modul main.c |
110 | |
111 | ;/////////////////////////////////////////////////////////// |
112 | ; Anordung der Segmente fuer den Linker, ab hier nur relative |
113 | ; Adressen |
114 | |
115 | .area _CODE |
116 | .area _INITIALIZER |
117 | .area _HOME |
118 | .area _GSINIT |
119 | .area _GSFINAL |
120 | .area _DATA |
121 | .area _INITIALIZED |
122 | .area _BSEG |
123 | .area _BSS |
124 | .area _HEAP |
125 | |
126 | ;/////////////////////////////////////////////////////////// |
127 | ;; ------- Start des Hauptprogramms nach der Zeropage ----------- |
128 | |
129 | .area _CODE |
130 | init: |
131 | |
132 | ld sp,#stack ;; Stack an Spitze des RAM legen |
133 | |
134 | call gsinit |
135 | |
136 | ; Teste ob Userprogramm im RAM vorhanden |
137 | ; .... |
138 | |
139 | ; Ram ausnullen (auskommentieren, wenn von PC Upload erfolgt) |
140 | xor a ; clear a and carry |
141 | ld bc,#0xdfff ; ram size left |
142 | ld hl,#0x2000 ; starting from 2000 |
143 | ld de,#0x2001 |
144 | ld (hl),a ; 0 -> (2000) |
145 | ldir ; (HL) -> (DE) |
146 | |
147 | ; ###### Hauptprogramm aufrufen ####### |
148 | call _main |
149 | endlos: |
150 | halt |
151 | jr endlos |
152 | |
153 | .area _GSINIT |
154 | |
155 | ; Initialisiere globale Variablen im RAM |
156 | ld bc, #l__INITIALIZER |
157 | ld a, b |
158 | or a, c |
159 | jr Z, weiter |
160 | ld de, #s__INITIALIZED |
161 | ld hl, #s__INITIALIZER |
162 | ldir |
163 | |
164 | weiter: |
165 | |
166 | ; // Hier muss ein ret rein |
167 | .area _GSFINAL |
168 | ret |
Bei Dir sieht das ja auch anders aus da wird die Numerierung beo 0xc72 fortgesetzt, bei mir bei 0. 0119 C9 [10] 165 ret 166 167 ; Initialisiere globale Variablen im RAM 168 .area _GSINIT 0C72 169 gsinit:: 0C72 01 02 00 [10] 170 ld bc, #l__INITIALIZER 0C75 78 [ 4] 171 ld a, b 0C76 B1 [ 4] 172 or a, c 0C77 28 08 [12] 173 jr Z, weiter 0C79 11 02 20 [10] 174 ld de, #s__INITIALIZED 0C7C 21 70 0C [10] 175 ld hl, #s__INITIALIZER 0C7F ED B0 [21] 176 ldir 0C81 177 weiter: meines: 151 152 ; ###### Hauptprogramm aufrufen ####### 0013 CDr00r00 [17] 153 call _main 0016 154 endlos: 0016 76 [ 4] 155 halt 0017 18 FD [12] 156 jr endlos 157 158 .area _GSINIT 159 160 ; Initialisiere globale Variablen 0000 01r00r00 [10] 161 ld bc, #l__INITIALIZER 0003 78 [ 4] 162 ld a, b 0004 B1 [ 4] 163 or a, c 0005 28 08 [12] 164 jr Z, weiter 0007 11r00r00 [10] 165 ld de, #s__INITIALIZED 000A 21r00r00 [10] 166 ld hl, #s__INITIALIZER 000D ED B0 [21] 167 ldir 168 000F 169 weiter:
Hier alles zusammen, ich arbeite ohne Makefile, nur mit compile.sh
Wie kriegt man deine Kompiliert? >make > Fuer das Ziel all ist nichts zu tun"
Christian J. schrieb: > Hier die crt0.s und den Memory Dump musst du mir glauben, den ich im > Brenner Tool sehe und wo der Call auf 0x0000 zeigt. vorher nach 0x2000. Das muß ich überhaupt nicht glauben. ;) Schließlich habe ich oben den Linkerschalter gepostet. Falls Du immer noch das Shellscript zum compilieren verwendest, dann schreib doch mal das -u dazu. Konkret:
1 | sdcc -mz80 --verbose --no-std-crt0 -Wl-u --code-loc 0x0100 --data-loc 0x2000 crt0.rel main.rel |
Und dann schau dir die *.rst-Dateien an.
>make > Fuer das Ziel all ist nichts zu tun" In dem Archiv war ja auch alles schon fertig $ make clean $ make
Bei Dir liegt alles richtig, bei mir falsch :-( Kann also nur noch daran liegen dass ich ohne Makefile arbeite. ich versthehe von den Dingern nichts, habe sie noch nie benötigt. Kann ich das auch für 3 oder 4 Source dateien modifizieren? Bei mir binde ich die anderen dateien ja direkt ein, so dass nur noch main.c existiert für den Compiler. -u geht nur bei sdld nicht bei sdcc
Christian J. schrieb: > Compiler option -W1-u ignored ^ Das muß ein l sein. ell ell ell Außerdem: ?ASlink-Warning-Undefined Global 'gsinit' referenced by module 'crt0' Das label 'gsinit' fehlt in Deiner crt0. Da kommt dann auch der 'Call 0x0000' her. Das kommt davon, wenn man dem Assembler sagt, er soll alle undefinierten Symbole als Global annehmen. Das wiederum liegt aber nicht an Dir.
Zusammenfassung: Ich brauche eine Weile um das alles auf Makefile umzuschrieben. Das scheint mir auf jeden Fall sinnvoller, denn auch sonst überall wird zuerst alles kompiliert und dann gelinkt. All in One kenne ich nur vom CCS Compiler für PIC, der kann auch nur ein File verarbeiten und man muss tricksen, damit man mehr haben kann. Von Makefiles verstehe ich nichts, das hat bisher die jeweilige IDE alles übernommen. Es geht also nur darum ob es durch Ergänzung der Zeile SRC im Makefile um die anderen .c Sourcen ausreicht das Projekt zu kompilieren?
Habe das korrigiert, es wird immer noch CD 00 00 erzeugt, da _GSINIT auf 0x0000 definiert wurde. Bevor ich das alles umgearbeitet habe mache ich hier erstmal Sendepause. So schnell kann ich das nicht.
Christian J. schrieb: > Kann ich das auch für 3 oder 4 Source dateien modifizieren? Ja, einfach an die Zeile 'SRC = ' anfügen. Den Namen des Outputs (Hex- und bin-File kannst Du unter TARGET anpassen. > Bei mir binde ich die > anderen dateien ja direkt ein, so dass nur noch main.c existiert für den > Compiler. Das ist Murks.
das .rst File zeigt die gsinit übrigens an der richtigen Stelle.Da stimmt alles. Jetzt wird aber kein .ihx File mehr erzeugt, warum weiss ich auch nicht. Vorher ging das problemlos.... -opt-code-size verhindert das aus welchen Gründen.
Bevor du mir beim Modifzieren wieder daszwischen funkst und ich den Text nicht mehr ändern kann: --opt statt -opt..... und alles ist da. Grad alles gebrannt und eingesteckt. Es läuft. Mit der .sh Methode. Alles liegt richtig. Wie gesagt arbeite ich das heute abend auf Makefile um, weil mir das vernünftiger zu sein scheint als der "Murks". Dank Dir erstmal,war ne schwere Geburt aber das Kind ist da....
Hi, kurze Rückmeldung. Nach fixer Umarbeitung des Source auf Makefile und einigen "extern" die zugeführt werden mussten lief die Kiste auf Anhieb. Gruss, Christian
So..... mit dem Ram upload geht das Ganze doch schon deutlich entspannter vor sich als mit der EEPROM Stöpselei. Und bei einem reset bleibt auch alles im Ram erhalten und wird gestartet. NMI, Mode 2 Ints, alles klappt. Etwas nervig ist derzeit noch die fixe Größe der .bin datei da unnützer Müll übertragen wird aber aktuell fällt mir noch nichts Gescheites ein, wie ich sehr einfach das Ende des Datenstromes erkennen kann in dem ich die Dateilänge vorher sende ohne dass ich die Ascii Zeichenkette mit variabler Länge wiederin Binärzahlen wandeln muss.Gibt zwar ein paar umständliche Lösungen aber die gefallen mir alle nicht. Der Upload "Monitor" ist grad mal 150 Bytes. Wens interessiert, noch absolut suboptimal weil kein Fehlerababfangen etc aber es läuft. "st" sind die Startzeichen, die nacheinander erkannt werden müssen, "--" bläst irgendwelchen Einschalt-Einstöpsel-müll vorher raus, danach kommen die Daten fixer Länge. echo -n muss sein, da sonst ein Zeilentrenner mit gesendet wird.
1 | #!/bin/bash
|
2 | dd if=z80rom.bin of=z80rom4.bin ibs=4096 conv=sync |
3 | echo "Datei zum Target uebertragen..." |
4 | stty raw ospeed 9600 -F /dev/ttyUSB0 |
5 | echo -n "--st" > /dev/ttyUSB0 |
6 | cat z80rom4.bin > /dev/ttyUSB0 |
Etwas tricky ist die Verwendung von Variablen im Monitor Programm, da die nicht durch den Ram Upload überschrieben werden dürfen. Man muss sich weit weg genug legen, knapp unter "die Decke" des RAM. Eine ASM Lösung nur mit Registern wäre hier sicherlich optimaler gewesen.
Christian J. schrieb: > Etwas nervig ist derzeit noch die fixe Größe der .bin datei da unnützer > Müll übertragen wird aber aktuell fällt mir noch nichts Gescheites ein, So nervig können die paar Millisekunden doch nicht sein. Ansonsten: Lader für Intel-Hex einbauen. Das ist nicht so schwer, und Beispiele findes Du sicher massig im Netz. Da war noch was in der Pipeline.. Christian J. schrieb: > arbeite ich das heute abend auf Makefile > um, weil mir das vernünftiger zu sein scheint als der "Murks". "Murks" bezog sich nicht auf Script vs. Makefile. Du könntest ja auch im Script den Compiler für jede C-Datei einzeln aufrufen. Mit Murks meinte ich das hier:
1 | // Einbindung von weiteren Modulen.
|
2 | #include "driver.c" |
3 | |
4 | |
5 | void main() |
6 | {
|
7 | ....
|
8 | }
|
9 | |
10 | #include "interrupts.c" |
11 | |
12 | // An das Ende des Codes die Interrupt Routinen dran hängen
|
Und dann stehen die includes noch nicht mal am Anfang der Datei, wo man sie noch leicht finden könnte, sondern In der Mitte und am Ende. Wie heißt nochmal die Steigerung von Murks? ;-)
Leo C. schrieb: > Und dann stehen die includes noch nicht mal am Anfang der Datei, wo man > sie noch leicht finden könnte, sondern In der Mitte und am Ende. Wie > heißt nochmal die Steigerung von Murks? ;-) Tja, da denkst du wieder nicht soweit wie ich...... das habe ich ganz absichtlich gemacht, damit ich im Editor den .lst Code schnell wiederfinde und nicht mittendrin suchen muss, weil sich bei jedem Kompliervorgang die Fenster neu laden und der Cursor nach oben springt. Ich wollte die Ints hinten im Code liegen haben :-) Ich musste wegen dem Brenner unter Windows arbeiten und hatte folgendes Chaos auf dem Bildschirm: Brenneranwendung Notepad ++ putty Kompilier-Window zum Cubietruck wo die Z80 Sache abläuft noch ein putty zum Cubietruck für die USB Schnittstelle Terminalfenster für die Ausgabe ganz schön eng ;:-) // An das Ende des Codes die Interrupt Routinen dran hängen Stand auch da! >>Lader für Intel-Hex einbauen. Das ist nicht so schwer, und Beispiele >>findes Du sicher massig im Netz. Jede Menge aber die blasen die Code Size erst richtig auf durch scanf und jede Menge String Funktionen, schlucken ordentlich Memory im Ram und genau das habe ich nicht. Wobei ....15 Minuten mal eingelesen und reingeschaut in das Format... das schreibe ich auch selbst in 1/2 Tag. Nur Record Typ 00 wird verwendet. http://en.wikipedia.org/wiki/Intel_HEX
Wenigstens Record Type 01 solltest du unterstützen, sonst ist dein Ziel - nämlich das Dateiende zu erkennen - relativ schwierig. Geht übrigens auch ohne scanf und Stringfunktionen. Dann dürftest du den Lader in ein paar Bytes bekommen.
:
Bearbeitet durch User
Ja, ich habe mir das alles nochmal angeschaut. Problem ist, dass ich kein RTS/CTS habe, ich muss entweder on the fly decodieren oder eine ganze Zeile parsen und da ist nicht viel Zeit zwischen den Bytes (0,83ms = 3200 Maschinenzyklen, eher weniger), wenn ich Lib Funktionen benutze. Allerdings wird aus einer "5" auch durch Subtraktion von 0x48 auch eine \5, und BCD nach Binaer ist schnell gemacht. Codeprüfung evtl drauf verzichten. Den ganzen Satz auf einmal geht nicht, weil der das Ram füllt was ich ja brauche. Werde das Ganze heute mal in einer Statemachine codieren, wahrscheinlich in Asm. Leo ? Bist du da? Weisst Du ob der Compiler feststehende Ausdrücke hat, um zb die Adresse der Segmente (start und Ende) im Programmcode zu verarbeiten? Da würde einiges vereinfachen wie zb Prüfsummen über den RAM Bereich usw. Das hier scheint ja sowas zu sein: .globl l__INITIALIZER .globl s__INITIALIZER .globl s__INITIALIZED Sind die auch aus dem C Code erreichbar? Und gibt es davon noch mehr?
Christian J. schrieb: > Problem ist, dass ich kein RTS/CTS habe, XON/XOFF Software Handshake verwenden.
A. K. schrieb: > XON/XOFF Software Handshake verwenden. Das hat er ja auch nicht. Er denkt ja jetzt schon über den Lader, den er erst partout nicht haben und dann in einem halben Tag fertig haben wollte, so laut nach, bis irgend jemand so genervt ist, daß er ihm eine fertige Lösung präsentiert... Dabei könnte er ja durchaus mal eine Weile bei dem Binärlader bleiben, bis er ein besseres Gefühl für Codegrößen und Ausführungsgeschwindigkeiten bekommt. Ich bin nämlich der Meinung, daß es auch in C ohne Handschake gehen müßte. Frage mich allerdings, wie er auf 0,83ms/Zeichen kommt.
Leo C. schrieb: > Er denkt ja jetzt schon über den Lader, den er > erst partout nicht haben und dann in einem halben Tag fertig haben > wollte, so laut nach, bis irgend jemand so genervt ist, daß er ihm eine > fertige Lösung präsentiert... Nur mal kurz so ganz abseits der Technik: Das Internet besteht aus Leuten, die bereit sind das was sie machen anderen zu präsentieren. Ich kriege das alles (irgendwann) auch so hin, ohne hier darüber auch nur ein Wort zu verlieren. Ingenieure und Techniker gelten nicht gerade als "sozial kompetent" wie mir viele Jahre im Job zeigten wo ich genügend Spinner kennenlernte, die man bloss nicht aus dem Labor lassen sollte. Kein Thema, erledigt. Ein Mod kann den Thread gern zu machen. Ab hier gehts auch so weiter.... Die 0.83ms sind die reinen Maschinenzyklen, die vergehen, bis 9 x 1/9600 s Zeit vergangen ist für ein 8N1 protokoll. Grob über den Daumen gepeilt.
Wundere Dich doch bitte nicht Christian wenn hier Einer nach dem Anderen mitbekommt das Du Deine Probleme gerne gelöst bekommen hättest. :-) Ich habe vor ein paar Dave Dunfields Mon85 auf ein olles tschechisches Board mit 8080 Prozessor und 2 Mhz portiert. Ich weiß nicht ob u das weißt, ein 8080 ist der Vorgänger des Z80 und zeichnet sich dadurch aus, das ihm der komplette Schattenregistersatz, die Indexregister, der IM2 Interruptmode und etliche Z80 befehle fehlen (keine relativen Sprünge etc), der weiteren möchte der noch einen 2 Phasen Takt und 3 Betriebsspannungen, trotzdem hat das Ding nur eine geringfügig geringere Rechenleistung als ein Z80. CP/M2 läuft auch darauf. Der Monitor unterstützt jedenfalls bei dieser Gurke problemlos das laden von Intel-Hex Files, im meinem Falle über eine 8251 Uart. Da gibts kein Zeitproblem. Den Monitor gibts hier: https://github.com/phillipjohnston/8085-HI6130-Port/tree/master/Compiler/MON85 Evtl. möchtest Du da ja mal rein schauen, aber sei gewarnt, das Assembler File benutzt 8080 Mnemonics die nicht kompatibel zu Z80 Mnemonics sind, der Maschinencode ist aber für beide Prozessoren identisch. Es gibt aber auch jede Menge fertige Z80 Debug-Monitore die Leute schon ins Internet geladen haben, die haben nämlich kein Problem damit :-) und schwadronieren nicht nur drüber .. Du wurdest gewarnt: Nimm eine SIO ..nein Du wusstest das besser. Nimm IM2 .. nein..Du wusstest das besser. Die wird nahegelegt Dich nach der Source eines IHEX Loaders umzusehen.. nein, Du kannst das selber.. Dann mach mal.. Gruß, Holm
Naja Holm Man muß ihm schon zugestehen, dass er mit seinem Sturschädel schon weiter gekommen ist als manch andere Pussi hier im Forum und das ohne wirklich zu Ende durchdachtes Konzept. Namaste
:
Bearbeitet durch User
Leo C. schrieb: > Wenn man dieses Beispiel ohne Framepointer compiliert, wird beim Laden > des 2. Parameters das Zwischenergebnis in hl teilweise zerstört. (sdcc > 3.4.0) :( Der Bug wurde inzwischen bestätigt. Er tritt leider schon bei so etwas trivialem auf:
1 | int test(int pa, int pb) |
2 | {
|
3 | return pa*2 + pb; |
4 | }
|
Workaround: --fno-omit-framepointer
Leo C. schrieb: > Das hat er ja auch nicht. Brauchte er ja auch nicht. > Er denkt ja jetzt schon über den Lader, > den er erst partout nicht haben Was er jetzt hat ist das, was ich ihm geraten hatte. Einen einfachstmöglichen Loader, um die Brennerei los zu sein. Dem Hex-Loader kann er sich jetzt im RAM widmen, um den erst ins EPROM zu bannen, wenn fertig. > wollte, so laut nach, bis irgend jemand so genervt ist, daß er ihm eine > fertige Lösung präsentiert... Dabei hatte ich das schon beinahe, aber für SIO und nicht als C Programm. Aber psssst, nicht weitersagen. ;-) > Ich bin nämlich der Meinung, daß > es auch in C ohne Handschake gehen müßte. Vermute ich auch. Aber schaden tuts auch nicht und er will ja was zu tun haben. > Frage mich allerdings, wie er > auf 0,83ms/Zeichen kommt. 9600bd, 8 Bits pro Byte. Aber für BISYNC hätte er dann doch den Z80 SIO nehmen müssen. ;-)
:
Bearbeitet durch User
Tse....tse.... sowas habe ich schon 1987 mit dem 8085 mal gemacht, aber mit anderen Werkzeugen und dem Kenntnisstand von damals auch ich "drin" war. Das ist Jahre her. Upload vom C64 in das Ram des 8085 Systems. Es gibt noch einige Dinge nicht so erklärbar sind wie binäre Chaoszeichen nach dem Reset bei der Ausgabe über die Uart. Sporadisch, nicht ständig und immer in der ersten Zeile des Menu String Satzes. So als müsste die Uart sich erst "warmlaufen". Der Hex Uploder ist erstmal Konzept, verbal aufgeschrieben. Die Zeit reicht nicht um eine ganze Zeile zu bearbeiten bei 1 Byte Puffer Groesse des STI, wo es alle 0,9 ms mit einem neuen Bytes klingelt. Eas sei denn.... und dann verlassen wir den einfachen Bereich, ich mache die Zeicheneingabe über den Interrupt, spiele einen Puffer voll mit zwei Zeiger drauf, der dann vom Hauptprogramm abgearbeitet wird. Damit entkopple ich auf jeden Fall die Auswertung vom Datenstrom, da die Ints ja prior sind und jedes zeichen reingeholt wird. Endresultat soll ja mal sein, dass ein kleines Menü da steht. Einfache Befehle per Handeingabe aufzurufen sind und der Upload auch manuell aus Menüpunkt durchgeführt wird. Ein Erstellen im RAM und später brennen ins ROM ist nicht einfach, es warern unzählige Änderungen am Source nötig für die Adressen damit es aus dem RAM raus läuft, dam ich keine "Schlüsselwörter" kenne, die als Platzhalter fungieren. Da schüttel ich mir aber nicht aus dem Ärmel sonst muss da estmal ein Konzept machen, ein pflichteheft.
Christian J. schrieb: > des STI, wo es alle 0,9 ms mit einem neuen Bytes klingelt. Glaub ich dir nicht. Nicht bei 9600bd. Für die vorhin genannten 0,83ms bräuchtest du 12000bd.
:
Bearbeitet durch User
Über den Daumen! Fangen wir jetzt nicht an um die Mikrosekunden zu feilschen. 9600 baud = 9600 bit/s = 0,0001s / Bit 1 Byte 8N1 = 8 Bit Nutzlast + 2 Steuerbits = 10 Bits => 0,001s/byte = 1000 Bytes/s Maschinentakt 3.964.000 Takte /s = 0,25us/Takt => 3964 Takte zwischen den Bytes reicht für on-the-fly Decodierung aus aber NICHT um eine ganze Zeile komplett zu decodieren.
Christian J. schrieb: > => 0,001s/byte = 1000 Bytes/s Von hinten durch die Brust ins Auge. ;-) 9600bd bei 10 Bits sind 960 Bytes/s. > reicht für on-the-fly Decodierung aus Eben. Ok, das ist zunächst nicht absolut narrensicher, dafür wäre eine Adressvalidierung nötig, denn die könnte einen Übertragungsfehler haben.
:
Bearbeitet durch User
A. K. schrieb: > Von hinten durch die Brust ins Auge. ;-) > 9600bd bei 10 Bits sind 960 Bytes/s. Jaaaaaaaa.... Ok. Das ist auf jeden Fall machbar, wenn man etwas in Asm schreibt und vielleicht auf prüfsumme etc verzichtet. Der Abend ist noch lang..... > denn die könnte einen Übertragungsfehler haben. Hobby! Auf demSchreibtisch. Nicht Industrie! Keine Leitungen, die den Schrank verlassen daher auch keine Anwendung der Feldbus-Norm, die einen Zeitstempel+Frame+CRC etc verlangt :-)
Christian J. schrieb: > => 3964 Takte zwischen den Bytes Also mindestens 500 Befehle. Da geht einiges.
A. K. schrieb: > Christian J. schrieb: >> => 3964 Takte zwischen den Bytes > > Also mindestens 500 Befehle. Da geht einiges. Fetch = 3 T-Zyklen Decode = 3-4 T-Zyklen Execute = 2-5 T-Zyklen Eher deutlich weniger als 500. Worst Case eher 100-200. Oder eer kriegt einen Arduino davor mit 12 Mhz, der das fix macht..... naja, nicht so ganze Retro vielliecht.
Christian J. schrieb: > Fetch = 3 T-Zyklen > Decode = 3-4 T-Zyklen > Execute = 2-5 T-Zyklen Quark. Wo hast du das den aufgelesen? Einfache Befehle, die nur aus dem M1 Zyklus bestehen, brauchen 4 Takte. Fetch steckt in der ersten Hälfte vom M1, Decode in der zweiten (dem Refresh). Ausgeführt wird danach, währen dem M1 vom Folgebefehl.
:
Bearbeitet durch User
@A.K. Unbestätiogten Gerüchten zufolge, soll es bereits streng geheime Mikrocomputer geben, die den ganzen Klumpatsch an Chips auf EINEM EINZIGEN Chip haben! Mit 256kb Flassch, 80kb RAM, SIO, PIO, CTC, JTAG Debug Interface ... alles drauf! Kannst du dir das vorstellen? . . . . . :-)
Und was willst du mir damit sagen? Sorry, aber wie der Z80 tickt und timet weiss ich. Also das Original von Zilog aus den 70ern. Wer mal die Arbeitsweise eines Sinclar ZX80 analysiert hat, der kennt das, Sir Clive hatte da einige Tricks ausgenutzt. Und wenn du damit ausdrücken willst, es hätte in damaligen Mikroprozessoren keine Überlappung von F/D/X Phasen gegeben (= Pipelining), dann darf ich dich korrigieren. Es hat. Im 6502 auch.
:
Bearbeitet durch User
A. K. schrieb: > Und was willst du mir damit sagen? Das das Thema unangenehm wird, und er es gerne wechseln möchte... Im Anhang ist eine ein kompletter Intel-Hex-Lader in Assembler. Die Kommentare sind etwas spärlich, sollte aber reichen. Das Listing stammt ursprünglich aus einem Dissassembler. Hab den vor fast 30 Jahren auf ROM umgestellten ddtz auf dem Höhepunkt meines Retrofiebers ;) aus einem EPROM ausgelesen. Ein gedrucktes Listing hatte ich noch, so daß das ganz flott ging. Der Lader addiert zu jedem Byte einen Offset (normalerweise 0), überprüft untere und obere Ladegrenze und checkt natürlich an jedem Record-Ende die gleichnamige Summe.
Sehr kompakt...... ! bevor ich gleich pause mache .... Experimente mit gets und atoi sind zwar erfolgreich aber allein atoi bläst den Code um fast 500 Bytes auf um aus "2000" ein 0x2000 zu machen. printf schießt ihn auf 5300 Bytes hoch und scanf dabei sprengt die 8KB Grenze fast. Grundsätzlich aber ist mit minicom jetzt ein interaktiver Dialog möglich, mit Eingabe und Ausgabe. printf("a=?") scanf("%d",&a); printf("b=?") scanf("%d",&c); printf("a+b=&d",a+b); Läuft wie auf dem PC. Sehr nett...
Christian J. schrieb: > 8N1 Das funktioniert natürlich, zeigt aber sofort den Theoretiker. 8N2 ist wesentlich robuster und nur unwesentlich langsamer. (und ein Übertragungs "Protokoll" sind beide nicht)
Christian J. schrieb: > Tse....tse.... > > sowas habe ich schon 1987 mit dem 8085 mal gemacht, aber mit anderen > Werkzeugen und dem Kenntnisstand von damals auch ich "drin" war. Das ist > Jahre her. Upload vom C64 in das Ram des 8085 Systems. Ich nicht, ich hatte damals schon Z80. Ich habe aber im Wesentlichen die olle Karte repariert: http://www.tiffe.de/Robotron/TESLA/SM2138/P4070208s.JPG und wie man sieht ist due auch nicht so bestückt wie ursprünglich mal vorgesehen, die ziemlich vergriesgnaddelten Schaltpläne die ich da bekommen habe waren nur teilweise hilfreich. Das Ding stammt aus einem alten TESLA Terminal (CM7201 IMHO) das mal an einem tschechischen Nachbau einer PDP11 tätig war. Ich habe das eigntlich nur repariert um einem Freund aus dem Robotron-Forum die Reparatur des Terminals leichter zu machen, allerdings hat dieser in einem Anfalls von Aufräumwahn das Terminal entsorgt als ich fertig war. Die Karten von dem Ding hat er aber aufgehoben. Ich habe nun drüber nachgedacht Sohnemann das Ding zum Spielen auf den Tisch zu legen, mit einer 7Seg Anzeige und einer Hexa Tastatur dran, Allerdings ist Jemand aus dem Robotron-Frorum gerade dabei den LC80 neu aufzulegen, sowas wie die DDR Variante des "Mikroprofessors", ist wegen existierendem Handbuch sicher besser geeignet und mit Z80. > > Es gibt noch einige Dinge nicht so erklärbar sind wie binäre > Chaoszeichen nach dem Reset bei der Ausgabe über die Uart. Sporadisch, > nicht ständig und immer in der ersten Zeile des Menu String Satzes. So > als müsste die Uart sich erst "warmlaufen". Frequenzzähler an den Taktgenerator hängen... > > Der Hex Uploder ist erstmal Konzept, verbal aufgeschrieben. Die Zeit > reicht nicht um eine ganze Zeile zu bearbeiten bei 1 Byte Puffer Groesse > des STI, wo es alle 0,9 ms mit einem neuen Bytes klingelt. Eas sei > denn.... und dann verlassen wir den einfachen Bereich, ich mache die > Zeicheneingabe über den Interrupt, spiele einen Puffer voll mit zwei > Zeiger drauf, der dann vom Hauptprogramm abgearbeitet wird. Damit > entkopple ich auf jeden Fall die Auswertung vom Datenstrom, da die Ints > ja prior sind und jedes zeichen reingeholt wird. > > Endresultat soll ja mal sein, dass ein kleines Menü da steht. Einfache > Befehle per Handeingabe aufzurufen sind und der Upload auch manuell aus > Menüpunkt durchgeführt wird. > > Ein Erstellen im RAM und später brennen ins ROM ist nicht einfach, es > warern unzählige Änderungen am Source nötig für die Adressen damit es > aus dem RAM raus läuft, dam ich keine "Schlüsselwörter" kenne, die als > Platzhalter fungieren. > > Da schüttel ich mir aber nicht aus dem Ärmel sonst muss da erst mal ein > Konzept machen, ein pflichteheft. Christian, das Laden von Intel Hex Dateien funktioniert aus diesen 8 Bit Prozessoren seit über 20 Jahren ohne Zeitprobleme und damals liefen die Teile eher nicht mit 4Mhz. Gruß, Holm
Holm Tiffe schrieb: > Christian, das Laden von Intel Hex Dateien funktioniert aus diesen 8 Bit > Prozessoren seit über 20 Jahren ohne Zeitprobleme und damals liefen die > Teile eher nicht mit 4Mhz. Holm, nette Spielsachen, die du das hast..... da habe ich früher mit nem Luftgewehr drauf geschossen und geguckt wie das splittert :-) Sind sicher auf der Rückseite noch ein paar Gleichrichterröhren und Relais für die CPU? Wo ist denn der Anschluss für den Dampfdruck:-) Nee..... mache das schon mit etwas mehr Komfort, auch wenn es bisher nur ein 1-Wort Parser ist. Bald wird es schon mehr ... so wie einst Linus Trovalds nur einen Terminal schreiben wollte und dann entdeckte, dass er ein Betriebssystem geschrieben hat ... da fühlt man sich wie Kolumbus vor der Entdeckung Amerikas :-) Ich brauche kein Intel Hex mehr.... da wo ich hinfliege gibt es keine Strassen :-) Das Doofe ist nur, dass auch Backspace, Pfeile etc übertragen werden und bei gets() lässt sich da nix filtern, das sichere fgets gibt es nicht und es werden echos erzeugt. minicom hat als echtes Terminal keinen <CR> übertragungsmode.
Etwas nervig ist nur das "Krücken-Script", da ich noch versuche mit der Bash warm zu werden und sogar das "Galileo Shell programming" in der Nähe des Kopfkissens liegen habe. Allein schon der Umstand mit den Leerzeichen, die mal fehlen und mal zuviel sind. sleep kann nur 1s verzögern, ohne Verzögerung ist der PC zu schnell und es werden Zeichen verschluckt im riesigen 1-Byte Buffer der SIO. Vorteil ist nur: Es klappt, zusammen mti Geany, da drin angepassten Kompilieroptionen ist es ein sehr kurzer Weg von der Änderung zum Testen. 2 Klicks um genau zu sein.
1 | #!/bin/bash
|
2 | echo "---------------------------------" |
3 | echo "Datentrasnfer zum Z80" |
4 | echo "---------------------------------" |
5 | |
6 | echo "Stelle tty/USB0 auf 9600 baud ein....." |
7 | stty 9600 -crtscts -ixoff -F /dev/ttyUSB0 |
8 | |
9 | echo "Sende "load" Startsequenz...." |
10 | echo "load" > /dev/ttyUSB0 |
11 | sleep 1
|
12 | stat -c %s z80rom.bin > /dev/ttyUSB0 |
13 | sleep 1
|
14 | |
15 | echo "Uebertrage Daten...." |
16 | cat z80rom.bin > /dev/ttyUSB0 |
17 | sleep 1
|
18 | echo "Sende "start" Signal um Upload zu starten..." |
19 | sleep 1
|
20 | echo "start" > /dev/ttyUSB0 |
21 | echo "Fertig!" |
Christian J. schrieb: > Holm Tiffe schrieb: >> Christian, das Laden von Intel Hex Dateien funktioniert aus diesen 8 Bit >> Prozessoren seit über 20 Jahren ohne Zeitprobleme und damals liefen die >> Teile eher nicht mit 4Mhz. > > Holm, > > nette Spielsachen, die du das hast..... da habe ich früher mit nem > Luftgewehr drauf geschossen und geguckt wie das splittert :-) Sind > sicher auf der Rückseite noch ein paar Gleichrichterröhren und Relais > für die CPU? Wo ist denn der Anschluss für den Dampfdruck:-) > > Nee..... mache das schon mit etwas mehr Komfort, auch wenn es bisher nur > ein 1-Wort Parser ist. Du denkst scheinbar wirklich das Du da eine höhere Qualität erreicht hast? Einbildung ist auch eine Bildung, mancher Leute Einzigste.. :-) Komm mal wieder runter, in den ROMs der Platine steckt ein kompletter Debugger mit Assembler und Disassembler sowie u.A. auch ein IHEX Loader. Da darfst Du noch eine Weile dran herumschrauben. Auch für den 8080 Gibts C-compiler, BDS-C z.B. unter emuliertem CP/M. Den Menüchen da sieht zwar schön grün aus, ist aber nicht im Geringsten irgendwie beeindruckend. > Bald wird es schon mehr ... so wie einst Linus > Trovalds nur einen Terminal schreiben wollte und dann entdeckte, dass er > ein Betriebssystem geschrieben hat ... da fühlt man sich wie Kolumbus > vor der Entdeckung Amerikas :-) Joh..machmal. > > Ich brauche kein Intel Hex mehr.... da wo ich hinfliege gibt es keine > Strassen :-) > Ist recht. > Das Doofe ist nur, dass auch Backspace, Pfeile etc übertragen werden und > bei gets() lässt sich da nix filtern, das sichere fgets gibt es nicht > und es werden echos erzeugt. minicom hat als echtes Terminal keinen <CR> > übertragungsmode. Jaa, das ist einer der Gründe warum es Intel Hex gibt, brauchst Du aber nicht...ich weiß... Gruß, Holm
Christian J. schrieb: > Etwas nervig ist nur das "Krücken-Script", da ich noch versuche mit der > Bash warm zu werden und sogar das "Galileo Shell programming" in der > Nähe des Kopfkissens liegen habe. Allein schon der Umstand mit den > Leerzeichen, die mal fehlen und mal zuviel sind. > > sleep kann nur 1s verzögern, ohne Verzögerung ist der PC zu schnell und > es werden Zeichen verschluckt im riesigen 1-Byte Buffer der SIO. > > Vorteil ist nur: Es klappt, zusammen mti Geany, da drin angepassten > Kompilieroptionen ist es ein sehr kurzer Weg von der Änderung zum > Testen. 2 Klicks um genau zu sein. > >
1 | > #!/bin/bash |
2 | > echo "---------------------------------" |
3 | > echo "Datentrasnfer zum Z80" |
4 | > echo "---------------------------------" |
5 | > |
6 | > echo "Stelle tty/USB0 auf 9600 baud ein....." |
7 | > stty 9600 -crtscts -ixoff -F /dev/ttyUSB0 |
8 | > |
9 | > echo "Sende "load" Startsequenz...." |
10 | > echo "load" > /dev/ttyUSB0 |
11 | > sleep 1 |
12 | > stat -c %s z80rom.bin > /dev/ttyUSB0 |
13 | > sleep 1 |
14 | > |
15 | > echo "Uebertrage Daten...." |
16 | > cat z80rom.bin > /dev/ttyUSB0 |
17 | > sleep 1 |
18 | > echo "Sende "start" Signal um Upload zu starten..." |
19 | > sleep 1 |
20 | > echo "start" > /dev/ttyUSB0 |
21 | > echo "Fertig!" |
22 | > |
Oh Shit. Du überträgst wirklich Binärdaten über eine "nicht rohe" Schnittstelle. Laß Dir von Anderen erlären warum das keine gute Idee ist. Auf Sowas schieße ich normalerweise heute noch mit dem Luftgewehr. Dein Shellscript ist Scheiße. Es gibt Make und die dazugehörigen Makefiles die die Targets und deren Abhängigkeiten deklarieren. Diese Mechanismus wird sogar von den von Dir geliebten IDEs wie AVR-Studio benutzt, sollte einen Grund haben. Gruß, Holm
Lass gut sein, Holm. Das ist Beratungsresistenz vom allerfeinsten.
Holm Tiffe schrieb: > Dein Shellscript ist Scheiße. Es gibt Make und die dazugehörigen > Makefiles die die Targets und deren Abhängigkeiten deklarieren. Keine Ahnung von .... man muss nicht alles wissen und können. Makefiles gehören bei mir dazu.
Christian J. schrieb: > Holm Tiffe schrieb: >> Dein Shellscript ist Scheiße. Es gibt Make und die dazugehörigen >> Makefiles die die Targets und deren Abhängigkeiten deklarieren. > > Keine Ahnung von .... man muss nicht alles wissen und können. Makefiles > gehören bei mir dazu. Jawoll! Offensichtlich mußt DU nicht mal Wesentliches wissen, es reicht Dir Tatsachen einfach zu ignorieren. Ok, das ist auch eine Art Weltanschauung. Gruß, Holm
Christian J. schrieb: > .... man muss nicht alles wissen und können. Makefiles > gehören bei mir dazu. Es gibt einen Unterschied zwischen "nicht wissen" und "nicht wissen wollen". Für letzteres gibt es eigene Begriffe wie "Lernresistenz". Die meisten empfinden das als Schimpfwort. Du anscheinend nicht. 'nuff said, XL
Wär das nicht etwas für dich? "Der Kernel-Hacker Alan Cox hat ein unixoides Betriebssystem für den 8-Bit-Prozessor Zilog Z80 erstellt." http://www.golem.de/news/fuzixos-alan-cox-zeigt-betriebssystem-fuer-8-bit-cpu-z80-1411-110302.html
:
Bearbeitet durch User
Läuft wohl nur auf Z180 oder als -lite Z80 mit Banked memory :-( UZI180 makes extensive use of the Memory Management (MMU) of the Z180 core to provide as much process isolation as possible with the chip. Since the MMU granularity is 4k, this establishes the basic process structure. The top 4k of logical address space (one MMU slice) is defined as Common1 memory space and contains critical routines that either must always be resident in Minimal Requirements -------------------- - Z80 processor - 128K memory (the kernel itself wants between 32 and 40K R/O and about 8-16K R/W depending upon the configuration. - Some kind of memory banking giving a common area and multiple banks - A storage device, preferable hard disk or SD card or similar - A timer interrupt (but you can sort of run single user with just a serial / keyboard irq) In the ideal world 256K of RAM or more An RTC 16K flexible memory banking "....... Doch ganz ernst gemeint ist die Frage nicht, denn Fuzix bedient keinesfalls den Consumer- oder Desktop-Bereich, sondern richtet sich eher an Entwickler des in letzter Zeit vor allem im Enbedded-Bereich wiederentdeckten Zilog Z80 – ein 8-Bit-Mikroprozessor, der von der Firma Zilog Mitte der siebziger Jahre entwickelt wurde...."
Hmm....... das nächste Projekt? 512kB RAM. http://www.zcontrol.narod.ru/diagrams/ZramBankSwitch.pdf Grad durch die Sourcen durch ... ist noch sehr "rudimentär" aber alles für den SDCC, kompiliert so durch. Nur ein referenz Schaltplan wäre gut, Flopy usw scheint es auch zu geben. Allerdings würde ich beim nächsten Mal eine Möglichkeit vorsehen Software Breakpoints zu setzen und einen Single Step Mode. Den vermisse ich doch etwas und missbrauche RST dafür derzeit, um den Monitor und das wachsende Intel-Hex Decoding zu debuggen.
Bei folgendes Thema habe ich leider nicht genug Kenntnissem, bzw hatte ich damit noch nie zu tun: Ich benutze derzeit miniciom als Terminal. minicom schickt jeden Tastendruck an den Z80 und je nach Einstellung echot dieser es oder minicom macht es. Ich möchte den Monitor doch schon noch etwas ausbauen und habe mir auch den Tiny Basic Interpreter besorgt für den AVR, der sich sicherlich anpassen lassen wird. mincom soll bzw geht das überhaupt, dass der Z80 Steuerzeichen schickt, wie Cursor Move, Backspace usw und minicom tut genau das? zb einen blinkenden Cursor darstellen durch ein/aus eines _ usw? Die Eingabe soll genau der eines PC gleichen und mit EOL wird sie übernommen, an einen Parser gereicht und der decodiert dann den Befehl für den Z80 und die Parameterliste. Auf die Weise müsste sich eine erweiterbare Struktur bauen lassen die einfache Dinge erledigt und vielleicht später auch mal ein ganzes Basic Programm eingeben lässt bzw es auch abspeichert, da ich als "Floppy" ein 64K E2PROM im Auge habe, angesteuert durch einen AVR. Ginge das mit minicom? Oder mit was anderem?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.