PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ATMega8515: Problem mit Timer-Interrupt



MrWhite
19.04.2010, 10:51
Hallo Leute,

leider konnte mir im Mikrocontroller Forum keiner helfen, deswegen probiere ich es hier noch einmal. Bitte habt Nachsicht mit diesem Cross-Posting.

Problem: Einfacher Timer-Interrupt funktioniert nicht

Folgender (simpler) Code:


#ifndef MCU
#define __AVR_ATmega8515__
#endif

#ifndef F_CPU
#define F_CPU 4000000UL
#endif

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/portpins.h>
#include <util/delay.h>

ISR(TIMER0_OVF_vect)
{
PORTC = ~PORTC;
}

int main()
{
DDRA = 0xff;
PORTA = 0x0f;

DDRC = 0xff;
PORTC = 0x0f;

TIMSK |= (1 << TOIE0); //overflow timer einschalten
TCCR0 = (1 << CS02) | (0 << CS01) | (1 << CS00); //prescaler auf 1024

//sei(); //hauptschleife funktioniert wenigstens wenn auskommentiert

while(1)
{
PORTA = ~PORTA;
_delay_ms(500);
}
}


Effekt: Wenn der call auf sei() auskommentiert ist, funktioniert die Hauptschleife. Sonst geht gar nichts.

Das Programm ist meines Erachtens nach absolut korrekt! Der Chip sitzt auf dem STK500 und soll dort die LEDs zum Leuchten bringen. Sobald der Call auf sei() drin ist, geht gar nichts mehr!

Vermutung: Controller hängt permanent in der Interrupt-Routine oder ist gar defekt.

Frage: Müssen eigentlich entsprechende Fuses oder Taktungen gesetzt werden, um den Timer-Interrupt zu betreiben? Der Controller wird auf einem STK500 in der Standard Einstellung betrieben (beides out-of-the-box). STK500 gibt den Takt vor (3,68 MHz).

Link zum Original-Thread im Mikrocontroller.net forum: http://www.mikrocontroller.net/topic/174886

Hoffe ihr könnt mir weiterhelfen!

sternst
19.04.2010, 12:08
Aus dem anderen Thread:

Hier mal der exakte Compiler-Aufruf:
avr-gcc -g -Os -I/usr/lib/avr/include/ -funsigned-char
-funsigned-bitfields -fpack-struct -fshort-enums -Wall
-Wstrict-prototypes -Wa,-ahlms=program.lst -Wl,-Map=program.map,--cref
-L../../lib program.c -o program

1)
Wo ist die mcu-Option?
Das hier
#ifndef MCU
#define __AVR_ATmega8515__
#endif
ist kein adäquater Ersatz dafür (z.B. erfolgt das Linken dann nicht für den richtigen Controller).

2)
Was programmierst du dann in den Controller? Doch wohl nicht etwa jenes "program", oder?

MrWhite
19.04.2010, 12:45
1)
Wo ist die mcu-Option?
Das hier
#ifndef MCU
#define __AVR_ATmega8515__
#endif
ist kein adäquater Ersatz dafür (z.B. erfolgt das Linken dann nicht für den richtigen Controller).

Nie angegeben worden! Danke für den Hinweis, ich dachte die Definition reicht aus. Werde heute Abend mit MCU-Argument versuchen! Das klingt sehr plausibel, danke für den Hinweis!



2)
Was programmierst du dann in den Controller? Doch wohl nicht etwa jenes "program", oder?

Der Code, den ich oben gepostet in diesem Thread gepostet habe, landet im Flash. Gibt es da ein Problem?

Vielen Dank jedenfalls schonmal für den Hinweis mit dem MCU Argument. Das klingt sehr plausibel.

sternst
19.04.2010, 13:06
Der Code, den ich oben gepostet in diesem Thread gepostet habe, landet im Flash.Welche Datei programmierst du in das Flash? Wenn es "program" ist, wird niemals irgendein Interrupt funktionieren.

MrWhite
19.04.2010, 13:18
Der Code, den ich oben gepostet in diesem Thread gepostet habe, landet im Flash.Welche Datei programmierst du in das Flash? Wenn es "program" ist, wird niemals irgendein Interrupt funktionieren.

Doch, die Datei namens program lade ich ins Flash. Also das Kompilat von program.c.

Wieso kann das nicht funktionieren? Die Hauptschleifen funktionieren ja??!

sternst
19.04.2010, 13:28
Wieso kann das nicht funktionieren?Weil das der ELF-Output des Compilers ist. Da ist eine Menge Zeug mit drin, was im Controller nichts zu suchen hat. Und nichts steht dann im Controller an der Adresse, wo es eigentlich stehen sollte (weshalb niemals irgendein Interrupt funktionieren wird). Das, was in den Controller zu programmieren ist, muss aus dieser ELF-Datei erst mal mittels objcopy extrahiert werden (*).

Die Hauptschleifen funktionieren ja??!Ja, das ist die Crux an diesem ELF-Datei-Programmieren. Sehr simple Programme funktionieren meist trotzdem, weshalb derjenige dann denkt, er würde bei diesem Schritt keinen Fehler machen.

PS: Warum benutzt du nicht einfach ein bekanntermaßen funktionierendes Makefile (z.B. von MFile generiert), dann hast du diese ganzen Probleme nicht. Denn in (*) lauert schon der nächste Fehler, den fast jeder macht, der das "von Hand" versucht.

MrWhite
19.04.2010, 13:33
Mit diesen Informationen werde ich den Timer heute Abend hoffentlich zum Laufen bringen.

Vielen Dank für die Hinweise!

MrWhite
20.04.2010, 09:19
Danke, du hast mir sehr geholfen.

Der Overflow-Timer wird nun brav in der richtigen Frequenz aufgerufen.

Allerdings habe ich ein neues Problem! Wenn ich im Interrupt-Handler auf globale Variablen zugreife, vergessen diese ihren Zustand beim nächsten Call. Die Variablen sind als volatile deklariert:


#ifndef MCU
#define __AVR_ATmega8515__
#endif

#ifndef F_CPU
#define F_CPU 4000000UL
#endif

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/portpins.h>
#include <util/delay.h>
#include <inttypes.h>

volatile uint8_t frequencyAdjustmentCounter = 0;
volatile uint8_t frequencyAdjustmentThreshold = 14;

ISR(TIMER0_OVF_vect)
{
frequencyAdjustmentCounter++; //ist nach durchlaufen des handlers wieder 0 ohne Port C zu schalten!
if(frequencyAdjustmentCounter == frequencyAdjustmentThreshold)
{
PORTC = ~PORTC;
frequencyAdjustmentCounter = 0;
}
}

int main()
{
DDRA = 0xff;
PORTA = 0x0f;

DDRC = 0xff;
PORTC = 0x0f;

TIMSK |= (1 << TOIE0); //overflow timer einschalten
TCCR0 = (1 << CS02) | (0 << CS01) | (1 << CS00); //prescaler auf 1024

sei();

while(1)
{
PORTA = ~PORTA;
_delay_ms(500);
}
}


Die Variable "frequencyAdjustmentCounter" gilt komischerweise nur im Scope des Interrupt-Handlers!

Den Compiler-Aufruf habe ich auf das äußerste simplifiziert, es wird praktisch nur das mmcu Argument angegeben.

Woran kann das denn liegen?

sternst
20.04.2010, 10:33
Den Compiler-Aufruf habe ich auf das äußerste simplifiziert, es wird praktisch nur das mmcu Argument angegeben.Du machst es also immer noch "von Hand", und ich weiß nicht, wie die Compiler-Kommandozeile denn nun genau aussieht. Und ich weiß auch nicht, wie du die zu programmierende Datei erzeugst und ob du dort den oben von mir angesprochenen Fehler machst (der durchaus der Grund für das aktuelle Problem sein kann). Du musst mir diese Dinge aber auch nicht unbedingt mitteilen, denn von mir wirst du erst wieder Hilfe bekommen, wenn du ein vernünftiges fertiges Makefile verwendest. Ich habe nämlich keine Lust, dir jetzt dieses "wie mache ich es selbst" bis ins letzte Detail zu erklären, einfach weil es Zeitverschwendung wäre.

Also nimm ein fertiges Makefile (am besten generiert durch MFile), dann haben wir eine solide Ausgangsbasis, und wenn dann das Problem immer noch besteht, dann bin ich auch bereit mal einen intensiveren Blick auf den Code zu werfen.

MrWhite
20.04.2010, 10:59
Entschuldigung bitte, ich werde in Zukunft MFile nutzen um ein Makefile zu erzeugen und falls die Probleme dann noch bestehen, mich wieder hier melden.

Leider bin ich in der Arbeit und habe die genauen Aufrufe nicht zur Hand. Ein Makefile nutze ich schon, das habe ich aber von Hand geschrieben (hehe).

Vielen Dank jedenfalls für deine Hilfsbereitschaft.

MrWhite
20.04.2010, 18:50
Hallo sternst,

seit ich MFile nutze gibt es ueberhaupt keine Probleme mehr!

Vielen Dank fuer die wertvollen Informationen, fuer mich bist du der Held des Tages.