Forum: Mikrocontroller und Digitale Elektronik Z80 Interrupthandling


von Tobias B. (tobiasz80)


Lesenswert?

Hallo Leute,

ich habe hier eine Z80 CPU mit der ich ein wenig rum spiele. Ich hab sie 
soweit auch zum laufen bekommen, das ist alles kein Problem, jedoch 
verhalten sich die Interrupts merkwürdig.
Die kommen zwar, verhalten sich aber vollkommen merkwürdig wenn das 
Interruptsignal etwas länger an dem INT Pin anliegt. Ein etwas längerer 
Zeitpunkt ist dabei 1ms.
Liegt er etwas kürzer an (den Zeitraum kann ich leider nicht bestimmten) 
funktioniert er zuverlässig.
Wie Prüfe ich die Interrupts? Ich habe dazu für den Arduino Uno ein 
kleines Programm geschrieben, was alle 5 Sekunden ein Interrupt 
triggert.
Der Code auf dem Arduino:
1
void vSetClock(bool active)
2
{
3
  digitalWrite(clk, active);
4
}
5
6
...
7
8
  bool clock = false;
9
  while(1)
10
  {
11
    vSetClock(clock);
12
    clock = !clock;
13
    //delay(1);
14
    vSetClock(clock);
15
    clock = !clock;
16
    delay(5000);
17
  }

Der Code auf dem Z80
1
#target     bin                 ; declare target file format
2
3
#code       0,$38             ; declare code segment start, size
4
5
; Stack Konfigurieren
6
        LD IX, $ffff
7
        LD SP, IX
8
; PIO Konfigurieren
9
        LD A, $80
10
        OUT ($03), A
11
; Enable Interrupts
12
        IM 1
13
        EI
14
; App Init
15
        LD D, $00
16
17
mainLoop:
18
        CP D
19
        JP Z, mainLoop
20
        CALL wait
21
        LD A, $01
22
        OUT ($00), A
23
        CALL wait
24
        LD A, $00
25
        OUT ($00), A
26
        JP mainLoop
27
28
wait:
29
        LD BC, $ffff
30
        LD HL, $100
31
waitLoop:
32
        LD ($ff), BC
33
        CP (HL)
34
        RET Z
35
        DEC BC
36
        JP waitLoop
37
38
#code $38, $2E
39
INT:
40
        DI
41
        CP D
42
        LD D, $01
43
        JR Z, $ + 4
44
        LD D, $00
45
        EI
46
        RETI
47
48
#code $0066, 20
49
NMI:
50
        HALT
51
#end                            ; terminate #target
Der Code auf dem Z80 macht nichts anderes als eine LED blinken zu 
lassen. Durch den Interrupt schalte ich das Blinken alternierend aus 
oder an.
Das Funktioniert aber nur zuverlässig wenn in dem Arduino Programm kein 
Delay vorhanden ist. Warum ist das so?

MfG
Tobias

von (prx) A. K. (prx)


Lesenswert?

Das INT Signal ist pegelgetriggert. Wenn INT bei RETI noch low ist, dann 
gibts sofort wieder einen Interrupt.

Wenn INT also länger low ist, als der Interrupt-Handler dauert, dann 
gibts den Handler doppelt oder noch häufiger.

von Peter D. (peda)


Lesenswert?

Üblicher Weise steuert man den Interrupt ja nicht direkt an, sondern 
über die PIO. Und die PIO setzt man dann einfach auf flankengetriggert.

Einen nackten Z80 ohne PIO, SIO, CTC zu verwenden, halte ich für wenig 
sinnvoll. Man verschenkt damit die meisten Möglichkeiten.

von (prx) A. K. (prx)


Lesenswert?

Irgendeinen PIO scheint es zu geben, aber zum Z80 PIO passen die 
Adressen 00=data und 03=control nicht. Sehr wohl aber zum 8255, und der 
hat mit Interrupts nichts im Sinn.

von Tobias B. (tobiasz80)


Lesenswert?

Danke für die Antwort!
Dann weiß ich nun wie die gestrichelten Linien im Timingdiagram zu 
interpretieren sind.
Das heißt die Interruptleitung wird im letzten Taktstate von der gerade 
aktiven Instruktion gesampled, (angenommen INT ist Low was bedeutet, das 
ein Interrupt ausgelöst wird) dann macht die CPU ein IORQ um einen 8 Bit 
Vektor vom Datenbus zu lesen, welcher das Gerät das den Interrupt 
ausgelöst hat auf den Datenbus schreibt, und dann wird zu der Adresse im 
RAM/ROM gesprungen.
Was nun mit dem Vektor geschieht hängt von dem Interruptmode ab. Bei dem 
IM 1 wie oben in dem Programm benutzt sollte das, was auf dem Datenbus 
geschrieben wurde, gänzlich egal sein, da er bei einem INT und NMI immer 
zu festen Adressen springt.
Das bedeutet also, wenn ich ein Interrupt auslöse, kann ich dann als 
Gerät durch das IORQ und dem zusätzlich aktivem M1 erkennen, das der 
Interrupt verarbeitet wird, und kann dann die Leitung wieder auf High 
schalten und somit dem Interrupt deaktivieren.

MfG
Tobias

von Tobias B. (tobiasz80)


Lesenswert?

