mikrocontroller.net

Forum: Compiler & IDEs Function Pointer führt bei 8515 zu Reset?


Autor: Michael Dahlke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ahoi zusammen,

ich habe ein Problem, das vermutlich schon einmal behandelt wurde, habe

aber doch keinen entsprechenden Eintrag im Forum oder auf Google finden

können, also poste ich mal, vielleicht kann mir ja jemand von Euch
helfen.
Es geht um

  Function Pointer in C (ja, ich weiß...)

Leider warte ich schon seit einigen Wochen auf meinen ISDN Anschluß
(danke,
Telekom, dass Ihr den für mich erfinden wollt), und muss von meinem
Arbeitsplatz aus posten, so dass ich die Quellen nicht zur Hand habe
und
aus dem Gedächtnis zitieren muss, ich hoffe, ich vertue mich nicht...

Also folgendes Trivialprogramm


...
static void toggle_led8 ()
{
    PORTB = PINB ^ 0x80;
}

static void toggle_led1 ();
{
    PORTB = PINB ^ 0x01;
}

typedef void (* fptr_t) ();

void main ()
{
    DDRB = 0xFF;


    /* Funktionszeiger definieren */

    fptr_t func;
    func = toggle_led1;


    /* Umschalten von LED 8 zeigt den Programmbeginn an */

    toggle_led8 ();


    /* LED 1 Blinkenlichten */

    for (;;) {
        delay ();
        func ();
    }

}



zeigt folgendes Verhalten:

  * läßt sich anstandslos kompilieren:
    avr-gcc -std=c99 -Wall -ffreestanding -O2 -mmcu=at90s8515 -o
dingens dingens.c
    (ist das cdk4avr-Paket mit dem avr-gcc 3.3.1, meine ich)

  * Der generierte Assemblercode scheint mir in Ordnung zu sein, ich
habe mir
    einmal den Dump angeschaut. An der Stelle, an der der toggle_led1
über den
    Function Pointer aufgerufen wird, zeigen die Register R30 & R31
unmittelbar
    vor dem ICALL auf die korrekte Adresse (Dump habe kann ich aus dem
Kopf
    natürlich nicht zitieren...).

  * Das Programm lässt sich im Simulator sehr besonders prima ausführen
und
    zeigt genau das erwartete Verhalten: LED 8 schaltet einmal um, LED
1 blinkt.

  * Auf einem STK-500 in einen 8515 geflasht blinkt(!) LED 8, es wird
also
    offenbar ständig resettet.

Ich habe schon einiges ausprobiert, tappe aber immer noch im Dunkeln.
Hat jemand
eine Lösung oder einen Vorschlag, in welche Richtung ich da weiter
forschen könnte?
Kann das evtl. ein Bug im '8515 sein? Compilerfehler schließe ich mal
aus, da der
Assemblercode ja okay zu sein scheint.


Besten Dank vorab und schönen Gruß,

  Michael

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> static void toggle_led8 ()
> {
>     PORTB = PINB ^ 0x80;
> }

Nur so: PORTB = PORTB ^ 0x80; oder kurz
PORTB ^= 0x80; ist meines Erachtens
sinnvoller.

Außerdem: wir schreiben das Jahr 2005, nicht 1985.  Seit ANSI-C89
alias ISO-C90 gibt's Funktionsprototypen.  Also

static void toggle_led8(void)...

und:

> typedef void (* fptr_t) ();

typedef void (*fptr_t)(void);

>   * läßt sich anstandslos kompilieren:
>     avr-gcc -std=c99 -Wall -ffreestanding -O2 -mmcu=at90s8515 -o
> dingens dingens.c
>     (ist das cdk4avr-Paket mit dem avr-gcc 3.3.1, meine ich)

-ffreestanding würde ich persönlich nicht benutzen.  Zwar erreichst du
damit, dass "void main(void);" ein gültiger Prototyp für main()
wird,
aber das erkaufst du u. U. recht teuer, da der Compiler sein Wissen um
die Standardbibliothek komplett vergessen muss.  Schreibst du irgendwo
"x = strlen("foo");", so muss er z. B. wirklich strlen() aufrufen,
statt der Variablen x einfach die Konstante 3 zuzuweisen, usw. usf.

Sowie eine C-Standardbibliothek dazukommt, ist eben selbst eine
Microcontroller-Applikation gar nicht mehr so "freestanding", wie
sie
es auf den ersten Blick zu sein scheint.

>   * Auf einem STK-500 in einen 8515 geflasht blinkt(!) LED 8, es
> wird also offenbar ständig resettet.

Ist das der einzige Code, oder hast du da noch mehr drin?  (Das
delay() muss ja auch irgendwo her kommen.)  Insbesondere die Frage:
hast du irgendwo Interrupts gestattet und dich vielleicht im
Interrupt-Handler verschrieben?

> * Der generierte Assemblercode scheint mir in Ordnung zu sein, ich
> habe mir einmal den Dump angeschaut.

avr-gcc -mmcu=at90s8515 -O2 -S dingens.c

hätte dir die Assemblerdatei direkt geliefert.

Autor: Michael Dahlke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Jörg,

danke für die schnelle Antwort.

Das delay() ist eine simple Verzögerungsschleife, es existieren keine
Interrupthandler o.ä., d.h. dieses Simpelprogramm ist tatsächlich
beinahe vollständig.

Wenn innerhalb der Schleife die Funktion toggle_led1() direkt
anstelle von func() aufgerufen wird, läuft alles tadellos, daher kann
ich (denke ich?) Fehlerquellen wie Interrupts oder einen "heimlich"
laufenden Watchdog ausschließen.

Den Dump hatte ich angefertigt, weil er m.E. um einiges
übersichtlicher ist, als das nackte Assemblerlisting. Ich werde heute
mal Disketten kaufen gehen (lange nicht mehr gemacht...), und die
richtigen Dateien morgen früh posten.


Viele Grüße,

  Michael

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Pliebe eigentlich nur ein Problem mit dem Stack als verdächtig
übrig.  Der Indirektaufruf erzwingt einen ICALL, während
möglicherweise in der direkten Variante die super-simple
,,Funktion'' einfach inlined wird, sodass Stack-Probleme keine
Auswirkung haben.

Autor: Michael Dahlke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmmm, nein, in der direkten Variante läuft's auf einen RCALL raus,
das hatte ich mal gesehen, ge-inline-d wird das wohl nicht.

Ist vermutlich tatsächlich irgendein Stack-Problem, merkwürdig nur,
dass der Simulator das nicht aufdeckt. Dummerweise ist das genau die
Sorte von Fehlern, die sich richtig schlecht "live" debuggen
lassen.

Mist. ;-)

Ich werde heute Nachmittag mal in der Richtung weiter forschen, danke
für den Tip.


Gruß,

  Michael

Autor: Michael Dahlke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, ich hab's!

Es ist ein Hardware-Defekt, die Bits in R31 kippen offenbar
willkürlich, damit geht der ICALL natürlich ins Nirvana.

Ich war wohl zu sehr daran gewöhnt, dass Hardware einfach
funktioniert. Besonders, wenn sie recht frisch eingekauft ist, da
habe ich mit dieser Sorte Fehler nicht gerechnet. Die letzten Tage
waren nicht sehr gut für mein Ego ;-)

Besten Dank an Jörg und alle anderen, die sich vielleicht auch um
eine Lösung bemüht haben.


Gruß und schönes Wochenende

  Michael

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Shit happens.

Aber sag mal, warum kaufst du noch AT90S8515 neu?

Autor: Michael Dahlke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tja, gab's halt günstig (ca. 2,20 €).
Jetzt weiß ich auch, warum... ;-)

Autor: Peter Dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Es ist ein Hardware-Defekt, die Bits in R31 kippen offenbar
willkürlich"

In AVRfreaks war mal ein Thread, daß die LPM-Instruktion bei einigen
Chargen des Mega128 extrem empfindlich gegen hohen Takt war, lief wohl
erst unter 12MHz einigermaßen, d.h. weit unter den erlaubten 16MHz.
Das könnte ja auch auf andere Z-Operationen zutreffen.

Geh doch einfach mal mit dem Takt auf 1..4MHz runter, obs dann läuft.


Peter

Autor: Michael Dahlke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter,

Entschuldigung für die späte Antwort. Die Schaltung läuft mit den
3,686400 MHz, die das STK-500 Board zur Verfügung stellt, es muss
sich wohl um einen anderen (genau so massiven) Knall handeln.
Trotzdem vielen Dank für den Hinweis.


Gruß,

  Michael

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.