Probleme bei verschachtelten Interuppt

Gast #2423402
Lesenswert?

Guten Morgen

habe soeben hier gelesen das ein AVR keine verschachtelten Interuppts 
kann. Hab nähmlich das Problem das ein TIMER0_OVF kein INT0 zulässt.
Wenn das so ist dann verstehe ich nicht warum es eine 
Interuppt-Prio-Liste gibt?
Danke für euere Hilfe!!!
Hier Auszüge aus meinem Code:

.ORG  0x0000    RJMP  RETURN
.ORG  0x0001    RJMP  INT_INT0
.ORG  0x0008    RJMP   TIMER1_OVF
.ORG  0x000B    RJMP  TIMER0_OVF

// TIMER0
LDI temp, (1<<WGM02)|(1<<CS00)
OUT TCCR0B, temp
IN temp, TIMSK0
SBR temp, (1<<TOIE0)
OUT TIMSK0, temp

//INT0-Freigabe
IN temp, MCUCR
SBR temp, (1<<ISC01)  //Fallende FLanke
OUT MCUCR, temp
IN temp, GIMSK
SBR temp, (1<<INT0)
OUT GIMSK, temp

Wenn ich folgenden TIMER0 Code auskommentiere funktioniert INT0:
IN temp, TIMSK0
SBR temp, (1<<TOIE0)
OUT TIMSK0, temp

Gruß und Dank
Bernd
#2423409
Lesenswert?

BerndB schrieb:
> Hab nähmlich das Problem das ein TIMER0_OVF kein INT0 zulässt.

Das wäre aber auch ne saudämliche Idee, in einem Interrupt auf nen 
anderen zu warten.

Ein Interrupt macht sein Ding und kehrt sofort zum Main zurück.
Und dann kommt der andere Interrupt ran.


BerndB schrieb:
> Hier Auszüge aus meinem Code:

Schön für Dich.
Und wie arbeiten die zusammen?
Und wo sind die Interrupthandler?

Mit Schnipselchen kann keiner was anfangen.


Peter
(Firma: TravelRec.) Persönliche Seite #2423427
Lesenswert?

BerndB schrieb:
> habe soeben hier gelesen das ein AVR keine verschachtelten Interuppts
> kann.

Falsch. Wenn Du in einer Interrupt-Serviceroutine ein 'sei' ausführst, 
kann auch ein weiterer Interrupt ausgelöst werden. Braucht aber - 
normalerweise - kein Mensch. Vorausgesetzt, er hat sich vor dem 
Schreiben des Programms einige Gedanken zum Konzept gemacht.
Gast #2423436
Lesenswert?

Sorry Peter,
habe viele deiner Beiträge gelesen die mir oft sehr geholfen habe. Danke 
dafür!
Also in einer TIMER0 ISR kontrolliere ich über ADC permanent alle 4ms 
eine Spannung.
Durch drücken eines Tasters (verbunden mit INT0) soll ein Port meines 
ATtiny44A gesetzt werden.
Wenn ich das Ganze im AVR Studio debugge funktioniert das auch.
Leider nicht in Wirklichkeit.

Hier mein TIMER0_OVF:
TIMER0_OVF:
    IN temp, SREG
    PUSH temp

    INC R26
    TST R26
    BREQ TIMER0_OVF_REGULATION
    RJMP TIMER0_OVF_END

TIMER0_OVF_REGULATION:
    RCALL SET_CHANNEL_ADC1      //Kanal: 1

    LDI temp5, LOW(OUTPUT_700mA)  //Sollwert
    LDI temp6, HIGH(OUTPUT_700mA)

    LDS temp, (START_UP_VALUE)    //Status
    TST temp            //0: BRSH noch nicht erreicht  1: BRSH bereits 
errreicht
    BREQ STARTING_UP
    RJMP TIMER0_OVF_CONTROLL

