www.mikrocontroller.net

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


Autor: Bill (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
UDR0 = 0x00;

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

also das ist mir zu hoch :)

bin für jeden hinweis dankbar!


(...)
volatile uint8_t v_test = 0;

ISR(USART0_UDRE_vect) {

  static uint8_t s_test = 0;
  
  v_test++;
  s_test++;

  UDR0 = 0x00;
}


---------

AVR Memory Usage
----------------
Device: atmega644

Program:    6832 bytes (10.4% Full)
(.text + .data + .bootloader)

Data:        864 bytes (21.1% Full)
(.data + .bss + .noinit)

Build succeeded with 0 Warnings...


Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Bill (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

#include <string.h>
#include <avr/io.h>
#include <avr/interrupt.h>

#include "rs232.h"


volatile int vorher0 = 255;
volatile int vorher1 = 255;
volatile uint8_t v_test = 0;
volatile int nachher = 255;
 
uint8_t put_frame() {

  // enable UDRE Interrupt 
  UCSR0B |= (1 << UDRIE0);

  return 0;

}


//----------------------------------------------------------------------------- 
// UART TX data register empty interrupt 
ISR(USART0_UDRE_vect) {

  static uint8_t s_test = 0;
  
  v_test++;
  s_test++;

  vorher1 = 100;

  UDR0 = 0x00;
   
}


Autor: Bill (Gast)
Datum:

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


ist da evtl was falsch gesetzt?
UBRR0H=(uint8_t)((F_CPU / (16 * BAUD_RATE)) - 1)>>8;
UBRR0L=(uint8_t)((F_CPU / (16 * BAUD_RATE)) - 1);
UCSR0B = (1<<RXCIE0) | (1<<RXEN0) | (1<<TXEN0);

OCR0A  = ((F_CPU / BSP_TICKS_PER_SEC / 1024) - 1);

//switch (HMI) timer
TCCR2B = (1<<CS22);            // divide by 64
TIMSK2 = 1<<TOIE2;            // enable timer interrupt


//framework tick timer
//set Timer0 in CTC mode, 1/1024 prescaler, start the timer ticking */
TCCR0A = ((1 << WGM01) | (0 << WGM00));
TCCR0B = (5 << CS00);

TIMSK0 = (1 << OCIE0A);             

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Bill (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: STK500-Besitzer (Gast)
Datum:

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

Das Datenbl

Autor: Bill (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
att

Autor: Bill (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Bill (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>att

w0t?

Autor: Bill (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...!

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Lernender (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.
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.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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
ISR(__vector_default)
{}
oder auch
ISR(BADISR_vect)
{}
aufsetzt...

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Lernender (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Bill (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.