AVR ATmega16+Timer

Aha. Habe ich nicht gewusst.

Bei Debuggen meiner C-Programme ist mit das bisher nicht aufgefallen. Da springt das Programm nach dem return sofort in die nächste ISR wenn ein Interrupt offen ist. Man sollte halt ab und zu auf Assemblercode umschalten.

Schöne Grüsse Georg

Reply to
Georg Meister
Loading thread data ...

Dein Vorschlag funktioniert glaube ich nicht, weil bei dem NOP möglicherweise höher priorisierte Interrupts ausgeführt werden, und nicht der Timer-Int. Was ich jedoch sagen kann ist: Bei allen Versuchen, die ich gemacht habe, passiert es sehr selten das TCTR0 zwischen 0 und 9 liegt und SystemTime noch nicht erhöht wurde. Es gibt nie größere Werte. Die längste mögliche Verzögerung scheint also bei 36us zu liegen, was in etwa der berechneten Dauer der Hardware ISR entspricht. Das ist auch bei dem Vorschlag von Georg so, und hier ist mir noch nicht klar warum das so ist.

Das habe ich ausgeschlossen: Ich habe einen Zähler beim Eintritt in die ISR erhöht, und auch die Zahl der fallenden Flanken am Int.Pin extern mitgezählt. Die Zähler laufen synchron.

Aber man merkt nicht, ob die Routine sehr selten einmal länger dauert als erwartet. Es wäre schon großes Glück das am Speicher-Oszi. einmal zu treffen. Mein Problem trat etwa alle vier Minuten auf, wenn ununterbrochen TCTR0 und Systemtime ausgelesen wurden.

mfg Helmut

Reply to
Helmut Neemann

Ja, stimmt. Dadurch ist mein Vorschlag unbrauchbar.

Die 36us sind deine gezaehlten 533 Zyklen.

Du verwendest doch einen Prescaler von 64(?). Waehrend des Interrupts sollte sich TCNT0 um 8 (533/64) erhoehen. Daher sollten keine Werte zwischen 0-8 fuer TCNT0 im Hauptprogramm vorkommen.

Oder hab ich jetzt einen Logikfehler.

Aber die von Georg vorgeschlagene Idee muss funktionieren.

  • hs1:
  • IN R3,TCNT0
  • LDS R17,SYSTEMTIME
  • LDS R18,SYSTEMTIME+1
  • LDS R19,SYSTEMTIME+2
  • LDS R20,SYSTEMTIME+3
  • IN R4,TCNT0
  • CP R4,R3
  • BRLO hs1

Diese Code funktioniert nicht bei,

*) Interrupt zwischen CP/BRLO, keine Rekonstruktion der SREG-Flags am Ende der ISR *) Interrupt zwischen IN R3../CP welcher den Wert von R3 aendert

oder ein aehnlicher Fehler in deiner Test-/Vergleichsroutine

servus thomas «

--
Die 4. Österreichische Fan-Convention zum Thema Japanische Popkultur
** AniNite 2004 ** 20.-22.August 2004 ** http://www.aninite.at/ **
Anime & Manga * J-Pop Bar * Cosplay * Videogames * Go * DDR * AMV *
Manga Workshop * Quiz * Trading Cards * Vortraege * Origami * Kyudo *
Reply to
Thomas Mozgan

Die Hardware ISR für den CAN-Bus ist 533 Zyklen lang. Die Timer ISR dauert maximal 76 Zyklen, und in den allermeisten Fällen sogar nur 40.

Ich glaube ich habe einen Denkfehler gemacht, und die Prioritäten der ISR nicht richtig im Kopf gehabt. Ich habe noch eine ADC ISR die mit knapp 10kHz läuft und etwa 3.5% Rechenleistung verbraucht. Bisher dachte ich sie hat die niedrigste Prio und muss nicht berücksichtigt werden. Eben sehe ich aber, dass der Timer0 Compare Handler die niedrigste Prio hat. Damit gibt es zwei Interrupts mit höhererer Priorität als der Timer. Wenn nun das folgende Szenario eintritt: Unmittelbar vor dem ersten IN wird die CAN-ISR gestartet. Während der CAN-ISR kommen ADC-Int und Timer-Int. Nach der Hardware-ISR wird der IN Befehl ausgeführt und, da der Timer schon überglaufen ist, ließt er eine Zahl zwischen 0 und 9. Danach kommt die ADC-ISR an die Reihe und dann kommt das erste LDS. Erst danach die wird die Timer-ISR ausgeführt. Wenn dann nach den restlichen LDS-Befehlen der zweite IN Befehl kommt, wird eine Zahl größer 9 gelesen und der Vergleich ist ok. Ich habe aber ein falsches Byte SystemTime geladen und es ergibt sich genau das beobachtete Phänomen.

