statische variable in ISR nicht wirklich statisch.

Gast #1218611
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...
Gast #1218832
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
}
Gast #1218835
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);
#1218846
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.
Gast #1218930
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?
Gast #1218937
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.
Gast #1218940
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.
#1218941
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...
Gast #1218943
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...!
Gast #1218947
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.
#1219042
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.
#1219043
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...
#1219046
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.
Gast #1219146
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.
Gast #1219199
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.

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