Forum: Mikrocontroller und Digitale Elektronik statische variable in ISR nicht wirklich statisch.


von Bill (Gast)


Lesenswert?

hi,

ich hab hier nen ganz kuriosen fehler.

die beiden zähler laufen bis 4, beim nächsten interrupt sind sie wieder 
auf 0.
dann laufen sie immer bis 2 bevor sie wieder auf 0 gesetzt werden.
irgendwas in meinem programm schreibt auf ihre speicheradressen, aber 
was - und warum?
wie kann ich das rausfinden wer da aus der reihe tanzt?
ich kann den AVR-debugger ja nicht anhalten wenn eine variable geändert 
wird, oder?

übrigens: wenn ich die zeile
1
UDR0 = 0x00;

auskommentiere passiert das nicht. dann laufen die ganz normal hoch.

also das ist mir zu hoch :)

bin für jeden hinweis dankbar!
1
(...)
2
volatile uint8_t v_test = 0;
3
4
ISR(USART0_UDRE_vect) {
5
6
  static uint8_t s_test = 0;
7
  
8
  v_test++;
9
  s_test++;
10
11
  UDR0 = 0x00;
12
}
13
14
15
---------
16
17
AVR Memory Usage
18
----------------
19
Device: atmega644
20
21
Program:    6832 bytes (10.4% Full)
22
(.text + .data + .bootloader)
23
24
Data:        864 bytes (21.1% Full)
25
(.data + .bss + .noinit)
26
27
Build succeeded with 0 Warnings...

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Aus dem Codefragment kann man leider nichts entnehmen, dort liegt der 
Fehler nicht, denn sonst hättest du den schon gefunden  :-/

> wie kann ich das rausfinden wer da aus der reihe tanzt?
Indem du anschaust, was z.B. vor der Variable v_test deklariert 
wird. Ist da ein char-Array? Läuft der Index über das Arayende hinaus?

von Bill (Gast)


Lesenswert?

ich kann nicht den kompletten code posten, viel zu viel.

ich habe jetzt mal eine variable "vorher" vor v_test gesetzt.
im .map file liegt die aber ganz woanders als v_test ...

aber ich glaube eh nicht das da was aus den grenzen läuft.
es scheint eher so zu sein, dass alle variablen in diesem file neu 
initialisiert werden.
(vorher1 wird wieder 255 gesetzt, v_test, s_test auf 0)

was könnte der grund dafür sein?

1
#include <string.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
5
#include "rs232.h"
6
7
8
volatile int vorher0 = 255;
9
volatile int vorher1 = 255;
10
volatile uint8_t v_test = 0;
11
volatile int nachher = 255;
12
 
13
uint8_t put_frame() {
14
15
  // enable UDRE Interrupt 
16
  UCSR0B |= (1 << UDRIE0);
17
18
  return 0;
19
20
}
21
22
23
//----------------------------------------------------------------------------- 
24
// UART TX data register empty interrupt 
25
ISR(USART0_UDRE_vect) {
26
27
  static uint8_t s_test = 0;
28
  
29
  v_test++;
30
  s_test++;
31
32
  vorher1 = 100;
33
34
  UDR0 = 0x00;
35
   
36
}

von Bill (Gast)


Lesenswert?

insbesondere ist ja auch seltsam, dass das nicht passiert wenn ich die 
zeile UDR0=... auskommentiere...


ist da evtl was falsch gesetzt?
1
UBRR0H=(uint8_t)((F_CPU / (16 * BAUD_RATE)) - 1)>>8;
2
UBRR0L=(uint8_t)((F_CPU / (16 * BAUD_RATE)) - 1);
3
UCSR0B = (1<<RXCIE0) | (1<<RXEN0) | (1<<TXEN0);
4
5
OCR0A  = ((F_CPU / BSP_TICKS_PER_SEC / 1024) - 1);
6
7
//switch (HMI) timer
8
TCCR2B = (1<<CS22);            // divide by 64
9
TIMSK2 = 1<<TOIE2;            // enable timer interrupt
10
11
12
//framework tick timer
13
//set Timer0 in CTC mode, 1/1024 prescaler, start the timer ticking */
14
TCCR0A = ((1 << WGM01) | (0 << WGM00));
15
TCCR0B = (5 << CS00);
16
17
TIMSK0 = (1 << OCIE0A);