In der Tat benutze ich einen WS82C55A ;)
Da steht zwar im Datenblatt auch etwas über Interrupts drinnen, aber 
soweit bin ich noch nicht ;)

von (prx) A. K. (prx)


Lesenswert?

Tobias Bla schrieb:
> Das heißt die Interruptleitung wird im letzten Taktstate von der gerade
> aktiven Instruktion gesampled,

Genauer gesagt im M1 Zyklus.

> IM 1 wie oben in dem Programm benutzt sollte das, was auf dem Datenbus
> geschrieben wurde, gänzlich egal sein, da er bei einem INT und NMI immer
> zu festen Adressen springt.

Richtig.

> Das bedeutet also, wenn ich ein Interrupt auslöse, kann ich dann als
> Gerät durch das IORQ und dem zusätzlich aktivem M1 erkennen, das der
> Interrupt verarbeitet wird, und kann dann die Leitung wieder auf High
> schalten und somit dem Interrupt deaktivieren.

Ja. Üblicherweise überlässt man dieses Spiel aber der Peripherie, wie 
Peter schon darlegte.

von (prx) A. K. (prx)


Lesenswert?

Tobias Bla schrieb:
> Da steht zwar im Datenblatt auch etwas über Interrupts drinnen, aber
> soweit bin ich noch nicht ;)

Wenn du dort angekommen bist, wirst du feststellen, dass der Z80 PIO 
wundersamerweise besser zur Z80 CPU passt als der 8255, was Interrupts 
angeht. Die Z80 hatte ein recht ausgefeiltes Interrupt-Verfahren, 
insbesondere im IM2.

Die Interrupts des 8255 wurden ursprünglich für sowas wie die parallele 
Druckerschnittstelle gebaut, nicht als Interrupt-Controller für diverse 
externe Ereignisse.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

A. K. schrieb:
> angeht. Die Z80 hatte ein recht ausgefeiltes Interrupt-Verfahren,
> insbesondere im IM2.

 Und auch andere feine Sachen wie z.B. die Alternate Registers -
 - ideal für schnelle Interrupts...
 Interrupt-Tabelle im RAM...

von Michael_ (Gast)


Lesenswert?

Tobias Bla schrieb:
> In der Tat benutze ich einen WS82C55A ;)
> Da steht zwar im Datenblatt auch etwas über Interrupts drinnen, aber
> soweit bin ich noch nicht ;)

Vergiss den für den Z80! Der ist für das INTEL 8085 System gemacht. Mit 
IM2 ist die PIO einfach genial.

Peter Dannegger schrieb:
> Einen nackten Z80 ohne PIO, SIO, CTC zu verwenden, halte ich für wenig
> sinnvoll. Man verschenkt damit die meisten Möglichkeiten.

Doch, die FuA-melo-Klingel funktioniert nur mit NMI 1000-fach :-)

von Georg (Gast)


Lesenswert?

Tobias Bla schrieb:
> kann ich dann als
> Gerät durch das IORQ und dem zusätzlich aktivem M1 erkennen, das der
> Interrupt verarbeitet wird, und kann dann die Leitung wieder auf High
> schalten und somit dem Interrupt deaktivieren.

Wenn du mit dem einen IRQ auskommst. Die Schaltung ist etwas aufwendig, 
vielleicht kommst du auch mit einem Monoflop aus, das aus dem INT einen 
flankengesteuerten Eingang macht.

Georg

von Tobias B. (tobiasz80)


Lesenswert?

> Wenn du dort angekommen bist, wirst du feststellen, dass der Z80 PIO
> wundersamerweise besser zur Z80 CPU passt als der 8255, was Interrupts
> angeht. Die Z80 hatte ein recht ausgefeiltes Interrupt-Verfahren,
> insbesondere im IM2.

Das glaube ich, jedoch ist nicht ganz so einfach an solch ein PIO dran 
zu kommen. Die Z80 und alles drum rum ist doch leider recht betagt, 
jedoch scheint sie zum Einstieg in die Rechnerachitektur noch recht gut 
geeignet zu sein.
Man kann solch ein System wunderbar auf dem Steckbrett aufbauen und kann 
sich über LEDs die Aktivität auf dem Bus anzeigen lassen (eine Niedrige 
Tacktung im Hz Bereich voraus gesetzt ;) ), man bekommt Details mit, wie 
z. B. das Handling der IO Geräte, die doch auf moderneren Architekturen 
wunderbar weg abstrahiert wurden und das alles ohne das es übermäßig 
kompliziert wird.

von Georg G. (df2au)


Lesenswert?

Tobias Bla schrieb:
> nicht ganz so einfach an solch ein PIO dran
> zu kommen

Farnell oder Mouser haben so viele auf Lager, die müssen die schon 
verkaufen.
Für Mouser gibt es den Sammelbestellungs Thread hier im Forum.

von Uwe (de0508)


Lesenswert?

Hallo Tobias,

ich habe noch einige Bausteine im Lager.

Auf die Schnelle:
Zilog z80 dma
Zilog z80 ctc
Toshiba z84c30 (z80 ctc)
Sharp LH5082AL (Z80 CMOS CTC)
diverse statische Rambausteine
Intersil IM6402-LI Keramik Uart
ay-38910 sound

der Rest ist noch auf Europaplatinen.

Melde dich halt, wenn Du etwas davon brauchst.

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.