STARTING_UP:
    RCALL GET_VOLTAGE
    RCALL DELAY_1_MSEC
    CP ADC_VAL_LOW, temp5
    CPC ADC_VAL_HIGH, temp6
    BRLO STARTING_UP_LOW_OUTPUT
    BRSH STARTING_UP_SAME_OR_HIGHER_OUTPUT

STARTING_UP_LOW_OUTPUT:
    IN temp, OCR0B
    INC temp
    OUT OCR0B, temp
    RJMP STARTING_UP

STARTING_UP_SAME_OR_HIGHER_OUTPUT:
    IN temp, OCR0B          //aktuellen Wert holen
    STS (START_UP_VALUE), temp
    RJMP TIMER0_OVF_END

TIMER0_OVF_CONTROLL:
    LDI temp5, LOW(OUTPUT_700mA +80)
    LDI temp6, HIGH(OUTPUT_700mA +80)

    RCALL SET_CHANNEL_ADC1
    RCALL GET_VOLTAGE
    CP ADC_VAL_LOW, temp5
    CPC ADC_VAL_HIGH, temp6
    BRSH OUTPUT_SAME_OR_TO_HIGH

    LDI temp5, LOW(OUTPUT_700mA +40)
    LDI temp6, HIGH(OUTPUT_700mA +40)
    CP ADC_VAL_LOW, temp5
    CPC ADC_VAL_HIGH, temp6
    BRLO OUTPUT_TO_LOW
    RJMP TIMER0_OVF_END
OUTPUT_TO_LOW:
    IN temp, OCR0B
    INC temp
    OUT OCR0B, temp
    RJMP TIMER0_OVF_END

OUTPUT_SAME_OR_TO_HIGH:
    IN temp, OCR0B
    DEC temp
    OUT OCR0B, temp
    RJMP TIMER0_OVF_END

TIMER0_OVF_END:
    POP temp
    OUT SREG, temp

    RETI

Hier mein INT0 ISR:
INT_INT0:
  IN temp, SREG
  PUSH temp
sbi porta, 5
  TST temp_var
  BREQ SWITCH_ON
  RJMP INT_INT0_END

SWITCH_ON:
  INC temp_var
  LDS temp, (SWITCH_ON_STATUS)
  INC temp
  STS (SWITCH_ON_STATUS), temp
  CPI temp, 1
  BREQ POWER_ON
  CPI temp, 2
  BREQ FLASHING_ONE
  CPI temp, 3
  BREQ FLASHING_TWO
  CPI temp, 4
  BREQ FINISH
  RJMP INT_INT0_END
POWER_ON:
  SBI PortA, 0          //N-FET Freigabe
//  RCALL START_PHASE_POWER
  RJMP INT_INT0_END
FLASHING_ONE:
  LDI temp, 1
  STS (FLASH_STATUS), temp
  RJMP INT_INT0_END
FLASHING_TWO:
  LDI temp, 2
  STS (FLASH_STATUS), temp
  RJMP INT_INT0_END
FINISH:
  CBI PortA, 0        //N-FET gesperrt
  CLR temp
  STS (SWITCH_ON_STATUS), temp
  STS (FLASH_STATUS), temp
  RJMP INT_INT0_END

INT_INT0_END:
  POP temp
  OUT SREG, temp
  RETI
#2423442
Lesenswert?

Graesslichst ... Kompletter Schrott. Klop das in die Tonne. Das macht 
man nicht so. Der Timer interrupt setzt ein Flag, das man im main 
abfragt. Und wenn das Flag dann kam, wandelt man. Auch der ADC 
Interrupt, so man das will, liest den ADC in eine speicherstelle und 
setzt ein Flag.
Gast #2423466
Lesenswert?

Knut Ballhause schrieb:

> Falsch. Wenn Du in einer Interrupt-Serviceroutine ein 'sei' ausführst,
> kann auch ein weiterer Interrupt ausgelöst werden. Braucht aber -
> normalerweise - kein Mensch. Vorausgesetzt, er hat sich vor dem
> Schreiben des Programms einige Gedanken zum Konzept gemacht.

