Moin,
ich habe hier ein kleines Problem mit meinem mega88pa.
In meinem Programm nutze ich alle 3 Timer. Doch egal bei welchem und
egal ob Timer-Overflow oder Output-Compare, jedesmal wenn ein Interrupt
ausgelöst werden soll, startet der µC neu. Allerdings nur bei
Timer-Interrupts. Daher befürchte ich, habe ich dort nen Denkfehler
drinnen.
Ich hab meinen Code schon auf ein Minimum reduziert, um evtl.
Fehlerquellen auszuschließen. Vielleicht mag sich das einer von euch mal
ansehen:
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
#include"uart.h"
4
5
6
ISR(TIMER2_OVF_vect){
7
TCCR2B=0;
8
sendData(1,1,1,0,0);
9
}
10
11
intmain(void){
12
initUart(0);
13
sei();
14
sendData(0,0,0,0,0);
15
16
TIMSK2=(1<<TOIE2);
17
TCCR2B=(1<<CS22)|(1<<CS20);
18
while(1){
19
}
20
return0;
21
}
sendData überträgt mir Daten über nen RS485-Bus an den PC. Die Funktion
arbeitet einwandfrei und kann als Fehlerquelle ausgeschlossen werden,
daher habe ich sie nicht extra mit aufgeführt. Wenn ich den Timer
deaktiviert lasse, werden die Daten des nach sei() kommenden sendData
genau einmal übertragen, wie erwartet.
Stelle ich jedoch den Timer so ein, das er ein Interrupt generiert,
bekomme ich die Daten im Takt des Interrupts. Das sendData in der ISR
hingegen wird nie erreicht. Folglich wird die ISR nie ausgeführt und der
µC resettet sich ständig.
Die Interrupt-Vektortabelle sieht für mich auch ok aus:
1
00001800<__vectors>:
2
1800:19c0rjmp.+50;0x1834<__ctors_end>
3
1802:28c0rjmp.+80;0x1854<__bad_interrupt>
4
1804:27c0rjmp.+78;0x1854<__bad_interrupt>
5
1806:26c0rjmp.+76;0x1854<__bad_interrupt>
6
1808:25c0rjmp.+74;0x1854<__bad_interrupt>
7
180a:24c0rjmp.+72;0x1854<__bad_interrupt>
8
180c:23c0rjmp.+70;0x1854<__bad_interrupt>
9
180e:22c0rjmp.+68;0x1854<__bad_interrupt>
10
1810:21c0rjmp.+66;0x1854<__bad_interrupt>
11
1812:35c0rjmp.+106;0x187e<__vector_9>
12
1814:1fc0rjmp.+62;0x1854<__bad_interrupt>
13
1816:1ec0rjmp.+60;0x1854<__bad_interrupt>
14
1818:1dc0rjmp.+58;0x1854<__bad_interrupt>
15
181a:1cc0rjmp.+56;0x1854<__bad_interrupt>
16
181c:1bc0rjmp.+54;0x1854<__bad_interrupt>
17
181e:1ac0rjmp.+52;0x1854<__bad_interrupt>
18
1820:19c0rjmp.+50;0x1854<__bad_interrupt>
19
1822:18c0rjmp.+48;0x1854<__bad_interrupt>
20
1824:17c0rjmp.+46;0x1854<__bad_interrupt>
21
1826:16c0rjmp.+44;0x1854<__bad_interrupt>
22
1828:15c0rjmp.+42;0x1854<__bad_interrupt>
23
182a:14c0rjmp.+40;0x1854<__bad_interrupt>
24
182c:13c0rjmp.+38;0x1854<__bad_interrupt>
25
182e:12c0rjmp.+36;0x1854<__bad_interrupt>
26
1830:11c0rjmp.+34;0x1854<__bad_interrupt>
27
1832:10c0rjmp.+32;0x1854<__bad_interrupt>
Hat jemand ne Idee, wo mein Fehler liegt?
Achja, mein Controller läuft mit 16Mhz auf 5V und im AvrStudio-Simulator
scheint der Code ohne Probleme zu laufen...
Hallo,
wenn die Fehlerbeschreibung die du gepostet hast, tatsächlich so ist,
wie Du beschreibst, würde ich den Fehler erstmal in sendData suchen, da
anscheinend dort etwas nicht stimmt.
Gruß
Frank
Makefile gibt's nicht, ist ein Eclipse Projekt mit AVRGCC-Plugin.
Watchdog ist nicht an.
Das mit der LED wird schwirig, da es sich um eine fertige Platine
handelt, wo ich nicht einfach was anschließen kann. Aber evtl. könnte
ich einen Eingang vom RS485 Receiver dafür missbrauchen.
mee..
zuerst dachte ich:
-falscher interrupt definiert, das problem hatte ich letztens kurz, dann
springt der avr immer in einen reset.
aber dann kurz überflogen:
-in der ISR wird eine grosse funktion aufgerufen welche daten ausgibt -
die wird ewig brauchen, während dessen kommen neue interuppts und
schwupps ist der stack voll...
empfehlung: nie in einer ISR eine funktion aufrufen, statt dessen nur an
volatile variablen schrauben.
die zu sendenden daten einfach in einen kleinen ringpuffer schieben, und
den dann entweder per ISR oder in der main-schleife ausspucken.
stru_aus schrieb:> -in der ISR wird eine grosse funktion aufgerufen welche daten ausgibt -> die wird ewig brauchen, während dessen kommen neue interuppts und> schwupps ist der stack voll...
Alle AVR's blockieren per default weitere Interrupts beim Einsprung in
eine ISR. Da läuft nix über.
Mit dem Problem desr "ewig dauernden" sendDAta in der ISR hast du zwar
recht, das führt abe nicht zum o.a. Problem.
Ansonsten gefällt mir die Initialisierungsreihenfolge des Timers nicht.
Prinzipiell sollte man erst die Konfigurationsregister setzen, und dann
per die Interrupts freigeben.
Stefan Ernst schrieb:> Und wo in deinem Minimal-Code werden die Interrupt-Vektoren in den> Bootloader-Bereich umgeschaltet?
Das sieht in der Tat seltsam aus.
Oliver
Ja, für ein normales Programm müssen die Vektoren natürlich an Adresse 0
liegen. Oder du musst die Interruptvektoren in den Bootloader verlegen.
Dass man in einer ISR keine Funktionen aufrufen darf ist Mumpitz. Da
darf man eigentlich so gut wie alles machen, was man auch woanders
machen darf. Bei Atomizität (ATOMIC_BLOCK) und Race Conditions
(volatile) muss man eben aufpassen.
Überlaufen bei langen Funktionen tut da auch nichts. Es gibt nur ein
einziges Interruptflag für jeden Interrupt, das zum entsprechenden
Zeitpunkt gesetzt wird. Und wenn alle Bedingungen erfüllt sind
(Interrupt aktiviert, globale Interrupts aktiviert, nicht in einer
aktiven ISR) wird das Flag gelöscht (in der Regel) und der Interrupt
Vektor ausgeführt.
Wenn nicht, dann eben nicht.