Forum: Mikrocontroller und Digitale Elektronik Retro Fieber: Z80 oder 68000 ?


von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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?

von Leo C. (rapid)


Lesenswert?

> 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.

von Christian J. (Gast)


Lesenswert?

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....

von Holm T. (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
von Holm T. (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
von Holm T. (Gast)


Lesenswert?

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

von Christian J. (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von Christian J. (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
von Holm T. (Gast)


Lesenswert?

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

von Christian J. (Gast)


Lesenswert?

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.
1
/* Initialize the interrupt controller */
2
/******************************************************************************
3
** Function name:       init_VIC
4
**
5
** Descriptions:        Initialize VIC interrupt controller.
6
** parameters:          None
7
** Returned value:      None
8
**
9
******************************************************************************/
10
void Init_VIC(void)
11
{
12
    uint32_t i = 0;
13
    uint32_t *vect_addr, *vect_prio;
14
15
    /* initialize VIC*/
16
    VICIntEnClr = 0xffffffff;
17
    VICVectAddr = 0;
18
    VICIntSelect = 0;
19
20
    /* set all the vector and vector control register to 0 */
21
    for ( i = 0; i < VIC_SIZE; i++ )
22
    {
23
        vect_addr = (uint32_t *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + i*4);
24
        vect_prio = (uint32_t *)(VIC_BASE_ADDR + VECT_PRIO_INDEX + i*4);
25
        *vect_addr = 0x0;
26
        *vect_prio = 0xF;
27
    }
28
    return;
29
}
30
31
/******************************************************************************
32
** Function name:       install_irq
33
**
34
** Descriptions:        Install interrupt handler
35
** parameters:          Interrupt number, interrupt handler address,
36
**                      interrupt priority
37
** Returned value:      true or false, return false if IntNum is out of range
38
**
39
******************************************************************************/
40
unsigned long install_irq( uint32_t IntNumber, void *HandlerAddr, uint32_t Priority )
41
{
42
    uint32_t *vect_addr;
43
    uint32_t *vect_prio;
44
45
    VICIntEnClr = 1 << IntNumber;   /* Disable Interrupt */
46
    if ( IntNumber >= VIC_SIZE )
47
    {
48
        return ( FALSE );
49
    }
50
    else
51
    {
52
        /* find first un-assigned VIC address for the handler */
53
        vect_addr = (uint32_t *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + IntNumber*4);
54
        vect_prio = (uint32_t *)(VIC_BASE_ADDR + VECT_PRIO_INDEX + IntNumber*4);
55
        *vect_addr = (uint32_t)HandlerAddr; /* set interrupt vector */
56
        *vect_prio = Priority;
57
        VICIntEnable = 1 << IntNumber;  /* Enable Interrupt */
58
        return( TRUE );
59
    }
60
}

von Holm T. (Gast)


Lesenswert?

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

von Christian J. (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
von Christian J. (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

Christian J. schrieb:
> Gibt es irgendwas was Du nicht weisst?

Ja. Die Antwort darauf. ;-)

: Bearbeitet durch User
von Christian J. (Gast)


Angehängte Dateien:

Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
von Christian J. (Gast)


Lesenswert?

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.

von Christian J. (Gast)


Lesenswert?

Sowas hier macht Spass zu Programmieren :-) Mal sehen ob der Z80 damit 
auch klar kommt und mit wieviel Code.
1
///////////////////////////////////////////////////////////////////////////////////
2
/*
3
    Funktion:   CalcSonnenAufgang()
4
    Modul   :   rtc_user.c
5
    --------------------------------------------------------------------------------
6
    Beschreibung            : Berechnet den Sonnenaufgang und Untergang
7
8
    Zeitgleichung:          WOZ - MOZ = -0.171*sin(0.0337 * T + 0.465) - 0.1299*sin(0.01787 * T - 0.168)
9
                            Deklination = 0.4095*sin(0.016906*(T-80.086))
10
                            Zeitdifferenz = 12*arccos((sin(h) - sin(B)*sin(Deklination)) / (cos(B)*cos(Deklination)))/pi;
11
                            Sonnenaufgang h=-50 Bogenminuten = -0.0145
12
13
                            Aufgang Ortszeit = 12 - Zeitdifferenz - Zeitgleichung
14
                            Untergang Ortszeit = 12 + Zeitdifferenz - Zeitgleichung
15
16
                            Aufgang = Aufgang Ortszeit - geographische Länge /15 + Zeitzone
17
                            Untergang = Untergang Ortszeit - geographische Länge /15 + Zeitzone
18
19
    aufgerufene Funktionen  :
20
    Eingabeparameter        : ptr           (Zeiger auf aktuelle Zeit für Sommerzeit)
21
                              sonne         (Zeiger auf Ergebnisstruktur
22
                              T             (Tag des Jahres)
23
    Rückgabe                : -
24
    veränderte Globals      : SAG_Std,SAG_Min, SUG_Std,SUG_Min
25
    öffentlich/private      : öffentlich
26
27
    Autor:  Christian J.
28
    letzte Änderung: 20.2.2009
29
*/
30
////////////////////////////////////////////////////////////////////////////////////
31
32
33
uint8_t CalcSonnenAufgang(zeit_t *ptr, struct sonnenstand *sonne, uint16_t T)
34
{
35
    #define hoehe   -0.0145     // Sonnenhöhe in RAD
36
    #define PI      3.141592654
37
38
    float   B,
39
            Deklination,        // Deklination der Sonne
40
            Zeitdiff,           // Zeitdifferenz
41
            DIFF_WOZ_MOZ,
42
            Aufgang_MOZ,        // Aufgang mittlere Ortzeit
43
            Untergang_MOZ,      // Aufgang mittlere Ortszeit
44
            Aufgang_WOZ,        // Aufgang wahre Ortszeit
45
            Untergang_WOZ;      // Untergang wahre Ortszeit
46
47
    static  uint16_t oldvalue = 0;
48
49
50
    // Prüfen, ob Berechnungen für aktuellen Tag bereits vorliegen
51
52
    if (oldvalue == T)
53
        return 1;
54
55
    oldvalue = T;
56
57
    // Berechnungen
58
    B = PI *N_BREITE / 180;
59
    Deklination = 0.4095*sin(0.016906*(T-80.086));
60
    Zeitdiff = 12*acos((sin(hoehe) - sin(B)*sin(Deklination)) / (cos(B)*cos(Deklination)))/PI;
61
    DIFF_WOZ_MOZ = -0.171*sin(0.0337*T+0.465) - 0.1299*sin(0.01787*T-0.168);    // WOZ-MOZ
62
63
    Aufgang_MOZ   = 12 - Zeitdiff - DIFF_WOZ_MOZ;
64
    Untergang_MOZ = 12 + Zeitdiff - DIFF_WOZ_MOZ;
65
66
    Aufgang_WOZ   = Aufgang_MOZ + (15 - O_LAENGE)*(float)4/60;
67
    Untergang_WOZ = Untergang_MOZ + (15 - O_LAENGE)*(float)4/60;
68
69
70
    // Sommerzeit berücksichtigen
71
    if (IsSommerzeit(ptr)) {
72
        Aufgang_WOZ = Aufgang_WOZ + 1;
73
        Untergang_WOZ = Untergang_WOZ + 1;
74
    }
75
76
    // globale Float Werte setzen
77
    sonne->f_SAG = Aufgang_WOZ;
78
    sonne->f_SUG = Untergang_WOZ;
79
    sonne->f_Tagdauer = sonne->f_SUG - sonne->f_SAG;
80
81
    // Umrechnung in Stunden/Minuten
82
83
    sonne->SAG_Std = floor(Aufgang_WOZ);                    // Sonnenaufgang
84
    sonne->SAG_Min = (Aufgang_WOZ - (float)sonne->SAG_Std) * 60;
85
86
    sonne->SUG_Std = ceil(Untergang_WOZ)-1;             // Sonnenuntergang
87
    sonne->SUG_Min = (Untergang_WOZ - (float)sonne->SUG_Std) * 60;
88
89
    return 1;
90
}

von (prx) A. K. (prx)


Lesenswert?

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. ;-)

: Bearbeitet durch User
von Christian J. (Gast)


Lesenswert?

Schön! Dann bin ich wohl auch 80.

von (prx) A. K. (prx)


Lesenswert?

Sorry, aber diese Vorlage war unwiderstehlich. ;-)

von Christian J. (Gast)


Angehängte Dateien:

Lesenswert?

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.....

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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".

: Bearbeitet durch Moderator
von Holm T. (Gast)


Lesenswert?

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

von Leo C. (rapid)


Lesenswert?

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. :)

von (prx) A. K. (prx)


Lesenswert?

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).

von Holm T. (Gast)


Lesenswert?

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

von Christian J. (Gast)


Lesenswert?

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 ;
}

von Leo C. (rapid)


Angehängte Dateien:

Lesenswert?

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.

von Christian J. (Gast)


Lesenswert?

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.

von Leo C. (rapid)


Lesenswert?

> 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.

von Christian J. (Gast)


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

: Bearbeitet durch Moderator
von Christian J. (Gast)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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_t ch)
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.

: Bearbeitet durch Moderator
von Christian J. (Gast)


Lesenswert?

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.

1
void putchar(char c)
2
{
3
4
  while(tx.f_buf_full); // FIXXXME! 
5
6
  __asm
7
    di
8
  __endasm ;
9
10
  tx.buf[tx.wr_ptr] = c;            //  Zeichen  einschreiben
11
  tx.wr_ptr = (tx.wr_ptr +1) & tx.mask;    //  Zeiger rollen
12
  tx.f_buf_full = (tx.wr_ptr == tx.rd_ptr) ? true : false; // Buffer voll?
13
  if (tx.f_idle)                // Wenn TX inaktiv muss ISR angestossen werden
14
    STI_UDR = tx.buf[tx.rd_ptr];
15
16
  __asm
17
    ei
18
  __endasm ;
19
20
21
}