Ich frage mich manchmal, wie viele Gedanken sich die Menschen vor dem 
Posten machen. Vor Allem, wenn es so pauschale und arrogante Aussagen 
sind. Interrupthandling mit Prioritaeten und mehreren Ebenen ist seit 
Jahrzehnten gaengige Technik und natuerlich gibt es dafuer zig sinnvolle 
Anwendungsfaelle. Natuerlich braucht man das nicht fuer kleine 
Feld-Wald-Wiesen Mikrocontroller-Anwendungen und man sollte schon eine 
gewisse Kompetenz haben, bevor man sich an sowas ranwagt. Genauso wie 
beim Posten von grossen Aussagen in Foren...
Gast #2423472
Lesenswert?

Vielen Dank!

Werde nun mein Programm so umschreiben das ich in der main-Funktion das 
TIFR0 abfrage und dann in eine entsprechende Funktion verzweige.
Ich gehe davon aus das meine ISR zu lang ist.

Gruß
Bernd
#2423474
Lesenswert?

BerndB schrieb:
> Durch drücken eines Tasters (verbunden mit INT0) soll ein Port meines
> ATtiny44A gesetzt werden.

Aha.
Tasten prellen.
Daher ist dafür ein externer Interrupt schlecht und unnütz zugleich.


BerndB schrieb:
> Also in einer TIMER0 ISR kontrolliere ich über ADC permanent alle 4ms
> eine Spannung.

4ms Intervall ist auch gut geeignet für eine Entprellroutine.
Mach also die Tastenentprellung und -abfrage hier mit.


Peter
(Firma: TravelRec.) Persönliche Seite #2423479
Lesenswert?

xXx schrieb:
> Ich frage mich manchmal, wie viele Gedanken sich die Menschen vor dem
> Posten machen. Vor Allem, wenn es so pauschale und arrogante Aussagen
> sind. Interrupthandling mit Prioritaeten und mehreren Ebenen ist seit
> Jahrzehnten gaengige Technik und natuerlich gibt es dafuer zig sinnvolle
> Anwendungsfaelle.

Hallo?! Wir reden hier von einem AVR. Leg´ Dich ruhig wieder hin.
#2423494
Lesenswert?

BerndB schrieb:
> Sorry,
> ich möchte trotzdem zu meiner Frage zurückkehren und fragen kann nun
> ein ATtiny44A verschachtelte Interrupts oder nicht?
>
> Gruß
> Bernd

Ja, das geht. Ist aber mit höchster Warscheinlichkeit nicht sinnvoll.

Knut Ballhause schrieb:
> Falsch. Wenn Du in einer Interrupt-Serviceroutine ein 'sei' ausführst,
> kann auch ein weiterer Interrupt ausgelöst werden. Braucht aber -
> normalerweise - kein Mensch. Vorausgesetzt, er hat sich vor dem
> Schreiben des Programms einige Gedanken zum Konzept gemacht.
#2423503
Lesenswert?

Und nochmal.

Ja, er kann.
Und nein, man benutzt es normalerweise nicht. Es besteht bei einem 
sauberen Programmaufbau auf einem AVR normalerweise keine NOtwendigkeit 
dafür.

Und nein, Tastenabfrage mittels Interrupt ist meistens eine ganz blöde 
Idee. Wenn eine Taste überhaupt einen Interrupt auslösen können soll, 
dann beschränkt sich das darauf, dass die Taste den AVR aus dem 
Tiefschlaf holen muss. Die eigentliche Abfrage macht man dann wieder 
über ganz normales Polling (weldches zb über Timer-Interrupts getrieben 
wird).
#2423510
Lesenswert?

Stefan schrieb:
> Mist!
> Gestern gingen bei meinem XMEGA noch priorisierte Interrupts.

Schön für deinen XMEGA.

