Input Capture Interrupt so langsam?

#785883
Lesenswert?

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]
#785971
Lesenswert?

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.
Moderator Persönliche Seite #786078
Lesenswert?

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...
#786229
Lesenswert?

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
#786275
Lesenswert?

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.
Gast #786401
Lesenswert?

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.
#786505
Lesenswert?

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!!!
Moderator Persönliche Seite #786560
Lesenswert?

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).
#786828
Lesenswert?

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?
#787353
Lesenswert?

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.
#787412
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren