SIGNAL + static Var initialisieren

Gast #77978
Hi, zusammen,

habe ein kleines Problem.
In einer Signal-Routine brauche ich einen Zähler, der statisch ist und
vorinitialisiert sein soll:

static uint16_t counter = 1;

Dummerweise ist der bei Programmstart aber eben nicht 1, sondern
aktuell 37900, warum auch immer.
Im aktuellen Programm ist das nicht so schlimmm, ein zeitgesteuerter
Programmteil arbeitet nicht direkt nach dem Einschalten, sondern erst
ca. 8 Sekunden später, aber blöd ist das schon und in anderen Projekten
undenkbar.

Wo liegt da der Fehler und was muss ich anders machen?
Danke!
Gast #77980
Hallo, Patrick,

die Variable wird erst in der ISR deklariert. Habe es auch mit anderen
ausprobiert, da ist es dasselbe.
Kann es sein, dass statische Variablen in ISRs anders behandelt
werden?

Zur Not kann ich auch eine Init-Routine für jede ISR schreiben und die
Variable dann global definieren. Wäre aber nicht so schön.

Grüsse,
Dieter
Gast #77981
Variablen, die erst in einer Funktion deklariert werden, sind ja nicht
global zugreifbar. Sie existieren zwar, dürfen aber NUR von der
Funktion verwendet werden, die sie angelegt hat.
Ich weis jetzt nicht genau, wo Du versuchst, auf diese Variable
zuzugreifen, aber es hört sich danach an, als wolltest Du in einem
anderen Kontext als der ISR darauf zugreifen!

Wenn Du eine globale Variable brauchst, dann muss sie auch global
deklariert werden. static sagt nur aus, daß die Variable beim verlassen
der Funktion - samt Inhalt - erhalten bleibt.

Gruß,
Patrick...
Gast #77982
P.S.: auch Globale Variablen lassen sich "vorinitialisieren",
allerdings macht

static int i = 0;

keinen Sinn, da sie eh mit 0 initialisiert wird.

static int i = 16;

macht dagegen schon schon Sinn, wenn man halt i mit einem Startwert von
16 verwenden möchte.
Gast #77983
Habe mich wohl falsch ausgedrückt.
Ich meinte Folgendes:

SIGNAL(xxx) {
  static uint16_t counter = 1;

  xxx;
}

Dabei wird die Variable counter aber NICHT initialisiert.
Bei einer "normalen" Funktion wird die Variable beim ersten Aufruf
mit dem Wert - hier die 1 - initialisiert.

In der ISR bei mir haben die Variable nur irgendwelche wilden Werte,
habe das mit mehreren ausprobiert.
Gast #77984
Selbstverständlich werden diese Variablen wie alle anderen statischen
Variablen initialisiert.

Womit hast Du denn festgestellt, daß sie nicht initialisiert würde?

Hast Du einen Sourcecode, mit dem man das reproduzieren könnte?

Ich sollte mal wieder an Eric Raymonds Artikel erinnern:

http://www.catb.org/~esr/faqs/smart-questions.html

bzw. dessen deutsche Übersetzung:

http://www.lugbz.org/documents/smart-questions_de.html

Besonders hier der Abschnitt ``Don't claim you have found a bug.''
Gast #77985
Hallo,