Millionen von AVR-Programmierer (Tiny und Mega) kommen bei ihren 
Programmen ohne das Feature aus, dass ein Interrupt einen anderen 
unterbrechen muss. Und das ohne dass ihre Programme deswegen schlecht 
funktionieren oder schlecht zu lesen wären. Ganz im Gegenteil.
Gast #2423513
Lesenswert?

HI

>ich möchte trotzdem zu meiner Frage zurückkehren und fragen kann nun
>ein ATtiny44A verschachtelte Interrupts oder nicht?

Wie schon gesagt, ja. Aber um den ADC zu starten brauchst du keinen 
Interrupt. Dafür hat der ADC eine Autotriggerfunktion. Im AD Complete 
Interrupt setzt du ein Flag (ADC fertig) und liest ggf. die ADC-REgister 
aus.
Dazu reichen etwa 10 Befehle, also ein paar µs.

MfG Spess
#2423518
Lesenswert?

BerndB schrieb:
> ich möchte trotzdem zu meiner Frage zurückkehren und fragen kann nun
> ein ATtiny44A verschachtelte Interrupts oder nicht?

Nein, das kann er nicht.

Man kann sowas nur in Software nachbilden.
Das bedingt aber einen beträchlichen Aufwand im niederpriorisierten 
Interrupt (Sichern und Sperren all niederpriorisierten Freigaben), der 
einige CPU-Zyklen kostet, ehe der höherpriorisierte wieder bearbeitet 
werden kann.

Oftmals wird gedankenlos nur ein SEI im Interrupt empfohlen. Das macht 
aber noch lange keine Prioritäten, dafür aber schnell einen 
Stacküberlauf.


Peter
Gast #2423530
Lesenswert?

Sorry das ich hier nicht mit der dem Thema angemessenen entspechenden 
Ernsthaftigkeit geantwortet habe. Ich wollte nur darauf hinweisen das 
AVR's,und darum ging es, durchaus solche Features bieten.

>> Millionen von AVR-Programmierer (Tiny und Mega) kommen bei ihren
Programmen ohne das Feature aus

Und die kommen auch ohne dieses vollkommen unnütze Eventsystem und 
diesen schwachsinnigen DMA aus.
#2423553
Lesenswert?

Stefan schrieb:

>>> Millionen von AVR-Programmierer (Tiny und Mega) kommen bei ihren
> Programmen ohne das Feature aus
>
> Und die kommen auch ohne dieses vollkommen unnütze Eventsystem und
> diesen schwachsinnigen DMA aus.

Das wiederrum hab ich nicht gesagt oder behauptet.

Aber ist ein wenig kontraproduktiv, mit den Fähigkeiten eines XMEGA zu 
argumentieren, wenn die Community einem Neuling beibringen will, wie man 
auf einem Tiny (oder klassischem Mega, also nicht XMega) das 
Interrupt-System zu seinem Nutzen einsetzt, wenn er sich in einer 
falschen Vorstellung verlaufen hat oder einer Lösung nachläuft, die ihn 
nicht weiterbringt.
#2423603
Lesenswert?

BerndB schrieb:
> Ich danke euch allen!
> Nun werde ich mich auf nur einen Interrupt beschränken und meine anderen
> Anforderungen in dieser ISR einbinden!
>


Genau das ist der WEg, den du NICHT gehen sollst.

Die bewährte Programmstrategie sieht so aus:

Deine Aktionen kommen alle in die Hauptschleife.
Dazu gibt es zb ein Register, in dem ein Bit eine Aktion anstösst. Ist 
das Bit gesetzt, dann wird die Aktion gemacht, ist es nicht gesetzt, 
dann wird sie nicht gemacht.

ISR reagieren auf irgendwelche Ereignisse und stossen Aktionen an. Sie 
führen aber die Aktion nicht selber aus, sondern setzen nur das Bit im 
Register. Die eigentliche Aktion wird dann von der Hauptschleife aus 
gemacht.


