mikrocontroller.net

Forum: Compiler & IDEs Input Capture Interrupt so langsam?


Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht 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]

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jojo S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht 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!!!

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast du denn die Optimierung des Compilers eingeschaltet?

Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich kenne diese Details gar nicht.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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).

Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  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

Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Besten Dank!!!

Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
   for (;;)
      asm volatile("nop");

Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich aber die Optimierung ausschalte, wird auch die Schleife bei der 
Simulation ausgeführt, solange bis ein Interrupt kommt.

Autor: Witali G. (witali)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.