von Leo C. (rapid)


Lesenswert?

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.

von Christian J. (Gast)


Lesenswert?

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...

von Leo C. (rapid)


Lesenswert?

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...

: Bearbeitet durch User
von Christian J. (Gast)


Lesenswert?

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?
1
void int_sti_transmit_buffer_empty(void)  __interrupt
2
{
3
  /* TX hat letztes Byte gesendet und muss nachschauen
4
   * ob weitere Bytes zu senden sind */
5
6
  /* TX ISR muss extern angestossen werden, damit
7
   * diese Routine hier aufgerufen wird, wenn Puffer
8
   * leer ist */
9
10
    // Sind noch Zeichen im TX Buffer?
11
    if (tx.rd_ptr != tx.wr_ptr)
12
    {   // ja...
13
    tx.f_idle    = false;            // Flag TX aktiv
14
    tx.f_buf_full = false;            // TX Full Flag zurücksetzen
15
        STI_UDR       = tx.buf[tx.rd_ptr];       // Byte einschreiben
16
    tx.rd_ptr     = (tx.rd_ptr +1) & tx.mask;  // Rotieren
17
    } else
18
    {
19
       //nein...
20
    tx.f_idle = true;              // TX Idle Flag, Uart inaktiv
21
    tx.f_buf_full = false;
22
  }
23
    __asm
24
         ei
25
    __endasm ;
26
}

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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_interrupt aktivieren;

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.

von Christian J. (Gast)


Lesenswert?

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.

von Leo C. (rapid)


Lesenswert?

Danke Frank, genau das sollte mein "Gestammel" ausdrücken.

von Leo C. (rapid)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

: Bearbeitet durch Moderator
von Christian J. (Gast)


Lesenswert?

1
void putchar(char c)
2
{
3
  char tx_empty;
4
  _asm
5
    di
6
  __endasm ;
7
8
  tx_empty = STI_TSR & 0x80;
9
10
  // TX frei und Ring leer?
11
  if (tx_empty &&  (tx.wr_ptr==tx.rd_ptr))
12
      STI_UDR = c;                    // Byte einschreiben
13
14
  else {
15
    tx.buf[tx.wr_ptr] = c;            //  Zeichen  einschreiben
16
    tx.wr_ptr = (tx.wr_ptr +1) & tx.mask;    //  Zeiger rollen
17
    tx.f_buf_full = (tx.wr_ptr == tx.rd_ptr) ? true : false; // Buffer voll?
18
  }
19
  __asm
20
    ei
21
  __endasm ;
22
23
24
}

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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:
1
init ()
2
{
3
  TX_EMPTY_interrupt aktivieren;
4
}
5
6
putchar (uint8_t ch)
7
{
8
  if (ringbuffer_leer && STI_bereit_zum_senden)
9
  {
10
      zeichen_an_sti_senden;
11
  }
12
  else
13
  {
14
      zeichen_in_ringbuffer_ablegen
15
  }
16
}
17
18
ISR(TX_EMPTY)
19
{
20
     if (! ringbuffer_leer)
21
     {
22
         ein_zeichen_aus_ringbuffer_lesen;
23
         das_zeichen_auf_die_reise_schicken;
24
     }
25
}

von Christian J. (Gast)


Lesenswert?

>>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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Christian J. schrieb:
>
1
> void putchar(char c)
2
> {
3
>   char tx_empty;
4
>   _asm
5
>     di
6
>   __endasm ;
7
>   ....
8
>   __asm
9
>     ei
10
>   __endasm ;
11
> }
12
>

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?!?

: Bearbeitet durch Moderator
von Christian J. (Gast)


Lesenswert?

@Frank:

meinst du vielleicht das hier?

1. Ring ist leer = gar nix drin oder
2. Im Ring ist noch Platz für 1 Zeichen

?

von Christian J. (Gast)


Lesenswert?

>>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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Christian J. (Gast)


Lesenswert?

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....

von Leo C. (rapid)


Lesenswert?

Christian J. schrieb:
> Gabs alles schonmal hier:
>
> Beitrag "UART Sendepuffer"

Was sollen denn diese Nebelkerzen?

von Route_66 H. (route_66)


Lesenswert?

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.

von Christian J. (Gast)


Lesenswert?

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 :-)

von Christian J. (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Route_66 H. (route_66)


Lesenswert?

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.

: Bearbeitet durch User
von Christian J. (Gast)


Lesenswert?

Nichts anderes steht hier...

void putchar(char c)
{

  while ((STI_TSR & 0x80) == 0);
  STI_UDR = c;

}

von Route_66 H. (route_66)


Lesenswert?

Christian J. schrieb:
> Nichts anderes steht hier...

Stimmt!

von Leo C. (rapid)


Lesenswert?

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.

von Christian J. (Gast)


Lesenswert?

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.

von Christian J. (Gast)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

: Bearbeitet durch Moderator
von Christian J. (Gast)


Lesenswert?

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....

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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:
1
    cli();
2
    uart_txsize++;
3
    sei();

Das ist die einzige Stelle!

von Christian J. (Gast)


Lesenswert?

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.... :-)

von Leo C. (rapid)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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
static void
2
mcurses_puti (uint8_t i)
3
{
4
    uint8_t ii;
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.

von Leo C. (rapid)


Lesenswert?

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.

von Christian J. (Gast)


Lesenswert?

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.

von Holm T. (Gast)


Lesenswert?

Die Routine ist ein Bisschen kurz und füllt wohl nicht mal die Puffer, 
schicke mal was Dickeres...

Gruß,

Holm

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Christian J. (Gast)


Lesenswert?

@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.

von Leo C. (rapid)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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....

: Bearbeitet durch Moderator
von Frank M. (ukw) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

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ß!

: Bearbeitet durch Moderator
von Frank M. (ukw) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

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.

: Bearbeitet durch Moderator
von Christian J. (Gast)


Lesenswert?

Frank M. schrieb:
> Wäre schön, wenn ich da endlich mal eine Antwort bekäme....

128 Bytes aktuell.

von Christian J. (Gast)


Lesenswert?

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!

von Leo C. (rapid)


Lesenswert?

Christian J. schrieb:
> 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

Übrigens kann sdcc hier die Modulo-Op zu "& 0x7F" optimieren, wenn man 
die Zeile so schreibt:
1
rx.rd_ptr = ++rx.rd_ptr % RX_BUF_SIZE;

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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:
1
            if (idx == MAX_KEYS)
2
            {
3
                ch = KEY_ESCAPE;
4
            }

Neu:
1
            if (idx == MAX_KEYS)
2
            {
3
                ch = ERR;
4
            }

So bleibst Du länger "im Spiel". ;-)

: Bearbeitet durch Moderator
von Leo C. (rapid)


Lesenswert?

> 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...

von Christian J. (Gast)


Lesenswert?

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".

von Christian J. (Gast)


Lesenswert?

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... :-)

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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:
1
#define PEEK(x)         *((unsigned char *) (x))

durch
1
#define PEEK(x)         (volatile) *((unsigned char *) (x))

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 ;-)

von Leo C. (rapid)


Lesenswert?

Ups, Beitrag schon wieder weg.
Ist eigentlich meine letzte Mail (vorgestern) mit dem Makefile Update 
nicht angekommen?

von Christian J. (Gast)


Lesenswert?

@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);

von Christian J. (Gast)


Lesenswert?

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!

von Christian J. (Gast)


Angehängte Dateien:

Lesenswert?

@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);
}

von Christian J. (Gast)


Angehängte Dateien:

Lesenswert?

@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
};

von Christian J. (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Leo C. (rapid)


Lesenswert?

Dafür kannst Du Dir doch schnell dieses Macro ändern:
1
#define IS_PRINT(ch)    (((ch) >= 32 && (ch) < 0x7F) || ((ch) >= 0xA0))

von Christian J. (Gast)


Angehängte Dateien:

Lesenswert?

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?

von Leo C. (rapid)


Lesenswert?

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.

von Christian J. (Gast)


Lesenswert?

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.

von Leo C. (rapid)


Lesenswert?

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.

von Christian J. (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Christian J. (Gast)



Lesenswert?

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.

von Leo C. (rapid)


Angehängte Dateien:

Lesenswert?

> Wäre gut, wenn man das Data Segment direkt hinter dem Codesegment
> plazieren könnte, automatisch.

Anhang

von Leo C. (rapid)


Lesenswert?

> Ok, ich versuche nur ein prinft zum Laufen zu kriegen. Allerdings fehlen

Wie wärs denn mit Chans xprintf:
http://elm-chan.org/fsw_e.html

von Christian J. (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von Christian J. (Gast)


Lesenswert?

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.

von Leo C. (rapid)


Lesenswert?

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...

: Bearbeitet durch User
von Christian J. (Gast)


Lesenswert?

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.
1
 1 2 3 4 5 6
2
+-+-+-+-+-+-+
3
|O|#|#|#|O|#|
4
|O|O|O|#|#|O|
5
|#|#|#|O|O|#|
6
|O|O|O|#|#|O|
7
|O|#|#|O|#|O|
8
|#|#|#|O|O|O|
9
+-+-+-+-+-+-+
10
 1 2 3 4 5 6
11
12
draw! no one won..
13
Total remis: 2
14
player #1: computer
15
player #2: computer
16
17
 1 2 3 4 5 6
18
+-+-+-+-+-+-+
19
| | |O| | | |
20
| | |O| |#| |
21
|O|#|O|#|#|#|
22
|O|#|#|#|O|O|
23
|O|O|O|#|O|#|
24
|O|#|#|O|O|#|
25
+-+-+-+-+-+-+
26
 1 2 3 4 5 6
27
28
player 1 (computer) won!
29
Total wins player 1: 10
30
Total wins player 2: 7
31
Total remis: 2
32
player #1: computer
33
player #2: computer

von Leo C. (rapid)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von Christian J. (Gast)


Lesenswert?

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.

von Holm T. (Gast)


Lesenswert?

Das ist kein Problem vom Compiler sondern eines des Linkers.
Versuche halt zu lesen was dokumentiert ist.

Gruß,

Holm

von Christian J. (Gast)


Lesenswert?

@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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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
1
  #define IS_PRINT(ch)    (((ch) >= 32 && (ch) < 0x7F) || ((ch) >= 0xA0))

änderst in
1
  #define IS_PRINT(ch)    (((ch) >= 32 && (ch) < 0x7F))

: Bearbeitet durch Moderator
von Philipp (Gast)


Lesenswert?

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

von Christian J. (Gast)


Angehängte Dateien:

Lesenswert?

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

von Holm T. (Gast)


Lesenswert?

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

von Christian J. (Gast)


Angehängte Dateien:

Lesenswert?

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....

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Christian J. (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Matthias (Gast)


Lesenswert?

Macht dein C Compiler kompakten Code ?
Wie Gross ist er im Vergleich mit ASM ?

(Hello World)

von Christian J. (Gast)


Lesenswert?

@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?

von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

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.

von Christian J. (Gast)


Angehängte Dateien:

Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
von Christian J. (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

Was für einen Wert musst du denn ins Timer-Register des STI bisher 
reinschreiben, um auf deine 9600bd zu kommen?

von Holm T. (Gast)


Lesenswert?

....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

von Christian J. (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von Christian J. (Gast)


Lesenswert?

A. K. schrieb:
> Was für einen Wert musst du denn ins Timer-Register des STI bisher
> reinschreiben, um auf deine 9600bd zu kommen?

3.

von Christian J. (Gast)


Lesenswert?

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 :-)

von (prx) A. K. (prx)


Lesenswert?

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.

von Christian J. (Gast)


Angehängte Dateien:

Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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?

von Christian J. (Gast)


Lesenswert?

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?

von Holm T. (Gast)


Lesenswert?

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

von Holm T. (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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. ;-)

von Christian J. (Gast)


Lesenswert?

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

von Holm T. (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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:.

von Christian J. (Gast)


Lesenswert?

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.

von Holm T. (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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.

von Holm T. (Gast)


Lesenswert?

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

von Jens (Gast)


Lesenswert?

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

von Holm T. (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
von Christian J. (Gast)


Lesenswert?

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?

von Holm T. (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

A. K. schrieb:
> Oszillator für Baudratenquarz.

Oops, das war ein anderer.

von Holm T. (Gast)


Lesenswert?

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

von Christian J. (Gast)


Lesenswert?

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?

von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
von Christian J. (Gast)


Lesenswert?

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...

von Christian J. (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

Was spricht gegen Direktanschluss der SD-Card an Z80, statt Umweg über 
Arduino?

: Bearbeitet durch User
von Christian J. (Gast)


Lesenswert?

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...

von (prx) A. K. (prx)


Lesenswert?

AVR als Busmaster oder als Slave? Wenn Letzteres, dann wie?

: Bearbeitet durch User
von Christian J. (Gast)


Lesenswert?

AVR als I/O Bus "Device", eingemapped mit fixere Adresse für maximal 32 
Bytes möglich.

von (prx) A. K. (prx)


Lesenswert?

Christian J. schrieb:
> AVR als I/O Bus "Device", eingemapped mit fixere Adresse für maximal 32
> Bytes möglich.

Mit welchem AVR geht das?

von Christian J. (Gast)


Lesenswert?

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.

von Christian J. (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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?

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

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.

von Christian J. (Gast)


Lesenswert?

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.....

von (prx) A. K. (prx)


Lesenswert?

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.

von Leo C. (rapid)


Lesenswert?

Nur daß Christian den Artikel nicht zu Ende gelesen hat. Der PIC macht 
nämlich genau daß, was Du oben vorgeschlagen hat: BUS-Master.

von (prx) A. K. (prx)


Lesenswert?

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.

von Christian J. (Gast)


Angehängte Dateien:

Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
von Christian J. (Gast)


Lesenswert?

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.

von Christian J. (Gast)


Angehängte Dateien:

Lesenswert?

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?

von (prx) A. K. (prx)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

: Bearbeitet durch Moderator
von Christian J. (Gast)


Lesenswert?

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.....

von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
von Christian J. (Gast)


Lesenswert?

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,

von (prx) A. K. (prx)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

Christian J. schrieb:
> Auch CF karten sind bekannt

Den Aufwand von 16-Bit Parallel-IDE (aka CF) mit 1-Bit SPI zu 
vergleichen...

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Holm T. (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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.

von Christian J. (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Christian J. (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

: Bearbeitet durch Moderator
von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
von Christian J. (Gast)


Angehängte Dateien:

Lesenswert?

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...

1
Funktion:   SPI_SendFrame
2
    Modul   :   port_cpu.c
3
    --------------------------------------------------------------------------------
4
    Beschreibung            : Verpackt den Datensatz und sendet ihn zum Slave
5
                              Erzeugt das Protokoll, um mit Slave zu kommunizieren
6
                              Es findet keine Auswertung statt, es werden nur rohe
7
                              Daten gesendet und empfangen.
8
9
                              Diese Routine ist universell einsetzbar für SPI
10
                              Kommunikation
11
12
    Protokoll (ohne Checksumme)
13
14
    Sendung des Masters:
15
    <MASTER_START> <Anzahl> <ssize> <...> <...> <MASTER_END> ...
16
17
    Slave antwortet mit:
18
    a) ... <SLAVE_END>      (wenn keine Sendedaten vorliegen)
19
    b) ... <SLAVE_START> <rsize> <...> <...> <SLAVE_END>
20
21
    aufgerufene Funktionen  : SPI
22
23
    enum chips {devIR,devLCD,devPORT......};
24
25
    Eingabeparameter        : dev           Device (siehe enum chips)
26
                              *tosend       Zeiger auf Quelldaten
27
                              ssize         Anzahl zu sendender Daten
28
                              *receive      Zeiger auf Empfangspuffer
29
                              *rsize        Zeiger auf Puffer für Anzahl empf. Datenbyte
30
31
    Rückgabe                : OK,FAIL
32
    veränderte Globals      : -
33
    öffentlich/private      : public
34
35
36
    letzte Änderung: 28.3.2009

von (prx) A. K. (prx)


Lesenswert?

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. ;-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.