Hallo zusammen!! Ich wundere mich wie langsam der Aufruf vom Input Capture Interrupt im Simulator (AVR-Studio) ist. In möchte die Periode eines Rechtecksignals messen und rechne damit, dass die Interrupt-Routine einige Takte nach Auftreten des Capture-Ereignisses ausgeführt wird. In meinem Code unten will ich von dem aktuellen Zählerstand (Timer1) den Zählerstand zum Moment des Capture-Ereignisses abziehen um dann den InputCapture-Wert auszuwerten. Bei der Simulation stelle ich fest, dass nach der Substraktion der Zählerdatenregister auf 52 hexadezimal ist. Das heißt doch, dass bis die ISR-Routine (speziell diese Substraktion) ausgeführt wird ca. 80 Takte vergehen, oder? Ist es normal oder doch etwas zu viel? Oder habe ich hier irgend einen dummen Fehler gemacht? Wäre für jeden Tipp sehr dankbar. Bin nur Anfänger. [c]#include <avr/io.h> #include <avr/interrupt.h> #include <avr/io.h> union{ struct{ char b00:1; //Bits 0-15 char b01:1; char b02:1; char b03:1; char b04:1; char b05:1; char b06:1; char b07:1; char b08:1; char b09:1; char b10:1; char b11:1; char b12:1; char b13:1; char b14:1; char b15:1; }b; struct{ char low; // LowByte char high; // HighByte }byte; unsigned short l; //LowWord unsigned short h; //HighWord unsigned long VDDig; //LongWord }VD; unsigned long Var = 15441085; unsigned long temp = 31456; int main(void) { DDRD = 0xff; //Port D: alle Pins als Ausgang DDRB = 0xfe; //Port B: Pin 0 als Eingang, Pins 1-7 als Ausgang PORTB |= 0x01; //PullUp-Widerstand von PB0/ICP1 aktivieren TIMSK1 = 1 << ICIE1; TCCR1B = ((1 << ICNC1) | (1 << CS10)); sei(); while (1) { } return 0; } ISR(TIMER1_CAPT_vect) { TCNT1 = TCNT1 - ICR1; }[c]
Na, 80 Takte ist wirklich zu viel. Aber warum gehst Du nicht im Simulator schrittweise durch. Dann siehst Du am Zähler, wie viele Takte zwischen Capture-Ereignis und Eintritt in die ISR vergehen. Wesentlich mehr als 20 Takte sollten es selbst mit viel Register-Sichern nicht sein. Aber Du solltest zum Probieren vielleich mal alles an überflüssigem Ballast aus dem Programm rauswerfen. Die ganzen Variablen, die Du da deklarierst, werden eh nirgends benutzt.
Johannes M. wrote: > Wesentlich > mehr als 20 Takte sollten es selbst mit viel Register-Sichern nicht > sein. 8 Takte benötigt allein die Interruptannahme mit dem anschließenden Sprung aus der Vektortabelle. Weitere 8 Takte braucht der minimale Prolog einer ISR. Damit sind bereits 16 Takte erreicht, wenn die ISR selbst keine weiteren Register sichern muss. Wenn die ISR aber einen 16-bit-Wert lesen soll, muss sie wenigstens noch 2 Register sichern, macht 4 weitere Takte dafür. Erst dann kann sie überhaupt irgendwas auf den IO-Ports machen. > Aber Du solltest zum Probieren vielleich mal alles an überflüssigem > Ballast aus dem Programm rauswerfen. Die ganzen Variablen, die Du da > deklarierst, werden eh nirgends benutzt. Dann generieren sie aber auch keinen Code, wenn man die Optimierung einschaltet. Aber genau da vermute ich, dass der Hase im Pfeffer liegt...
Jörg Wunsch wrote: > 8 Takte benötigt allein die Interruptannahme mit dem anschließenden > Sprung aus der Vektortabelle. Weitere 8 Takte braucht der minimale > Prolog einer ISR. Damit sind bereits 16 Takte erreicht, wenn die ISR > selbst keine weiteren Register sichern muss. Klar, hatte grad nur kurz im Kopf überschlagen... > Wenn die ISR aber einen 16-bit-Wert lesen soll, muss sie wenigstens > noch 2 Register sichern, macht 4 weitere Takte dafür. Erst dann kann > sie überhaupt irgendwas auf den IO-Ports machen. Auch das ist natürlich nicht von der Hand zu weisen. Trotzdem halte ich 80 Takte in einem Programm solchen Umfangs für zu viel. >> Aber Du solltest zum Probieren vielleich mal alles an überflüssigem >> Ballast aus dem Programm rauswerfen. Die ganzen Variablen, die Du da >> deklarierst, werden eh nirgends benutzt. > > Dann generieren sie aber auch keinen Code, wenn man die Optimierung > einschaltet. Aber genau da vermute ich, dass der Hase im Pfeffer > liegt... Das mit dem Wegschmeißen des unnötigen Ballasts war auch eher so gedacht, dass der OP erst mal ein übersichtliches Programm erstellen soll, das kein überflüssiges Zeug enthält, das vom Kern der Sache ablenkt. Gruß johnny
Erstmals vielen Dank für eure Antworten! Johannes M. wrote: > Na, 80 Takte ist wirklich zu viel. Aber warum gehst Du nicht im > Simulator schrittweise durch. Dann siehst Du am Zähler, wie viele Takte > zwischen Capture-Ereignis und Eintritt in die ISR vergehen. Genau das habe ich getan. Ich habe nur das Endergebnis mitgeteilt. Zwischen Capture-Ereignis und Eintritt in die ISR vergehen 12 Takte, nur bis zu dem Punkt, wo der Pfeil am Anfang der Interrupt-Routine steht. Bei dem Sprung zu dem einzigen Statement in der Routine werden dann gleich 34 Takte verbraucht. Ich habe aber keine Ahnung woran das liegt. > Aber Du solltest zum Probieren vielleich mal alles an überflüssigem > Ballast aus dem Programm rauswerfen. Die ganzen Variablen, die Du da > deklarierst, werden eh nirgends benutzt. Ich werde die Variablen dann zur Umrechnung und zur Ausgabe brauchen. Aber ich versuche mal die zunächst mal auszulassen.
Die 34 Takte sind exakt das Sichern der Register. Beim Debuggen und durch den C-Code steppen siehst du das nicht, schalte die View/Disassembler Ansicht ein. Auch wenn es erstmal unübersichtlicher aussieht: zu jeder C-Code Zeile wird der Maschinencode angezeigt und man sieht das am Anfang der ISR jede Menge Register umkopiert werden.
Ich habe auch versucht, die ganzen Variablendeklarationen auszukommentieren und neuzukompilieren, doch es ändern die Sache nicht. Das ist wohl normal, dass so viel Takte zum Aufruf notwendig sind. Na ja, bei 20MHz dauert es nicht so lang. Ich danke euch allen für die Antworten!!!
Witali Gustschin wrote: > Ich kenne diese Details gar nicht. Dann solltest du sie wohl kennen lernen. ;-) Den Compiler ohne Optimierung zu benutzen ist sowas, wie einen Ferrari mit angezogener Handbremse zu fahren. Da du von AVR Studio geschrieben hast, vermute ich stark, dass die Optimierung noch ausgeschaltet ist, da das die Voreinstellung von AVR Studio ist (leider).
Ich habe jetzt im Tutorial und in avr-libc manual die Sachen über Optimierung gelesen aber irgend wie nicht schlau daraus geworden, wie man die Optrimierung einschaltet. Kann man das im AVR-Studion durch setzten eines Häckchens in irgendeinem Dialogfenster oder auf so eine ähnliche Art machen? Oder passiert das nur über die Änderung von Makefile? Muss ich im Makefile irgendwo so etwas wie OPT = 'Optimierungsgrad' z.B. s, oder -Os einfügen?
@ Witali Gustschin (witali) >Kann man das im AVR-Studion durch setzten eines Häckchens in irgendeinem >Dialogfenster oder auf so eine ähnliche Art machen? Oder passiert das Ja. Menu Project -> Configuration Options -> Optimization MfG Falk
Jetzt habe ich die Optimierung eingeschaltet und stelle fest, dass mir anscheinend die Endlosschleife wegoptimiert wurde. Bei der Simulation springt der Simulator nicht in die Schleife. Die braucht man aber doch, wenn man nur bei Interrupts was tun möchte und sonst nur wartet.
Die wird nicht wegoptimiert, aber das AVR Studio kann offenbar nicht damit umgehen, eine leere Schleife allein zu haben (das ist ja dann nur ein RJMP auf sich selbst). Abhilfe: schreib was rein:
1 | for (;;) |
2 | asm volatile("nop"); |
Wenn ich aber die Optimierung ausschalte, wird auch die Schleife bei der Simulation ausgeführt, solange bis ein Interrupt kommt.
Vielen Dank für den Hinweis! Jetzt vergehen nur 37 (hex) Takte bis die ISR ausgeführt wird, deutlich schneller als mit 52 (hex) Takten. Eine Frage, die mir jetzt aufkommt, ist: Leidet das Programm selber nicht unter dieser Optimierung? Wenn früher mehr Takte bis zum Aufruf von ISR vergingen für wichtige Aktionen wie Zwischenspeicherung von wichtigen Registern und sonstiges, so werden diese Aktionen auf einmal unnötig.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.