von (prx) A. K. (prx)


Lesenswert?

Bill wrote:

> aber ich glaube eh nicht das da was aus den grenzen läuft.
> es scheint eher so zu sein, dass alle variablen in diesem file neu
> initialisiert werden.

Das klingt nach Neustart oder Sprung nach 0.

von Johannes M. (johnny-m)


Lesenswert?

Bill wrote:
> TIMSK0 = (1 << OCIE0A);
Wo ist der Interrupt Handler dazu?

Und noch was: Du gibst den RXC-Interrupt frei, der Handler oben ist aber 
für den UDRE-Interrupt, der (zumindest im geposteten Code) nicht 
freigegeben ist. Da passt wohl einiges nicht...

von (prx) A. K. (prx)


Lesenswert?

Bill wrote:

> insbesondere ist ja auch seltsam, dass das nicht passiert wenn ich die
> zeile UDR0=... auskommentiere...

Und das wiederum deutet drauf hin, dass nur mit dieser Zeile ein 
Interrupt ausgelöst wird, ohne nicht. Und ein fehlender oder falsch 
implementierter Handler zum Neustart führt.

von Bill (Gast)


Lesenswert?

danke sehr! :)

es war die fehlende ISR für timer2.

wusste nicht, das sich das derart rächt. was passiert da wenn der INT 
ausgelöst wird und nicht gehandled wird. scheint ja nicht so gesund zu 
sein.


danke euch!
ich werde jetzt wohl mal ein bisschen was lesen zu interrupt handling 
und so.
empfehlungen?

von STK500-Besitzer (Gast)


Lesenswert?

>ich werde jetzt wohl mal ein bisschen was lesen zu interrupt handling
>und so.
>empfehlungen?

Das Datenbl

von Bill (Gast)


Lesenswert?

>> insbesondere ist ja auch seltsam, dass das nicht passiert wenn ich die
>> zeile UDR0=... auskommentiere...

>Und das wiederum deutet drauf hin, dass nur mit dieser Zeile ein
>Interrupt ausgelöst wird, ohne nicht. Und ein fehlender oder falsch
>implementierter Handler zum Neustart führt.


ja, das sollte man doch vermuten.
aber es hat auch irgendwas mit dem timer2 zu tun...

myteriös (jedenfalls für einen newbe wie mich)
...aber spassig.

von STK500-Besitzer (Gast)


Lesenswert?

att

von Bill (Gast)


Lesenswert?

>>ich werde jetzt wohl mal ein bisschen was lesen zu interrupt handling
>>und so.
>>empfehlungen?

>Das Datenbl


booo wirklich :(  gääähn

ich muss aber zu meiner verteidigung sagen, dass ich da schon einiges 
gelesen hab. eigentlich ganz gut, aber nicht sonderlich fesselnd... aber 
du hast wohl recht.

von Johannes M. (johnny-m)


Lesenswert?

Bill wrote:
> danke sehr! :)
>
> es war die fehlende ISR für timer2.
Und was ist mit dem UDRE-Interrupt?

> wusste nicht, das sich das derart rächt. was passiert da wenn der INT
> ausgelöst wird und nicht gehandled wird.
Wenn das ne Frage sein soll: Dann gibt's einen "Warmstart", sofern 
nichts anderes eingestellt ist.

> ich werde jetzt wohl mal ein bisschen was lesen zu interrupt handling
> und so.
> empfehlungen?
Datenblätter, AVR-GCC-Tutorial...

von Bill (Gast)


Lesenswert?

>att

w0t?

von Bill (Gast)


Lesenswert?

>> wusste nicht, das sich das derart rächt. was passiert da wenn der INT
>> ausgelöst wird und nicht gehandled wird.
>Wenn das ne Frage sein soll: Dann gibt's einen "Warmstart", sofern
>nichts anderes eingestellt ist.

ja, aber warum gibts den warmstart nur, wenn ich in dem UDR-handler 
UDR-setze? der warmstart kommt doch von dem nicht gehandleden 
timer2-overflow...!

von STK500-Besitzer (Gast)


Lesenswert?