ich habe in der ISR-Routine die Variable in eine Temp-Variable kopiert
und mir auf einem LCD-Display anzeigen lassen.
Code werde ich heute abend posten.
Und dass der Fehler nicht bei mir liegt, würde ich auch nie
behaupten...
Habe das jetzt nur zwei Tage lang probiert und bin jetzt wohl
problemblind :(
Gast #77987
So, habe mal ein Code-Fragment angehängt:

//********************************************
#include <inttypes.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include "timer0.h"
#include "helper.h"
#include "globals.h"
#include "keyboard.h"
#include "lcd4bit.h"


void init_timer0( void ) {
  TCNT0 = 0x00;
  OCR0 = 0xFA;
  TCCR0 |= ( 1<<WGM21 ) | ( 1<<CS01 );    // OutputCompare With
Prescaler 8 => 250µs @ 8MHz
}


//
// Timer Interrupt 0
//
SIGNAL(SIG_OUTPUT_COMPARE0) {      // Output Compare0 Interrupt
  static uint8_t key_pending;
  static uint16_t counter = 1, key_counter, test, tt = 422;
  uint8_t i, key_temp;

if( tt != 345 ) {
  test = counter;
  tt = 345;
}

// Increment Counter
  counter++;


// 1s Counter
  if( counter == 4000 ) {
  // Update Real Time Clock
    if( ++clock.second == 60 ) {
      if( ++clock.minute == 60 ) {
        if( ++clock.hour == 24 ) {
          clock.hour = 0;
        }
        clock.minute = 0;
      }
      clock.second = 0;
    }
    counter = 1;
  }

// Keyboard Scan + Debouncing
  [xxx];
// End Of IRQ
}

//********************************************


Der Effekt ist, dass aufgrund der Nichtinitialisierung die
Tastenfeldabfrage und die Echtzeituhr erst später loslaufen. Im
aktuellen Fall ca. 8 Sekunden später, da der Zähler nicht bei 1 startet
sondern bei genau 37900.
Gast #77988
Ich kann da erstmal keinen offensichtlichen Fehler erkennen.
Vielleicht hast Du eine Kollision mit dem Stack?

Der Schnipsel genügt leider auch nicht für ein sinnvolles
Test-Compile.

Davon abgesehen, wenn Du die Variable nicht mit 1 initialisierst, wird
sie implizit als 0 initialisiert.  Zählweitenbegrenzung stattdessen
auf 3999 setzen, schon hast Du 2 Bytes ROM für die Initialwerte
gespart. ;-)

Andere Falle: eventuell wird Deine ISR auch zu lang?  Wenn Du da drin
noch keyboard scan + debounce machst, vielleicht bist Du ja schon an
Deinen 250 µs ran?
Gast #77989
Danke für die Antwort.
An eine Stackkollision glaub ich nicht. Ich verbrauche für die Vars und
Puffer ca. 500 Byte eines Mega16. Da sollte genug übrig sein.

Die ISR ist auch recht kurz. Sie funktioniert ja auch, nur dass sie
halt mit einem zu hohem counter-Wert startet und somit erst nach ca. 8
Sekunden das erste Mal in die Echtzeituhr-Routine kommt.

Allerdings habe ich es jetzt mit Deinem Tip probiert und die implizite
Initialisierung und die Abfrage auf 3999 gemacht - siehe da, es
funktioniert!
Damit bin ich vorerst glücklich, aber ich wüsste trotzdem, warum es so
nicht geht (falls ich mal andere Werte brauch und es nicht umständlich
über globale Vars machen möchte).

Dankeschön erstmal!
Gast #77990
Womit testest Du?  Reales Device oder Simulator?

Wie erstellst Du die Ladedatei für den Controller bzw. den Simulator?

Mir dünkt, daß Du vergißt, die Initialwerte für .data mitzugeben...
Die Initialisierung mit 0 funktioniert trotzdem, da die Variable dann
im .bss ist und das immer ausgenullt wird beim Programmstart.
Gast #77991
Ich benutze eine reale Schaltung.
Das Makefile habe ich mit Deinem mfile-Tool erstellt und ich flashe den
MC mit Ponyprog (über das Makefile, nach einer hier vor einiger Zeit
geposteten Kommandozeile).

Ich werde das aber überprüfen, wenn ich am Donnerstag abend zurück bin.
Danke schonmal!
Gast #77992
Damit sollte eigentlich wirklich alles im grünen Bereich sein.

Ggf. würde ich mir das Ganze nochmal komplett angucken, wenn Du gar
nicht klarkommst.
Gast #77994
Ja, und?

Wenn Dein Stack mit dem statisch zugewiesenen Bereich kollidiert, hast
Du dennoch `random garbage' in denen drin.  Genau darumg ging's ja.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 22 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.