Forum: Mikrocontroller und Digitale Elektronik Atmel AVR Sleep Pin Change Interrupt - Verständnisfrage


von Borsty B. (mantabernd)


Lesenswert?

Guten Abend,

ich habe hier einen Code der zwar wunderbar funktioniert, ich aber gerne 
wüsste warum.

Geht um den Power Down Sleep Mode eines Atmel Attiny44 µC, der bei einem 
Pinchange an einem der beiden Pins aufwachen soll.

Folgende ISR Routine wird beim Pinchange aufgerufen:
1
ISR (PCINT1_vect) {
2
3
 arbeiten = true;
4
5
}

Folgende Funktionen konfigurieren den Sleep Mode und schicken den µC ins 
Bett:
1
void setup_sleep() {
2
  
3
  cli();
4
  GIMSK |= (1<<PCIE1); 
5
  PCMSK1 |= ((1<<PCINT8)|(1<<PCINT9));
6
  sei();
7
}
8
9
void goto_sleep() {
10
  
11
  ADCSRA &= ~_BV(ADEN); //ADC ausschalten
12
  
13
  MCUCR |= (1 << SM1) & ~(1 << SM0); //Sleep Modus = Power Down
14
  MCUCR |= _BV(SE); //Sleep Enable setzen
15
  sleep_cpu(); // Schlafe
16
  MCUCR &= ~(1<<SE); // Sleep Disable Bit setzen
17
}

Wie gesagt, das funktioniert auch super wenn ich goto_sleep(); aufrufe.

Nun meine Frage: Woher weiß der µC welche ISR er beim Pinchange aufrufen 
soll? Warum weiß er dass PCINT1_vect hierfür zuständig ist?

Vielen Dank :)

von Steve van de Grens (roehrmond)


Lesenswert?

Borsty B. schrieb:
> Woher weiß der µC welche ISR er beim Pinchange aufrufen soll? Warum weiß
> er dass PCINT1_vect hierfür zuständig ist?

Schau dir im Datenblatt die Beschreibung der Register GIMSK und PCMSK1 
an.

Auch das Einleitende Kapitel zu "Interrupts"  sind hilfreich.

Du hast nicht angegeben, um welchen Mikrocontroller es geht.

: Bearbeitet durch User
von Mario P. (mario_71950c)


Lesenswert?

der TO schrieb:
... Atmel Attiny44 µC ...

von Steve van de Grens (roehrmond)


Lesenswert?

Mario P. schrieb:
> der TO schrieb:
> ... Atmel Attiny44 µC ...

Oh, das ist mir jetzt aber unangenehm.

von Steve van de Grens (roehrmond)


Lesenswert?

Im Datenblatt Kapitel 10, 10.1, 11, 11.2.2, 11.2.4

von Klaus H. (hildek)


Lesenswert?

Steve van de Grens schrieb:
> Im Datenblatt Kapitel 10, 10.1, 11, 11.2.2, 11.2.4

Hängt vom Alter des Datenblatts ab, bei meinen gespeicherten sind es 
andere Kapitel. 😀 (Die Kapitel sind bei der Automotiv-Variante andere).

@Borsty B.
Suche nach "Sleep Modes" und nach den Registernamen GIMSK (General 
Interrupt Mask Register) und evtl. PCMSK1.
Die Sleep Modes nennen die möglichen Interruptquellen fürs Aufwachen aus 
den verschiedenen Sleep-Zuständen.
In GIMSK wird definiert, welchen Interrupt du verwenden willst (bei dir 
ist es PCINT1 weil PCIE1 gesetzt wird) und dementsprechend gibt es in 
deinem Programm auch die ISR (PCINT1_vect) und die muss es auch geben.
PCMSK ist eine Maske, die diejenigen Pins definiert, bei denen der 
Interrupt ausgelöst werden darf/soll. In deinem Programm sind es die 
Pins PCINT8 (PB0) und PCINT9 (PB1).

Du hast das Programm wohl nicht selber geschrieben, sonst müsste das ja 
alles klar sein?

: Bearbeitet durch User
von Oliver S. (oliverso)


Lesenswert?

Borsty B. schrieb:
> Nun meine Frage: Woher weiß der µC welche ISR er beim Pinchange aufrufen
> soll?

Woher weiß der, was der bei irgend einem Assemblerbefehl ausführen soll? 
Weil dem das halt ins Innerste eingebrannt wurde.

> Warum weiß er dass PCINT1_vect hierfür zuständig ist?

Das wiederum weiß der µC überhaupt nicht, das steht im Programmcode, den 
der Compiler erzeugt.

Oliver

von Veit D. (devil-elec)


Lesenswert?

Borsty B. schrieb:

> Nun meine Frage: Woher weiß der µC welche ISR er beim Pinchange aufrufen
> soll? Warum weiß er dass PCINT1_vect hierfür zuständig ist?

Weil diese Registereinstellungen
1
GIMSK |= (1<<PCIE1);
2
PCMSK1 |= ((1<<PCINT8)|(1<<PCINT9));
dem Controller in Hardware sagen das er hierbei immer auf dieses 
Ereignis schauen und reagieren soll. Auch die ISR ist damit mittels 
Vector Adresse hinterlegt. Und weil letzteres so ist, läuft der 
Controller undefiniert Amok wenn jemand einen Interrupt per Register 
konfiguriert aber die dazugehörige ISR vergisst zu schreiben. Kannste 
dir mal im Hinterkopf abspeichern. Biste nicht der Erste und wirst nicht 
der Letzte bleiben. Lies mal das Interrupt Kapitel im Manual. Ist sehr 
hilfreich.

: Bearbeitet durch User
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Veit D. schrieb:
> Und weil letzteres so ist, läuft der
> Controller undefiniert Amok wenn jemand einen Interrupt per Register
> konfiguriert aber die dazugehörige ISR vergisst zu schreiben.

Nöö...
Bei AVRs (zumindest in C und C++ (Gcc)) wird die Vektortabelle mit 
__bad_interrupt geflutet

Ausschnitt:
1
00000000 <__vectors>:
2
       0:  0c 94 5f 00   jmp  0xbe  ; 0xbe <__dtors_end>
3
       4:  0c 94 87 00   jmp  0x10e  ; 0x10e <__bad_interrupt>
4
       8:  0c 94 87 00   jmp  0x10e  ; 0x10e <__bad_interrupt>
5
       c:  0c 94 87 00   jmp  0x10e  ; 0x10e <__bad_interrupt>
6
      10:  0c 94 87 00   jmp  0x10e  ; 0x10e <__bad_interrupt>
7
      14:  0c 94 87 00   jmp  0x10e  ; 0x10e <__bad_interrupt>
8
      18:  0c 94 87 00   jmp  0x10e  ; 0x10e <__bad_interrupt>
9
      1c:  0c 94 87 00   jmp  0x10e  ; 0x10e <__bad_interrupt>
10
      20:  0c 94 87 00   jmp  0x10e  ; 0x10e <__bad_interrupt>
11
      24:  0c 94 87 00   jmp  0x10e  ; 0x10e <__bad_interrupt>
12
      28:  0c 94 87 00   jmp  0x10e  ; 0x10e <__bad_interrupt>
13
      2c:  0c 94 87 00   jmp  0x10e  ; 0x10e <__bad_interrupt>
14
      30:  0c 94 87 00   jmp  0x10e  ; 0x10e <__bad_interrupt>
15
      34:  0c 94 87 00   jmp  0x10e  ; 0x10e <__bad_interrupt>
16
      38:  0c 94 87 00   jmp  0x10e  ; 0x10e <__bad_interrupt>
17
      3c:  0c 94 87 00   jmp  0x10e  ; 0x10e <__bad_interrupt>
18
      40:  0c 94 96 05   jmp  0xb2c  ; 0xb2c <__vector_16>
1
0000010e <__bad_interrupt>:
2
     10e:  0c 94 00 00   jmp  0  ; 0x0 <__vectors>


Von Amok kann also keine Rede sein!
Es tut vielleicht nicht das was man sich erwartet hat, ist aber doch gut 
definiert/reproduzierbar.

: Bearbeitet durch User
von Borsty B. (mantabernd)


Lesenswert?

Danke! Die Infos haben mir sehr weitergeholfen :)

von Klaus H. (hildek)


Lesenswert?

Arduino F. schrieb:
> Von Amok kann also keine Rede sein!

Ja, wollte ich auch schon erwähnen. Sieht eher aus wie ein Soft-Reset. 
Aber das wiederholt sich dann, denn die fehlende ISR ist ja dann noch 
immer nicht da 😀.

von Εrnst B. (ernst)


Lesenswert?

Klaus H. schrieb:
> Ja, wollte ich auch schon erwähnen. Sieht eher aus wie ein Soft-Reset.
> Aber das wiederholt sich dann, denn die fehlende ISR ist ja dann noch
> immer nicht da 😀.

Lässt sich per
1
ISR(BADISR_vect) { ...
auch anders belegen, wenn man da ein anderes Verhalten möchte... z.B. 
was zum Debuggen, einfach ignorieren, oder Endlosschleife die den 
Watchdog auslösen lässt...

von Klaus H. (hildek)


Lesenswert?

Danke @Ersnt B.!
Das wusste ich bisher nicht, kann mal hilfreich sein.

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.