Forum: Mikrocontroller und Digitale Elektronik MSP430, Programm stoppt nach Interrupt Enable


von Max G. (l0wside) Benutzerseite


Lesenswert?

Hallo zusammen,

folgender Code auf dem MSP430F5310 führt zu seltsamen Ergebnissen. Die 
ISR des Timers A0 wird bedient, aber der Code in main() nach Interrupt 
Enable wird nach dem ersten Aufruf der ISR nicht mehr ausgeführt.
1
#include "msp430.h"
2
3
volatile int x = 0, z=0, y=0;
4
5
int main(void) {
6
  WDTCTL = WDTPW + WDTHOLD;
7
  
8
  TA0CCR0 = 100;
9
  TA0CCTL0 = CCIE | OUTMOD_2;
10
  TA0CTL = TASSEL_1 + ID_0 + MC_1 + TAIE;
11
  _BIS_SR(GIE);
12
  
13
  while(1) {
14
    x=y;
15
    z++;
16
  }
17
}
18
19
#pragma vector=TIMER0_A0_VECTOR
20
__interrupt void A1(void) {
21
  y++;
22
}  
23
24
#pragma vector=TIMER0_A1_VECTOR
25
__interrupt void A2(void) {
26
}

Wenn ich nach einer Weile anhalte, bekomme ich im Debugger folgende 
Werte:
y = 1066 (zählt im Laufe der Zeit auch noch weiter hoch)
z = 272 (was auch immer dieser Wert sagen soll - er erhöht sich bei 
längerem Laufen nicht weiter)
x = 1 (also der Stand von y, als die while(1)-Schleife zum letzten Mal 
bedient wurde - sprich nach dem esten Aufruf der ISR ist Schluss für die 
while(1)-Schleife).

100 Zyklen sollten für die ISR locker reichen, ein größerer Wert für 
TA0CCR0 macht auch keinen Unterschied. Es ist also noch genug Zeit für 
die while(1)-Schleife da. Low Power Mode ist auch nicht aktiviert, der 
Watchdog ist es auch nicht.
Wenn ich die Zeile mit BIS_SR auskommentiere, zählt die 
while(1)-Schleife anstandslos hoch, nur die ISR wird nicht mehr bedient. 
TAIE auskommentieren hat den gleichen Effekt.
Was mache ich falsch?

Gruß,

Max

von Max G. (l0wside) Benutzerseite


Lesenswert?

Habe noch ein bisschen recherchiert: ggf. muss man die LPM-Bits am Ende 
der ISR noch mal neu setzen...aber ich dachte, da kümmert sich der 
Compiler selber drum?

Max

von Christian R. (supachris)


Lesenswert?

Muss man nicht. Nach der ISR ist der gleiche PowerMode wie vorher, wenn 
man das innerhalb der ISR nicht explizit ändert. Und du hast ja gar 
keinen Low Power Mode aktiv, der läuft immer im Active Mode.

von Uhu U. (uhu)


Lesenswert?

Max G. schrieb:
> aber ich dachte, da kümmert sich der Compiler selber drum?

Nicht der Compiler, sondern der reti-Befehl.

von Christian R. (supachris)


Lesenswert?

Ich vermute, der nächste Interrupt für den Timer kommt schon in der ISR, 
somit kommt der Prozessor nicht mehr zum Abarbeiten der While(1) 
Schleife und springt nach Ende der ISR wieder sofort rein.

von Stefan (Gast)


Lesenswert?

Beim TIMER0_A0 Interrupt wird das Interrupt Flag automatisch gelöscht.
Beim TIMER0_A1 Interrupt geschieht dies nicht. Hier wird das Flag erst 
beim Zugriff auf das Timer Interrupt Vector Register zurückgesetzt. Wenn 
klar ist, dass nur ein Timer Overflow zum TIMER0_A1 Interrupt geführt 
haben kann, kann man natürlich auch das TAIFG Flag direkt zurücksetzen.

von Max G. (l0wside) Benutzerseite


Lesenswert?

Stefan schrieb:
> Beim TIMER0_A0 Interrupt wird das Interrupt Flag automatisch gelöscht.
> Beim TIMER0_A1 Interrupt geschieht dies nicht. Hier wird das Flag erst
> beim Zugriff auf das Timer Interrupt Vector Register zurückgesetzt. Wenn
> klar ist, dass nur ein Timer Overflow zum TIMER0_A1 Interrupt geführt
> haben kann, kann man natürlich auch das TAIFG Flag direkt zurücksetzen.

Stefan, danke Dir. Ich denke, das war der Punkt, leider kann ich es erst 
nächste Woche ausprobieren.

Max

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.