Leo C. schrieb:> 0x80 ist das "Transmit-Buffer-Empty"-Flag. Deine Routine wartet also,> bis ein neues Zeichen im Transmitbuffer passt.
Okay. Aber ist diese Warteschleife unterbrechbar, wenn währenddessen ein
Zeichen hereinkommt? Und passiert das denn auch?
> Okay. Aber ist diese Warteschleife unterbrechbar, wenn währenddessen ein> Zeichen hereinkommt? Und passiert das denn auch?
Wenn er fürs Empfangen die ISR mit Empfansfifo verwendet, ja.
Jedenfalls sollte es, wenn die Routinen so funktionieren, wie gedacht.
Ich habe mir aber nicht alles so genau angesehen. Und das letzte
Programm, in dem der Editor auch aufgerufen wird, kenne ich nicht.
Hallo,
letzlich ist ein Bitbanging in den Flaschenhals der TX Einheit. Das ist
was anderes als wenn ein Int ständig läuft, der bei Buffer Empty
aufgerufen wird.
Und die hauptroutine schriebt ständig neue Bytes in den Software Buffer
rein. Das ganze lässt sich schon automatisieren druch die Verwendung von
Ints, die aber dann auch mit RX kollidieren. Beides gleichzeitig in der
CPU geht eben nicht, auch wenn TX und RX einheit gleichzeitig arbeiten
können.
Ihr müsst da aber auch nicht reinkriechen, das ist meine Sache. Ich
teste aber gern eure Software für euch.
>Okay. Aber ist diese Warteschleife unterbrechbar, wenn währenddessen ein>Zeichen hereinkommt? Und passiert das denn auch?
Natürlich wird die dann unterbrochen. Ich möchte aber hier noch nicht
weiter spekulieren, da alles noch halbfertig ist und ich auch nicht
weiss, ob ich heute abend dazu komme bzw Lust habe. War etwas viel die
letzte Zeit und ich habe noch 2 Kinder....
Christian J. schrieb:> Hallo,>> letzlich ist ein Bitbanging in den Flaschenhals der TX Einheit. Das ist> was anderes als wenn ein Int ständig läuft, der bei Buffer Empty> aufgerufen wird.
Die STI wird nicht um Bits bangen... was schreibst Du wieder fürn Zeuch?
Das ist Hardware, ein Schieberegister das die Bits rausklappert mit
konstantem Takt.
> Und die hauptroutine schriebt ständig neue Bytes in den Software Buffer> rein. Das ganze lässt sich schon automatisieren druch die Verwendung von> Ints, die aber dann auch mit RX kollidieren. Beides gleichzeitig in der> CPU geht eben nicht, auch wenn TX und RX einheit gleichzeitig arbeiten> können.
Ich weiß nicht was Deine STI so kann, hatte ja ne SIO empfohlen. So eine
SIO hat erstens Prioritäten bei internen Interrups und eine Mimik namens
"Status affects Vector" um so schnell wie möglich die richtige ISR
anspringen zu können, die SIO hat selbst je nach Interrupt Grund den
Vector im IM2 Mode modifiziert. Ich besutze 0 Stück STI ber so ca 50
SIOs
und habe deshalb keinen richtigen Bock darauf ein STI Datenblatt zu
lesen.
>> Ihr müsst da aber auch nicht reinkriechen, das ist meine Sache. Ich> teste aber gern eure Software für euch.
Genau. Und dann solltest Du mal von Deiner Meinung wegkommen das die Z80
mit 4Mhz zu langsam ist eine Serielle mit 9600 Baud zu bedienen. Das
geht mit 2,5Mhz auch prima. Nur weil Du Atmels mit 20Mhz kennst ist die
4Mhz Z80 nicht langsam. Du kannst das nur nicht einschätzen.
>>>Okay. Aber ist diese Warteschleife unterbrechbar, wenn währenddessen ein>>Zeichen hereinkommt? Und passiert das denn auch?>> Natürlich wird die dann unterbrochen. Ich möchte aber hier noch nicht> weiter spekulieren, da alles noch halbfertig ist und ich auch nicht> weiss, ob ich heute abend dazu komme bzw Lust habe. War etwas viel die> letzte Zeit und ich habe noch 2 Kinder....
Mach Dir mal einen richtigen Plan mit diesen Umlaufpuffern. Lies die
Doku zur STI wie die das bei konkurrierenden Interrupts löst. Der Fall
ist ja nicht wirklich selten und auch schon zu Z80 Zeiten haben die
Leute Synchronprotokolle mit mehr als 9600 Baud über SIOs gefahren..
(wobei diese Protokolle auch Füllzeichen senden können)
Gruß,
Holm
Holm Tiffe schrieb:> Mach Dir mal einen richtigen Plan mit diesen Umlaufpuffern. Lies die> Doku zur STI wie die das bei konkurrierenden Interrupts löst.
Feste Priorisierung der 16 internen Interruptquellen mit getrennte
Vektoren. Die 8 externen Interrupt-Eingänge (IO Pins), 4 Timer, 4
UART-Fälle. Für verschachtelte STI Interrupts muss man dessen "in
service" Register einschalten. Das "I" in STI steht für
Interrupt-Controller.
Eigentlich sollte ich mich ja wundern, wie man aus dieser Mücke so einen
Elefanten machen kann, aber ...
Synchron würde ich mit dem STI aber wirklich nicht machen wollen.
Bitsync kann er nicht, aber irgendeine nahezu undokumentierte Bytesync
Variation. Bei der hätte man wohl gute Chancen, der erste zu sein, der
das seit Erfindung des Bausteins ausprobiert. Jeder, der Sync im Auge
hatte, hat den SIO verwendet.
A. K. schrieb:> Holm Tiffe schrieb:>> Mach Dir mal einen richtigen Plan mit diesen Umlaufpuffern. Lies die>> Doku zur STI wie die das bei konkurrierenden Interrupts löst.>> Feste Priorisierung der 16 internen Interruptquellen mit getrennte> Vektoren. Die 8 externen Interrupt-Eingänge (IO Pins), 4 Timer, 4> UART-Fälle. Für verschachtelte STI Interrupts muss man dessen "in> service" Register einschalten. Das "I" in STI steht für> Interrupt-Controller.>
Naja, aus meiner Sicht ist das Ding ein ganzes Stück weit Krücke um
andere nicht zum System gehörende Ics einzubinden. Wozu zum Teufel
bräuchte man sonst in einem Z80 System einen Interrupt Controller?
Ok, rotierende Prioritäten kann der IM2 Mode nicht, aber ein Atmega hat
gar keine konfigurierbaren Prioritäten.Ich rotierende P. noch nie
gebraucht.
> Eigentlich sollte ich mich ja wundern, wie man aus dieser Mücke so einen> Elefanten machen kann, aber ...
hmm...
>> Synchron würde ich mit dem STI aber wirklich nicht machen wollen.> Bitsync kann er nicht, aber irgendeine nahezu undokumentierte Bytesync> Variation. Bei der hätte man wohl gute Chancen, der erste zu sein, der> das seit Erfindung des Bausteins ausprobiert. Jeder, der Sync im Auge> hatte, hat den SIO verwendet.
:-) YMMD!
Gaanz früher (Tm) als die Erde noch jung war und der Wind noch richtig
aus Holz, da haben wir mal ein Magnetbandinterface mit SIO und SDLC
gebastelt und immerhin 9600 Baud vom Band wieder runter bekommen...
...aber einem Kassettentonband trauere ich jetzt nicht wirklich nach..
Gruß,
Holm
Holm Tiffe schrieb:> Wozu zum Teufel> bräuchte man sonst in einem Z80 System einen Interrupt Controller?
Weil Zilog es sträflich unliess, Bausteine wie den Z80-FDC und den
Z80-ADC zu entwickeln. Wenn man also Bausteine ausserhalb der Z80 Serie
in den IM2 integrieren wollte und nicht zufällig noch einen passenden
CTC- oder PIO-Eingang frei hatte, dann waren 8 Interrupt-Eingänge
sicherlich sehr praktisch.
Kurzum: Genau für solche Platinen wie seine, wo der ADC-Interrupt einen
Anschluss sucht. Bereits bestehende Backplanes der 8080 Ära hatten auch
keine IM2 Daisy Chain vorgesehen.
> Ok, rotierende Prioritäten kann der IM2 Mode nicht,
Der STI auch nicht, der integriert neben Timern und UART 8 klassische
Interrupt-Anschlüsse in den IM2.
A. K. schrieb:> Holm Tiffe schrieb:>> Wozu zum Teufel>> bräuchte man sonst in einem Z80 System einen Interrupt Controller?>> Weil Zilog es sträflich unliess, Bausteine wie den Z80-FDC und den> Z80-ADC zu entwickeln. Wenn man also Bausteine außerhalb der Z80 Serie> in den IM2 integrieren wollte und nicht zufällig noch einen passenden> CTC- oder PIO-Eingang frei hatte, dann waren 8 Interrupt-Eingänge> sicherlich sehr praktisch.
Na das ist aber jetzt Quatsch ...
Wenn man keinen Eingang frei hat muß man einen Interruptcontroller
einsetzten der gleichzeitig Timer und Uart enthält?
Die Begründung ist irgendwie "von hinten durch die Brust ins Auge"...
Auf einem ADC Bord macht sich ein Timer und oder eine DMA nicht schlecht
und die haben jeweils die entsprechenden Möglichkeiten.
>> Kurzum: Genau für solche Platinen wie seine, wo der ADC-Interrupt einen> Anschluss sucht. Bereits bestehende Backplanes der 8080 Ära hatten auch> keine IM2 Daisy Chain vorgesehen.
Für wie hoch hältst Du den potentiellen Markt für eine Umrüstung damals
im Vergleich zu "Neubauten"?
Soo viel besser performt ein Z80 nun auch nicht als ein 8080 und für die
Rückwärtskompatibilität gabs IM0 und IM1, man ist also nicht auf IM2
angewiesen wenn man eine 8080 Backplane unbedingt benutzten möchte.
Du ziehst ganz schön an den Haaren..
>>> Ok, rotierende Prioritäten kann der IM2 Mode nicht,>> Der STI auch nicht, der integriert neben Timern und UART 8 klassische> Interrupt-Anschlüsse in den IM2.
Braucht kein Mensch sonst hätte Zilog das Ding gebaut. Statt dessen gabs
dann SCC und CIO.
Gruß,
Holm
Hallo,
ihr habt Sorgen um Dinge, die seit Äonen abgfrühstückt sind. Die Bitsync
Funktion des MK3801 ist wirklich sehr interessant. Da sscheint eine Art
Sync Wort gescchickt zu werden, auf die sich das Slave dann ein
sycnrhonisieren kann. Einfach einen Takt und Bits dabei rein und raus
war wohl zu einfach.
Verschachtelte Ints sind kein Thema, einfach EI direkt am Einsprung
einer ISR und schon kann das sich gegenseitig munter unterbrechen,
wieder und immer wieder bis wir eine nie endende Rekursion haben und der
Stack sich bedrohlich nahe dem Programm nähert und es dann "auffrisst".
Für solche Konstrukte ist mir der ARM lieber mit seinen nested
interrupts, da er einen sehr ausgeklügelten Interrupt Controller names
VIC drin hat, Vektor Interrupt Controller :-)
@Holm: Die Ints sind fest priorisiert in einer Tabelle. TX Empty
niedriger als RX Full.
Übrigens finde ich 9600 baud cool. Erinnert mich an die zeit wo ich mit
dem C64 und einem 300 baud Akkustikooppler gesessen habe, eine Liste mit
NUI's wo wir ins Datex P rein gingen :-) Glaube da ich ich 15 oder so.
Holm Tiffe schrieb:> Wenn man keinen Eingang frei hat muß man einen Interruptcontroller> einsetzten der gleichzeitig Timer und Uart enthält?
Man muss nicht. Man kann.
> Du ziehst ganz schön an den Haaren..
Den STI gab es, also hat sich damals jemand Chancen ausgerechnet. Für
68000 gab es m.W. einen ähnlichen Baustein.
Warum du nun aber so aggressiv wirst ist mir unklar.
A. K. schrieb:> Warum du nun aber so aggressiv wirst ist mir unklar.
Das hat er vom Röhrenforum, zu oft an die Anode gefasst .... :-)
Der hies TS38230 für den 68000. 48 Pins a 1,27mm Raster.
Christian J. schrieb:> Die Bitsync Funktion des MK3801 ist wirklich sehr interessant.
Scheint mir eher bytesychron zu sein. Bitsync wäre SDLC/HDLC, bytesync
eher sowas in Richtung IBM BISYNC. Und die normale PC-Schnittstelle
nicht taugt für keines davon.
> ... bis wir eine nie endende Rekursion haben.
Du unterschätzt den Interrupt Mechanismus der Z80. Verschachtelte
Interrupts beim Z80 im IM2 arbeiten prinzipiell ähnlich wie dein
ARM/CMx, d.h. nur höher priorisierte Interrupts können eine laufende ISR
unterbrechen. Nur ist die Priorität innerhalb eines Bausteins nicht
wählbar und die Priorität der Bausteine ergibt sich aus der Verdrahtung.
Deshalb gibt es auch den RETI Befehl, der sich seitens der CPU nicht vom
RET unterscheidet. Dieser Befehl wird von den Z80 Peripherie-Bausteinen
dekodiert und gibt die Daisy Chain wieder frei. Deshalb hat der der STI
ein optionales "in service" register, damit das auch innerhalb seiner 16
Interrupts funktionieren kann.
> Für solche Konstrukte ist mir der ARM lieber mit seinen nested> interrupts, da er einen sehr ausgeklügelten Interrupt Controller names> VIC drin hat, Vektor Interrupt Controller :-)
Vorsicht bei Vergleichen, sie könnten Rohrkrepierer sein ;-). Das
Interrupt-System der ARM Prozessoren ist deren schwächere Seite, bevor
die Cortex M kamen. Zumal die VICs separate Module waren und jeder
Hersteller eigene Brötchen buk (Atmel und ST verwendete bei den ARM7/9
Controllern eigene Module, AD überhaupt keines).
Der VIC von ARM ist zumindest in seiner ersten Ausprägung (PL190), zu
finden in den LPC2100, keine echte Meisterleistung. Mit dem PL192 in den
LPC2300 wurde es besser. Aber erst mit dem NVIC der Cortex M wurde es
gut, weil erst da die CPU gut mit Nesting umgehen kann.
A. K. schrieb:> Holm Tiffe schrieb:>> Wenn man keinen Eingang frei hat muß man einen Interruptcontroller>> einsetzten der gleichzeitig Timer und Uart enthält?>> Man muss nicht. Man kann.>>> Du ziehst ganz schön an den Haaren..>
Eben weil der Fall sehr selten Auftreten wird. Klar schlägt das Ding für
kleine Rechner mehrere Fliegen mit einer Klappe für die man sonst
mehrere Bausteine bräuchte. Dein Beispiel mit der 8080 Backplane geht
aber nach hinten los, weil dieses System Peripherie hat die sowieso
Systemfremd ist
und mit den beiden "alten" Interruptmodi abgedeckt wird.
> Den STI gab es, also hat sich damals jemand Chancen ausgerechnet. Für> 68000 gab es m.W. einen ähnlichen Baustein.>
Keine Ahnung. Ich findeden 68k Klasse, habe aber keine Erfahrung damit
bis auf die Bastelei mit dr KatCe die schon wieder wegen anderer Dinge
in der Ecke liegt..
> Warum du nun aber so aggressiv wirst ist mir unklar.
Ich bin doch nicht aggressiv.., calm down.
Gruß,
HOlm
A. K. schrieb:> Du unterschätzt den Interrupt Mechanismus der Z80. Verschachtelte> Interrupts beim Z80 im IM2 arbeiten prinzipiell ähnlich wie dein> ARM/CMx, d.h. nur höher priorisierte Interrupts können eine laufende ISR> unterbrechen.
Moment, mal kurz einhaken. Ich habe keine Chain, weiss nur dass die Prio
eben durch die Anordung kodiert ist. Wieso kann jetzt ein Int einen
anderen nicht unterbrechen, wenn ich EI setze? Der STI hat die Bits
"Interuppt liegt an" und "Pending Ints". Wann werden die gelöscht? Denn
nur wenn es irgendeine Meldung gibt, dass ein Int abgearbeitet wurde
kann verhindert werden, dass die sich gegenseitig kloppen.
Ich habe mit dem LPC2368 mit dem VIC einiges gemacht, fand den sehr
durchschaubar und gut zu handeln. Nicht ganz trivial aber noch machbar.
Christian J. schrieb:> Hallo,>> ihr habt Sorgen um Dinge, die seit Äonen abgfrühstückt sind. Die Bitsync> Funktion des MK3801 ist wirklich sehr interessant. Da sscheint eine Art> Sync Wort gescchickt zu werden, auf die sich das Slave dann ein> sycnrhonisieren kann. Einfach einen Takt und Bits dabei rein und raus> war wohl zu einfach.
Die SIO unterstützt Asynchron mit verschiedenen Wortlängen sowie
synchron Monosync und Bisync (und externe Synchronisation) sowie SDLC
und HDLC.
Für die, denen das zu komplex ist, gibts den Z80-Dart, eine kaputte SIO
bei der irgendwas im Synchronblock kaputt ist :-)
Die SIO ist komplexer als die CPU.
Diene SIT hat offenscichtlich nun eine weitere Synchronbetriebsart die
sonst keiner macht..wichtig wie ein drittes Knie, das ist was AK meinte.
>> Verschachtelte Ints sind kein Thema, einfach EI direkt am Einsprung> einer ISR und schon kann das sich gegenseitig munter unterbrechen,> wieder und immer wieder bis wir eine nie endende Rekursion haben und der> Stack sich bedrohlich nahe dem Programm nähert und es dann "auffrisst".> Für solche Konstrukte ist mir der ARM lieber mit seinen nested> interrupts, da er einen sehr ausgeklügelten Interrupt Controller names> VIC drin hat, Vektor Interrupt Controller :-)>
Ein "ARM" an sich hat keinen VIC, das haben allenfalls Implementationen
der ARM Architektur. Du müßtest schon mal klar machen von welchem Du
redest, sicher nicht Luminary Micro :-)
> @Holm: Die Ints sind fest priorisiert in einer Tabelle. TX Empty> niedriger als RX Full.
Wie ich mirs gedacht hatte.
>> Übrigens finde ich 9600 baud cool. Erinnert mich an die zeit wo ich mit> dem C64 und einem 300 baud Akkustikooppler gesessen habe, eine Liste mit> NUI's wo wir ins Datex P rein gingen :-) Glaube da ich ich 15 oder so.
Ich weniger, das kostet mich meine Zeit. Ich habe schon früher das
machbare bevorzugt, wegen CTC als Taktgenerator und 2,5Mhz war das oft
gerade mal 19200.
Gruß,
Holm
Holm Tiffe schrieb:> Die SIO ist komplexer als die CPU.
Ich weiss..... darum habe ich sie auch nicht benutzt :-) 58 Seiten
Handbuch für eine "Tür" mit 2 Drähten dran waren mir zuviel.
Christian J. schrieb:> Moment, mal kurz einhaken. Ich habe keine Chain, weiss nur dass die Prio> eben durch die Anordung kodiert ist.
Logisch. Du hast ja auch nur einen entsprechenden Baustein.
> Wieso kann jetzt ein Int einen> anderen nicht unterbrechen, wenn ich EI setze?
Die Doku zum STI ist auch hier ein wenig maulfaul, aber sind dir die
optionale ISRA/B nicht aufgefallen? Bissel was steht dazu sogar drin.
Die ergeben nur dann Sinn, wenn damit Interrupts gleicher oder
niedrigerer Priorität unterbunden werden, wenngleich das nicht explizit
drinsteht. Immerhin ist der STI (auch) ein Interrupt Controller, von dem
man so etwas erwarten sollte.
> "Interuppt liegt an" und "Pending Ints". Wann werden die gelöscht?
Steht in der Doku. Mit Aufruf des Handlers. Aber dann kommen dir ISRA/B
ins Spiel und die werden erst mit dem dekodierten RETI Befehl gelöscht.
> Ich habe mit dem LPC2368 mit dem VIC einiges gemacht, fand den sehr> durchschaubar und gut zu handeln. Nicht ganz trivial aber noch machbar.
Der ist leidlich ok. Das Problem ist die CPU selbst, denn die ARM Cores
vor den Cortex M haben sämtlich ein verbocktes Interrupt-System, wenn
man Nesting jenseits des FIQ haben will
Diese ARMs haben zwar einen partiell separaten Registerkontext und damit
auch Stack für Interrupts (an sich eine gute Idee), aber der ist
aufgrund eines Konstruktionsfehlers bei Nesting kaum zu gebrauchen. Die
Return-Adresse eines Interrupts liegt in gleichen Register des
Interrupt-Kontextes wie die Return-Adresse von Unterprogrammaufrufen.
Um trotzdem Nesting zu ermöglichen muss man im Handler etwas Aufwand
treiben und den Register-Kontext manuell wechseln. Das wirst du aber
evtl. dank fertiger IDE nicht gemerkt haben. Entweder macht der
Support-Code einen Wrapper um normale C Funktionen als Interrupt-Handler
(so machte ich das), oder in den Handlern sind am Anfang und Ende
entsprechende Makros mit ASM Befehlen darin.
A. K. schrieb:> Um trotzdem Nesting zu ermöglichen muss man im Handler etwas Aufwand> treiben und den Register-Kontext manuell wechseln. Das wirst du aber> evtl. dank fertiger IDE nicht gemerkt haben. Entweder macht der> Support-Code einen Wrapper um normale C Funktionen als Interrupt-Handler> (so machte ich das), oder in den Handlern sind am Anfang und Ende> entsprechende Makros mit ASM Befehlen darin.
Gibt es irgendwas was Du nicht weisst? Ich habe mich so tief damit gar
nicht befasst sondern die von NXP empfohlenen Sourcen benutzt, die
dieses Problem scheinbar umgehen. Die IDE hat damit nichts zu tun, die
erzeugt mir nur den Startup Code je nach CPU Type.
Aha :-) Ja, ab ddder Primce Cell 0192 haben die da was geändert. Damit
musste ich mich mal rumschlagen, immer schön errate sheets lesen :-)
The following list shows the functional differences between the PL192
and PL190 PrimeCell VICs:
• VIC port fully supported, both in synchronous and asynchronous modes.
• The programmers model is different between PL192 and PL190, so code is
not backwards-compatible.
• 16 standard interrupts replaced with vectored interrupts to give 32
vectored interrupts.
• 16 software-programmable interrupt priority levels added, in addition
to
Aber das ist was anderes als Z80, ein paar Jahre liegen dazwischen....
und doch nur 0 und 1 und das ist einem immer komplizierter werdenden
Zusammenhang.
Nut mal als beispiel ein Anhang. Mit sowas habe ich nicht die geringste
Lust mich damit zu befassen oder es gar verstehen zu wollen. Das
Interface einer MMC karte an die PHY im Chip. Das soll einfach nur
funktionieren und fertig.
Christian J. schrieb:> Aha :-) Ja, ab ddder Primce Cell 0192 haben die da was geändert.
Yep, aber das hat nichts mit dem Problem der CPU zu tun. Aber die
teilweise nichtvektorierten Interrupts der PL190 waren damit Geschichte.
Wenn du ein wenig im Web suchst wirst du sowohl bei NXP als auch im Web
einige hitzige Diskussionen zu "spurious interrupts" und "surprise
interrupts" finden. Wobei die NXP Doku dazu nicht unbedingt der Stein
der Weisen ist.
Die "spurious interrupts" landen bei der PL190 im gleichen Vektor wie
die nichtvektorierten, was viele Leute irritierte. Atmel war bei den
SAM7 immerhin so klug, die "spurious interrupts" separat unterzubringen.
Die "surprise interrupts" sind ein weiterer Konstruktionsfehler der
Basisarchitektur der ARMs vor den Cortexen und können bei Verwendung von
FIQs seltsame Blüten treiben.
Christian J. schrieb:> Nut mal als beispiel ein Anhang.
Nesting kriegst du mit diesem Code aber nicht. Auch wenns der VIC kann,
dein Code kann es nicht, denn wie auch bei der Z80 muss man die IRQs
dazu explizit am Anfang des Handlers freigeben - und eben den erwähnten
Hack fürs Nesting einbauen.
Solange man kein Nesting braucht ist es daher auch besser, wenn man
drauf verzichtet.
A. K. schrieb:> Nesting kriegst du mit diesem Code aber nicht. Auch wenns der VIC kann,> dein Code kann es nicht, denn wie auch bei der Z80 muss man die IRQs> dazu explizit am Anfang des Handlers freigeben.
Ahh..... nein, das war nur ein Beispiel wo MEINE Grenzen liegen, ok?
Worüber sich hier einige aufregen. Das war nur mal für die SD karte, die
ich auch innendrin kannte, zumindest das SPI Interface, nicht aber das
MMC. Und das ist eine Adaption dieser Karte an eine PHY im LPC und um
die schreiben zu können kann man sich 1 Monat damit auseinandersetzen
wie die MMC Spec 3.0 funktioniert und dazu noch wie der ARM das
unterstützt. Oder man nimmt .... eine fertige LIB die ca 20 API
Funktionen hat, schliesst die an eigene Routinen an, verdrahtet die Ints
und kümmert sich einen Shice darum wie die das macht.
Christian J. schrieb:> Sowas hier macht Spass zu Programmieren :-)
Ach herrje. Genau das hat mein Vater von einigen Jahren in BASIC
programmiert. Da ging er schon auf die 80 zu. ;-)
Stör mich jetzt nicht, ich arbeite ARM auf Z80 grad um.... das Rad wurde
von mir ja schon vor 5 jahren erfunden und was sich am Porsche bei 200
km/h dreht wird es sicher auch am VW Käfer mit 80 km/h.....
Wenn ich sowas lese:
Die Ausgabe von Zeichenketten im Hauptprogramm erfolgt mit
sprintf(uart_buffer," Text 1......");
Uart_Write();
dann wundere ich mich, wie Du den darunterstehenden Code hinbekommen
hast. Oder ist der abgekupfert?
Das Monstrum sprintf() braucht man nur für formatierte Ausgabe. In dem
obigen Beispiel wird aber überhaupt keine Formatierung enthalten. Hier
reicht ein einfacher strcpy(), welcher um ein Vielfaches kleiner ist:
strcpy(uart_buffer," Text 1......");
Also: Entweder ersetzt Du obiges Beispiel durch etwas komplexeres oder
sprintf() durch strcpy(). ;-)
P.S.
Der größte Fehler von K&R war es, das allererste Hello-World-Programm
mit einem printf() zu beginnen. Ein simpler Aufruf von puts() hätte es
auch getan und wäre taktisch viel klüger gewesen. Aber so wurden direkt
alle angehenden Programmierer "versaut".
Christian J. schrieb:> A. K. schrieb:>>> Warum du nun aber so aggressiv wirst ist mir unklar.>> Das hat er vom Röhrenforum, zu oft an die Anode gefasst .... :-)
Das letzte mal das ich von irgend einer Anode eine gelatscht bekommen
habe muß so ca. Mitte der 80er gewesen sein.
>> Der hies TS38230 für den 68000. 48 Pins a 1,27mm Raster.
Hieß er nicht. der 68230 hieß in erster Linie MC und TS nur als Nachbau
von Toshiba, das ist der PIT. Er meint aber eigentlich den MC68901.
Gruß,
Holm
Frank M. schrieb:> Ein simpler Aufruf von puts() hätte es> auch getan und wäre taktisch viel klüger gewesen.
Schlaue Compiler wissen das, und machen bei einem Aufruf von printf(),
der nur den Formatstring hat, genau das. :)
Holm Tiffe schrieb:> Er meint aber eigentlich den MC68901.
Der ist dermassen dicht am STI dann man dessen etwas bessere Doku wohl
auch für den STI verwenden kann. Sogar den IM2 Modus hat er (eine
IEI/IEO Chain).
A. K. schrieb:> Holm Tiffe schrieb:>> Er meint aber eigentlich den MC68901.>> Der ist dermassen dicht am STI dann man dessen etwas bessere Doku wohl> auch für den STI verwenden kann. Sogar den IM2 Modus hat er (eine> IEI/IEO Chain).
Ja, ist irre für ein MC68K Peripheral.
Auf so weitgehende Ähnlichkeit das man die Doku verwenden kann würde ich
mich aber nicht verlassen wollen.
Eine ähnliche Ähnlichkeit habe ich mal zwischen Z80-SIO und µPD7201
festgestellt, der µPD7201 ist eine SIO mit umgerüstetem Interrupt System
für 8086 und Ähnliche CPUs wie es aussieht. Ich habe aber irgnendwo
gelesen das die Leute auch nicht ganz so zufrieden mit dem Ding waren..
Gruß,
Holm
Hallo Fans!
Aktuel ist kleine Pause, da ich noch mit den Ringpuffern kämpfe, die
sich bei genauem Hinschauen und "Wenn dann was?" Durchdenken doch ewas
komplexer verhalten. Nicht wie sie sie ringeln, dazu reicht wr_ptr =
(wr_ptr +1) % SIZE sondern die Sonderfälle und 1:1000000 Fälle, die
auftreten können und die gegeneinander abgeriegelt werden müssten durch
"Semaphore". Außerdem meldet sich TX int per Mode 2 nur wenn Buffer leer
ist, muss aber zum Senden wieder angetriggert werden. TX und RX komplett
beide in einer ISR jetzt. Das muss erstmal laufen und der Code
fehlerfrei sein....
Bis später....
[code]
// RX Empfangspuffer
struct rx_type{
int8_t buf[RX_BUF_SIZE+1];
uint8_t rd_ptr; // Read Pointer, nur durch
Hauptprogramm lesen
uint8_t wr_ptr; // Write Pointer, nur durch Interrupt
schreiben
uint8_t f_buf_full; // flag:Es sind Zeichen da
uint8_t f_buf_overflow; // flag:Overflow: WR Zeiger hat RD
überholt: Buffer wertlos
};
// TX Sendepuffer
struct tx_type{
int8_t buf[TX_BUF_SIZE+1];
uint8_t rd_ptr; // Read Pointer, nur durch
Hauptprogramm lesen
uint8_t wr_ptr; // Write Pointer, nur durch Interrupt
schreiben
uint8_t f_buf_full; // Ringpuffer ist komplett voll
uint8_t f_buf_empty; // Ringpuffer ist ganz leer
uint8_t f_idle; // TX Hardware ist inaktiv
};
/* Sonderfaelle des RX Receive Ringpuffers
* 0......................END
* ...rd->......wr->......... Normalfall
* .......wr-> ....rd->...... Normalfall
* rd/wr...................... Start oder Puffer leer
* ........rd/wr.............. Puffer leer
* */
char getchar()
{
register char ch;
// Bei leerem Puffer 0 zurück liefern
if (!rx.f_buf_full)
return (0);
// Ints aus, da Lesezugriff
__asm
di
__endasm ;
// Zeichen auslesen
ch = rx.buf[rx.rd_ptr];
// Read Pointer am Array Ende zurück setzen
rx.rd_ptr = (rx.rd_ptr +1) % RX_BUF_SIZE;
// Alle Zeichen gelesen?
rx.f_buf_full = (rx.rd_ptr == rx.wr_ptr) ? false : true;
__asm
ei
__endasm ;
return(ch);
}
/////////////////////////////////////////////////////////
// Zeichenausgabe für printf auf der STI mit 9600 Baud
/* Sonderfaelle des TX Transfer Ringpuffers
* 0......................END
* ...rd->......wr->......... Normalfall
* .......wr-> ....rd->...... Normalfall
* wr/rd...................... Start oder Puffer voll
* ........wr/rd.............. Puffer voll
* */
void putchar(char c)
{
if (!tx.f_buf_full) {
__asm
di
__endasm ;
// Zeichen einschreiben
tx.buf[tx.wr_ptr] = c;
// wr+1 am Bufferende auf 0 zurücksetzen
rx.wr_ptr = (rx.wr_ptr +1) % RX_BUF_SIZE;
// Wurde Position ISR RD Zeiger erreicht? Dann voll.
tx.f_buf_full = (tx.wr_ptr == tx.rd_ptr) ? true : false;
// Wenn TX inaktiv muss ISR angestossen werden
if (tx.f_idle)
STI_UDR = tx.buf[tx.rd_ptr];
__asm
ei
__endasm ;
}
}
void int_sti_receive_buffer_full(void) __interrupt
{
register uint8_t zeichen;
zeichen = STI_UDR; // Zeichen abholen
if (!rx.f_buf_overflow) {
PIO8255_PORT_A = ~zeichen; // Zeichen auf LED
// Zeichen in Ringpuffer schreiben
rx.buf[rx.wr_ptr] = zeichen;
// wr+1 Zeiger am Bufferende? Dann 0 setzen
rx.wr_ptr = (rx.wr_ptr +1) % RX_BUF_SIZE;
// WR >= RD : Buffer Overflow => Aktion erforderlich
rx.f_buf_overflow = (rx.wr_ptr == rx.rd_ptr) ? true : false;
// Meldung an Hauptprogramm: Zeichen ist da
rx.f_buf_full = true;
}
__asm
ei
__endasm ;
}
////////////////////////////////////////////////
// ISR: Uart TX Sendepuffer ist leer
// putchar() muss dafür sorgen, dass er wieder voll wird
/* Sonderfaelle des TX Transfer Ringpuffers
* 0......................END
* ...rd->......wr->......... Normalfall
* .......wr-> ....rd->...... Normalfall
* wr/rd...................... Start oder Puffer voll
* ........wr/rd.............. Puffer voll
* */
void int_sti_transmit_buffer_empty(void) __interrupt
{
/* TX hat letztes Byte gesendet und muss nachschauen
* ob weitere Bytes zu senden sind */
tx.f_idle = true; // TX Idle Flag, Uart inaktiv
/* TX ISR muss extern angestossen werden, damit
* diese Routine hier aufgerufen wird, wenn Puffer
* leer ist */
// Sind noch Zeichen im TX Buffer?
if (tx.rd_ptr < tx.wr_ptr)
{
tx.f_idle = false; // Flag TX aktiv
tx.f_buf_full = false; // TX Full Flag zurücksetzen
STI_UDR = tx.buf[tx.rd_ptr]; // Byte einschreiben
tx.rd_ptr = (tx.rd_ptr +1) % RX_BUF_SIZE; // Read Pointer bei
Überlauf auf 0
} else
tx.f_buf_empty = true;
__asm
ei
__endasm ;
}
Machs nicht so kompliziert.
Im Anhang sind getestete Routinen für AVR. Aus Performancegründen dürfen
die Ringpuffer hier nur maximal 256 Byte groß sein, und die Größe muß
eine 2-er Potenz sein. Der Hardwareteil sollte sich leicht auf STI
umstricken lassen.
Ansonsten
- Die Funktion _write() und alles was damit zusammen hängt, rauswerfen.
Dafür muß dann wahrscheinlich stdint.h rein
- In serial.c die ersten 5 Includes rauswerfen.
- Statt ATOMIC_BLOCK: di/ei
- Die auskommentierte String-Ausgabefunktion ring_write() kann einen
Deadlock produzieren. Da man die nicht unbedingt braucht, habe ich
mich nicht weiter drum gekümmert. Also nicht benutzen.
Das müßte es eigentlich gewesen sein. Wenn das so läuft, kann man noch
optimieren.
Ich denke es kostet genauso viel Zeit einen Fremdcode anzupassen wie es
Zeit dauert was eigenes zu schreiben was man dann auch komplett
versteht. Nicht kompliziert, nur gibt es einige Sonderfälle zu
betrachten und Fehler abzufangen, wenn da was nicht so läuft wie es
soll. Das sausen ja 2 Zeiger drin herum, die sich kreuz und quer
überholen können und was vonn außen kommt kann weder aufgehalten noch
gebremst werden.
AVR Code ja recht kurz aber andere UART, meine ist deutlich mehr Retro,
da klappern noch die Relais im Chip :-)
Denksport, soll ja Spass machen und schöner Code macht mir Spass :-)
Die normale getchar() wartet glaube ich ewig bis was reinkommt? Timeout
und Flags zur Anzeige sind da nicht vorgesehen.
> AVR Code ja recht kurz aber andere UART, meine ist deutlich mehr Retro,> da klappern noch die Relais im Chip :-)
Der Code ist aber nicht wegen AVR so kurz. Allenfalls die
Initialisierung ist da etwas kompakter.
Er ist deshalb so kurz, weil er gut überlegt ist (*), und es die Sonder-
und Fehlerfälle, wegen denen Du Dir Dein Hirn marterst, hier garnicht
gibt.
* Wenn beide Zeiger, bzw. Indexe gleich stehen, ist der Puffer leer.
* Wenn der Lesezeiger eins hinter dem Schreibzeiger steht,
ist der Puffer voll.
* Counter braucht man dann nicht. Man kann nur ein Byte im Puffer nicht
benutzen.
* Durch die Limitierung der Pufferlänge auf 2-er Potenzen, reduziert die
Prüfung eines Zeigers auf Pufferende und ggf. Zurücksetzen beim
Weiterzählen auf eine einfache Maskierung.
Das ist alles.
(*) Nicht von mir. Das haben Generationen von Programmierern schon
vorher so gemacht.
Den einzigen Unterschied zu meiner Lösung sehe ich nur
hier:
ep = (ep + 1) & ring->mask;
Ich habe
ep = (ep + 1) % SIZE;
wobei % etwas mehr Code braucht als eine Maske, weil _modint aufgerufen
werden muss und das jedesmal.
und ich benutze globale Variablen, damit keine dynamischen erzeugt und
Parameter übergeben werden müssen.
that all.
Macht schon was aus:
a) driver.c:79: rx.rd_ptr = (rx.rd_ptr +1) % RX_BUF_SIZE;
0064 16 00 [ 7] 165 ld d,#0x00
0066 13 [ 6] 166 inc de
0067 C5 [11] 167 push bc
0068 21 80 00 [10] 168 ld hl,#0x0080
006B E5 [11] 169 push hl
006C D5 [11] 170 push de
006D CDr00r00 [17] 171 call __modsint
0070 F1 [10] 172 pop af
0071 F1 [10] 173 pop af
0072 C1 [10] 174 pop bc
0073 55 [ 4] 175 ld d,l
0074 21r08r01 [10] 176 ld hl,#(_rx + 0x0081)
0077 72 [ 7] 177 ld (hl),d
b) 178 ;driver.c:80: rx.rd_ptr = (rx.rd_ptr +1) & rx.mask;
0078 14 [ 4] 179 inc d
0079 3Ar0Ar01 [13] 180 ld a, (#_rx + 131)
007C A2 [ 4] 181 and a, d
007D 57 [ 4] 182 ld d,a
007E 72 [ 7] 183 ld (hl),d
Christian J. schrieb:> Macht schon was aus:
Es ist nicht nur die Zeilenanzahl-Differenz, sondern das hier ist
richtig heftig:
> 006D CDr00r00 [17] 171 call __modsint
Da kommt noch einiges dazu.
Hi,
ja, ich habe es umgeschrieben auf "Maske", recht simple Überlegung aber
schon "pfiffig". Erinnert mich an das Zaks Buch Z80: Der erste Entwurf
läuft aber es ist kein optimaler Entwurf. Im Buch wird eine 16 Bit
Multiplikation optmiert, vom ersten Entwurf und dann dem Optimum, was
50% schneller läuft.
Trotzdem läuft es noch nichr richtig. Zeicheneingabe ja, Ausgabe hakt
noch, da verhaspelt er sich und es kommt Müll. Total vorbei ist es wenn
ich vom Z80 dauernd sende und gleichzeitig vom PC Daten schicke so dass
RX und TX aufgerufen werden.
Es gibt nur einen "TX empty" Interrupt. D.h. der TX muss vom
Hauptprogram getriggert werden durch STI_TX = zeichen, damit der nächste
Int, wenn Zeichen raus ist dann in der ISR die weitere Verarbeitung des
Puffers übernimmt. Wenn letztes Zeichen raus, dann bleibt TX stehen, der
Int wird nicht mehr aufgerufen. Das Antriggern läuft noch nicht.
Aktuell schreibe ich Testroutinen, die das simulieren sollen, Volllast
usw.
So einfach ist das nicht.
Christian J. schrieb:> Es gibt nur einen "TX empty" Interrupt. D.h. der TX muss vom> Hauptprogram getriggert werden durch STI_TX = zeichen, damit der nächste> Int, wenn Zeichen raus ist dann in der ISR die weitere Verarbeitung des> Puffers übernimmt. Wenn letztes Zeichen raus, dann bleibt TX stehen, der> Int wird nicht mehr aufgerufen. Das Antriggern läuft noch nicht.
Schau Dir mal mcurses_phyio_putc() für den AVR an.
Verfahren als Pseudocode:
1
mcurses_phyio_putc(uint8_tch)
2
{
3
zeichen_in_ringbuffer_schreiben;
4
tx_empty_interrupt_aktivieren;
5
}
6
7
ISR(TX_EMPTY)
8
{
9
if(ringbuffer_leer)
10
{
11
tx_empty_interrupt_deaktivieren;
12
}
13
else
14
{
15
ein_zeichen_aus_ringbuffer_lesen;
16
das_zeichen_auf_die_reise_schicken;
17
}
18
}
> Wenn letztes Zeichen raus, dann bleibt TX stehen,
Der Witz ist, dass Du in dem Teil, wo Du ein Zeichen in den Ringbuffer
schreibst, danach auf jeden Fall den TX-Empty-Interrupt aktivieren
musst. Ohne wenn und aber.
Frank M. schrieb:> Der Witz ist, dass Du in dem Teil, wo Du ein Zeichen in den Ringbuffer> schreibst, danach auf jeden Fall den TX-Empty-Interrupt aktivieren> musst. Ohne wenn und aber
Eben! und wie aktiviert man den? Obn so tricks funktionieren wie das
Interrupt Flag der STI per Hand zu setzen weiss ich nicht. Der würde
dann in genau dem Moment ausgelöst, wo der Schreib Befehl zu Ende ist.
Es steht nicth dabei ob das register schreibbar ist. Die Flags werden
von der hardware gesetzt. INT Empty wird normalerweise nur aufgerufen,
wenn da das TX Schieberegister leer ist.
Frank M. schrieb:> Der Witz ist, dass Du in dem Teil, wo Du ein Zeichen in den Ringbuffer> schreibst, danach auf jeden Fall den TX-Empty-Interrupt aktivieren> musst. Ohne wenn und aber.
Wahrscheinlich hat Christian oben recht, und die Freigabe allein reicht
nicht. kann sein, daß das Tx-Interrupt-Flag des STI nur gesetzt wird,
wenn der Tx-Buffer leer wird, und nicht, wenn er leer ist.
Wenn daß so ist, muß man beim Schreiben in den Sendefifo prüfen, ob der
Tx-Interrupt enabled ist, und wenn nicht, das Zeichen in den STI, statt
in den FIFO schreiben.
Leo C. schrieb:> Wenn daß so ist, muß man beim Schreiben in den Sendefifo prüfen, ob der> Tx-Interrupt enabled ist, und wenn nicht, das Zeichen in den STI, statt> in den FIFO schreiben
Die TX ISR läuft nur an, nachdem ein Zeichen rausgeschoben wurde, was im
Hauptprogramm in den STI Data geschoben wurde. Dann guckt die ISR nach
ob weitere Zeichen vorliegen und stoppt sobald die Indexe sich decken.
Das kann immer der Fall sein und schon ist "Schluss".
Da muss ich mir was einfallen lassen...
Nachtrag:
2. Möglichkeit (wenn obiges zutrifft):
Man braucht den STI-Interrupt in der Tx-Interrupt-Routine dann nicht zu
sperren. In der Fifo-Schreibroutine dann prüfen, ob Fifo leer und
STI-TxBuf leer, und Zeichen dann in STI schreiben.
Edit:
Wenn das Gestammel unverständlich ist, bitte nochmal nachfragen...
So, mal streng nach Sherlock McCoder:
1. "TX empty" muss nur einmal eingeschaaltet werden und bleibt dann auch
an. Gibt keinen Grund die abzuschalten.
2. "TX Empty ISR" setzt Flag: Ring ist leer, bin fertig!" Damit das
kommt muss der Ring aber erstmal voll sein! Mindest 1 Zeichen.
3. putchar() guckt nach: Ist Ring leer?
Dann wird es schwieriger: Muss das Zeichen in den Ringpuffer rein UND in
das Data Register der TX? Die TX ISR wird nur laufen, wenn TX Data
beschrieben wurde und beim nächstsen Aufruf würde sie das gleiche
zeichen doppelt holen und senden.
Henne oder Ei? Was war zuerst?
Leo C. schrieb:> Wahrscheinlich hat Christian oben recht, und die Freigabe allein reicht> nicht. kann sein, daß das Tx-Interrupt-Flag des STI nur gesetzt wird,> wenn der Tx-Buffer leer wird, und nicht, wenn er leer ist.
Wenn dem tatsächlich so ist, dann kann man das mit folgendem PseudoCode
erschlagen:
1
if(ringbuffer_leer&&STI_bereit_zum_senden)
2
{
3
zeichen_an_sti_senden;
4
}
5
else
6
{
7
zeichen_in_ringbuffer_ablegen
8
}
9
TX_EMPTY_interruptaktivieren;
Das erste Zeichen geht damit direkt an den STI und damit wird
garantiert ein Interrupt erzeugt, sobald das zeichen auf den Weg
geschickt wurde. Im Interrupts kann nun das nächste Zeichen an den STI
geschickt werden - falls ein weiteres Zeichen bereits wartet.
Andere Herangehensweise:
Problem: putchar() kann ununterbrochen aufgerufen werden, kann ja sein
dass jede Menge Text zu schreiben ist. Der Puffer ist viel schneller
voll geschrieben als er von der ISR geleert wird. D.h. sobald eine
zeichen raus ist schon das nächste im Ring, der zeiger WRITE steht immer
DIREKT hinter READ bzw auf READ.
D.h. putchar MUSS warten! Oder es gehen zeichen verloren.
Es kann sein dass es keinen Unterschied macht ob man eine ISR verwendet
oder die Bytes per Hand reinschreibt und immer nachschiebt wenn es raus
ist.
>>TX_EMPTY_interrupt aktivieren;
Was heisst das? Den einschalten oder den "anspringen" lassen, was nicht
geht.
Frank M. schrieb:> TX_EMPTY_interrupt aktivieren;
Die Zeile habe ich übersehen. Der Interrupt kann einmalig in der
Initialisierung freigegeben werden. Da er nicht gesperrt wird, wenn der
FIFO leer ist, reicht das.
Christian J. schrieb:> D.h. putchar MUSS warten! Oder es gehen zeichen verloren.
Korrekt: Jeder Ringbuffer kann voll werden. Solange putchar immer noch
unterbrechbar (zum Lesen von ankommenden Zeichen) ist, sollte das nicht
tragisch sein.
BTW:
Als Z80-User hast Du ja den Komfort eines gigantisch großen RAMs
(jedenfalls im Vergleich zu AVRs). Wie groß sind Deine TX- und
RX-Buffer?
> Was heisst das? Den einschalten oder den "anspringen" lassen, was nicht> geht.
Den Einschalten. Anspringen wird er von selbst, nämlich dann, wenn das
erste Zeichen raus ist.
Leo C. schrieb:> Die Zeile habe ich übersehen. Der Interrupt kann einmalig in der> Initialisierung freigegeben werden. Da er nicht gesperrt wird, wenn der> FIFO leer ist, reicht das.
Gut, wenn das einmalig reicht, weil man nur Interrupts bekommt, wenn der
TX leer wird und nicht leer ist (Dauerfeuer wie beim AVR), dann
haben wir ja jetzt die Lösung:
>>TX leer wird und nicht leer ist
das muss ich noch ausprobieren, genau weiss ich das nicht, ob der pegel
oder flankengetriggert ist. NMI ist pegelgetriggert, der steht dann auf
Dauerfeuer.
Durch "di" am Anfang und "ei" am Ende machst Du putchar ununterbrechbar.
Kein Wunder, dass das nicht sauber funktioniert. Hatte ich nicht schon
mehrfach geschrieben, dass putchar unterbrechbar sein muss, wenn es
wartet?
Apropos.... Wo wartest Du da eigentlich, wenn der Buffer voll ist? Du
überschreibst ja den Buffer im Kreis ohne Rücksicht auf Verluste! Wo
hast Du denn diese Sch...-Routinen gekupfert?!?
>>Apropos.... Wo wartest Du da eigentlich, wenn der Buffer voll ist? Du>>überschreibst ja den Buffer im Kreis ohne Rücksicht auf Verluste! Wo>>hast Du denn diese Sch...-Routinen gekupfert?!?
Fraaaaaaaaaaaaaaaaaaaaaank!
Das ist kein fertiger Code, sonder das was ich gerade auf dem Schirm
habe! Der tut noch nicht. Brettert alles platt, wenn es da nichts ist
was ihn aufhält.
Christian J. schrieb:> Das ist kein fertiger Code, sonder das was ich gerade auf dem Schirm> habe! Der tut noch nicht.
Warum postest Du den dann?
Warum nimmst Du nicht den Ringbuffer-Code aus mcurses? Der kommt mit
minimalen volatile-Variablen aus und braucht auch keine
Ringbuffer-Größe, welche eine Zweierpotenz ist. Zudem ist er absolut
simpel und effizient.
Gabs alles schonmal hier:
Beitrag "UART Sendepuffer"
Ich benutze ungern Code, den ich nicht komplett verstanden habe. Und ein
AVR ist kein Z80. Es geht nicht um das Prinzip von Ringpuffer, sondern
daran wie der hier mit der Hardware verquickt wird. und das werde ich
jetzt auf dem Balkon mit einem Kaffee durchdenken....
Hallo!
Habe gerade noch mal im Quelltext zu meinem CP/M-System nachgesehen:
Beitrag "Re: Retro Fieber: Z80 oder 68000 ?"
Ich nutze nur für den Empfang vom PC den RX-Interrupt der SIO. Damit
wird der Ringpuffer gefüllt. Per Hardware-Handshake gibt es keinen
Pufferüberlauf.
Das Senden geht mit Polling. Dafür braucht es keinen INT. Für das
Anzeigen am PC-Terminal muß es nicht mikrosekundengenau sein.
Ich sehe in der putchar-Routine nach: ist das vorherige Zeichen weg,
dann das nächste ins Senderegister und wieder raus.
Route 66 schrieb:> Das Senden geht mit Polling. Dafür braucht es keinen INT. Für das> Anzeigen am PC-Terminal muß es nicht mikrosekundengenau sein.> Ich sehe in der putchar-Routine nach: ist das vorherige Zeichen weg,> dann das nächste ins Senderegister und wieder raus.
Genau das überlege ich mir auch grad ..... wobei man abkläören muss, ob
zb während des Wartens, bis TX frei wird noch RX Ints zugelassen werden,
damit das Ganze mehr "Duplex" wird.
Aktuell wird alles rückwärts angezeigt..... d.h. ich nähere mich dem
Ziel :-)
So,
eine Routine
while (1)
putchar(getchar());
spielt mir bei
cat main.c > /dev/ttyUSB0
genau das auf den Schirm. RX über Ints in Puffer, TX direkt in die Dose
gehämmert.
Und ich denke so bleibt es auch! denn putchatr muss sowieso warten, ob
nach jedem zeichen oder erst wenn Buffer voll ist eigentlich egal.
Christian J. schrieb:> zb während des Wartens, bis TX frei wird> denn putchatr muss sowieso warten, ob> nach jedem zeichen
Hier nochmal konkret: Nicht das Zeichen ins Senderegister und dann
warten, bis es weg ist, sondern wenn Zeichen ins Senderegister
geschrieben wurde, gleich wieder raus, und was Anderes machen. Beim
nächsten Zeichen ist dann das Senderegister vielleicht schon leer. Also
beim nächsten Zeichen nur kurz vergewissern und nur ggf. warten.
Christian J. schrieb:> wobei man abkläören muss, ob> zb während des Wartens, bis TX frei wird noch RX Ints zugelassen werden
Da gibts überhaupt nichts zu klären. Frank weist schon die ganze Zeit
darauf hin. Seine Routinen in mcurses (und meine in der gestern
geposteten ring.zip) kommen völlig ohne Interrupt-Sperre aus.
So ein Monitor Programm ist ja auch eher einfach, da kann getchar() auch
ewig warten, wie es definiert ist in C. Was sollte der Rechner auch
machen, wenn ein Timeout kommt? Zwischendurch schon mal Geschirr spülen
gehen?
Solange keine Eingabe vom User kommt passiert auch nix. es ist ja nicht
so dass während des Betriebes Kommandos von außen kommen können, die
dann gesonders abgearbeitet werden.
Es gibt siche eine pfiffige Lösung, dass in TX Buffer gschrieben werden
kann, während im Hintergrund die Zeichen rausgehämmert werden. Trotzdem
muss auch da immer gewartet werden, denn das Füllen geht immer schneller
als das Senden.
Leo C. schrieb:> Da gibts überhaupt nichts zu klären. Frank weist schon die ganze Zeit> darauf hin. Seine Routinen in mcurses (und meine in der gestern> geposteten ring.zip) kommen völlig ohne Interrupt-Sperre aus.
Defintiv nicht! Ohne geht es nicht! Eine Veränderung von globalen
Variablen während die gelesen werden kann nicht akzeptiert werden. Da
sind Semaphore nötig oder eine Sperre. Kann Framnk gern so machen, ich
aber nicht. Zwischen Int Routinen und normalen grenze ich klar ab, vor
allem wenn die auf gemeinsame Bereiche zugreifen.
/ Ints aus, da Lesezugriff
__asm
di
__endasm ;
ch = rx.buf[rx.rd_ptr]; rx.rd_ptr =
(rx.rd_ptr +1) & rx.mask;
rx.f_buf_full = (rx.rd_ptr == rx.wr_ptr) ? false : true; // Alle
Zeichen gelesen?
__asm
ei
__endasm ;
return(ch);
wr_ptr kann im Int verändert werden.
Leo C. schrieb:> Seine Routinen in mcurses (und meine in der gestern> geposteten ring.zip) kommen völlig ohne Interrupt-Sperre aus.
So ist es. Das liegt daran, dass die Variablen tx_start und tx_stop
voneinander unabhängig sind und in keiner Konkurrenz zueinander stehen.
tx_stop ist static in der putchar()-Funktion und tx_start ist static in
der TX-ISR(). Das einzige, was die beiden zusammenhält, ist die Variable
tx_size. Diese ist die einzige (bis auf den buffer selbst), welche
volatile sein muss.
Dasselbe gilt für den RX-Ringbuffer - nur spiegelbildlich. rx_start ist
static in getchar(), rx_stop ist static in der RX-ISR(). Für rx_size
gilt dasselbe wie für tx_size.
Der RX-Ringbuffer und der TX-Ringbuffer sind auch komplett voneinander
entkoppelt, d.h. man kann damit Full-Duplex realisieren.
Wenn der TX-Buffer volläuft, ist das überhaupt kein Problem. Dann wird
halt gewartet. Kritischer ist es beim RX-Buffer. Wenn der volläuft,
verliert man Zeichen. Daher sollte man im Zweifel den RX-Buffer größer
dimensionieren als den TX-Buffer.
Einfacher und effizienter gehts nicht.
Frank M. schrieb:> Dasselbe gilt für den RX-Ringbuffer - nur spiegelbildlich. rx_start ist> static in getchar(), rx_stop ist static in der RX-ISR(). Für rx_size> gilt dasselbe wie für tx_size.
Diese entkopplung baue ich jetzt noch ein....
Christian J. schrieb:> Defintiv nicht! Ohne geht es nicht! Eine Veränderung von globalen> Variablen während die gelesen werden kann nicht akzeptiert werden. Da> sind Semaphore nötig oder eine Sperre.
Quatsch. Wie gerade oben geschrieben, sind tx_start und tx_stop NICHT
global. Das ist ja gerade der Witz!
Einzig der Zugriff auf tx_size muss gesperrt werden und zwar nur genau
dann, wenn geschrieben wird:
Ich habe es jetzt an Frank Hex Editor ausprobiert. Einandfrei scrollt
der durch auch mit Taste festhalten. Lässt man los scrollt der weiter
bis alles abgearbeitet ist.
Der "Absturz" kommt erst, wenn man nach unten schrollt und der ganze
Bildschirm neu aufgebaut werden muss. irgendwan ist der Puffer voll
gelaufen und dann müssen die Zeichen verworfen werden. Das muss ich noch
abfangen.
Frank, hast du schon die Weiterschaltung bei der Eingabe und auch Test
ob ROM oder RAM? Aktuell lässt sich das ROM auhc beschreiben :-)
PageUp UNd PageDown wäre auch nicht schlecht, ein goto Adresse
vielleicht noch ... und (Sonderwunsch 1 )..... und (Sonderwunsch 2
).....und.... :-)
Frank M. schrieb:> cli();> uart_txsize++;> sei();>> Das ist die einzige Stelle!
Ups, die Stelle hatte ich übersehen. Meine Routinen kommen auch ohne die
Füllstandszähler aus, und deshalb gibts da übehaupt keine
Interrupt-Sperren.
Auf CPUs, auf denen Interrupt-Sperren billig sind, (AVR, Z80) ist Deine
Variante wahrscheinlich etwas effizienter. Auf ARMs sieht es etwas
anders aus.
Christian J. schrieb:> Ich habe es jetzt an Frank Hex Editor ausprobiert. Einandfrei scrollt> der durch auch mit Taste festhalten. Lässt man los scrollt der weiter> bis alles abgearbeitet ist.
Okay, das ist normales Verhalten.
> Der "Absturz" kommt erst, wenn man nach unten schrollt und der ganze> Bildschirm neu aufgebaut werden muss.
Der wird niemals neu aufgebaut. Wenn Du oben bzw. unten anschlägst, dann
wird der Bildschirm mit einem Befehl nach oben/unten gescrollt und dann
eine(!) Zeile hinterhergeschickt - mehr nicht.
> Irgendwan ist der Puffer voll> gelaufen und dann müssen die Zeichen verworfen werden. Das muss ich noch> abfangen.
Müsste dann der RX-Buffer sein. Wie groß ist der? Im Zweifel: Mach ihn
größer. Ich schrieb ja eben schon, dass der RX-Buffer die einzige
"Gefahr" bei der Sache ist. Wenn der TX-Buffer voll ist, macht das gar
nichts.
> Frank, hast du schon die Weiterschaltung bei der Eingabe und auch Test> ob ROM oder RAM? Aktuell lässt sich das ROM auhc beschreiben :-)
Nö, ich weiß ja gar nicht, wo bei Deinem System die Grenze ist. Könnte
man noch als Argument an hex_edit() runtergeben.
> PageUp UNd PageDown wäre auch nicht schlecht, ein goto Adresse> vielleicht noch ... und..... und .....und :-)
Ich habe in der Zwischenzeit noch Pos1 und Ende eingebaut. PageUp/Down
wäre auch trivial. Und ein goto ist dank getnstr() nun auch nicht mehr
schwierig. Okay, baue ich ein.
Übrigens, ich habe da vor ein paar Tagen noch einen Fehler in
mcurses_puti() gefunden.
Ersetze die Funktion bitte mit:
1
staticvoid
2
mcurses_puti(uint8_ti)
3
{
4
uint8_tii;
5
6
if(i>=10)
7
{
8
if(i>=100)
9
{
10
ii=i/100;
11
mcurses_putc(ii+'0');
12
i-=100*ii;
13
}
14
15
ii=i/10;
16
mcurses_putc(ii+'0');
17
i-=10*ii;
18
}
19
20
mcurses_putc(i+'0');
21
}
Die alte hatte den Bug, dass Zahlen zwischen 101 und 109 nicht richtig
umgerechnet wurden. Ein move(10,105) hatte dann dasselbe wie ein
move(10,15) gemacht. Ein relativ unrealistischer Fall - gerade dann,
wenn man sich auf 24x80 beschränkt - aber trotzdem. So passt es besser.
Frank M. schrieb:>> Frank, hast du schon die Weiterschaltung bei der Eingabe und auch Test>> ob ROM oder RAM? Aktuell lässt sich das ROM auhc beschreiben :-)>> Nö, ich weiß ja gar nicht, wo bei Deinem System die Grenze ist. Könnte> man noch als Argument an hex_edit() runtergeben.
Bin auch der Meinung, daß der Anwender wissen sollte, was er tut. Ich
habe mir nicht angesehen was der Editor genau macht. Aber wenn er das
Geschriebene wieder zurückliest und die Anzeige (bei Änderung)
aktualisiert, dann sieht man ja, obs ROM oder RAM ist.
Müsste dann der RX-Buffer sein. Wie groß ist der? Im Zweifel: Mach ihn
größer
leider muss das ein Vielfaches von 2 sein, also nur 64, 128 möglich. 256
wäre 0x00. Damit man die Maske benutzen kann. 128 sind es derzeit.
Leo C. schrieb:> Bin auch der Meinung, daß der Anwender wissen sollte, was er tut. Ich> habe mir nicht angesehen was der Editor genau macht. Aber wenn er das> Geschriebene wieder zurückliest und die Anzeige (bei Änderung)> aktualisiert, dann sieht man ja, obs ROM oder RAM ist.
Nein, er liest den Wert nicht zurück. Die einzige Möglichkeit,
festzustellen, ist, die geänderte Zeile einmal rausrollen zu lassen, um
sie dann wieder reinzurollen.
Aber danke für den Tipp, ich werde das mit dem sofortigen Zurücklesen
einbauen.
@Frank:
Früher oder später rennt der Puffer voll und dann kann es sein, dass da
2 x ESC gelesen wird und er aussteigt. Ich habe da ja keine Kontrolle,
da es sich in hexedit abspielt.
Christian J. schrieb:> leider muss das ein Vielfaches von 2 sein, also nur 64, 128 möglich. 256> wäre 0x00. Damit man die Maske benutzen kann. 128 sind es derzeit.
Denk nochmal nach.
Bei 256 ist die Maske 256-1, also 255 (0xFF). Bei einer 8-Bit Variablen
kannst Du sie dann auch weg lassen. Eigentlich sollte das dann aber auch
der Compiler erledigen. Also (erst mal) drin lassen.
Christian J. schrieb:> Früher oder später rennt der Puffer voll und dann kann es sein, dass da> 2 x ESC gelesen wird und er aussteigt. Ich habe da ja keine Kontrolle,> da es sich in hexedit abspielt.
Natürlich hast Du da die Kontrolle! Jetzt zum ALLERLETZTEN MAL:
hexedit
|
getch
|
mcurses_phyio_getch
|
getchar
|
DEINE FIFO-Routinen!
Das kann doch nicht so schwer zu verstehen sein! Wenn Du den RX-Buffer
größer machst, profitieren davon ALLE MCURSES-Funktionen!
Die Frage zum Xten Mal: Wie groß ist Dein RX-Buffer?
Wäre schön, wenn ich da endlich mal eine Antwort bekäme....
Anbei eine neue Version von hexedit.
Neuigkeiten:
- Pos1 und Home gehen an Anfang/Ende der Zeile
- Bild-Tasten springen um eine Seite vor/zurück
- STRG-G macht ein Goto: Abfrage Hex-Adresse und Sprung
- Geschriebene Werte werden zwecks Prüfung wieder zurückgelesen (ROM)
- Statuszeilen oben/unten in Farbe
Viel Spaß!
Frank M. schrieb:> Anbei eine neue Version von hexedit.
Sorry, da war noch ein Bug drin, wenn man die Bild-Tasten benutzt,
während man in den ASCII-Spalten steht.
Anbei der Fix.
Grad ausprobiert.... klappte nachdem ich da einige "static" wegnahm,
weil ich sonst die Funtkionen nicht aus main.c haette sehen können, bzw
aus irgendwelchen gründen (error: Old stycle C .-....) keinen prototypen
in hexedit.h anlegen konnte.
Jetzt kannich sogar den Stack sehen ;-) Nicht schlecht und mit 9600 baud
echt Retro Gangnam style!
Christian J. schrieb:> Grad ausprobiert.... klappte nachdem ich da einige "static" wegnahm,> weil ich sonst die Funtkionen nicht aus main.c haette sehen können, bzw> aus irgendwelchen gründen (error: Old stycle C .-....) keinen prototypen> in hexedit.h anlegen konnte.
Hm, ich weiß jetzt nicht, was für statics Du da wegnehmen musstest...
vermutlich liegt es daran, dass Du nicht komplett alles über mcurses
laufen lässt - was ich Dir immer noch empfehle.
> Jetzt kannich sogar den Stack sehen ;-) Nicht schlecht und mit 9600 baud> echt Retro Gangnam style!
Freut mich. Schaffst Du mit dem STI eigentlich auch 19200 Baud? Könnte
vielleicht die RX-Buffer-Overflow-Problematik etwas entschärfen.
Ich habe hier noch eine Verbesserung, die dafür sorgt, dass bei
RX-Buffer-Überlauf nicht direkt jede Sondertaste als Doppel-ESCAPE
erkannt wird:
mcurses.c, Funktion getch(), alt:
> Hm, ich weiß jetzt nicht, was für statics Du da wegnehmen musstest...
Das wird er selbst nicht so genau wissen, weil der Compiler bei ihm ja
nie konkrete Fehlermeldungen oder Warnungen ausgibt, sondern immer nur
"...", oder so...
if (value != value_read)
{
====> move (line, FIRST_HEX_COL + 3 * byte);
itoxx (value_read);
}
Warning: unreachable code
Nur so: Damit ich das nutzen kann muss ja die Funktion hexedit bekannt
gemacht werden :-) So um 1990 herum machte man das über Prtotypen in der
#include Datei. darum habe ich Franks Code obenrum in eine solche
verfrachtet und Prototypen angelegt, wobei ich include hexedit.h in
mai.cn benutze.
Vielleicht ist das ja im jahre 2014 anders.... außerdem habe ich Franks
Code so um gefühlt 300 {} gestripped, so dass er 150 zeilen kürzer ist
und "dichter".
Frank könnte jetzt hier im Wiki echt einen wirklich coolen Hex Editor
präsentieren.
Das Ding hat was!
19200 geht nicht, lässt sich kein Teiler für finden :-(
Aber 2400 und 300 gehen... :-)
Christian J. schrieb:> if (value != value_read)> {> ====> move (line, FIRST_HEX_COL + 3 * byte);> itoxx (value_read);> }>>> Warning: unreachable code
Da ist der SDCC doch schlauer als ich dachte. Er nimmt natürlich an,
dass ein PEEK (siehe Macro in hexedit.c) exakt dasselbe ausliest, was
der POKE vorher ins Memory geschrieben hat. Ein POKE auf eine
ROM-Adresse macht ihm aber einen Strich durch die Rechnung.
Ersetze bitte in hexedit.c:
Christian J. schrieb:> Frank könnte jetzt hier im Wiki echt einen wirklich coolen Hex Editor> präsentieren.
Gibt es schon:
http://www.mikrocontroller.net/articles/MCURSES#Beispielanwendung> 19200 geht nicht, lässt sich kein Teiler für finden :-(
Schade.
> Aber 2400 und 300 gehen... :-)
300 wäre dann natürlich dasselbe wie in den Science-Fiction-Spielfilmen,
wo Meldungen auf dem Bildschirm heute noch mit 300Bd rausgeschrieben
werden - untermalt von etwas Zirpen ;-)
@Frank:
wie kriegt man es hin, dass nach der Ausgabe diverser String der
minieditor genau da steht, wo der letzte Buchstabe wa?
Der Cursor steht nämlichn immer nochn in der ersten Zeile. Ich möchte ja
einen fliessenden Buildschirm.
// Bildschirm vorbereiten
initscr ();
clear();
move(0,1);
for (i=0;i<12;i++)
addstr (menu[i]);
getnstr (inbuf, 20);
Leo C. schrieb:> Ups, Beitrag schon wieder weg.> Ist eigentlich meine letzte Mail (vorgestern) mit dem Makefile Update> nicht angekommen?
Doch, ist da .... aber noch nicht eingebaut. Eines nach dem anderen.
Danke!
@Frank:
Etwas seltsam das verhalten von getstrng... der erste Buchstabe stimmt
alle andere sind dann aber oben.... erst ein move(....) zwingt den
Cursor in die richtige Zeile. Glaube der zähtl nicht richtig mit wo der
Cursor steht nach einer Ausgabe.
default:
if (curlen < maxlen && (ch & 0x7F) >= 32 && (ch & 0x7F)
< 127) // printable ascii 7bit or printable 8bit ISO8859
{
for (i = curlen; i > curpos; i--)
str[i] = str[i - 1];
insch (ch);
str[curpos] = ch;
curpos++;
curlen++;
}
}
move (starty, startx + curpos);
Die beiden stimmen aber nach jedem Tastendruck:mcurses_curx,mcurses_curx
Nur steht der Cursor nicht da.
Das aber stimmt nicht, nach dem ersten Tastendruck ist bei startx eine 0
drin.
move (starty, startx+curpos);
schon der Startwert ist falsch nach einer Reihe von addstr. Die nächste
Ausgabeposition liegt nicht direkt hinter dem letzten Zeichen. Ich habe
\n\r als CR verwendet. Er vergisst die CR's als Erhöhung der y
Koordinate mit zu zählen in
static void mcurses_putc (uint8_t ch)
{
mcurses_phyio_putc (ch);
}
@Frank:
So stimmt es, nur ein Leerzeichen rutscht dazwischen. Ich habe für CR
und LF den Zähler erhöht. Allerdings kriege ich das Leerzeichen nach dem
ersten Buchstaben nicht weg.
//
------------------------------------------------------------------------
----------------------------------------------
// INTERN: put a character (raw
//
------------------------------------------------------------------------
----------------------------------------------
static void mcurses_putc (uint8_t ch)
{
mcurses_phyio_putc (ch);
if (ch=='\n')
mcurses_cury++;
if (ch=='\r')
mcurses_curx=0;
}
Key END erzeugt übrigens die Ausgabe "0F" im Minieditor.
Hier meine Strings zum Testen, auch mit nur \r das gleiche Ergebnis.
// Menu Ausgabe
const char* const menu[] = {
"\r\n---------------------------------",
"\r\nZ80 System ist online.\r\n", // 0
"---------------------------------", // 1
"\r\n[load].......... .Lade User Program", // 2
"\r\n[start]...........Start User Program", // 3
"\r\n[clear]...........Loesche Memory", // 4
"\r\n[dump]........... Dump Memory", // 5
"\r\n[reset]...........Restart System", // 6
"\r\n[basic]...........Basic Interpreter", // 7
"\r\n---", // 8
"\r\nDeine Wahl?:" // 9
};
Und nochwas für Frank, wenn er mal wieder da ist:
Da steht ab und zu was über rechts..... weiss aber nicht ob das nicht
auch vielleicht an meinem Terminal liegt. es würde eh reichen nur
Buchstaben und Zahlen anzuzeigen und keine Sonderzeichen.
Schon gefunden.
Aber mal was für Dich als sdcc Spezialisten und Coder.
Guck mal den Dump an. Oben liegt der Stack von 0xffff abwärts und
verdammt nah dran liegt "irgendwas" von dem ich nicht weiss wie es dahin
kommt. Man sieht auch ein Wort was ich eingegeben hatte. Das Data
Segment liegt nämlich schön brav bei 0x8000.
Ist das so normal?
Christian J. schrieb:> Guck mal den Dump an. Oben liegt der Stack von 0xffff abwärts und
Dein Stack liegt nicht von 0xfff an abwärts, sondern von 0xfffe an. Das
hatte ich schon mal versucht, Dir zu erklären.
> verdammt nah dran liegt "irgendwas" von dem ich nicht weiss wie es dahin> kommt.
Seufz, wirst Du es jemals lernen? Ich sehe da kein "irgendwas" sondern
nur ganz normale Bytes. Welche von denen sollen denn das "irgendwas"
sein?
> Man sieht auch ein Wort was ich eingegeben hatte. Das Data> Segment liegt nämlich schön brav bei 0x8000.
Lokale Variable werden aber auf den Stack gelegt. Wahrscheinlich hat
irgendeine Funktion ein character array. Z.B. die Eingabezeile. Das ist
jetzt nur geraten. Ich habe nicht vor, in Dein Programm zu schauen.
> Ist das so normal?
Ja, deshalb habe ich auch schon mal geschrieben, daß 254 Byte Stack
warhscheinlich etwas knapp ist.
Ok.... ich dachte nur die 00 würden eine Grenze bilden, dass der Stack
sich nur so ca 32 Bytes ausgebreitet hätte.
Hats du für das rprintf vielleicht mal die config.h Datei? Die fehlt da
scheinbar. Auch alloca.h wird nicht gefunden.
rprintf?
Meinst Du das hier?
Beitrag "Re: Retro Fieber: Z80 oder 68000 ?"
Das habe ich mir noch nicht angeschaut.
> Auch alloca.h wird nicht gefunden.
alloca() scheint es für sdcc nicht zu geben. Anscheinend hat es auch
noch niemand vermißt. Kein Bug-Report/Feature-Request, nix auf den
Mailinglisten.
Ok, ich versuche nur ein prinft zum Laufen zu kriegen. Allerdings fehlen
mir einige C kenntnisse was recht komplexe Zeiger Geschichten angeht. Es
gibt da noch mehr Sourcen aber die lassen sich nicht kompilieren.
Ist trotzdem schon irre....... das kann der stundenlang, gegen sich
selbst spielen :-) Nur bei 23k wird es jetzt langsam eng im Speicher.
Wäre gut, wenn man das Data Segment direkt hinter dem Codesegment
plazieren könnte, automatisch.
Hi,
haeb chan installluert, kompiliert durch. Leider hast Du bei dem
Makefile wohl nioch mehr geändert, ich sehe erstmal keine Meldungen mehr
und das .bin File ist ein Image des ganzen Speichers, nicht mehr wie
früher eines des Rams. Versuche grad da zu ändern aber weiss nicht genau
wo ich das suchen soll.
Zur Vedeutlichung: Vorher hatte ich ein Image, was ich direkt nach 2000
laden konnte. VOM Rom aus wurde dann nach 2100 gesprungen und es lief.
Jetzt habe ich ein Image, was am Hex Editor ab 0x0000 beginnt und Luft
bis 0x2000 hat, dort fängt der Code erst an. Das läuft natürlich nicht.
Christian J. schrieb:> Hats du für das rprintf vielleicht mal die config.h Datei? Die fehlt da> scheinbar. Auch alloca.h wird nicht gefunden.
config.h ist eine zentrale Config meiner Projekte, hier irrelevant.
alloca() kann durch einen lokalen oder globalen Puffer fester
(maximaler) Länge ersetzt werden.
Kämpfe grad mit den Chan printf, die keine Ausgabe erzeugen. Wohin geht
deren Ausgabe? Ein putchar ist nirgendwo zu finden. Beispiel ist leider
falsch verlinkt.
Ok, läuft... sehr nett.
xdev_out(putchar);
count = 1234;
xprintf("Hallo Welt!");
xprintf("Teststring = %d",count);
>config.h ist eine zentrale Config meiner Projekte, hier irrelevant.>alloca() kann durch einen lokalen oder globalen Puffer fester>(maximaler) Länge ersetzt werden.
Dennoch entstehen leider viele Compilerfehler bei long long Auusdrücken,
die ich nicht weiter verfolgt habe bei rprintf. Da die Chan Funktion
deutlich kürzer ist und die elementaren Dinge abdeckt verwende ich die
weiter.
Hoffentlich steht Frank mal auf bald, damit seine Mcurses von dem Bug
befreit wird.
@Leo: Problem gefunden mit dem Image. Hat sich erledigt. Zeile für zeile
durchgegangen und geändert.
Christian J. schrieb:> Leider hast Du bei dem> Makefile wohl nioch mehr geändert, ich sehe erstmal keine Meldungen mehr
Meldungen sieht man wieder, wenn man "make V=1" eingibt. Ja, wenn man
gar nichts mehr sieht, ist auch nicht optimal. Das ging gestern Abend
aus Versehen raus.
> und das .bin File ist ein Image des ganzen Speichers, nicht mehr wie> früher eines des Rams.
Wenn Du für ROM und RAM eine Startadresse eingibst, sollte das
Verhalten wie vorher sein. Wenn nicht, habe ich dafür jeztzt auch keine
Erklärung.
> Hoffentlich steht Frank mal auf bald, damit seine Mcurses von dem Bug> befreit wird.
Manche Menschen haben außer Windmühlenkampf auch noch andere Hobbies.
Ich werde die nächsten Tage auch keine Zeit haben.
> @Leo: Problem gefunden mit dem Image. Hat sich erledigt. Zeile für zeile> durchgegangen und geändert.
Und natürlich wird wieder nicht verraten, wo das Problem war...
Leo C. schrieb:> Und natürlich wird wieder nicht verraten, wo das Problem war...
crt0.s vergessen einzutragen.
Ich habe den SP jetzt mal auf 0xfffe gesetzt, eine gerade Adresse. Hoffe
das ist dann so richtig. Früher lief der Stack nach unten zu den
niederen Adressen, hofffe das ist immer noch so.
Ärgerlich ist dass sdcc unbenutzte Routinen nicht weg optimiert, der
erste Compiler den ich kenne der das nicht macht. Man kann ja nicht
alles auskommentieren aus Modulen, nur weil man es eben mal nicht
braucht.
Bin jetzt sowieso endgültig bei Wargames angekommen. Und werde auch mal
etwas Pause machen. Nächste Woche sinf wichtige Termine und da muss ich
durch Deutschland mal eben ganz durch.
Lassen wir ihn mal spielen den Tag über, dann hat er was zu tun.
Christian J. schrieb:> Ich habe den SP jetzt mal auf 0xfffe gesetzt, eine gerade Adresse. Hoffe> das ist dann so richtig.
Das ist genauso richtig oder falsch wie 0xffff. Nur verschenkst Du damit
noch ein weiteres Byte RAM. Vielleicht versuchst Du in einer ruhigen
Minute mal zu verstehen, was ich schon mal geschrieben hatte:
------------------------------------------------------------------
Wenn Du das letzte Byte RAM auch noch verwenden willst, wäre hier
stack .equ 0
richtig, da der Stackpointer beim push zuerst dekrementiert wird, und
beim pop werden die daten zuerst gelesen, und dann der sp inkrementiert.
Hier kommt es auf das eine Byte sicher nicht an, aber an anderen Stellen
muß man ggf. ganz genau wissen, wie der Stackpointer im Verhältnis zu
den Daten steht.
------------------------------------------------------------------
> Früher lief der Stack nach unten zu den> niederen Adressen, hofffe das ist immer noch so.
Allerdings, nur anders, als Du es Dir vorstellst. Der SP zeigt nicht auf
die höchste freie Adresse, sondern auf die niedrigste, vom Stack belegte
Adresse.
Leo C. schrieb:> Allerdings, nur anders, als Du es Dir vorstellst. Der SP zeigt nicht auf> die höchste freie Adresse, sondern auf die niedrigste, vom Stack belegte> Adresse.
Zumindest oft, und auch bei Z80. Es gibt aber auch Prozessoren, bei
denen SP auf die höchste freie Adresse zeigt, sowie welche mit aufwärts
wachsenden Stacks.
Leo C. schrieb:> Vielleicht versuchst Du in einer ruhigen> Minute mal zu verstehen, was ich schon mal geschrieben hatte:
Es ist eigentlich Jacke wie Hose ob der auf 0xffff steht oder 0x0000,
was ja eine ROM Adresse ist. Da der erste Zugriff immer ein call oder
pop sein wird, "wächst" er nach unten: 0xffff,0xfffe,0xfffd usw.
Da ich aber nicht genau wusste, ob er 0x0000 auch beschreibt oder erst
decrementiert setzte ich es auf 0xffff, was auch in vielen beispielen so
ist, selbst in den sdcc Files wie crts.0. 0x0000 läuft genauso wie
0xffff.
Das Thema, dass sdcc nicht klug genug ist, zu erkennen, ob ich eine
Funktion benutze wird wohl ungelöst bleiben.
@Holm:
Das nützt nichts. Der sdcc hat den sdld Linker, ein mit installiertes
Programm. sdcc kann laut Manual nur ein Source File kompilieren, d.h man
müsste alle durch includes zu einem zusammen ketten. So wie der CCS für
PIC auch, mit dem ich fast 10 Jahre gearbeitet habe. Den besseren Umweg
über compile+link geht man wohl mit Linker Skript und Makefile. Die sog
"Dead code elimination" funktioniert nur lokal.
Compiler wie der IAR oder Keil erstellen in 2 Durchläufen
Aufruf-Abhängigkeitsbäume aller Funktionen und berechnen zb auch den
Stack Bedarf und die Schachteltiefe. Dabei fliegen dann alle Funktionen
raus, die nicht benutzt werden. Zb benutze ich von Fransk mcurses und
der xprintf nur recht wenig, trotzdem wir alles mit eingebunden aber
niemals durchlaufen. Das ist für einen Compiler, der für Mikrocomputer
ausgelegt wurde nicht schön, es ist sogar ausgesprochen schlecht. Bei
mir hier verdoppelt es die Codesize mal eben. Abhilde geht durch
LÖibraries, die vorkompiliert sind und durch .h eingebunden werden. da
holt er sich dann nur raus was er braucht. Habe noch nie was mit Libs
gemacht und wie man die anlegt.
Habe nur das hier gefunden und das ist Asbach:
http://www.tensi.eu/thomas/programming/asxxx-linker/rev_sdcc_linker-documentation.pdf
Christian J. schrieb:> wie kriegt man es hin, dass nach der Ausgabe diverser String der> minieditor genau da steht, wo der letzte Buchstabe wa?>> Der Cursor steht nämlichn immer nochn in der ersten Zeile. Ich möchte ja> einen fliessenden Buildschirm.>> // Bildschirm vorbereiten> initscr ();> clear();> move(0,1);>> for (i=0;i<12;i++)> addstr (menu[i]);>> getnstr (inbuf, 20);
Wirf die '\n' aus den Menü-Strings raus! Positionierung machst Du mit
move(), aber nicht wie oben, sondern so:
1
initscr();
2
clear();
3
for(i=0;i<12;i++)
4
{
5
move(i,1);
6
addstr(menu[i]);
7
}
8
getnstr(inbuf,20);
Der move() muss also in die for-Schleife. Deine "\n" sind in mcurses
nicht geeignet für Positionierung. mcurses hält in internen Variablen
fest, wo der Cursor gerade steht. Ein \n bringt das durcheinander, denn
je nach Einstellung des Terminals geht der Cursor dabei entweder nur
eine Zeile nach unten, bleibt aber in derselben Spalte, ein andermal
geht er auch noch an den Anfang der Zeile (Wagenrücklauf, implizites
CR).
Deine '\n' bringen damit die interne Cursor-Verwaltung durcheinander. Du
musst immer mit move() positionieren. Das sollte auch Deine anderen
Positionierungs-Probleme erklären - auch mit getnstr(). Einfach weil der
interne virtuelle Cursor woanders steht als der reale!
Denk bitte auch daran: Die erste Zeile/Spalte in mcurses beginnt mit 0,
nicht mit 1. move (0, 0) ist die linke obere Ecke.
Christian J. schrieb:> Da steht ab und zu was über rechts..... weiss aber nicht ob das nicht> auch vielleicht an meinem Terminal liegt. es würde eh reichen nur> Buchstaben und Zahlen anzuzeigen und keine Sonderzeichen.
Ich schrieb ja: Dein Terminal muss auf ISO8859 eingestellt sein bei
Darstellung der Sonderzeichen. Deines arbeitet offenbar mit UTF-8. Du
kannst die Darstellung von 8-Bit-Zeichen ändern, wenn Du das Macro
Leo C. schrieb:> […]> alloca() scheint es für sdcc nicht zu geben. Anscheinend hat es auch> noch niemand vermißt. Kein Bug-Report/Feature-Request, nix auf den> Mailinglisten.
Es gibt ein RFE für VLAs.
Philipp
Hallo Frank,
tut mir leid aber dann kann ich damit nicht viel anfangen, da es
unüblich ist absolut zu positionieren auf fliessenden Bildschirmen.
Dafür gibt es seit der Erfonduing des Telex Sonderzeichen wie \n \r \b
usw.
Ich zähle da ja nicht die Koordinaten ab sondern nach jeder Zeile kommt
die nächste unter drunter. Die verwendung von printf Formaten ist ja
usus überall.
Was super geht sind statische Bildschirme, wo laufen Zahlen usw rennen,
also Masken. Ich habe bei dir ein wenig im Code gefummelt und die
Steuerzeichen werden mit berücksichtigt.
Aber Fliesstext wie eine Konsole.. Schade.....
Er daddelt mir grad mal Primzahlen durch.... wüsste nicht wie ich sowas
"einfach" ohne %6lu Format machen sollte, wenn ich absolut positioniere
minicom kann das nicht:
http://ubuntuforums.org/showthread.php?t=2063253
Christian da ist überhaupt Nichts schade.
Curses dient dem Handling "statischer Screens" mit Cursor
Positionierung,
und der Eingabe in Masken wie man es z.B. in Menüsystemen und z.B.
Hexeditoren braucht. Wenn Du einen scrollenden Console Modus willst,
mußt Du da wieder raus und dieses handling "statischer Screens"
abstellen.
Guck Die mal Dein Linux an, funktioniert dort haargenau so. Entweder
Console oder Editor.
Wenn Du in einem Editor z.B. oben ein stehendes Feld und darunter ein
scrollendes haben willst, mußt du das scrollen selber handeln.
Das ist exakt die vorgesehene Funktionalität. Ich dachte Du hättest das
indessen gerafft. Deine Vorlesung was woanders "Standard" ist, ist
demzufolge ziemlicher Quatsch....
Gruß,
Holm
Holm Tiffe schrieb:> Curses dient dem Handling "statischer Screens" mit Cursor> Positionierung,
Genau das ist es. Und je nachdem was man will muss man das eine oder das
andere nehmen :-) Mir fallen da zb einfache Spiele ein mit
Grafikzeichen. Oder Masken die Berechnungen ausgeben. Schade dass der
sdcc long long (64 bit) nicht vollständig unterstützt.
Ich sehe schon, mein Z80 wird eine Revolution bei der Lösung der
Riemann'schen Vermutung werden :-)
Klappt aber sonst super! versuche nur noch die Ursache für zufällige
Resets zu finden. Die gibt es leider :-(
Übrigens portiere ich grad das Prinzip auf meinen ARM Rechner, damit der
auch ein Terminal bekommt. Ist ja auch nur eine CPU ohne alles
drumherum, aber immerhin einen Grafiklbildschirm hat er. War damals ein
projekt hier, wo ich die Platinen fürs Forum machen liess, mit einem
Benedikt war das glaube ich....
Christian J. schrieb:> tut mir leid aber dann kann ich damit nicht viel anfangen, da es> unüblich ist absolut zu positionieren auf fliessenden Bildschirmen.> Dafür gibt es seit der Erfonduing des Telex Sonderzeichen wie \n \r \b> usw.
Holm hat da vollkommen recht: Entweder Console mit Fliesstext oder
Anwendung mit mcurses.
Ob Du Dein Menü mit oder ohne mcurses machst, bleibt Dir selbst
überlassen. Mit mcurses steht das immer an derselben Stelle, ohne
mcurses halt unter dem zuletzt ausgegebenen Text. Ist Geschmackssache.
Ich persönlich würde da mcurses nutzen - gerade dann wenn das Menü
umfangreicher wird.
Wälht der User dann einen Punkt aus, verwendest Du je nach ausgewähltem
Menüpunkt entweder mcurses oder die einfache Fließtext-Console.
Moin,
aktuell wächst die ganze Sache, wobei der Spieltrieb noch etwas
überwiegt. Ist eben was anderes einen PC mit fertiger Software zu
bespielen, einen Arduino zu "programmieren" wo es einfach funktioniert
oder einen peripherielose Rechner wo jede Leitung selbst gezogen wurde.
Im dauerbetrieb, zb Berechnung von Primzahlen bis zur Grenze der 32 Bit
traten nur "Seltsamkeiten" auf wie auf dem Screesnhot gezeigt. Ob da was
mit dem Compiler nicht stimmt oder der Hardware muss noch erforscht
werden. Aktuell rennt er daher seit Stunden über sein RAM und ROM und
prüft ob sich die CRC16 Checksumme verändert.
Das Thema Datenspeicher muss noch auf den Tisch, wobei ich fast schon an
eine Datasette Mit "Hard-Bit-Rock" denke, müsste per Frequenzumtastung
nicht zu schwer sein. Maximal 1200 baud leider. Oder doch eben ein
"Arduino" (ich nutze nur die IDE und die Libs, plaziere die Chips aber
einzeln), der ein Interface zu einem modernen Speicher wie SD Card
herstellt mit vereinfachter API zb File 1,2.3,4 usw. also nur 64kb
Sektoren als Ablage.
@A.K. :
Ich habe heute etwas an dem Erweiterungsboard gearbeitet und die Bus
Leiste verdrahtet, die hinten aufgesteckt wird. Da ich dort auch ports
brauche und gerne auch einen richtigen Timer ist die Wahl:
8254 (16 Bit!) und 8255 (3 Ports statt 2)
oder
CTC und PIO ?
Obige sind interruptlos und intern "einfach", Z80 Teile sind Mode 2
fähig und etwas aufwendiger, die PIO kann vor allem Einzelports
schalten.
Bei dem STI ist im Mostek App Note die rede von einem Bug, der Daisy
Chaining beeinflusst, so dass nichts da hinter geschaltet werden sollte.
Ich habe den 3801 von ST in der Rev H. Hoff es gibt da keine Probleme
wenn hinter den STI noch zwei Int erzeugende Bauteile kämen.
Wie sähe das Prinzip dann aus? Meine Int-1 Tabelle liegt fix bei 0x2040,
STI ist mit einem Vektor geladen, ebenso IM2 Register. Liessen sich die
neuen Vektoren der Timer dann huckepack direkt auf die bestehende
Tabelle plazieren?
Was ist deine "Int-1-Tabelle"? Im IM2 gibt es eine Tabelle aus bis zu
128 Vektoren. Die kannst du nach Laune belegen, jeder IM2 Baustein hat
dazu ein Vektor-Basisregister.
Was den Fehler angeht: Da steht, dass ab Ende 82 der Bug raus wäre. Das
Datum deines Exemplars dürfte auf ihm draufstehen.
Christian J. schrieb:> 8254 (16 Bit!) und 8255 (3 Ports statt 2)> oder> CTC und PIO ?
Ich würde den Z8536 nehmen, den Nachfolger von PIO und CTC, aus der
Z8000 Reihe, aber für Z80 Bus. Da gibts beides zusammen. Gibts bei ebay.
A. K. schrieb:> Was ist deine "Int-1-Tabelle"? Im IM2 gibt es eine Tabelle aus bis zu> 128 Vektoren. Die kannst du nach Laune belegen, jeder IM2 Baustein hat> dazu ein Vektor-Basisregister.
Ok, dann werde ich das so machen und eine 2.te Uart kriegt er auch noch
mit dem 65B20 Baustein, weil der höhere Baudraten erlaubt und einfach
anzuflanschen ist.
Es ist leider schn 5 Jahre her, dass ich hier mal eine Aktion laufen
hatte mit Platinenbestellung und jemandem der sich Benedikt Kullmann
nennt, einem Admin. Ich habe leider nur noch eine einzige dieser
unbestückten Platinen und auch keinen AVR Code dazu, keine Beschreibung,
nix mehr, auch das Eagle Layout ist weg, damals bei Datenunfall, wo 15
Jahre "Daten-Sammlung" bis 1996 sich in Luft auflösten. Denn das wäre
ein schönes Display für den Z80 mit Uart Interface, Text und Grafik,
allerdings komplett inkompatibel zu mcurses. habe das Ding grad mal
angeworfen, nach 4 Jahren im Schrank nur die Uhr verstellt weil Batterie
leer aber sonst läuft es prima.
Christian J. schrieb:> mit dem 65B20 Baustein, weil der höhere Baudraten erlaubt und einfach> anzuflanschen ist.
Wenn du mit dem hohe Baudraten hinkriegst, dann Respekt. Der 6520 ist
nämlich ein Portbaustein, identisch mit dem 6820. Und da die 65Axx beim
Takt den 68Bxx entsprechen hat es m.W. nie eine 65Bxx Serie gegeben. ;-)
Allerdings würde mich interessieren, wieso ein anderer Baustein aus
gleichem Basistakt abgeleitet höhere Baudraten zulässt als der STI.
Durch 16 teilen sie beide, und beide kriegen den 16x Takt aus einem
Timer.
Mit dem 68B50 (!) sind bei 3.964Mhz 56700 baud drin, abegleitet aus dem
Quartz, da es keinen Timer als Vorteiler gibt, der mir 1/16 klaut.
http://searle.hostei.com/grant/z80/SimpleZ80.html>>by changing the crystal to 3.6864MHz but the serial I/O speed is then also >>halved to 57600 baud.
Ich habe ja lange überlegt das zu übernehmen, da der Baustein, den ich
auch hier habe sehr einfach ist.
Eine gepufferte TX Übertzragung habe ich neulich ums Verrecken nicht hin
bekommen, egal wie ich den Code auch umschrieb. Das ging beim ARM
deutlch einfacher durch mehr Int Quellen als nur Buffer Empty.
CTC vs 8254: Der CTC benötigt den Z80 Clock als Basistakt für die Timer
wie ich sehe, damit die Adressieung mit M1 usw. funktioniert.. Der 8254
kann einen beliebigen Clock anliegen haben und hat selbst keinen Input
für einen Clock.
Christian J. schrieb:> Quartz, da es keinen Timer als Vorteiler gibt, der mir 1/16 klaut.
Nur wenn man vorsichtshalber drauf vertraut, dass dieser Baustein sein
Datasheet nicht gelesen hat und daher nicht weiss, dass darin an den
Rx/Tx-Takteingängen bei 1,5MHz Ende der Fahnenstange ist.
Christian J. schrieb:> Mit dem 68B50 (!) sind bei 3.964Mhz 56700 baud drin
Bei dieser Frequenz kommt ein Teiler von 68 raus. Das geht asynchron
überhaupt nicht. Ich nehme an, es sind 3,6864MHz.
Christian J. schrieb:> Das ging beim ARM> deutlch einfacher durch mehr Int Quellen als nur Buffer Empty.
Mehr als das braucht man dazu normalerweise auch nicht. Welche hältst du
noch zusätzlich für erforderlich?
Ok, mein STI hatte die Tastatur dran hängen. Die ging nur in eine
Richtung. Aber bei anderen Bausteinen hat mir das auch ausgereicht, wie
beispielsweise beim SIO.
....Also...Du bist Ratatui Koch..alles rein. Die Motorola Reihe hat Dir
ja bis jetzt noch gefehlt.. Was gibts denn noch so.. F8?
Wenn Du höhere Baudraten willst, solltest Du Dir Gedanken machen woher
die Uart ihren Sendetakt beziehen könnte, IMHO sind die Baudraten die
mit der Z80 SIO zu erzeugen sind nicht zu niedrig. Es ist eine Frage wie
Du zu einem Baudratenkonformen Takt kommst, der innerhalb der
Spezifikation der ICs liegt. Auch solltest Du mal erklären was Du mit
einer höheren Baudrate eigentlich so anfangen möchtest. Wenn Du so eine
Programmiererkoryphähe bist, stecke die Arbeit lieber in die
Verbesserung des Compilers den Du benutzen willst oder besser erlne erst
mal was das System mit seinem Assembler so kann.
So viel ich weiß ist die kürzeste Taktperiode 400ns für Rx/TX Clock. das
sind 2,5Mhz. Wenn ich mich richtig erinnere hattest Du einen Clock von
3,6864Mhz? Damit müßtest Du mit einem Vorteiler von 2 und Teilerfaktor
16 in einer Z80 SIO eine Baudrate von 115200 Baud erzeugen können, das
reicht nicht?
Das Problem ist dabei nicht das der SIO keine hohen Baudraten, sondern
das ein üblicherweise als Baudratengernerator benutzter CTC nicht die
erforderlichen Frequenzen erzeugen kann. Es steht Dir frei einen
externen Baudratengenerator zu verwenden wie andere Bausteine den auch
benötigen, Du kannst natürlich aber auch noch völlig andere beschissene
ICs an Deine Platine knoten und weiterhin kein potentes Z80 System
sondern einen Teller buntes Gemüse erzeugen.
Ich hätte für dich auch noch einen russischen Schaltplan einer völlig in
TTL Hardware gebauten PDP11 SLU, das ist etwa eine Doppeleuroplatine
voller ICs.
Es wurde Dir schon ein paar mal erzählt das Du Features verschenkst, Du
wirst daraus scheinbar wirklich nicht schlauer sondern bildest Dir ein
das Du es irgendwie eilig mit der seriellen Schnittstelle haben mußt?
Das Z80 System war so verbreitet weil die Entwickler regelrecht genial
damit waren mit ihrem Konzept kleine leistungsfähige Systeme mit wenigen
ICs der Systemfamilie zu ermöglichen, nicht weil die CPU ein paar
Register mehr hatte.
Gruß,
Holm
A. K. schrieb:> Bei dieser Frequenz kommt ein Teiler von 68 raus. Das geht asynchron> überhaupt nicht. Ich nehme an, es sind 3,6864MHz.
Ja 3.6864, ich hatte dazu ja einen Link gepostet. 1,5 Mhz stehen im
Datasheet aber scheinbar geht es ja auch mit mehr als der doppleten
Frequenz. Dieser Grant ist ja nicht blöde und hat das alles aufgebaut.
1,16,64 ist der Teiler dann, der möglich ist. Hoffe nur dass das auch
ohne CTS/RTS läuft, denn die habe ich nicht und brauche sie nicht.
Der CTc fliegt aber raus, der 8254 ist moderner und kann zb mit 1Mhz
geclocked werden statt mit dem krummen Baudraten Quarz.
Ich habe es einfach nciht hingekriegt, wie ich den TX anstosse, damit
er ab dann automatisch weiterläuft, solange zeichen da sind. Aber es
geht ja auch so ganz gut, nur RX muss gebuffert werden.
Zitat:
8K ROM 56K RAM (A version with 32K RAM is HERE)
Z80 Processor (overclocked - all processors 4MHz+ (Z80B) that I have
tried overclock to this with no issues) with a 7.3728MHz clock. You can
halve this, ie. to stop the overclocking, by changing the crystal to
3.6864MHz but the serial I/O speed is then also halved to 57600 baud.
115200 Baud serial interface, RS232 specification voltage levels. Full
interrupt driven input with buffer and hardware handshaking so no
incoming data loss. Power consumption - approx 200mA
A problem exists, however, as the /IORQ is also taken low during an
interrupt acknowledge. If this was allowed, then the data/control values
in the serial interface would be corrupted when the interrupt is
acknowledged by the Z80. Interrupt acknowledge is identified by /IORQ
and /M1 signals going low, so the 6850 is to be disabled if /M1 is low
(the Z80 /M1 signal connected to the active-high CS0 of the 6850). This
ensures that only real I/O triggers the serial interface. The /M1 signal
is much wider than the /IORQ and totally masks the /IORQ signal. This
ensures that there is no possibility of the ACK signal enabling a read
or write. The remaining chip selects on the serial interface are
connected to A7 and A6, so any I/O on address 10xxxxxx will select the
serial chip. Finally, the register select on the serial interface is
connected to A0, so the control register is addressed on port 80H and
the data register is addressed on port 81H.
Holm Tiffe schrieb:> Was gibts denn noch so.. F8?
F8 Peripherie an Z80, das wär mal wirklich spannend. Das Teil, also die
ursprüngliche 385x Variante, hat einen sehr speziellen Bus. ;-)
Den Z8536 hatte ich ihm ja schon vorgeschlagen. Viel besser gehts bei
Parallel/Timer-Bausteinen nicht.
> Wenn Du höhere Baudraten willst, solltest Du Dir Gedanken machen woher> die Uart ihren Sendetakt beziehen könnte,
Yep. Kann er beim STI auch. CPU-Takt halbieren und an den STI ran um auf
115kbd zu kommen. Das ist natürlich mit Faktor 2 weit jenseits von
dessen Limit. Aber wenn ich sehe, wie sein Web-Vorbild den 6850 mit
7,37MHz traktiert, obwohl der offiziell nur 1,5MHz kann, wärs doch beim
STI auch einen Versuch wert.
Holm Tiffe schrieb:> Es steht Dir frei einen> externen Baudratengenerator zu verwenden wie andere Bausteine den auch> benötigen, Du kannst natürlich aber auch noch völlig andere beschissene> ICs an Deine Platine knoten und weiterhin kein potentes Z80 System> sondern einen Teller buntes Gemüse erzeugen.
Du hast absolut recht. Ich brauche eine zweite Uart und je länger ich
drüber nachdenke umso wahrscheinlicher wird es, dass ein kleiner
niedlicher ATTiny mit 8 Pins, der alles tutto kompletti innendrin hat
incl einem Oszillator diese Aufgabe übernehmen könnte, statt einer 40
Pinner Oschi SIO, zu der ich dann noch 40 Leitungen ziehen muss,
Baudrate usw.
duckundwech :-)
Christian J. schrieb:> der 8254 ist moderner
Ich finden den ja ziemlich schaurig.
> Ich habe es einfach nciht hingekriegt, wie ich den TX anstosse, damit> er ab dann automatisch weiterläuft, solange zeichen da sind.
Üblicherweise gibts 2 Möglichkeiten. Meist reicht es, den TXBE Interrupt
freizugeben, weil der bei leerem Puffer sofort auslöst. Wenn der STI das
nicht tut, dann schreibt man eben zusätzlich das erste Byte ins
Datenregister.
> geht ja auch so ganz gut, nur RX muss gebuffert werden.
Eben.
Ist doch süss, oder? Mit ner SPI sogar dran! MISO, MOSI, SCK...
Richtig zum Knuddeln der Kleine! Habe noch 5 Stück hier ...
>Üblicherweise gibts 2 Möglichkeiten. Meist reicht es, den TXBE Interrupt>freizugeben, weil der bei leerem Puffer sofort auslöst.
Probier ich aus, Ende nächste Woche wenn ich wieder zurück bin.
Wo du doch so gerne jemand zum Vorbild nimmst, der alles übertaktet was
seine Kiste enthält, weshalb übertaktest nicht den Systemtakt auf
4,9152MHz und kriegst dann 38400 mit einem STI-Timerwert von 1?
A. K. schrieb:> Wo du doch so gerne jemand zum Vorbild nimmst, der alles übertaktet was> seine Kiste enthält, weshalb übertaktest nicht den Systemtakt auf> 4,9152MHz und kriegst dann 38400 mit einem STI-Timerwert von 1?
Weil ich nicht glaube, dass die Fädelverdrahtung mit 10cm langen
Taktleitungen, die mitten durch andere hochohmige Leitungen laufen
zum STI das aushält. Der "hüpft" jetzt schon mal.... nach so einigen
Stunden Lauf liegt er plötzlich im Reset.
Hast du eigentlich mal Bilder von Deinem Projekt?
Christian J. schrieb:> A. K. schrieb:>> Bei dieser Frequenz kommt ein Teiler von 68 raus. Das geht asynchron>> überhaupt nicht. Ich nehme an, es sind 3,6864MHz.>> Ja 3.6864, ich hatte dazu ja einen Link gepostet. 1,5 Mhz stehen im> Datasheet
Häh wo?
>aber scheinbar geht es ja auch mit mehr als der doppleten> Frequenz. Dieser Grant ist ja nicht blöde und hat das alles aufgebaut.> 1,16,64 ist der Teiler dann, der möglich ist. Hoffe nur dass das auch> ohne CTS/RTS läuft, denn die habe ich nicht und brauche sie nicht.>> Der CTc fliegt aber raus, der 8254 ist moderner und kann zb mit 1Mhz> geclocked werden statt mit dem krummen Baudraten Quarz.>
Ja klar, moderner. Der 8254 ist ein unwesentlich verbesserter 8253
(Taktfrequenzen: 8253 2Mz, 8253A 2,5Mhz, 8254 10Mhz) und der ist die
Standardperipherie des allerersten 8080 den Du hier ausgelacht hast...
Das Ding ist in keiner Weise in der Lage Interrupts auszulösen, Du muß
irgend einen Ausgang über Draht mit einem Deiner INT Eingänge der STI
verbinden...hochmodern..
> Ich habe es einfach nciht hingekriegt, wie ich den TX anstosse, damit> er ab dann automatisch weiterläuft, solange zeichen da sind. Aber es> geht ja auch so ganz gut, nur RX muss gebuffert werden.
Bei anderen Leuten funktionierte das dann so das die SIO (!) einen
Interrupt mit entspechendem Vector (Status Affects Vector) auslöste und
die Serviceroutine so lange Bytes aus dem Buffer nachgelegt hat bis
dieser alle war und dann den Int in der SIO ausgeschaltet, sowie diesen
Status in einem Semaphor hinterlegt hat) Die serielle Sendroutine hat
das nächste Byte dann nach Reset des Semaphors und Aktivierung des Ints
in den TXBuffer der Sio geschrieben, weitere Zeichen bei inaktivem
Sempahor dann wieder in den Buffer, Ausgabe über die Serviceroutine.
Ich hatte Dir gesagt Du solltest Dir Gedanken um die Pufferei machen..da
sind Deine Gedanken wohl nicht vorbei gekommen? Das Ganze ist wirklich
easy in Assembler zu programmieren.
Ich weiß aber nichts wirklich über diese STI.
>> Zitat:>> 8K ROM 56K RAM (A version with 32K RAM is HERE)> Z80 Processor (overclocked - all processors 4MHz+ (Z80B) that I have> tried overclock to this with no issues) with a 7.3728MHz clock. You can> halve this, ie. to stop the overclocking, by changing the crystal to> 3.6864MHz but the serial I/O speed is then also halved to 57600 baud.> 115200 Baud serial interface, RS232 specification voltage levels. Full> interrupt driven input with buffer and hardware handshaking so no> incoming data loss. Power consumption - approx 200mA>> A problem exists, however, as the /IORQ is also taken low during an> interrupt acknowledge. If this was allowed, then the data/control values> in the serial interface would be corrupted when the interrupt is> acknowledged by the Z80. Interrupt acknowledge is identified by /IORQ> and /M1 signals going low, so the 6850 is to be disabled if /M1 is low> (the Z80 /M1 signal connected to the active-high CS0 of the 6850). This> ensures that only real I/O triggers the serial interface. The /M1 signal> is much wider than the /IORQ and totally masks the /IORQ signal. This> ensures that there is no possibility of the ACK signal enabling a read> or write. The remaining chip selects on the serial interface are> connected to A7 and A6, so any I/O on address 10xxxxxx will select the> serial chip. Finally, the register select on the serial interface is> connected to A0, so the control register is addressed on port 80H and> the data register is addressed on port 81H.
Keine Ahnung was der da treibt. Halte Dich an die IO-Decodiererei die im
Kieser-Meder zu finden ist, das Zeuch funktioniert.
Irgendwer hatte mal festgestellt das es Differenzen zwischen
Original-CTC und DDR-CTC gibt, die Ossis hatten wohl diesen BUG
ausgebaut. Von der SIO sind mir solche Probleme nicht bekannt, das was
ich gebastelt hatte ging jedenfalls auch mit den Originalen und ich
hatte mich nach eben dieser OST-Bibel gerichtet.
Einen Grund für eine beschissene synchrone Schnitte was Anderes als eine
SIO einzusetzen hatte ich jedenfalls nie.
Ich hhabe ins Datenblatt geguckt, da steht minimaler Taktzyklus für die
RX-TX Takte 400ns. Wo hast Du die 1,5Mhz (666ns) her?
...aha, es gibt eine Note: Die Taktfrequenz muß das 4,5-fache der
Baudrate sein.
D.h. bei 115200 Baud muß die Systemtaktfrequenz am SIO mindestens
115200*4.5=0,5184 Mhz sein.. hmm... betreifft Dich wohl nicht.
Gruß,
Holm
Christian J. schrieb:> Ist doch süss, oder? Mit ner SPI sogar dran! MISO, MOSI, SCK...> Richtig zum Knuddeln der Kleine! Habe noch 5 Stück hier ...>>>Üblicherweise gibts 2 Möglichkeiten. Meist reicht es, den TXBE Interrupt>>freizugeben, weil der bei leerem Puffer sofort auslöst.>> Probier ich aus, Ende nächste Woche wenn ich wieder zurück bin.
Ja, mach aber einen Neuen Thread auf.."Dummfug mit dem Z80..."
Mit Retro hat das wohl nicht viel zu tun und es soll hier im Forum Leute
geben die einen 8080 auf einem Atmega emulieren um darauf CP/M laufen zu
lassen. (für ne Z80 hat der Atmega wohl zu kleine Hände womit
Turbopascal ausfällt)
Solche Leute bauen also Deine Ganzen Platinen in einem 40 Pinner.
Gruß,
Holm
Holm Tiffe schrieb:>> Ja 3.6864, ich hatte dazu ja einen Link gepostet. 1,5 Mhz stehen im>> Datasheet>> Häh wo?
Beim MC68B50 als Höchstfrequenz der RxCLK/TxCLK Pins. Bei Grants MC6850
sind es sogar nur 0,8MHz, aber betrieben mit 7,37MHz. Davon können
heutige Übertakter nur träumen. ;-)
Hallo Holm,
habe mir deinen guten Beitrag mal ausgedruckt. Genauso habe ich es aber
bei der STI gemacht. Semaphore hatte ich auch. Auf den Trick mit dem
Abschalten der STI in der TX Service Routine bin ich aber nicht
gekommen. Denn es ist wirklich so, dass man nur von außerhalb TX EN
einschalten muss und dann rennt der TX Empty sofort los und schaut was
man ihm ins Körbchen gelegt hat.
Dann sieht es nämlich so aus:
TX aus und noch Platz im Buffer? Zeichen rein und TX EN einschalten.
Sofort danach kommt der TX Empty Int vorbei und sieht, dass der Zeiger
eines weiter ist und schiebt das Byte raus. Ist dann wieder eines da
gleiches Spiel, bis Körbchen leer, dann schaltet er sich ab indem er
sein Enable Bit zurüpck setzt (und evtl Pending Ints auch noch).
Allerdings ....... das Raushämmern von Bytes über die STI ohne Interrupt
braucht genauso lange wie mit Int. Der einzige Vorteil ist, dass das
Hauptprogramm mal eben 80 Bytes wegschreiben kann in den Buffer und
sich danach nicht mehr drum kümmern muss, weil der TX Int die ins
gegnerische Tor am PC spielt.
>>Das Ganze ist wirklich easy in Assembler zu programmieren.
Ich will aber nicht. Das ist so und bleibt so ;-)
Hier gehts lang für "Du machst das so wie ich es dir sage!" :-)
http://www.jogis-roehrenbude.de/forum/forum/forum.php
Christian J. schrieb:> Hallo Holm,
[..]
>> Allerdings ....... das Raushämmern von Bytes über die STI ohne Interrupt> braucht genauso lange wie mit Int. Der einzige Vorteil ist, dass das> Hauptprogramm mal eben 80 Bytes wegschreiben kann in den Buffer und> sich danach nicht mehr drum kümmern muss, weil der TX Int die ins> gegnerische Tor am PC spielt.
Du hast eben gerade die Synchronisation langsamer Peripherie durch
Interrupts entdeckt!
Congrats...
Um Dir zu zeigen was wirklich ein cleverer IO IC ist:
Die SIO unterstützt einen weiteren Modus für zeitkritische Sachen wo
bereits die Interruptlatenzzeiten stören: Die Synchronisation durch
WAIT.
Man kann mit OTIR einen Block zur Ausgabe auf die SIO ansetzen und sie
ativiert die WAIT-Leitung der CPU so lange der Sendepuffer voll ist und
gibt das Ding bei leerem Puffer wieder frei. schneller geht es dann
nicht, das dürfte schneller sein als DMA.
Ob das im Empfangsmodus auch geht weiß ich nicht mehr, müßte ich
nachlesen.
Gruß,
Holm
Holm Tiffe schrieb:> Bei anderen Leuten funktionierte das dann so das die SIO (!) einen> Interrupt mit entspechendem Vector (Status Affects Vector) auslöste und> die Serviceroutine so lange Bytes aus dem Buffer nachgelegt hat bis> dieser alle war und dann den Int in der SIO ausgeschaltet, sowie diesen> Status in einem Semaphor hinterlegt hat) Die serielle Sendroutine hat> das nächste Byte dann nach Reset des Semaphors und Aktivierung des Ints> in den TXBuffer der Sio geschrieben, weitere Zeichen bei inaktivem> Sempahor dann wieder in den Buffer, Ausgabe über die Serviceroutine.
Geht beim SIO noch einfacher. Man muss den Interrupt nicht abschalten,
sondern bloss zurücksetzen. Siehe
Beitrag "Re: Retro Fieber: Z80 oder 68000 ?"
unter ivec$sioa$txbe: und putnw:.
Holm Tiffe schrieb:> Man kann mit OTIR einen Block zur Ausgabe auf die SIO ansetzen und sie> ativiert die WAIT-Leitung der CPU so lange der Sendepuffer voll ist und> gibt das Ding bei leerem Puffer wieder frei
Nicht schlecht ..... aber das Thema SIO ist eigentlich duch, auch wenn
du es bei jeder Gelegenheit hervorholst und noch 50 Stück davon hast,
die herum oxidieren. Das hätte eher gemacht werden müssen, dann hätte
ich auch 2 Uarts aber auf einer Euro Karte ist kein Platz mehr für eine
SIO. Aber es wird ja noch das Projekt "Retro Z80 V2.0" geben, einen
echten CP/M Rechner.... da werde ich dann darauf zurückgreifen, auch mit
richtigen Platinen, Tastatur und Bildschirm.
A. K. schrieb:> Holm Tiffe schrieb:
[..]
> Geht beim SIO noch einfacher. Man muss den Interrupt nicht abschalten,> sondern bloss zurücksetzen. Siehe> Beitrag "Re: Retro Fieber: Z80 oder 68000 ?"> unter ivec$sioa$txbe: und putnw:.
Ist ca 20 Jahre her das ich da wirklich Hand an eine SIO gelegt hätte,
sorry, Sowas weiß ich nicht mehr so genau.
Fakt ist aber, das mi die meisten integrierten Uarts in irgendwelchen
µCs immer sehr "hausbacken" betreffs ihrer Möglichkeiten UND Bugs
vorkommen..
:-)
Gruß,
Holm
Holm Tiffe schrieb:> Die SIO unterstützt einen weiteren Modus für zeitkritische Sachen wo> bereits die Interruptlatenzzeiten stören: Die Synchronisation durch> WAIT.
Da werden die aber eher an schnelle synchrone Betriebsarten gedacht
haben, nicht an asynchrone 9600bd. Und wer DRAM in der Kiste hat, der
sollte dabei etwas aufpassen.
Christian J. schrieb:> Holm Tiffe schrieb:>> Man kann mit OTIR einen Block zur Ausgabe auf die SIO ansetzen und sie>> ativiert die WAIT-Leitung der CPU so lange der Sendepuffer voll ist und>> gibt das Ding bei leerem Puffer wieder frei>> Nicht schlecht ..... aber das Thema SIO ist eigentlich duch, auch wenn> du es bei jeder Gelegenheit hervorholst und noch 50 Stück davon hast,> die herum oxidieren. Das hätte eher gemacht werden müssen, dann hätte> ich auch 2 Uarts aber auf einer Euro Karte ist kein Platz mehr für eine> SIO. Aber es wird ja noch das Projekt "Retro Z80 V2.0" geben, einen> echten CP/M Rechner.... da werde ich dann darauf zurückgreifen, auch mit> richtigen Platinen, Tastatur und Bildschirm.
Ich kann Dir aber nichts Anderes erzählen, ich habe zwar an einem 6809
auch schon einen 6850 programmiert, aber daran das der mich vom Sessel
gerissen hätte kann ich mich nicht erinnern.
Wie Du weißt kenne ich Dich ein Bisschen und Deine Art ist es Ratschläge
wegen fehlendem Wissen erst mal in den Wind zu schlagen.
Deine Platine sähe wenn es nach mir gegangen wäre anders aus: eine SIO
und eine CTC mit einem Z80 einem EPROM und einem RAM inklusive
Restelogik und V24 Treibern. Deine 2. Platine könnte jetzt 2 PIOs und
z.B. ADC/DAC nebst sauberer IM2 Mimik bekommen.
Du hättest Dir das nur nicht einreden lassen.
Gruß,
Holm
Holm Tiffe schrieb:> es soll hier im Forum Leute> geben die einen 8080 auf einem Atmega emulieren um darauf CP/M laufen zu> lassen.
Ja mich zum Beispiel.
> (für ne Z80 hat der Atmega wohl zu kleine Hände womit> Turbopascal ausfällt)
Z80 ist da seit geraumer Weile drin (und damit auch TP3). Das hat mit
dem ATmega nichts zu tun, sondern nur damit, das sich erst jemand finden
musste (Leo?), der die restlichen Opcodes nachgebaut hat.
Jens
A. K. schrieb:> Holm Tiffe schrieb:>> Die SIO unterstützt einen weiteren Modus für zeitkritische Sachen wo>> bereits die Interruptlatenzzeiten stören: Die Synchronisation durch>> WAIT.>> Da werden die aber eher an schnelle synchrone Betriebsarten gedacht> haben, nicht an asynchrone 9600bd. Und wer DRAM in der Kiste hat, der> sollte dabei etwas aufpassen.
Freilich, aber sie haben die Möglichkeit geschaffen. Guck Dir doch mal
die anderen Gurken die es gibt so an, CIO und SCC können wir mal außen
vor lassen.
Gruß,
Holm
Holm Tiffe schrieb:> Fakt ist aber, das mi die meisten integrierten Uarts in irgendwelchen> µCs immer sehr "hausbacken" betreffs ihrer Möglichkeiten UND Bugs> vorkommen..
Yep, beispielsweise die 16c550er UARTs in den NXP ARMs und deren
seltsame Interrupts. Wobei NXP mit dieser Wahl sowieso ins Klo griff,
weil dieses Teil für einen bei RS485 recht praktischen 9-Bit Modus
ziemlich um die Ecke greifen muss. Das kann die einfachere UART der AVRs
besser.
Holm Tiffe schrieb:> Freilich, aber sie haben die Möglichkeit geschaffen. Guck Dir doch mal> die anderen Gurken die es gibt so an, CIO und SCC können wir mal außen> vor lassen.
Auch nicht übel: TMS9902. Kein Luxusteil, aber wo gab es sonst schon
eine asynchrone Schnittstelle in 18 Pins, einschliesslich integriertem
Oszillator für Baudratenquarz.
Bei 68000ern war der 68681 recht beliebt.
So, zum Tagesschluss noch mal ne Frage...
Der Thread hier steht kurz vor seinem Absinken in die Tiefen, da er nur
noch von 3 Leuten am Leben gehalten wird und inzwischen alles soweit
klar ist, dass ich als der TS allein weitermachen kann. War mal was
Neues und hat Spass gemacht.
Bleibt die Frage: Was damit machen?
Bisher war die Kiste eine Programmierübung, 4 Gewinnt eingespielt, eine
Primzahlzerlegung für Arme. Das Erweiterungsboard soll schon was
"Sinnvolles" machen. Was kann man damit steuern was sich gut im
Wohnzimmer macht? Mir fallen da spontan Dinge aus Fischertechnik ein,
was ich noch komplett habe mit allen Elektronikbaukästen der später
70iger, Elektromagneten, Flipperkugeln, Wasserspiel mit Ventilen ....
Lichterspiel?
Jens schrieb:> Holm Tiffe schrieb:>> es soll hier im Forum Leute>> geben die einen 8080 auf einem Atmega emulieren um darauf CP/M laufen zu>> lassen.> Ja mich zum Beispiel.>>> (für ne Z80 hat der Atmega wohl zu kleine Hände womit>> Turbopascal ausfällt)> Z80 ist da seit geraumer Weile drin (und damit auch TP3). Das hat mit> dem ATmega nichts zu tun, sondern nur damit, das sich erst jemand finden> musste (Leo?), der die restlichen Opcodes nachgebaut hat.>> Jens
Ist recht Jens. Ich habe mal gelesen das das aber in das Ding nicht rein
paßt, von wann der Stand war, weiß ich nicht. Ich habe das nur mit
gemäßigtem Interesse gelesen da ich Emulationen maximals fürs Debugging
mag.
Ich habe Z80 CP/M Rechner hier, unter Anderem in einer Art Minitower
zusammen mit einem Z8000. Auf der Kiste läuft CP/M, RIO und Zeus, bzw.
deren Ost Benennungen OS/M,UDOS und WEGA, eine P8000 Compact.
Emuliertes CP/M habe ich hier auch im Terminalfenster unter FreeBSD
weswegen mich die Emulation auf einem AVR nicht vom Sessel reißt. Das
ist aber meine persönliche Vorliebe.
Hier gibts auch mit SIMH einen PDP11 und einen VAX Emulator, weiß nicht
ob PA-RISC und MIPS auch gänge, dann hätte ich jeweils das Equivalent
für meine PDP11/83 und die E60, die diversen MicroVaxen die SGI Indigo
und die kleine HP9000/710 :-)
Gruß,
Holm
Christian J. schrieb:> So, zum Tagesschluss noch mal ne Frage...>> Der Thread hier steht kurz vor seinem Absinken in die Tiefen, da er nur> noch von 3 Leuten am Leben gehalten wird und inzwischen alles soweit> klar ist, dass ich als der TS allein weitermachen kann. War mal was> Neues und hat Spass gemacht.>> Bleibt die Frage: Was damit machen?>> Bisher war die Kiste eine Programmierübung, 4 Gewinnt eingespielt, eine> Primzahlzerlegung für Arme. Das Erweiterungsboard soll schon was> "Sinnvolles" machen. Was kann man damit steuern was sich gut im> Wohnzimmer macht? Mir fallen da spontan Dinge aus Fischertechnik ein,> was ich noch komplett habe mit allen Elektronikbaukästen der später> 70iger, Elektromagneten, Flipperkugeln, Wasserspiel mit Ventilen ....> Lichterspiel?
Mir fällt nur Blödsinn ein.
Man kann so ziemlich Alles damit machen, die DDR Industrie ist mit den
Z80 bei Steuerungen sehr weit gekommen. Die Frage ist, ob das heute noch
Sinnvoll ist.
Ich habe ab und an mal das Problem das ich irgendwelche Speicher
auslesen muß oder auch Daten konvertieren oder das Steuern einer
Sequenz.
Mit einem PC geht das heute eigentlich nicht mehr weil blos noch
idiotische Interfaces dran sind, die zum Anschluß von irgendwas meist
einen weiteren Controller benötigen (Ethernet oder USB [nicht das ich
was gegen diese Schnittstellen hätte, aber sie berechtigen aus meiner
Sicht nicht den Wegfall Anderer]).
Wenn Du was Vernünftiges damit machen willst, dann stecke das Ding ein
ein Europakartengehäuse, mach ein paar PIOs dran und führe die PINs über
Buchsen nach außen, so das man was damit machen kann wenn mans braucht.
Keine Ahnung ob Du Sowas brauchst.
Gruß,
Holm
Holm Tiffe schrieb:> Mir fällt nur Blödsinn ein.
Das ist schon ganz ok. Und ein paar PIOs brauche ich nicht, dafür gibts
Arduino. Der hat ganz viele "PIOs" dran.
habe mir grad hier mal diesen CP/M Stick angeschaut, der hier als
Projekt hinterlegt ist, einen Emulator auf Atmega88. So ganz trivial ist
das ja nicht. CP/M habe ich mir noch nicht angeschaut, nur mal quer
gelesen. War vor meiner Zeit.
Wieso ist das so einfach zu emulieren? Das Ding ist doch sicherlich in
Assembler geschrieben worden für eine spezielle Hardware? Also BIOS im
EPROM, Floppys mit Userprogrammen, Ansteuerung eines Bildschirmes und
Tastatur. Es gibt ja auch Software dafür, die geladen werden kann. Wie
kriegt man sowas in einen Atmega Stick?
Christian J. schrieb:> Wieso ist das so einfach zu emulieren?
Wo ist das Problem? CP/M unterscheidet zwischen dem portablen BDOS und
dem hardwareabhängigen BIOS. Du musst für das CP/M nur den Befehlssatz
einer 8080 CPU emulieren. Das ist überschaubar. Das BIOS dazu kann man
selber stricken, weshalb man dafür keine echten I/O-Bausteine wie SIO
nachbilden muss, sondern eine emulationsfreundliches eigenes Interface
definieren kann.
Das BIOS-Interface von PCs erinnert übrigens nicht zufällig an das BIOS
von CP/M, ebenso wie der API von DOS an den vom BDOS erinnert.
Ok,
blicke ich zurück nach 1994 wo ich meinen ersten 386er bekam und dazu
ein dickes Buch hatte: PC Intern! Das Ding was nachher vom vielen
Nachschlagen in sich zerfiel und nur noch durch Klebeband zusammen
gehalten wurde. Da stand alles drin was man wissen musste um in Asm den
zu programmieren (auch wenn ich damals "nur" einen Virus schrieb. Die
API waren Int 10h Int 13h für Bios, Int21h für DOS und viele andere, die
man benutzen konnte, die ganze Floppy Kontrolle lief darüber, zumindest
auf Sektorebene, keine Fat natürlich.
D.h. Hardware <----> BIOS <-----> CP/M <-----> User Software
Aha...
Hallo,
glaube hier hat jemand sauber gemacht wie ich sehe :-) War aber auch
nötig. Hoffe dennoch dass der ein oder andere hierhin zurück findet.
Thema: externer Datenspeicher OHNE Retro.
Herausgeführt aus dem Z80 ist nur der I/O Teil, Datenbus, Clock, Reset
und sämtliche Decoderleitungen für Chip Selects. Ebenfalls sind 4 GPIO
Pins vorhanden die getoggelt werden können.
Ich überlege mir grad wie ich mit einem Arduino System, d.h. nur der IDE
einen Datenspeicher aufbaue. Ich weiss nicht genau ob ein AVR mit 8 Mhz
internem Oszillator schnell genug ist um direkt mit den Bus Leitungen
des Z80 zu kommunizieren, d.h. ein Peripheriegerät simuliert. Ich habe
noch einige Arduino Nanos hier, die mit 16Mhz Quarz arbeiten und einem
Atmel 328 mit 32k Flash.
Als Idee schwebt mir vor, dass der AVR einige Register in die I/O Map
des Z80 einbringt (möglich sind 8 Bytes), die dann mit einem Protokoll
dafür sorgen, dass eine angeschlossenen SD Card mit einem ganz einfachen
Filesystem als Speicher dient.
Falls es eine bessere Lösung gibt ..... bin da für alles offen.
A. K. schrieb:> Was spricht gegen Direktanschluss der SD-Card an Z80, statt Umweg über> Arduino?
Ich kenne mich mit dem SD card Protokoll 4.0 recht gut aus, weil ich da
mal Soft für geschrieben habe um Sektoren zu schreiben und zu lesen. Es
wäre zu gross und gehört eigentlich nicht in den Z80, sondern in die
"Floppy". Für den Arduino habe ich eine ganze fertige Lib mit FAT.
Idee ist also
AVR sitzt an Datenbus,RD,WR, IOREQ und Demuxer CS leitung
I/O Map: 00 01 02 03 04 05 06 07 .....
CMD LO HI B1 B2 B3 B4 ....
CMD = WRITE/READ/ERASE etc.
LO/HI = Zielfile... 0,1,2,3,4,5,6...
Nochmal.......
Jeder ARDUINO den ich habe, hat genug IO um an einen Z80 Bus gehängt zu
werden! Und ich habe Nanos, Einzelchips, Atmega32u usw. Wumpe, einer
wird passen und alle haben das gleiche Programmiermodell wegen der IDE.
Gibt es da ein problem? Nix anderes als wenn man in ein FPGA zb einen
CTC Timer schreiben würde, so dass sich der FPGA wie ein CTC verhält.
Kein Hexenwerk.
De AVR müsste nur dauernd an den Steuerleitungen horchen und sich genau
wie ein Z80 Baustein verhalten. Ob er schnell genug ist weiss ich nicht.
Ich müsste ja das ganze Timing des Z80 beachten.
Christian J. schrieb:> Gibt es da ein problem?
Nur dass die AVRs weder Buslatch noch automatischen Handshake haben und
die Reaktionszeit für Software leicht knackig ist. Oder machst dazu
etwas Logik dazwischen, um mit WAIT zu arbeiten?
Christian J. schrieb:> De AVR müsste nur dauernd an den Steuerleitungen horchen und sich genau> wie ein Z80 Baustein verhalten.
Da bin ich mal gespannt.
Genau.... das wäre eine reine Softwarelösung ohne jede
Harwareunterstützung. Wait ist bisher nicht rausgeführt, ginge
aber.
Der AVR sieht ja "nur" einen I/O Zugriff.
IOREQ auf low, RD oder WR, Demuxer Leitung "0" ..... dazu muss ich ins
Timing reinkriechen. Ein Latch rein ist absolut easy, so läuft die 7
Segment ja, die hat auch eine eigene Adresse.
http://www.nathandumont.com/blog/giving-the-z80-a-good-boot
"The Solution: A PIC and an SD card I've been looking at this problem
since I stopped working on the first version of my Z80 homebrew system.
A few months ago I came to the realisation that the PIC I was planning
on using to interface an SD card to the system was under-utilised. SD
cards are huge in storage and very cheap, plus you can interface to them
via SPI which is easy to do. I'd built a file browser that ran on a PIC
before that could cope with multiple partitions and FAT types, so knew
that was well within the capabilities of a PIC to do. So the plan was to
just use the PIC as an easy way to interface the storage to the Z80. The
space requirement and cost of a PIC microcontroller is much lower than
what would be needed for a 74xx logic solution, even if a parallel
standard like IDE was used instead of SPI."
CPLD habe ich leider nichts für und kann kein VHDL mehr nach fast 10
Jahren.....
Nett, dass du den Link gebracht hast. Dann muss ich dich nicht selber
auf Microchip ansetzen - die haben nämlich in manchen Devices exakt das,
was du hier benötigst: ein als Bus-Slave arbeitsfähiges Interface-Modul,
das die Z80 direkt ansprechen könnte.
Das Timing wird easy, wenn du WAIT verwendest. Viel mehr als einen
Bustreiber und ein RS-Flipflop brauchst du dann nicht. Zugriff der Z80
aktiviert WAIT, AVR deaktiviert.
A. K. schrieb:> ein als Bus-Slave arbeitsfähiges Interface-Modul,> das die Z80 direkt ansprechen könnte.
Habe recht viele 18F877 hier, wo Port E als Bus Slave geschaltet werden
kann inckl Steuerleitungen. Der CCS Compiler unterstützt das auch. Als
Master geht nicht, kein Adressbus rausgeführt.
Wozu Bustreiber? Wer soll wen treiben? Bidirektional, unidirektional?
Der PIC oder AVR ist doch keine Last für die Datenleitungen.
PSP Mode nennt sich das beim 18F877.... CS,RD,WR+8 Bits. Hardwarae
gesteuert.
Christian J. schrieb:> Habe recht viele 18F877 hier, wo Port E als Bus Slave geschaltet werden> kann inckl Steuerleitungen.
Na also. Dazu noch ein paar Portpins irgendeines Portbausteins auf
Z80-Seite für Status&Control des Protokolls und fertig.
> Wozu Bustreiber? Wer soll wen treiben?
Ich hatte da zwei Lösungsvarianten verknotet. In der WAIT Variante
brauchts den nicht.
Genau das was ich brauche bei 16F877..... jeder Zugriff ist
interruptgesteuert behandelbar. Allerdings habe ich für den PIC keine
FAT für SD karten und auch nichts als Low Level Treiber.
PORTD operates as an 8-bit wide Parallel Slave Port or
microprocessor port when control bit PSPMODE
(TRISE<4>) is set. In slave mode, it is asynchronously
readable and writable by the external world through RD
control input pin RE0/RD and WR control input pin
RE1/WR.
It can directly interface to an 8-bit microprocessor data
bus. The external microprocessor can read or write the
PORTD latch as an 8-bit latch. Setting bit PSPMODE
enables port pin RE0/RD to be the RD input, RE1/WR
to be the WR input and RE2/CS to be the CS (chip
select) input. For this functionality, the corresponding
data direction bits of the TRISE register (TRISE<2:0>)
must be configured as inputs (set). The A/D port con-
figuration bits PCFG3:PCFG0 (ADCON1<3:0>) must
be set to configure pins RE2:RE0 as digital I/O.
There are actually two 8-bit latches. One for data-out
and one for data input. The user writes 8-bit data to the
PORTD data latch and reads data from the port pin
latch (note that they have the same address). In this
mode, the TRISD register is ignored, since the micro-
processor is controlling the direction of data flow.
Moin,
nochmal zurück. Ich habe mich gegen den PIC entschieden, weil ich dafür
keine Libs habe die SD Karte betreffend und der CCS Compiler bekannte
Libs nicht kompiliert, habe eh nur eine 5 Jahre alte Version. Das Fass
den sdcc dafür zu beutzen mache ich nicht mehr auf, zudem der sich in
die MPLAB IDE integrieren müsste. Mein PIC KIT fliegt auch irgendwo rum,
keine Ahnung wo. Also AVR.
Nach einigem Lesen im Netz sind einige Lösungen zu finden ein IDE
Interface auf eine CF abzubilden, damit CP/M laufen kann. Das ist aber
zu aufgeblasen für diesen Minirechner, er hat ja auch keine Software für
ein IDE Interface.
Mannomann... welche Lösungen gibt es noch Speicher dran zu pappen ohne
dafür ein neues Fass auf zu machen wie mit dem PIC oder IDE?
Christian J. schrieb:> Mannomann... welche Lösungen gibt es noch Speicher dran zu pappen ohne> dafür ein neues Fass auf zu machen wie mit dem PIC oder IDE?
Wie man sich bettet, so liegt man.
Wenn du unbedingt auf FAT bestehst, und darauf, vom PC aus ohne jeden
irgendwie gearteten Aufwand dran zu kommen, dann hast du eben Arbeit im
Z80-Rechner.
Wenn du nicht so zwingend auf fix und fertiges Betanken durch den PC
bestehst und folglich auch FAT nicht zwingend ist, dann wird es
toteinfach. Aber das hatte ich früher schon beschrieben.
Christian J. schrieb:> Mannomann... welche Lösungen gibt es noch Speicher dran zu pappen ohne> dafür ein neues Fass auf zu machen wie mit dem PIC oder IDE?
Deine Denkweise ist einfach falsch. Du suchst immer nur nach fertigen
Lösungen. Wenn es diese nicht gibt, bist Du aufgeschmissen.
Mach das einfach anders:
Wenn es eine Lösung für ein bestimmtes Problem (noch) nicht gibt, dann
schaffe sie!
P.S.
Ich sehe das genauso wie A.K. Du brauchst kein FAT.
Frank M. schrieb:> Wenn es eine Lösung für ein bestimmtes Problem (noch) nicht gibt, dann> schaffe sie!
Frank,
in diesem Fall gibt es sie! FAT etc brauche ich alles nicht. Es reicht
ein 64kB Block Bytes, die nur geschrieben und gelesen werden müssen.
Trotzdem muss das irgendwie an den I/O Bus dran und selbst diese Latch
Geschichte hat ihre Tücken. Ohne I2C und SPI ist es einfach sch.....
Christian J. schrieb:> Ohne I2C und SPI ist es einfach sch.....
Du traust dir nicht einmal SPI in Software zu? Das Protokoll eines
Dataflash ist trivial.
A. K. schrieb:> Du traust dir nicht einmal SPI in Software zu? Das Protokoll eines> Dataflash ist trivial.
Natürlich! Auch CF karten sind bekannt, Paralleschnittstelle, bestens
dokumentiert. Trotzdem muss da einiges an Bausteinen drumherum. Ideal
wäre I2C EEPROM.... aber I2C kriegste mit den GPIO nicht hin. Der 8255
hat noch die blöde Eigenschaft bei jedem Mode Wechsel von RD auf WR
seine Register zu resetten, so dass es Glitches gibt,
Christian J. schrieb:> Trotzdem muss da einiges an Bausteinen drumherum.
Wüsste nicht, was ausser 4 Portpins und Pegelwandler für 3,3V SPI nötig
wäre. Und weshalb bei unidirektionalen Leitungen Glitches auftreten
müssen erschliesst sich mir nicht.
Christian J. schrieb:> Trotzdem muss da einiges an Bausteinen drumherum.
Naja, so ein paar Widerstände als Pegelwandler für SPI sind natürlich
hochkomplex...
Schnapp Dir eine alte SD-Card und hänge sie an Deinen 8255 oder was Du
sonst noch hast.
Hier hast Du noch einen Link:
http://elm-chan.org/docs/mmc/mmc_e.html
Eigentlich reicht das schon, um die SC-Card am Z80 zum Laufen zu
bekommen.
Er braucht auch nicht mal einen solchen Massenspeicher. Was zur Hölle
soll denn da drauf? CP/M geht wohl mit der Architektur nicht recht wenn
ich mich richtig erinnere, erfordert wohl zumindest Änderungen um
lückenlose 64K Ram zu erzeugen. Woher also kommen die vielen Daten?
Selbst entwickelte Programme? Eher unwahrscheinlich...
Ich habe mal darüber nachgedacht einen mit AT89C2051 gebauten PS2 zu
DDR Parallel-Tastaturanschluß den Jemand anders entworfen hatte zu Ende
zu bauen,
ging nicht, die IO-Zugriffe auf die der µC hätte reagieren müssen
dauerten nur 800ns, nicht zu schaffen. Der in der originalen Tastatur
rappelnde Z80 ohne RAM lief zwar nur mit 1Mhz, hatte aber externe
Latches zur Hilfe (8212).
Ein ATTINY mit Interrupt hätte es vielleicht gerade so geschafft..ich
habe es dann gelassen. PIC ollte ich mir nicht antun und andere µC mit
BUS fähigen Latches sind dünn gesäht. Eine PIO kann sowas, eine hornalte
UPI 8042 auch.
Gruß,
Holm
Holm Tiffe schrieb:> PIC ollte ich mir nicht antun und andere µC mit> BUS fähigen Latches sind dünn gesäht.
Hab ein paar alte Z8594 (Z8-UPC) rumliegen, mitsame 2K RAMs huckepack.
Die haben mehr als bloss ein Latch, die haben ein mustergültiges
Slave-Interface mit Dualport-Registern, Blocktransfer usw.
Den ganze Code für MMC habe ich schon mal geschrieben.... MMC karten
gibt übrigens nicht mehr, nur noch SD. Und die sind leicht anders.
Aber so könnte es gehen, der Code ist ja portierbar.
Frank M. schrieb:> Christian J. schrieb:>> Aber so könnte es gehen, der Code ist ja portierbar.>> Eben, Du musst doch nur SPIMMC() für den 8255 umschreiben.
Ich sagte ja vorhin schon eine Umsschaltung von Write auf Read beim 8255
einen kompletten Reset der internen Register erzeugt. Du musst danach
alles neu einschreiben. Der 8255 ist zu blöde Einzelpins auf RD oder WR
zu schalten, nur ganze Ports.
Ich lass mir da mal was einfallen. Einen "8 Bit Ausgabe PORT" am Z80
kann man sehr einfach mit einem Latch erzeugen. Einen Eingabeport
genauso, nur mit einem anderen Baustein.
Christian J. schrieb:> Ich sagte ja vorhin schon eine Umsschaltung von Write auf Read beim 8255> einen kompletten Reset der internen Register erzeugt.
Häh? Bei SPI brauchst Du gar nichts umzuschalten!
Das bräuchtest Du höchstens bei I2C. Ist hier aber bei einer SD-Card
nicht zielführend.
P.S.
Mich beschleicht das dumme Gefühl, dass Du von SPI keine Ahnung hast.
Wie Du dafür ein Programm selber(!) schreiben konntest, ist mir
schleierhaft.
Er hatte vmtl. nur das SPI-Interface des Controllers im Auge, und wie
man das anspricht steht im Datasheet. Wie SPI hardwareseitig abgeht muss
man dann ja nicht wissen, also muss man die begrenzte Anzahl grauer
Zellen nicht mit unnötigem Wissen belasten.
SPI in Software ist ungefähr das Zweiteinfachste, was man mit Ports tun
kann, kommt direkt nach LED an/aus.
Und was ist das hier? Eine komplette Komminikation per SPI mit mehreren
Nodes, die um einiges komplxer ist.
lasst gut sein, wir reden sonst aneinander vorbei. Mir fällt was ein...
Christian J. schrieb:> Und was ist das hier? Eine komplette Komminikation per SPI mit mehreren> Nodes......
Na also, man muss dich nur etwas kitzeln, dann kommst du ganz von selber
drauf. ;-)