Also in etwa so
1
    Vorgeplänkel wie Register einstellen, Hardware konfigurieren
2
    Interrupts einstellen, etc.
3

4
    sei
5

6
main_loop:
7

8
    wenn Job-Bit 1 gesetzt
9
        setze Job-Bit 1 zurück
10
        führe die zugehörige Aktion aus, zb den ADC starten
11

12
    wenn Job-Bit 2 gesetzt
13
        setze Job-Bit 2 zurück
14
        führe die zugehörige Aktion aus, zb den ADC auslesen
15
        und verarbeiten
16

17
    wenn Job-Bit 3 gesetzt
18
        setze Job-Bit 3 zurück
19
        führe zugehörige Aktion aus, zb Timer einschalten
20

21
    etc.
22
    etc.
23

24
    jmp main_loop

die ISR wiederrum, setzen nur das Job bit. Zb der Interrupt mit dem der 
ADC seine Fertigsein verkündet
1
ISR ( ADC_COMPLETE )
2
    ev. den ADC Wert abholen
3
    setzte Job-Bit 2
4
    reti

oder der Timer Overflow, der einen ADC-AUslesevorgang anstösst
1
ISR ( TIMER_OVERFLOW )
2
    setze Job-Bit 1
3
    (da das starten des ADC nicht lange dauert, könnte man
4
    den ADC auch direkt hier starten)
5
    reti

Aber auch wenn der Timer-Overflow den ADC startet, er wartet nicht 
darauf, dass dieser fertig wird. Ein ADC der fertig wird, ist selber 
wieder ein Ereignis, welches einen Interrupt feuern kann, welcher dann 
(durch das Job-Flag) die Auswertung des Ergebnisses veranlasst - in der 
main-loop

auf die Art laufen die Dinge geordnet und ganz wichtig: keine ISR 
braucht lange!
So ein Aufbau ist der Schlüssel zu einem Programm, bei dem der µC 
scheinbar mehrere Dinge gleichzeitig machen kann. Daher ist es gut, wenn 
du dir frühzeitig eine derartige Struktur angewöhnst.

Wieviel man dann tatsächlich in der ISR machen lässt und wieviel in die 
main_loop kommt, variiert. Eine ISR muss nicht zwanghaft nur aus dem 
Setzen des Job-Bits bestehen. Man kann dort durchaus schon auch Aktionen 
machen. Grundprinzip ist aber immer: Das darf alles nicht lange dauern. 
Übermässig viel auszuführender Code, oder gar Warteschleifen, sind 
allerdings verboten! Tu was du in der ISR tun musst, aber nicht mehr. 
Das mehr gehört in die Hauptschleife.
#2423633
Lesenswert?

BerndB schrieb:
> Ralf,
> meinst du ein Flag setzen und dann von der "main-Routine" aus agieren?

Genau. So, wie es Karl Heinz ausführlich erläutert hat.

Wenn du dir allerdings sicher sein kannst, dass du alles 'selbst steuern 
kannst', dann brauchst du nicht mal das Flag:
1
; Initialisierungen
2
; ...
3
; z.B. Timer auf 1ms (!) mit Interrupt
4
; Register für 'Status' reservieren
5
 ldi reg_s, 1
6

7
loop:
8
 sleep
9

10
 sbrc reg_s, 0
11
 rcall prog1
12
 sbrc reg_s, 1
13
 rcall prog2
14
 sbrc reg_s, 2
15
 rcall prog3
16
 sbrc reg_s, 3
17
 rcall prog4
18

19
 lsl reg_s
20
 brhc reg_s
21
 ldi reg_s, 1
22

23
 rjmp loop
Ich hoffe, das darf man so machen ;-) Ich find's so übersichtlich. Da 
hast du außer ADC und Taste noch zwei Unterprogramme 'in Reserve'. 
Wenn's mehr sein muss, läuft reg_s eben bis acht Bit.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren