mikrocontroller.net

Forum: Compiler & IDEs SIGNAL + static Var initialisieren


Autor: Dieter (Gast)
Datum:

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

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Dieter!

Wo wird denn die Variable deklariert, global oder erst in der ISR?

Gruß,
Patrick...

Autor: Dieter (Gast)
Datum:

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

Autor: OldBug (Gast)
Datum:

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

Autor: OldBug (Gast)
Datum:

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

Autor: Dieter (Gast)
Datum:

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

Autor: Jörg Wunsch (Gast)
Datum:

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

Autor: Dieter (Gast)
Datum:

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

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Poste mal den Code, oder zumindest den Teil des Codes, der die beiden
Variablen anlegt, den Inhalt kopiert und dann ausgibt.

Autor: Dieter (Gast)
Datum:

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

Autor: Jörg Wunsch (Gast)
Datum:

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

Autor: Dieter (Gast)
Datum:

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

Autor: Jörg Wunsch (Gast)
Datum:

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

Autor: Dieter (Gast)
Datum:

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

Autor: Jörg Wunsch (Gast)
Datum:

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

Autor: Christian Schifferle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
P.S. static-Variablen werden nicht auf dem Stack abgelegt.

Gruss
Christian

Autor: Jörg Wunsch (Gast)
Datum:

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

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.