>ja, aber warum gibts den warmstart nur, wenn ich in dem UDR-handler
>UDR-setze? der warmstart kommt doch von dem nicht gehandleden
>timer2-overflow...!

Die Timer2-Interrupt-Einsprungadresse liegt vor der des UDRE-Interrupts 
in der  Vektor-Tabelle. Vermutlich springt der Prozessor dorthin, findet 
aber keine Adresse und geht dann den Adressraum weiter hoch, bis er zum 
ersten sinnvollen Programmpunkt kommt, der dann die UDRE-ISR-Adresse 
ist.

von Lernender (Gast)


Lesenswert?

aus Interesse habe ich mal eine Frage:
Läßt sich der Compiler oder besser Linker dazu bewegen, an die 
Einsprungadressen ohne ISR ein RETI zu setzen?

von Stefan E. (sternst)


Lesenswert?

Lernender wrote:

> Läßt sich der Compiler oder besser Linker dazu bewegen, an die
> Einsprungadressen ohne ISR ein RETI zu setzen?

Definiere einfach einen leeren BADISR-Interrupt, das hat den gleichen 
Effekt.
1
ISR(BADISR_vect) {}

Nur so nebenbei:
Was STK500-Besitzer da geschrieben hat, ist Quatsch. Die AVR-Libc belegt 
jeden Interruptvektor mit einem Sprung. Die unbenutzten gehen halt zum 
BADISR-Interrupt, und die Default-Implementierung der AVR-Libc dieses 
Interrupts enthält dann den Sprung an die Adresse 0.

von Johannes M. (johnny-m)


Lesenswert?

Lernender wrote:
> aus Interesse habe ich mal eine Frage:
> Läßt sich der Compiler oder besser Linker dazu bewegen, an die
> Einsprungadressen ohne ISR ein RETI zu setzen?
Beim GCC indirekt ja, indem man einen Handler mit
1
ISR(__vector_default)
2
{}
oder auch
1
ISR(BADISR_vect)
2
{}
aufsetzt...

von Johannes M. (johnny-m)


Lesenswert?

Stefan Ernst wrote:
> Nur so nebenbei:
> Was STK500-Besitzer da geschrieben hat, ist Quatsch. Die AVR-Libc belegt
> jeden Interruptvektor mit einem Sprung. Die unbenutzten gehen halt zum
> BADISR-Interrupt, und die Default-Implementierung der AVR-Libc dieses
> Interrupts enthält dann den Sprung an die Adresse 0.
Richtig. Ich vermute mal, dass in dem nicht gezeigten Teil des Programms 
noch eine Reihe weiterer Klöpse stecken, von denen mindestens einer zu 
dem beschriebenen Effekt führt.

von Lernender (Gast)


Lesenswert?

Danke für die Antworten.
Dann gehört die BADISR eigentlich in jedes Projekt und sollte eine 
definierte Fehlerausgabe erzeugen. Während der Entwicklung kann man dort 
auch einen Breakpoint setzen, der ja nicht erreicht werden sollte.

von Simon K. (simon) Benutzerseite


Lesenswert?

Lernender wrote:
> Danke für die Antworten.
> Dann gehört die BADISR eigentlich in jedes Projekt und sollte eine
> definierte Fehlerausgabe erzeugen. Während der Entwicklung kann man dort
> auch einen Breakpoint setzen, der ja nicht erreicht werden sollte.

Ist auf jeden Fall klug.

von Bill (Gast)


Lesenswert?

>Richtig. Ich vermute mal, dass in dem nicht gezeigten Teil des Programms
>noch eine Reihe weiterer Klöpse stecken, von denen mindestens einer zu
>dem beschriebenen Effekt führt.


hehe... immer drauf auf die kleinen newbes.
eigentlich läuft jetzt aber alles ganz super, nachdem ich den timer2 
rausgenommen habe.
(das hatte ich halt versehentlich mit reinkopiert aus einem anderen 
projekt)

ich kann den code aber gerne der wissenschaft zur verfügung stellen, 
würde mich ja auch mal interessieren was da genau passiert.
also wenn ihr wollt, schrumpfe ich den code soweit zusammen, dass er 
lesbar wird und den beschriebenen effekt zeigt.

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.