Man kann die Zieladressen in der Sprungtabelle der Interrupts ändern. Defaultmässig springen die zu einem RETI. Einfach die Adresse der selbstgemachten ISR eintragen.
Druckbare Version
Man kann die Zieladressen in der Sprungtabelle der Interrupts ändern. Defaultmässig springen die zu einem RETI. Einfach die Adresse der selbstgemachten ISR eintragen.
Das ist mir noch nicht ganz klar, weil selbstverständlich an den Adressen (0 ... 17) entsprechende ISR Adressen/Marken stehen werden. Beispielweise, wenn ich den Timer/Counter0 permanent laufen lasse, wird nach jedem Überlauf an die Adresse 0x000Bh und weiter an dort stehende Adresse/Marke entsprechender ISR gesprungen und das kann ich nicht ändern, oder ? ;)
Hallo PICture,
ich seh das auch so, daß die Zuordnung von Interruptquelle und Programmadresse bei dem ATtiny festgelegt sind.
Das kann man nicht ändern und legt auch gleichzeitig in der Reihenfolge der Interruptnummern die Prioritäten fest. Der Inhalt der Programmadresse kann geändert werden und sollte bei generellem Gebrauch von Interrupts die Anweisung (zB RJMP) zum Aufsuchen der ISR enthalten. :)
Als Pre-Anfänger in ASM stelle mir das so vor, das der Programmcounter durch den Interrupt HW gesteuert unbeeinflußbar auf den in der Tabelle 9-1 aufgeführten unveränderbaren Wert gesetzt wird. Dort sollte dann ein Befehl stehen, der die Programmausführung mit der ISR fortführt.
;)
Gruß
Searcher
Die Interruptsvektoren sind fest, am Anfang des Flash je 1 (bzw. 2 ab 16 Kbytes Speicher) Worte auseinander. In der Regel steht da dann ein Sprung (RJMP oder JMP) auf die eigentliche ISR. Wenn man die Interrupts dahinter nicht braucht kann man da auch direkt mit der ISR anfangen ohne den Sprung. Da dies im Flash steht kann man es zur Laufzeit nicht (oder nur sehr umständlich) ändern. Falls man da je nach Programmteil eine andere ISR braucht macht man das als normale Verzweigung im Code.
Ein Sprung auf ein RETI für einen nicht genutzten Interrupt ist übrigens ziemlich sinnfrei: Da könnte auch gleich das RETI hinschreiben, und außerdem aktiviert man einen ungenutzten Interrupt einfach nicht.
Hallo!
Danke schön Euch beiden für ausführliche und verständliche Erklärungen. Man muss also damit leben, dass auftretende z.B. ein Timer1 interrupt immer die Timer0 interrupt für die Ausführung der ISR von Timer1 anhalten kann, was mir aber nicht gefällt. :(
Wann genau wird das Interruptflag in GIFR Register (einzige Möglichkeit die Quelle zu erkennen) gelöscht ? So wie ich das bisher verstanden habe wird es hardwaremässig (intern) vor dem Zwangsprung in die entsprechende ISR gemacht, oder ?
Dann hätte man keine Chance rechtzeitig die Interruptquelle zu erkennen und die Ausführung der entsprechender ISR zu verhindern/verzögern.
Wann genau das Interrupt-flag gelöscht wird, ist nicht so wichtig. Die Annahme beim Sprung zum Interruptvector kommt mir auch plausibel vor. Es gibt aber ein paar Ausnahmen wo das Bit gar nicht von der Hardware gelöscht wird und das von Hand gemacht werden muss (z.B. USI ?).
Da man für praktisch jede Interrupt-quelle einen eigenen Interrupt-vektor und damit bei Bedarf eine eigene ISR hat, braucht man die Interruptflags nicht um die Quelle zu erkennen. Gelöscht wird aber immer nur das Flag von der aktuell aufgerufenen ISR. Man könnte also in der ISR von Timer0 immer noch feststellen ob auch das Flag von Timer1 gesetzt ist. Wenn einem der Interupt von Timer1 so wichtig ist, kann man in den anderen ISRs ggf. per SEI weitere Interrupts zulassen. Das reduziert die Verzögerung, verhindert sie aber nicht ganz.
Danke sehr für deine Bestätigung meiner Vermutung. :D
Für mich wäre es aber aus Gewöhnheit schon wichtig, aber im Datenbblatt (DB) unauffndbar. :(
Wie auch immer nehme ich es so an, wie es ist, ohne zu fragen warum. ;)
Übrigens, wie genau ich leider bin, könnte folgender von mir zufällig bemerkter Fehler im Datenblatt von ATtiny24/44/84 ( http://www.atmel.com/dyn/resources/p...ts/doc8006.pdf ) bestätigen: 5 Seite, 11 Zeile, 2 Wort. Dort anstatt "disabled" steht "disbaled" ... nach Murphy: "Ein Fehler tritt erst dann auf, nachdem die letzte Kontrolle durchlaufen worden war."
Hallo!
Ich habe das im vorherigen Beitrag DB von ATtiny24/44/84 weiter aufmerksam gelesen, jedoch auf der Seite 18 war für mich schon Ende, weil ich in "Essembly Code Example" auf einen Befehl gestossen bin, wo in ein Register für mich unbekannte Zahl geladen wird: ldi r16,(0 << EEPM1) | (0 << EEPM0). Im darauf folgenden "C Code Example" kommt identische Zahl vor.
Deshalb meine wahrscheinlich letzte Frage: ist es überhaupt möglich AVR's ausschliesslich nur mit normalen Hexzahlen, wie bei allen bisherigen Prozessoren und µC's, in ASM zu programmieren ?
Ich möchte gleich sagen, dass ich C schon vor zig Jahren erfolgslos erlernen versucht und negativ für immer abgehackt habe. Es freut mich, das ich die AVR's näher kennenzulernen versucht habe, aber fast sicher muss ich anderen µC mit niedriger Referenzspannung für ADC nehmen oder beim PIC als Referenz den LM385-Z1,2 anwenden.
Klar kann man auch für die AVRs direkt die Zahlen hinschreiben. Es ist aber meist einfacher und besser verständlich wenn man die Symbolischen Namen benutzt. Bei einigen Registern wie z.B. ADMUX oder zur Einstellung des AD Teilers mache ich das auch, zumindest teilweise.
Die Schreibweise aus dem Beispiel ist halt wirklich an C angelehnt und etwas gewöhnungsbedürftig. Besonders mit der 0 ist es auch nicht so verbreitet, denn (0 << EEPM1) ist schließlich nichts anderes als eine umständliche Schreibweise für 0. Gängiger ist (1 << EEPM1) um das Bit mit dem Namen EEPM1 zu setzen. Sinnvoll halte ich die Version mit der 0 an Stellen wo man ab und zu mal was ändern muss und um zu zeigen das man das Bit explizit löscht.
Wenn man einen Macroassembler nutzt kann man sich auch ein Markro definieren für den Bitwert. Also z.B. BW(x) für (1 << x).
Das macht man zum Teil auch in C, z.B. wenn man von den ganzen << einen Linksdrall bekommt.
Hallo PICture,
die im Datasheet gebrauchten Assembleranweisungem scheinen mir im AVR-Assembler geschrieben. Dazu habe ich bisher kein anderes als dieses http://www.atmel.com/dyn/resources/p...ts/DOC1022.PDF User Guide gefunden.
Dort ist zB in Kapitel 4.6.3.8 das << erklärt.
Gruß
Searcher