Jetzt muß man sich nur noch überlegen wie wahrscheinlich das ist, oder den folgenden Code ausprobieren:

  • hs1:
  • IN R3,TCNT0 NOP
  • LDS R17,SYSTEMTIME
  • LDS R18,SYSTEMTIME+1
  • LDS R19,SYSTEMTIME+2
  • LDS R20,SYSTEMTIME+3
  • IN R4,TCNT0
  • CP R4,R3
  • BRLO hs1

mfg Helmut (für den die Welt wieder in Ordnung ist ;-)

Reply to
Helmut Neemann

Nicht schlecht.

Ich hatte gerade ein Szenario konstruiert, wo die Routine danebengeht, hab aber inzwischen MONK im Fernsehen geguckt und nun komm ich zurück und schon liegt die fertige Lösung da :-)

Also ich erzähl trotzdem noch kurz was ich mir ausgedacht habe:

Wenn einen Befehl VOR dem IN R3 der externe Interrupt und der Timeroverflow zugleich kommen, wird nach dem IN die ISR des ext. INT ausgeführt, und nach dem LDS R17 der Timerinterrupt. Das Register R17 ist dann falsch.

Mein Problem war allerdings nicht nur, dass das extrem unwahrscheinlich ist und nicht mit den 4 Minuten zusammenpasst, sondern auch, dass R3 dann auf jeden Fall 0 ist und nicht 9 sein kann.

Helmuts Lösung erklärt das tatsächlich Beobachtete. Assembler kann echt spannend sein.

Georg

Reply to
Georg Meister

Gut. Dann ist meine Ueberlegung hinfaellig. Da die Timer-ISR meist kuerzer als der Prescaler (64) ist.

Ca 60 Taktzyklen? Wenn die ADC-ISR mit rund 10kHz und die Timer0-ISR mit genau 1kHz auftreten, gibt es ein langes Zeitfenster mit aufeinander folgenden Kollisionen (d.h. die Timer0-ISR wird verzoegert). Deckt sich die Fehler-Haeufigkeit mit meiner Ueberlegung?

Aha, wirkt sehr konstruiert.

Wenn man jedoch verinnerlicht, dass die Timer-ISR zeitversetzt behandelt wird (verzoegert durch Abarbeitung der anderen ISR) und zwischen den einzelnen ISR je ein Befehl des Hauptprogrammes ausgefuehrt wird, ist es nachvollziehbar. Der Grundfehler liegt bisher in der Annahme, dass mit TCNT0=0..8 auf ein ausgefuehrten Timer0-Interrupt geschlossen wurde (LDS jedoch einen alten Wert las).

Zwischen IN R3 und dem LDS muss der Timer-ISR nun garantiert kommen. Also sollte der jetztige Code funktionieren (wenn weitere hoeherpriore ISR existieren, noch weitere NOPs/Befehle). Alternativ kannst du die ADC/CAN Interrupts unterbrechbar programmieren.

Wenn die Timer-ISR laenger als eine Aenderung von TCNT0 dauert (Prescaler) kannst du BRLO durch BRNE ersetzen (und NOP streichen). Dadurch stellst du sicher, dass zwischen den beiden IN keine Unterbrechung/Interrupt laenger als Prescaler auftratt.

servus thomas «

--
Die 4. Österreichische Fan-Convention zum Thema Japanische Popkultur
** AniNite 2004 ** 20.-22.August 2004 ** http://www.aninite.at/ **
Anime & Manga * J-Pop Bar * Cosplay * Videogames * Go * DDR * AMV *
Manga Workshop * Quiz * Trading Cards * Vortraege * Origami * Kyudo *
Reply to
Thomas Mozgan

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.