Hallo zusammen,
habe mit meinem AVR (ATMega644PA) ein kleines Problem, dass ich nicht
gelöst bekomme.
Folgendes:
Wenn ich einen Block mit der Funktion "eeprom_read_block" aus dem EEPROM
lesen funktioniert alles einwandfrei.
Wenn ich aber diese Funktion innerhalb eines Interrupt verwende, dann
werden alle Pins am PORT C zu Null. Am Port C hängen Relais, die dann
alle abfallen.
Hab auch schon gegoogelt, finde aber nichts in der Richtung.
Der Controller macht auch keinen RESET und der Watchdog schlägt auch
nicht zu.
Kann mit das Verhalten überhaupt nicht erklären.
Hatte von euch schon mal jemand so ein Verhalten?
Gruß und Danke
Ahnungsloser schrieb:> Hallo zusammen,>> habe mit meinem AVR (ATMega644PA) ein kleines Problem, dass ich nicht> gelöst bekomme.>> Folgendes:> Wenn ich einen Block mit der Funktion "eeprom_read_block" aus dem EEPROM> lesen funktioniert alles einwandfrei.> Wenn ich aber diese Funktion innerhalb eines Interrupt verwende, dann> werden alle Pins am PORT C zu Null. Am Port C hängen Relais, die dann> alle abfallen.> Hab auch schon gegoogelt, finde aber nichts in der Richtung.> Der Controller macht auch keinen RESET und der Watchdog schlägt auch> nicht zu.> Kann mit das Verhalten überhaupt nicht erklären.>> Hatte von euch schon mal jemand so ein Verhalten?>> Gruß und Danke
Sorry habe gerade gemerkt, dass ich die Überschrift falsch betitelt
habe.
Es muss heißen: EEPROM lesen im Interrupt.
Sorry
[ Mod: ich hab den Titel mal geändert ]
Ahnungsloser schrieb:> dann>> werden alle Pins am PORT C zu Null. Am Port C hängen Relais, die dann>> alle abfallen.>> Der Controller macht auch keinen RESET
Das sieht aber ganz danach aus das er genau das tut.
Ingo schrieb:>> Watchdog schlägt auch nicht zu.> Sicher? EEPROM lesen dauert etwas. Wie schnell kommen denn deine> Interrupts?> Code zeigen!
Ganz sicher, der Watchdog kommt nicht!
Das ganze passiert auch wenn ich nur einen einzelnen Interrupt auslöse
und in dem das EEPROM auslese. Der Port C wird komplett abgenullt.
Ich werde noch verrückt.
P.S. Der Block ist 4 Byte lang. Es passiert aber auch bei einem oder 8
Bytes.
Ich muss mal kucken, ob ich den Code so zusammen stutzen kann, dass ihr
etwas mit anfangen könnt.
holger schrieb:> Das sieht aber ganz danach aus das er genau das tut.
War auch meine Vermutung, aber er tut es nicht. Alle anderen Ports sind
auch nicht betroffen. Nur Port C.
Ahnungsloser schrieb:> Ich muss mal kucken, ob ich den Code so zusammen stutzen kann, dass ihr> etwas mit anfangen könnt.
Danke. Das wollte ich hören :-)
Schau aber auch, daß in der gestutzten Version der Fehler auch auftritt!
Einmal compilieren und testen vor dem Posten bitte.
Ahnungsloser schrieb:> Ganz sicher, der Watchdog kommt nicht!
Denk mal drüber nach wann du den WDT zurücksetzt (sofern du ihn
überhaupt aktiviert hast, weiß ja keiner) und wie lange deine ISR
blockiert wird mit dem Lesen des EEPROMs. Was ist mit den Anderen IOs?
Hast du evtl. ne wackelige VCC oder die BOD zu "scharf" eingestellt?
100nF da wo sie hin sollen?
Ingo schrieb:> Ahnungsloser schrieb:>> Ganz sicher, der Watchdog kommt nicht!> Denk mal drüber nach wann du den WDT zurücksetzt (sofern du ihn> überhaupt aktiviert hast, weiß ja keiner) und wie lange deine ISR> blockiert wird mit dem Lesen des EEPROMs. Was ist mit den Anderen IOs?>> Hast du evtl. ne wackelige VCC oder die BOD zu "scharf" eingestellt?> 100nF da wo sie hin sollen?
Ja ich bediene den Watchdog. Er ist gerade auf 2s eingestellt. Der BOD
ist bei 2,7V. Die Versorgung habe ich schon mehrmals mit dem Oszi
beobachtet, da tut sich nichts bei dem Lesevorgang. Und direkt an jedem
Versorgungspin sind 100nF. Ich habe auch den PullUp am Resetpin nicht
vergessen.
Das Lesen von 4 Bytes aus dem EEPORM geht auch schneller als gedacht.
Ich kann ja mal versuchen die genau Zeit des Interrupts zu messen.
Meine komplette Programmlaufzeit liegt etwa bei 50µs, also völlig i.O.
Der Interrupt wird übrigens von einem Timer im festen Zeitraster von
10ms ausgelöst.
ISR (TIMER2_OVF_vect)
{
eeprom_read_block(dev_info, &DevInfo, sizeof(TS_DEV_INFO));
}
Denn EEPROM lesen geht fix, dauer pro Byte um die 4 Takte +
Verwaltungskram. Sprich, dein 4 Byte Block ist in vielleicht 30-40
Takten gelesen. Das ist gar nix.
Ausserdem, warum muss man alle 10ms die exakt gleichen Daten aus dem
EEPROM lesen?
Falk Brunner schrieb:> Ausserdem, warum muss man alle 10ms die exakt gleichen Daten aus dem> EEPROM lesen?
Mach dir keine Gedanken, das ist gekürzt für Tests. Es ist aber egal wie
viele Bytes ich lese. Es ist auch egal welche. Und auch in welchem
Interrupt. Ich habe immer das selbe Verhalten, dass PORTC abgenullt
wird. Alle anderen PORTs bleiben unberührt.
Ahnungsloser schrieb:> Wenn ich aber diese Funktion innerhalb eines Interrupt verwende, dann> werden alle Pins am PORT C zu Null.
ALLE oder nur die, die zum JTAG gehören?
Ahnungsloser schrieb:> eeprom_read_block(dev_info, &DevInfo, sizeof(TS_DEV_INFO));
Was soll diese Aufzählung von 3 Unbekannten?
Damit kann keiner was anfangen.
Route 66 schrieb:> ALLE oder nur die, die zum JTAG gehören?
Alle, aber guter Einwand.
Falk Brunner schrieb:> Kann es sein, das im Hauptprogramm noch EEPROM-Zugriffe erfolgen und die> sich mit den Zugriffen in der ISR überschneiden?
Ich hab das Programm so zusammen gestutzt, dass nur dieser Interrupt
ausgeführt wird, sonst nichts.
Peter Dannegger schrieb:> Was soll diese Aufzählung von 3 Unbekannten?> Damit kann keiner was anfangen.
Ja Sorry du hast Recht.
Aber für diese Unbekannten kannst du dir denke was du willst, ich hab
schon alles probiert. Auch wenn ich nu ein Byte lese, passiert das
besagte.
Kann es sein, dass der falsche Prozessortyp im Compiler eingestellt ist
und der Zugriff auf falsche IO-Register erfolgt?
Lass man nur ein IO mit LED toggeln, um zu sehen, dass der Interrupt
läuft (ggf. mit Softwareteiler, damit man es blinken statt flimmern
sieht).
Falk Brunner schrieb:> Kann es sein, dass der falsche Prozessortyp im Compiler eingestellt ist> und der Zugriff auf falsche IO-Register erfolgt?
Also da steht ATMega644PA. Aber vielleicht liegt da wirklich das
Problem. Eventuell macht der Compiler etwas falsch.
Falk Brunner schrieb:> Lass man nur ein IO mit LED toggeln, um zu sehen, dass der Interrupt> läuft (ggf. mit Softwareteiler, damit man es blinken statt flimmern> sieht).
Der Interrupt läuft, dass habe ich mit einem Pin probiert. In jedem
Interrupt habe ich den Pin invertiert. Es hat alles perfekt
funktioniert.
Wenn ich allerdings einen Pin am PORTC nehme und die EEPORM-Leseroutine
benutze, dann gehts nicht. Der PORTC wird einfach überschrieben.
Ahnungsloser schrieb:> Eventuell macht der Compiler etwas falsch.
In 99,9% der Fälle macht der nix falsch.
Such besser bei Dir selber.
Formuliere folgenden Pseudocode aus:
1
ISR()
2
{
3
eeprom_auslesen();
4
}
5
6
main()
7
{
8
timer_init();
9
PORT_C_auf_ausgang();
10
PORT_C=0xFF;
11
Benutze_keinen_Watchdog();
12
13
sei();
14
15
while(1)
16
{
17
;
18
}
19
}
Ich wette, da passiert dann nichts mehr mit PORTC.
Noch etwas: Du solltest Dein Verfahren nochmal überdenken und
dahingehend abwandeln:
Frank M. schrieb:> static volatile eeflag;>> ISR (..)> {> eeflag = 1;> }>> main> {> ...> while (1)> {> ...> if (eeflag) { eeprom_auslesen(); flag = 0; }> ...> }> }
Genau so habe ich jetzt auch drum herum programmiert. Dann geht
natürlich alles. Würde es aber trotzdem gerne verstehen.
Also gut, dann fange ich nochmal von vorne an. So wie du es beschrieben
hast. Ich melde mich, nur heute wirds nix mehr. Muss leider weg.
Nils Friess schrieb:> Poste bitte mal deinen gesamten Code, mit diesem "rate rate was ist das"> kommt man hier selten weiter.
Ja!
Immer diese Schnipseltaktik.
Man kommt sich ja vor, wie mit ner Augenklappe, wo nur ein ganz kleines
Loch drin ist.
Was ist denn so geheim an einem compilierbaren Code.
Willst Du nicht auch selber wissen, was faul ist?
Ahnungsloser schrieb:> Genau so habe ich jetzt auch drum herum programmiert. Dann geht> natürlich alles.
Also vor dem Fehler wegrennen.
Hilft aber nicht lange, der holt Dich bestimmt bald wieder ein.
Peter Dannegger schrieb:> Also vor dem Fehler wegrennen.> Hilft aber nicht lange, der holt Dich bestimmt bald wieder ein.
Da hast du Recht, darum will ich es ja wissen.
Ich hätte gerne mal einen einzigen Grund dafür gewusst, warum man einen
EEPROM alle 10ms auslesen muss - und das auch noch in einer ISR. Und
dann hätte ich auch gerne mal für die Frage nach der JTAG Fuse eine
Antwort.
Man mag mich naiv nennen. Aber wie kann sich das interne EEPROM
verändern, wenn nicht unter Kontrolle des Programms? Und warum kann dann
derjenige Codeteil nicht gleich die betreffenden Variablen beschreiben
sondern muss den Umweg übers EEPROM nehmen?
Die Sache mit den Portpins sollte natürlich nicht sein und es ist nicht
uninteressant, was da eigentlich los ist. Aber das ganze stinkt schon
nach einem kleinen Problem, hinter dem sich ein noch viel größeres
Design-Problem versteckt.
Ich hab zwar nur nen ATMega644 ohne PA, aber wenn man endlich mal ein
compilierbares Programm hätte, wäre es ein Leichtes, das auf dem STK500
auszuprobieren und die 8 LEDs an PORT C zu hängen.
Dann könnte man sich auch das Listing ansehen, ob es ein Compilerfehler
ist.
Welcher Compiler und welche Optimierung überhaupt?
Ohne Not sollte man immer -Os verwenden (default).
Karl Heinz schrieb:> Man mag mich naiv nennen. Aber wie kann sich das interne EEPROM> verändern, wenn nicht unter Kontrolle des Programms? Und warum kann dann> derjenige Codeteil nicht gleich die betreffenden Variablen beschreiben> sondern muss den Umweg übers EEPROM nehmen?
Vielleicht hat er ja ein EEPROM-Stress-Test-Programm geschrieben ;-)
> Die Sache mit den Portpins sollte natürlich nicht sein und es ist nicht> uninteressant, was da eigentlich los ist. Aber das ganze stinkt schon> nach einem kleinen Problem, hinter dem sich ein noch viel größeres> Design-Problem versteckt.
Sehe ich genauso. Deshalb bat ich ihn ja auch, eine Mini-main() mit
Mini-ISR() zu veröffentlichen, mit dem er das Problem reproduzieren
kann.
Karl Heinz schrieb:> Man mag mich naiv nennen. Aber wie kann sich das interne EEPROM> verändern, wenn nicht unter Kontrolle des Programms? Und warum kann dann> derjenige Codeteil nicht gleich die betreffenden Variablen beschreiben> sondern muss den Umweg übers EEPROM nehmen?
Wer sagt denn, daß der EEPROM-Inhalt sich ändert? Oder daß das
10ms-EEPROM-Lesen überhaupt im Originalprogramm vorkam und nicht nur in
der abgespeckten Testversion?
Außerdem war es früher zumindest auf den kleineren Prozessoren üblich,
Konstantentabellen ins EEPROM zu legen, wenn man das nicht anderweitig
braucht und Flash knapp ist. Und wenn es sich bei den Konstanten um den
"Zeichensatz" eines Displays handelt, das man in Software multiplext,
dann ist ein Lesezugriff alle 10ms, auch im Interruptn gar nicht so
ungewöhnlich.
Nosnibor schrieb:> Und wenn es sich bei den Konstanten um den> "Zeichensatz" eines Displays handelt, das man in Software multiplext,> dann ist ein Lesezugriff alle 10ms, auch im Interruptn gar nicht so> ungewöhnlich.
Der Zeichensatz eines Display hat mMn ebenso wenig in einem EEPROM
verloren - sowas gehört ins Flash.
> Außerdem war es früher zumindest auf den kleineren Prozessoren üblich,> Konstantentabellen ins EEPROM zu legen
Es ist ein Mega644(!) - nichts, was ich als kleineren Prozessor
bezeichnen würde. Der Flash ist so gross, das ich da auch 4 Zeichensätze
unterbringe.
Und auch Performance zählt nicht, denn lt. DB:
> When the EEPROM is read, the CPU is halted for four clock> cycles before the next instruction is executed.
Ausserdem muss für jedes Lesen des EEPROM die Adresse gesetzt werden (in
EEARL und EEARH).